SON for Ethereum listener, WIP
This commit is contained in:
parent
51aa87130e
commit
f12c9f3ef9
9 changed files with 564 additions and 153 deletions
|
|
@ -1963,7 +1963,7 @@ void database::perform_son_tasks()
|
|||
asset_issuer_permission_flags::override_authority;
|
||||
a.options.core_exchange_rate.base.amount = 100000;
|
||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
||||
a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value
|
||||
a.options.core_exchange_rate.quote.amount = 2500;
|
||||
a.options.core_exchange_rate.quote.asset_id = a.id;
|
||||
a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty
|
||||
a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set
|
||||
|
|
@ -1977,6 +1977,40 @@ void database::perform_son_tasks()
|
|||
gpo.pending_parameters->extensions.value.btc_asset = btc_asset.get_id();
|
||||
});
|
||||
}
|
||||
// create ETH asset here because son_account is the issuer of the ETH
|
||||
if (gpo.parameters.eth_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_FOR_ETHEREUM_TIME)
|
||||
{
|
||||
const asset_dynamic_data_object& dyn_asset =
|
||||
create<asset_dynamic_data_object>([](asset_dynamic_data_object& a) {
|
||||
a.current_supply = 0;
|
||||
});
|
||||
|
||||
const asset_object& eth_asset =
|
||||
create<asset_object>( [&gpo, &dyn_asset]( asset_object& a ) {
|
||||
a.symbol = "ETH";
|
||||
a.precision = 8;
|
||||
a.issuer = gpo.parameters.son_account();
|
||||
a.options.max_supply = GRAPHENE_MAX_SHARE_SUPPLY;
|
||||
a.options.market_fee_percent = 500; // 5%
|
||||
a.options.issuer_permissions = UIA_ASSET_ISSUER_PERMISSION_MASK;
|
||||
a.options.flags = asset_issuer_permission_flags::charge_market_fee |
|
||||
asset_issuer_permission_flags::override_authority;
|
||||
a.options.core_exchange_rate.base.amount = 100000;
|
||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
||||
a.options.core_exchange_rate.quote.amount = 2500;
|
||||
a.options.core_exchange_rate.quote.asset_id = a.id;
|
||||
a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty
|
||||
a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set
|
||||
a.options.whitelist_markets.clear(); // might be traded with
|
||||
a.options.blacklist_markets.clear(); // might not be traded with
|
||||
a.dynamic_asset_data_id = dyn_asset.id;
|
||||
});
|
||||
modify( gpo, [ð_asset]( global_property_object& gpo ) {
|
||||
gpo.parameters.extensions.value.eth_asset = eth_asset.get_id();
|
||||
if( gpo.pending_parameters )
|
||||
gpo.pending_parameters->extensions.value.eth_asset = eth_asset.get_id();
|
||||
});
|
||||
}
|
||||
// create HBD asset here because son_account is the issuer of the HBD
|
||||
if (gpo.parameters.hbd_asset() == asset_id_type() && head_block_time() >= HARDFORK_SON_FOR_HIVE_TIME)
|
||||
{
|
||||
|
|
@ -1997,7 +2031,7 @@ void database::perform_son_tasks()
|
|||
asset_issuer_permission_flags::override_authority;
|
||||
a.options.core_exchange_rate.base.amount = 100000;
|
||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
||||
a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value
|
||||
a.options.core_exchange_rate.quote.amount = 2500;
|
||||
a.options.core_exchange_rate.quote.asset_id = a.id;
|
||||
a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty
|
||||
a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set
|
||||
|
|
@ -2031,7 +2065,7 @@ void database::perform_son_tasks()
|
|||
asset_issuer_permission_flags::override_authority;
|
||||
a.options.core_exchange_rate.base.amount = 100000;
|
||||
a.options.core_exchange_rate.base.asset_id = asset_id_type(0);
|
||||
a.options.core_exchange_rate.quote.amount = 2500; // CoinMarketCap approx value
|
||||
a.options.core_exchange_rate.quote.amount = 2500;
|
||||
a.options.core_exchange_rate.quote.asset_id = a.id;
|
||||
a.options.whitelist_authorities.clear(); // accounts allowed to use asset, if not empty
|
||||
a.options.blacklist_authorities.clear(); // accounts who can blacklist other accounts to use asset, if white_list flag is set
|
||||
|
|
@ -2297,14 +2331,17 @@ void database::perform_chain_maintenance(const signed_block& next_block, const g
|
|||
p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset;
|
||||
if( !p.pending_parameters->extensions.value.hive_asset.valid() )
|
||||
p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset;
|
||||
if( !p.pending_parameters->extensions.value.eth_asset.valid() )
|
||||
p.pending_parameters->extensions.value.eth_asset = p.parameters.extensions.value.eth_asset;
|
||||
|
||||
// the following parameters are not allowed to be changed. So take what is in global property
|
||||
p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset;
|
||||
p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset;
|
||||
p.pending_parameters->extensions.value.maximum_son_count = p.parameters.extensions.value.maximum_son_count;
|
||||
p.pending_parameters->extensions.value.btc_asset = p.parameters.extensions.value.btc_asset;
|
||||
p.pending_parameters->extensions.value.son_account = p.parameters.extensions.value.son_account;
|
||||
p.pending_parameters->extensions.value.gpos_period_start = p.parameters.extensions.value.gpos_period_start;
|
||||
p.pending_parameters->extensions.value.son_account = p.parameters.extensions.value.son_account;
|
||||
p.pending_parameters->extensions.value.btc_asset = p.parameters.extensions.value.btc_asset;
|
||||
p.pending_parameters->extensions.value.maximum_son_count = p.parameters.extensions.value.maximum_son_count;
|
||||
p.pending_parameters->extensions.value.hbd_asset = p.parameters.extensions.value.hbd_asset;
|
||||
p.pending_parameters->extensions.value.hive_asset = p.parameters.extensions.value.hive_asset;
|
||||
p.pending_parameters->extensions.value.eth_asset = p.parameters.extensions.value.eth_asset;
|
||||
|
||||
p.parameters = std::move(*p.pending_parameters);
|
||||
p.pending_parameters.reset();
|
||||
|
|
|
|||
7
libraries/chain/hardfork.d/SON_FOR_ETHEREUM.hf
Normal file
7
libraries/chain/hardfork.d/SON_FOR_ETHEREUM.hf
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef HARDFORK_SON_FOR_ETHEREUM_TIME
|
||||
#ifdef BUILD_PEERPLAYS_TESTNET
|
||||
#define HARDFORK_SON_FOR_ETHEREUM_TIME (fc::time_point_sec::from_iso_string("2022-07-01T00:00:00"))
|
||||
#else
|
||||
#define HARDFORK_SON_FOR_ETHEREUM_TIME (fc::time_point_sec::from_iso_string("2022-07-01T00:00:00"))
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -70,6 +70,7 @@ namespace graphene { namespace chain {
|
|||
optional < uint16_t > maximum_son_count = GRAPHENE_DEFAULT_MAX_SONS; ///< maximum number of active SONS
|
||||
optional < asset_id_type > hbd_asset = asset_id_type();
|
||||
optional < asset_id_type > hive_asset = asset_id_type();
|
||||
optional < asset_id_type > eth_asset = asset_id_type();
|
||||
};
|
||||
|
||||
struct chain_parameters
|
||||
|
|
@ -220,6 +221,9 @@ namespace graphene { namespace chain {
|
|||
inline asset_id_type hive_asset() const {
|
||||
return extensions.value.hive_asset.valid() ? *extensions.value.hive_asset : asset_id_type();
|
||||
}
|
||||
inline asset_id_type eth_asset() const {
|
||||
return extensions.value.eth_asset.valid() ? *extensions.value.eth_asset : asset_id_type();
|
||||
}
|
||||
private:
|
||||
static void safe_copy(chain_parameters& to, const chain_parameters& from);
|
||||
};
|
||||
|
|
@ -257,6 +261,7 @@ FC_REFLECT( graphene::chain::parameter_extension,
|
|||
(maximum_son_count)
|
||||
(hbd_asset)
|
||||
(hive_asset)
|
||||
(eth_asset)
|
||||
)
|
||||
|
||||
FC_REFLECT( graphene::chain::chain_parameters,
|
||||
|
|
|
|||
|
|
@ -76,14 +76,14 @@ bool verify_sig(const bytes &sig, const bytes &pubkey, const bytes &msg, const s
|
|||
//! Get sig_temp
|
||||
FC_ASSERT(sig.size() > 70);
|
||||
FC_ASSERT(sig[0] == 0x30);
|
||||
FC_ASSERT(sig[1] == static_cast<char>(sig.size()-3));
|
||||
FC_ASSERT(sig[1] == static_cast<char>(sig.size() - 3));
|
||||
FC_ASSERT(sig[2] == 0x02);
|
||||
const uint r_size = sig[3];
|
||||
std::vector<unsigned char> sig_temp(sig.begin()+4+(r_size-32), sig.begin()+4+r_size);
|
||||
FC_ASSERT(sig[4+r_size] == 0x02);
|
||||
const uint s_size = sig[5+r_size];
|
||||
FC_ASSERT(sig.size() == r_size+s_size+7);
|
||||
sig_temp.insert(sig_temp.end(), sig.begin()+6+r_size, sig.end());
|
||||
std::vector<unsigned char> sig_temp(sig.begin() + 4 + (r_size - 32), sig.begin() + 4 + r_size);
|
||||
FC_ASSERT(sig[4 + r_size] == 0x02);
|
||||
const uint s_size = sig[5 + r_size];
|
||||
FC_ASSERT(sig.size() == r_size + s_size + 7);
|
||||
sig_temp.insert(sig_temp.end(), sig.begin() + 6 + r_size, sig.end());
|
||||
|
||||
std::vector<unsigned char> pubkey_temp(pubkey.begin(), pubkey.end());
|
||||
std::vector<unsigned char> msg_temp(msg.begin(), msg.end());
|
||||
|
|
|
|||
|
|
@ -176,17 +176,18 @@ ws_reply ws_client::send_post_request(std::string body, bool show_log) {
|
|||
// Close the WebSocket connection
|
||||
ws.close(boost::beast::websocket::close_code::normal);
|
||||
|
||||
std::string rbody = boost::beast::make_printable(buffer.data());
|
||||
//std::string rbody{boost::asio::buffers_begin(buffer),
|
||||
// boost::asio::buffers_end(reading)};
|
||||
|
||||
ws_reply reply;
|
||||
reply.status = 200;
|
||||
reply.body = rbody;
|
||||
//reply.body = rbody;
|
||||
|
||||
if (show_log) {
|
||||
ilog("### Request URL: ${url}", ("url", url));
|
||||
ilog("### Request: ${body}", ("body", body));
|
||||
ilog("### Response: ${rbody}", ("rbody", rbody));
|
||||
}
|
||||
//if (show_log) {
|
||||
// ilog("### Request URL: ${url}", ("url", url));
|
||||
// ilog("### Request: ${body}", ("body", body));
|
||||
// ilog("### Response: ${rbody}", ("rbody", rbody));
|
||||
//}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ public:
|
|||
|
||||
std::string admin_node_info();
|
||||
std::string eth_get_block_by_number(std::string block_number, bool full_block);
|
||||
std::string eth_get_logs(std::string wallet_contract_address);
|
||||
std::string net_version();
|
||||
|
||||
std::string get_chain_id();
|
||||
|
|
@ -47,13 +48,9 @@ private:
|
|||
std::string rpc_url;
|
||||
std::string rpc_user;
|
||||
std::string rpc_password;
|
||||
std::string ws_url;
|
||||
std::string ws_user;
|
||||
std::string ws_password;
|
||||
std::string wallet_contract_address;
|
||||
|
||||
ethereum_rpc_client *ethereum_client_rpc;
|
||||
ethereum_ws_client *ethereum_client_ws;
|
||||
ethereum_rpc_client *rpc_client;
|
||||
|
||||
ethereum::chain_id_type chain_id;
|
||||
ethereum::network_id_type network_id;
|
||||
|
|
|
|||
|
|
@ -161,9 +161,6 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
cli.add_options()("ethereum-node-rpc-url", bpo::value<string>()->default_value("127.0.0.1:8545"), "Ethereum node RPC URL [http[s]://]host[:port]");
|
||||
cli.add_options()("ethereum-node-rpc-user", bpo::value<string>(), "Ethereum RPC user");
|
||||
cli.add_options()("ethereum-node-rpc-password", bpo::value<string>(), "Ethereum RPC password");
|
||||
cli.add_options()("ethereum-node-ws-url", bpo::value<string>()->default_value("127.0.0.1:8546"), "Ethereum node WS URL [ws[s]://]host[:port]");
|
||||
cli.add_options()("ethereum-node-ws-user", bpo::value<string>(), "Ethereum WS user");
|
||||
cli.add_options()("ethereum-node-ws-password", bpo::value<string>(), "Ethereum WS password");
|
||||
cli.add_options()("ethereum-wallet-contract-address", bpo::value<string>()->default_value("0000000000000000000000000000000000000000"), "Ethereum wallet contract address"),
|
||||
cli.add_options()("ethereum-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("5fbbb31be52608d2f52247e8400b7fcaa9e0bc12", "9bedac2bd8fe2a6f6528e066c67fc8ac0622e96828d40c0e820d83c5bd2b0589")),
|
||||
"Tuple of [Ethereum public key, Ethereum private key] (may specify multiple times)");
|
||||
|
|
|
|||
|
|
@ -172,18 +172,21 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
|||
#ifdef ENABLE_PEERPLAYS_ASSET_DEPOSITS
|
||||
//enable_peerplays_asset_deposits = (sed.sidechain == sidechain_type::peerplays) &&
|
||||
// (sed.sidechain_currency.compare("BTC") != 0) &&
|
||||
// (sed.sidechain_currency.compare("ETH") != 0) &&
|
||||
// (sed.sidechain_currency.compare("HBD") != 0) &&
|
||||
// (sed.sidechain_currency.compare("HIVE") != 0);
|
||||
#endif
|
||||
|
||||
bool deposit_condition = (sed.peerplays_to == gpo.parameters.son_account()) &&
|
||||
(((sed.sidechain == sidechain_type::bitcoin) && (sed.sidechain_currency.compare("BTC") == 0)) ||
|
||||
((sed.sidechain == sidechain_type::ethereum) && (sed.sidechain_currency.compare("ETH") == 0)) ||
|
||||
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HBD") == 0)) ||
|
||||
((sed.sidechain == sidechain_type::hive) && (sed.sidechain_currency.compare("HIVE") == 0)) ||
|
||||
enable_peerplays_asset_deposits);
|
||||
|
||||
bool withdraw_condition = (sed.peerplays_to == gpo.parameters.son_account()) && (sed.sidechain == sidechain_type::peerplays) &&
|
||||
((sed.sidechain_currency == object_id_to_string(gpo.parameters.btc_asset())) ||
|
||||
(sed.sidechain_currency == object_id_to_string(gpo.parameters.eth_asset())) ||
|
||||
(sed.sidechain_currency == object_id_to_string(gpo.parameters.hbd_asset())) ||
|
||||
(sed.sidechain_currency == object_id_to_string(gpo.parameters.hive_asset())));
|
||||
|
||||
|
|
@ -240,6 +243,10 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_
|
|||
withdraw_currency = "BTC";
|
||||
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.btc_asset()).options.core_exchange_rate;
|
||||
}
|
||||
if (sed.sidechain_currency == object_id_to_string(gpo.parameters.eth_asset())) {
|
||||
withdraw_currency = "ETH";
|
||||
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.eth_asset()).options.core_exchange_rate;
|
||||
}
|
||||
if (sed.sidechain_currency == object_id_to_string(gpo.parameters.hbd_asset())) {
|
||||
withdraw_currency = "HBD";
|
||||
withdraw_currency_price = database.get<asset_object>(database.get_global_properties().parameters.hbd_asset()).options.core_exchange_rate;
|
||||
|
|
@ -648,6 +655,7 @@ void sidechain_net_handler::on_applied_block(const signed_block &b) {
|
|||
|
||||
bool is_tracked_asset =
|
||||
((sidechain == sidechain_type::bitcoin) && (transfer_op.amount.asset_id == gpo.parameters.btc_asset())) ||
|
||||
((sidechain == sidechain_type::ethereum) && (transfer_op.amount.asset_id == gpo.parameters.eth_asset())) ||
|
||||
((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hbd_asset())) ||
|
||||
((sidechain == sidechain_type::hive) && (transfer_op.amount.asset_id == gpo.parameters.hive_asset()));
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ std::string ethereum_rpc_client::eth_get_block_by_number(std::string block_numbe
|
|||
return send_post_request("eth_getBlockByNumber", params, debug_rpc_calls);
|
||||
}
|
||||
|
||||
std::string ethereum_rpc_client::eth_get_logs(std::string wallet_contract_address) {
|
||||
std::string params = "[{\"address\": \"" + wallet_contract_address + "\"}]";
|
||||
std::string reply_str = send_post_request("eth_getLogs", params, debug_rpc_calls);
|
||||
return retrieve_value_from_reply(reply_str, "");
|
||||
}
|
||||
|
||||
std::string ethereum_rpc_client::net_version() {
|
||||
return send_post_request("net_version", "", debug_rpc_calls);
|
||||
}
|
||||
|
|
@ -72,18 +78,6 @@ sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidecha
|
|||
rpc_password = "";
|
||||
}
|
||||
|
||||
ws_url = options.at("ethereum-node-ws-url").as<std::string>();
|
||||
if (options.count("ethereum-node-ws-user")) {
|
||||
ws_user = options.at("ethereum-node-ws-user").as<std::string>();
|
||||
} else {
|
||||
ws_user = "";
|
||||
}
|
||||
if (options.count("ethereum-node-ws-password")) {
|
||||
rpc_password = options.at("ethereum-node-ws-password").as<std::string>();
|
||||
} else {
|
||||
ws_password = "";
|
||||
}
|
||||
|
||||
wallet_contract_address = options.at("ethereum-wallet-contract-address").as<std::string>();
|
||||
|
||||
if (options.count("ethereum-private-key")) {
|
||||
|
|
@ -98,16 +92,15 @@ sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidecha
|
|||
}
|
||||
}
|
||||
|
||||
ethereum_client_rpc = new ethereum_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls);
|
||||
ethereum_client_ws = new ethereum_ws_client(ws_url, ws_user, ws_password, debug_rpc_calls);
|
||||
rpc_client = new ethereum_rpc_client(rpc_url, rpc_user, rpc_password, debug_rpc_calls);
|
||||
|
||||
std::string chain_id_str = ethereum_client_rpc->get_chain_id();
|
||||
std::string chain_id_str = rpc_client->get_chain_id();
|
||||
if (chain_id_str.empty()) {
|
||||
elog("No Ethereum node running at ${url}", ("url", rpc_url));
|
||||
FC_ASSERT(false);
|
||||
}
|
||||
chain_id = std::stoll(chain_id_str);
|
||||
std::string network_id_str = ethereum_client_rpc->get_network_id();
|
||||
std::string network_id_str = rpc_client->get_network_id();
|
||||
network_id = std::stoll(network_id_str);
|
||||
|
||||
ilog("Running on Ethereum network, chain id ${chain_id_str}, network id ${network_id_str}", ("chain_id_str", chain_id_str)("network_id_str", network_id_str));
|
||||
|
|
@ -124,126 +117,418 @@ sidechain_net_handler_ethereum::~sidechain_net_handler_ethereum() {
|
|||
|
||||
bool sidechain_net_handler_ethereum::process_proposal(const proposal_object &po) {
|
||||
ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id()));
|
||||
return true;
|
||||
|
||||
bool should_approve = false;
|
||||
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
int32_t op_idx_0 = -1;
|
||||
chain::operation op_obj_idx_0;
|
||||
|
||||
if (po.proposed_transaction.operations.size() >= 1) {
|
||||
op_idx_0 = po.proposed_transaction.operations[0].which();
|
||||
op_obj_idx_0 = po.proposed_transaction.operations[0];
|
||||
}
|
||||
|
||||
int32_t op_idx_1 = -1;
|
||||
chain::operation op_obj_idx_1;
|
||||
(void)op_idx_1;
|
||||
|
||||
if (po.proposed_transaction.operations.size() >= 2) {
|
||||
op_idx_1 = po.proposed_transaction.operations[1].which();
|
||||
op_obj_idx_1 = po.proposed_transaction.operations[1];
|
||||
}
|
||||
|
||||
switch (op_idx_0) {
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_update_operation>::value: {
|
||||
bool address_ok = false;
|
||||
bool transaction_ok = false;
|
||||
son_wallet_id_type swo_id = op_obj_idx_0.get<son_wallet_update_operation>().son_wallet_id;
|
||||
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
const auto swo = idx.find(swo_id);
|
||||
if (swo != idx.end()) {
|
||||
|
||||
//auto active_sons = gpo.active_sons;
|
||||
//vector<son_info> wallet_sons = swo->sons;
|
||||
//
|
||||
//bool son_sets_equal = (active_sons.size() == wallet_sons.size());
|
||||
//
|
||||
//if (son_sets_equal) {
|
||||
// for (size_t i = 0; i < active_sons.size(); i++) {
|
||||
// son_sets_equal = son_sets_equal && active_sons.at(i) == wallet_sons.at(i);
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//if (son_sets_equal) {
|
||||
// address_ok = (op_obj_idx_0.get<son_wallet_update_operation>().address == wallet_account_name);
|
||||
//}
|
||||
//
|
||||
//if (po.proposed_transaction.operations.size() >= 2) {
|
||||
// object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
|
||||
// std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
|
||||
//
|
||||
// const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
|
||||
// const auto st = st_idx.find(object_id);
|
||||
// if (st == st_idx.end()) {
|
||||
//
|
||||
// std::string tx_str = "";
|
||||
//
|
||||
// if (object_id.is<son_wallet_id_type>()) {
|
||||
// const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
// const auto swo = idx.find(object_id);
|
||||
// if (swo != idx.end()) {
|
||||
//
|
||||
// std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str));
|
||||
// hive::signed_transaction op_trx;
|
||||
// fc::raw::unpack(ss_trx, op_trx, 1000);
|
||||
//
|
||||
// fc::flat_map<std::string, uint16_t> account_auths;
|
||||
// uint32_t total_weight = 0;
|
||||
// for (const auto &wallet_son : wallet_sons) {
|
||||
// total_weight = total_weight + wallet_son.weight;
|
||||
// account_auths[wallet_son.sidechain_public_keys.at(sidechain)] = wallet_son.weight;
|
||||
// }
|
||||
//
|
||||
// std::string memo_key = rpc_client->get_account_memo_key(wallet_account_name);
|
||||
//
|
||||
// hive::authority active;
|
||||
// active.weight_threshold = total_weight * 2 / 3 + 1;
|
||||
// active.account_auths = account_auths;
|
||||
//
|
||||
// hive::account_update_operation auo;
|
||||
// auo.account = wallet_account_name;
|
||||
// auo.active = active;
|
||||
// auo.memo_key = op_trx.operations[0].get<hive::account_update_operation>().memo_key;
|
||||
//
|
||||
// hive::signed_transaction htrx;
|
||||
// htrx.ref_block_num = op_trx.ref_block_num;
|
||||
// htrx.ref_block_prefix = op_trx.ref_block_prefix;
|
||||
// htrx.set_expiration(op_trx.expiration);
|
||||
//
|
||||
// htrx.operations.push_back(auo);
|
||||
//
|
||||
// std::stringstream ss;
|
||||
// fc::raw::pack(ss, htrx, 1000);
|
||||
// tx_str = boost::algorithm::hex(ss.str());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// transaction_ok = (op_tx_str == tx_str);
|
||||
// }
|
||||
//} else {
|
||||
// transaction_ok = true;
|
||||
//}
|
||||
}
|
||||
|
||||
address_ok = true;
|
||||
transaction_ok = true;
|
||||
|
||||
should_approve = address_ok &&
|
||||
transaction_ok;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_deposit_process_operation>::value: {
|
||||
bool process_ok = false;
|
||||
son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get<son_wallet_deposit_process_operation>().son_wallet_deposit_id;
|
||||
const auto &idx = database.get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
|
||||
const auto swdo = idx.find(swdo_id);
|
||||
if (swdo != idx.end()) {
|
||||
|
||||
//std::string swdo_txid = swdo->sidechain_transaction_id;
|
||||
//std::string swdo_sidechain_from = swdo->sidechain_from;
|
||||
//std::string swdo_sidechain_currency = swdo->sidechain_currency;
|
||||
//uint64_t swdo_sidechain_amount = swdo->sidechain_amount.value;
|
||||
//uint64_t swdo_op_idx = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-")));
|
||||
//
|
||||
//std::string tx_str = rpc_client->account_history_api_get_transaction(swdo_txid);
|
||||
//if (tx_str != "") {
|
||||
//
|
||||
// std::stringstream ss_tx(tx_str);
|
||||
// boost::property_tree::ptree tx;
|
||||
// boost::property_tree::read_json(ss_tx, tx);
|
||||
//
|
||||
// uint64_t op_idx = -1;
|
||||
// for (const auto &ops : tx.get_child("result.operations")) {
|
||||
// const auto &op = ops.second;
|
||||
// op_idx = op_idx + 1;
|
||||
// if (op_idx == swdo_op_idx) {
|
||||
// std::string operation_type = op.get<std::string>("type");
|
||||
//
|
||||
// if (operation_type == "transfer_operation") {
|
||||
// const auto &op_value = op.get_child("value");
|
||||
//
|
||||
// std::string sidechain_from = op_value.get<std::string>("from");
|
||||
//
|
||||
// const auto &amount_child = op_value.get_child("amount");
|
||||
//
|
||||
// uint64_t amount = amount_child.get<uint64_t>("amount");
|
||||
// std::string nai = amount_child.get<std::string>("nai");
|
||||
// std::string sidechain_currency = "";
|
||||
// if ((nai == "@@000000013" /*?? HBD*/) || (nai == "@@000000013" /*TBD*/)) {
|
||||
// sidechain_currency = "HBD";
|
||||
// }
|
||||
// if ((nai == "@@000000021") /*?? HIVE*/ || (nai == "@@000000021" /*TESTS*/)) {
|
||||
// sidechain_currency = "HIVE";
|
||||
// }
|
||||
//
|
||||
// std::string memo = op_value.get<std::string>("memo");
|
||||
// boost::trim(memo);
|
||||
// if (!memo.empty()) {
|
||||
// sidechain_from = memo;
|
||||
// }
|
||||
//
|
||||
// process_ok = (swdo_sidechain_from == sidechain_from) &&
|
||||
// (swdo_sidechain_currency == sidechain_currency) &&
|
||||
// (swdo_sidechain_amount == amount);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
process_ok = true;
|
||||
|
||||
should_approve = process_ok;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value: {
|
||||
bool process_ok = false;
|
||||
bool transaction_ok = false;
|
||||
son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get<son_wallet_withdraw_process_operation>().son_wallet_withdraw_id;
|
||||
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
|
||||
const auto swwo = idx.find(swwo_id);
|
||||
if (swwo != idx.end()) {
|
||||
|
||||
//uint32_t swwo_block_num = swwo->block_num;
|
||||
//std::string swwo_peerplays_transaction_id = swwo->peerplays_transaction_id;
|
||||
//uint32_t swwo_op_idx = std::stoll(swwo->peerplays_uid.substr(swwo->peerplays_uid.find_last_of("-") + 1));
|
||||
//
|
||||
//const auto &block = database.fetch_block_by_number(swwo_block_num);
|
||||
//
|
||||
//for (const auto &tx : block->transactions) {
|
||||
// if (tx.id().str() == swwo_peerplays_transaction_id) {
|
||||
// operation op = tx.operations[swwo_op_idx];
|
||||
// transfer_operation t_op = op.get<transfer_operation>();
|
||||
//
|
||||
// price asset_price = database.get<asset_object>(t_op.amount.asset_id).options.core_exchange_rate;
|
||||
// asset peerplays_asset = asset(t_op.amount.amount * asset_price.base.amount / asset_price.quote.amount);
|
||||
//
|
||||
// process_ok = (t_op.to == gpo.parameters.son_account()) &&
|
||||
// (swwo->peerplays_from == t_op.from) &&
|
||||
// (swwo->peerplays_asset == peerplays_asset);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
|
||||
//std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
|
||||
//
|
||||
//const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
|
||||
//const auto st = st_idx.find(object_id);
|
||||
//if (st == st_idx.end()) {
|
||||
//
|
||||
// std::string tx_str = "";
|
||||
//
|
||||
// if (object_id.is<son_wallet_withdraw_id_type>()) {
|
||||
// const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
|
||||
// const auto swwo = idx.find(object_id);
|
||||
// if (swwo != idx.end()) {
|
||||
//
|
||||
// std::stringstream ss_trx(boost::algorithm::unhex(op_tx_str));
|
||||
// hive::signed_transaction op_trx;
|
||||
// fc::raw::unpack(ss_trx, op_trx, 1000);
|
||||
//
|
||||
// uint64_t symbol = 0;
|
||||
// if (swwo->withdraw_currency == "HBD") {
|
||||
// symbol = hive::asset::hbd_symbol_ser;
|
||||
// }
|
||||
// if (swwo->withdraw_currency == "HIVE") {
|
||||
// symbol = hive::asset::hive_symbol_ser;
|
||||
// }
|
||||
//
|
||||
// hive::transfer_operation t_op;
|
||||
// t_op.from = wallet_account_name;
|
||||
// t_op.to = swwo->withdraw_address;
|
||||
// t_op.amount.amount = swwo->withdraw_amount;
|
||||
// t_op.amount.symbol = symbol;
|
||||
// t_op.memo = "";
|
||||
//
|
||||
// hive::signed_transaction htrx;
|
||||
// htrx.ref_block_num = op_trx.ref_block_num;
|
||||
// htrx.ref_block_prefix = op_trx.ref_block_prefix;
|
||||
// htrx.set_expiration(op_trx.expiration);
|
||||
//
|
||||
// htrx.operations.push_back(t_op);
|
||||
//
|
||||
// std::stringstream ss;
|
||||
// fc::raw::pack(ss, htrx, 1000);
|
||||
// tx_str = boost::algorithm::hex(ss.str());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// transaction_ok = (op_tx_str == tx_str);
|
||||
//}
|
||||
}
|
||||
|
||||
process_ok = true;
|
||||
transaction_ok = true;
|
||||
|
||||
should_approve = process_ok &&
|
||||
transaction_ok;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: {
|
||||
should_approve = true;
|
||||
son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer;
|
||||
std::string signature = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signature;
|
||||
sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id;
|
||||
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto sto = st_idx.find(sidechain_transaction_id);
|
||||
if (sto == st_idx.end()) {
|
||||
should_approve = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &s_idx = database.get_index_type<son_index>().indices().get<by_id>();
|
||||
const auto son = s_idx.find(signer);
|
||||
if (son == s_idx.end()) {
|
||||
should_approve = false;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_settle_operation>::value: {
|
||||
should_approve = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
should_approve = false;
|
||||
elog("==================================================");
|
||||
elog("Proposal not considered for approval ${po}", ("po", po));
|
||||
elog("==================================================");
|
||||
}
|
||||
|
||||
return should_approve;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_ethereum::process_primary_wallet() {
|
||||
const auto &swi = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
const auto &active_sw = swi.rbegin();
|
||||
if (active_sw != swi.rend()) {
|
||||
|
||||
if ((active_sw->addresses.find(sidechain_type::ethereum) == active_sw->addresses.end()) ||
|
||||
(active_sw->addresses.at(sidechain_type::ethereum).empty())) {
|
||||
|
||||
if (proposal_exists(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
auto active_sons = gpo.active_sons;
|
||||
string reply_str = create_primary_wallet_address(active_sons);
|
||||
|
||||
std::stringstream active_pw_ss(reply_str);
|
||||
|
||||
boost::property_tree::ptree active_pw_pt;
|
||||
boost::property_tree::read_json(active_pw_ss, active_pw_pt);
|
||||
if (active_pw_pt.count("error") && active_pw_pt.get_child("error").empty()) {
|
||||
if (!plugin.can_son_participate(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
std::stringstream res;
|
||||
boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result"));
|
||||
|
||||
son_wallet_update_operation swu_op;
|
||||
swu_op.payer = gpo.parameters.son_account();
|
||||
swu_op.son_wallet_id = active_sw->id;
|
||||
swu_op.sidechain = sidechain_type::ethereum;
|
||||
swu_op.address = res.str();
|
||||
|
||||
proposal_op.proposed_ops.emplace_back(swu_op);
|
||||
|
||||
const auto &prev_sw = std::next(active_sw);
|
||||
if (prev_sw != swi.rend()) {
|
||||
std::string new_pw_address = active_pw_pt.get<std::string>("result.address");
|
||||
std::string tx_str = create_primary_wallet_transaction(*prev_sw, new_pw_address);
|
||||
if (!tx_str.empty()) {
|
||||
sidechain_transaction_create_operation stc_op;
|
||||
stc_op.payer = gpo.parameters.son_account();
|
||||
stc_op.object_id = prev_sw->id;
|
||||
stc_op.sidechain = sidechain;
|
||||
stc_op.transaction = tx_str;
|
||||
stc_op.signers = prev_sw->sons;
|
||||
proposal_op.proposed_ops.emplace_back(stc_op);
|
||||
}
|
||||
}
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
plugin.log_son_proposal_retry(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id);
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//const auto &swi = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
//const auto &active_sw = swi.rbegin();
|
||||
//if (active_sw != swi.rend()) {
|
||||
//
|
||||
// if ((active_sw->addresses.find(sidechain_type::ethereum) == active_sw->addresses.end()) ||
|
||||
// (active_sw->addresses.at(sidechain_type::ethereum).empty())) {
|
||||
//
|
||||
// if (proposal_exists(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// const chain::global_property_object &gpo = database.get_global_properties();
|
||||
//
|
||||
// auto active_sons = gpo.active_sons;
|
||||
// string reply_str = create_primary_wallet_address(active_sons);
|
||||
//
|
||||
// std::stringstream active_pw_ss(reply_str);
|
||||
//
|
||||
// boost::property_tree::ptree active_pw_pt;
|
||||
// boost::property_tree::read_json(active_pw_ss, active_pw_pt);
|
||||
// if (active_pw_pt.count("error") && active_pw_pt.get_child("error").empty()) {
|
||||
// if (!plugin.can_son_participate(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// proposal_create_operation proposal_op;
|
||||
// proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
// uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
// proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
//
|
||||
// std::stringstream res;
|
||||
// boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result"));
|
||||
//
|
||||
// son_wallet_update_operation swu_op;
|
||||
// swu_op.payer = gpo.parameters.son_account();
|
||||
// swu_op.son_wallet_id = active_sw->id;
|
||||
// swu_op.sidechain = sidechain_type::ethereum;
|
||||
// swu_op.address = res.str();
|
||||
//
|
||||
// proposal_op.proposed_ops.emplace_back(swu_op);
|
||||
//
|
||||
// const auto &prev_sw = std::next(active_sw);
|
||||
// if (prev_sw != swi.rend()) {
|
||||
// std::string new_pw_address = active_pw_pt.get<std::string>("result.address");
|
||||
// std::string tx_str = create_primary_wallet_transaction(*prev_sw, new_pw_address);
|
||||
// if (!tx_str.empty()) {
|
||||
// sidechain_transaction_create_operation stc_op;
|
||||
// stc_op.payer = gpo.parameters.son_account();
|
||||
// stc_op.object_id = prev_sw->id;
|
||||
// stc_op.sidechain = sidechain;
|
||||
// stc_op.transaction = tx_str;
|
||||
// stc_op.signers = prev_sw->sons;
|
||||
// proposal_op.proposed_ops.emplace_back(stc_op);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
// try {
|
||||
// trx.validate();
|
||||
// database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
// if (plugin.app().p2p_node())
|
||||
// plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
// plugin.log_son_proposal_retry(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id);
|
||||
// } catch (fc::exception &e) {
|
||||
// elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what()));
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
void sidechain_net_handler_ethereum::process_sidechain_addresses() {
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_ethereum::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
if (proposal_exists(chain::operation::tag<chain::son_wallet_deposit_process_operation>::value, swdo.id)) {
|
||||
price asset_price = database.get<asset_object>(database.get_global_properties().parameters.eth_asset()).options.core_exchange_rate;
|
||||
asset asset_to_issue = asset(swdo.peerplays_asset.amount * asset_price.quote.amount / asset_price.base.amount, database.get_global_properties().parameters.eth_asset());
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
son_wallet_deposit_process_operation swdp_op;
|
||||
swdp_op.payer = gpo.parameters.son_account();
|
||||
swdp_op.son_wallet_deposit_id = swdo.id;
|
||||
proposal_op.proposed_ops.emplace_back(swdp_op);
|
||||
|
||||
asset_issue_operation ai_op;
|
||||
ai_op.fee = database.current_fee_schedule().calculate_fee(ai_op);
|
||||
ai_op.issuer = gpo.parameters.son_account();
|
||||
ai_op.asset_to_issue = asset_to_issue;
|
||||
ai_op.issue_to_account = swdo.peerplays_from;
|
||||
proposal_op.proposed_ops.emplace_back(ai_op);
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tx_str = create_deposit_transaction(swdo);
|
||||
|
||||
if (!tx_str.empty()) {
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
son_wallet_deposit_process_operation swdp_op;
|
||||
swdp_op.payer = gpo.parameters.son_account();
|
||||
swdp_op.son_wallet_deposit_id = swdo.id;
|
||||
proposal_op.proposed_ops.emplace_back(swdp_op);
|
||||
|
||||
sidechain_transaction_create_operation stc_op;
|
||||
stc_op.payer = gpo.parameters.son_account();
|
||||
stc_op.object_id = swdo.id;
|
||||
stc_op.sidechain = sidechain;
|
||||
stc_op.transaction = tx_str;
|
||||
stc_op.signers = gpo.active_sons;
|
||||
proposal_op.proposed_ops.emplace_back(stc_op);
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -343,10 +628,84 @@ void sidechain_net_handler_ethereum::schedule_ethereum_listener() {
|
|||
void sidechain_net_handler_ethereum::ethereum_listener_loop() {
|
||||
schedule_ethereum_listener();
|
||||
|
||||
std::string reply = ethereum_client_rpc->eth_get_block_by_number("latest", true);
|
||||
std::string reply = rpc_client->eth_get_block_by_number("latest", false);
|
||||
//std::string reply = rpc_client->eth_get_logs(wallet_contract_address);
|
||||
if (!reply.empty()) {
|
||||
std::stringstream ss(reply);
|
||||
boost::property_tree::ptree json;
|
||||
boost::property_tree::read_json(ss, json);
|
||||
if (json.count("result")) {
|
||||
std::string head_block_number_s = json.get<std::string>("result.number");
|
||||
uint64_t head_block_number = std::strtoul(head_block_number_s.c_str(), nullptr, 16);
|
||||
if (head_block_number != last_block_received) {
|
||||
std::string event_data = std::to_string(head_block_number);
|
||||
handle_event(event_data);
|
||||
last_block_received = head_block_number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sidechain_net_handler_ethereum::handle_event(const std::string &event_data) {
|
||||
std::string block = rpc_client->eth_get_block_by_number("latest", true);
|
||||
if (block != "") {
|
||||
add_to_son_listener_log("BLOCK : " + event_data);
|
||||
std::stringstream ss(block);
|
||||
boost::property_tree::ptree block_json;
|
||||
boost::property_tree::read_json(ss, block_json);
|
||||
|
||||
size_t tx_idx = -1;
|
||||
for (const auto &tx_child : block_json.get_child("result.transactions")) {
|
||||
boost::property_tree::ptree tx = tx_child.second;
|
||||
tx_idx = tx_idx + 1;
|
||||
|
||||
std::string from = tx.get<std::string>("from");
|
||||
std::string to = tx.get<std::string>("to");
|
||||
|
||||
std::string cmp_to = to;
|
||||
std::transform(cmp_to.begin(), cmp_to.end(), cmp_to.begin(), ::toupper);
|
||||
std::string cmp_wallet_contract_address = wallet_contract_address;
|
||||
std::transform(cmp_wallet_contract_address.begin(), cmp_wallet_contract_address.end(), cmp_wallet_contract_address.begin(), ::toupper);
|
||||
|
||||
if (cmp_to == cmp_wallet_contract_address) {
|
||||
|
||||
std::string value_s = tx.get<std::string>("value");
|
||||
boost::multiprecision::uint256_t amount(value_s);
|
||||
amount = amount / 100000;
|
||||
amount = amount / 100000;
|
||||
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, from, time_point_sec::maximum()));
|
||||
if (addr_itr == sidechain_addresses_idx.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "ethereum"
|
||||
<< "-" << tx.get<std::string>("hash") << "-" << tx_idx;
|
||||
std::string sidechain_uid = ss.str();
|
||||
|
||||
sidechain_event_data sed;
|
||||
sed.timestamp = database.head_block_time();
|
||||
sed.block_num = database.head_block_num();
|
||||
sed.sidechain = sidechain;
|
||||
sed.sidechain_uid = sidechain_uid;
|
||||
sed.sidechain_transaction_id = tx.get<std::string>("hash");
|
||||
sed.sidechain_from = from;
|
||||
sed.sidechain_to = to;
|
||||
sed.sidechain_currency = "ETH";
|
||||
sed.sidechain_amount = amount;
|
||||
sed.peerplays_from = addr_itr->sidechain_address_account;
|
||||
sed.peerplays_to = database.get_global_properties().parameters.son_account();
|
||||
price eth_price = database.get<asset_object>(database.get_global_properties().parameters.eth_asset()).options.core_exchange_rate;
|
||||
sed.peerplays_asset = asset(sed.sidechain_amount * eth_price.base.amount / eth_price.quote.amount);
|
||||
|
||||
add_to_son_listener_log("TRX : " + sed.sidechain_transaction_id);
|
||||
|
||||
sidechain_event_data_received(sed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
|
|||
Loading…
Reference in a new issue