From 776dc729b5679b0d401d0821c14b26f0373ec66c Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Tue, 2 Aug 2022 11:17:16 +0300 Subject: [PATCH 01/17] UpdateOwners: 1) process_proposal 2) sign_transaction 3) send_sidechain_transaction 4) settle_sidechain_transaction --- .../sidechain_net_handler_ethereum.hpp | 10 +- .../sidechain_net_handler_ethereum.cpp | 392 +++++++++++------- 2 files changed, 243 insertions(+), 159 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index 681ceaed..1af1ab10 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -22,6 +22,11 @@ public: std::string get_chain_id(); std::string get_network_id(); + + std::string send_transaction(const std::string& wallet_contract_address, const std::string& owner_address, const std::string& data); + std::string get_transaction_receipt(const std::string& params); + //std::string update_owners(const std::string& wallet_contract_address, const std::string& owner_address, const std::vector>& owners_weights, const std::string& object_id); + //std::string withdraw(); }; class sidechain_net_handler_ethereum : public sidechain_net_handler { @@ -49,14 +54,11 @@ private: ethereum::chain_id_type chain_id; ethereum::network_id_type network_id; - std::string create_primary_wallet_address(const std::vector &son_pubkeys); - - std::string create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address); + std::string create_primary_wallet_transaction(const std::vector &son_pubkeys, const std::string& object_id); std::string create_deposit_transaction(const son_wallet_deposit_object &swdo); std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); std::string sign_transaction(const sidechain_transaction_object &sto); - std::string send_transaction(const sidechain_transaction_object &sto); uint64_t last_block_received; fc::future _listener_task; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 58d22b00..c4f3dd87 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,18 @@ namespace graphene { namespace peerplays_sidechain { +std::string string_to_hex(const std::string& in) +{ + std::stringstream ss; + + ss << std::hex << std::setfill('0'); + for (size_t i = 0; in.length() > i; ++i) { + ss << std::setw(2) << static_cast(static_cast(in[i])); + } + + return ss.str(); +} + ethereum_rpc_client::ethereum_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) : rpc_client(url, user_name, password, debug_rpc_calls) { } @@ -55,6 +68,43 @@ std::string ethereum_rpc_client::get_network_id() { return retrieve_value_from_reply(reply_str, "protocols.eth.network"); } +std::string ethereum_rpc_client::send_transaction(const std::string& wallet_contract_address, const std::string& owner_address, const std::string& data) { + const std::string params = "[ { \"from\": \"" + owner_address + "\", \"to\": \"" + wallet_contract_address + "\", \"data\": \"" + data + "\" } ]"; + return send_post_request("eth_sendTransaction", params, debug_rpc_calls); +} + +std::string ethereum_rpc_client::get_transaction_receipt(const std::string& params) { + return send_post_request("eth_getTransactionReceipt", "[ \"" + params + "\"]", debug_rpc_calls); +} + +/*std::string ethereum_rpc_client::update_owners(const std::string& wallet_contract_address, const std::string& owner_address, const std::vector>& owners_weights, const std::string& object_id) { + const std::string function_hash = "23ab6adf"; //! updateOwners((address,uint256)[],string) + + const std::string data = [&function_hash, &owners_weights, &object_id] { + std::string data = "0x" + function_hash; + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), 64)).str(); + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), ((owners_weights.size() * 2 + 3) * 32))).str(); + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owners_weights.size())).str(); + for(const auto& owner : owners_weights) + { + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.first)).str(); + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.second)).str(); + } + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), object_id.size())).str(); + data += string_to_hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); + + return data; + }(); + + const std::string params = "[ { \"from\": \"" + owner_address + "\", \"to\": \"" + wallet_contract_address + "\", \"data\": \"" + data + "\" } ]"; + return send_post_request("eth_sendTransaction", params, debug_rpc_calls); +}*/ + +/*std::string ethereum_rpc_client::withdraw() { + const std::string params = "[ { \"from\": \"0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12\", \"to\": \"0x3E84f248Cd00A2FDaaDfa0dC5c3ff64D8767Fb01\", \"data\": \"0xe088747b00000000000000000000000009ee460834498a4ee361beb819470061b7381b490000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312e33362e330000000000000000000000000000000000000000000000000000\" } ]"; + return send_post_request("eth_sendTransaction", params, debug_rpc_calls); +}*/ + sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::ethereum; @@ -146,80 +196,45 @@ bool sidechain_net_handler_ethereum::process_proposal(const proposal_object &po) const auto swo = idx.find(swo_id); if (swo != idx.end()) { - //auto active_sons = gpo.active_sons; - //vector 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().address == wallet_account_name); - //} - // - //if (po.proposed_transaction.operations.size() >= 2) { - // object_id_type object_id = op_obj_idx_1.get().object_id; - // std::string op_tx_str = op_obj_idx_1.get().transaction; - // - // const auto &st_idx = database.get_index_type().indices().get(); - // const auto st = st_idx.find(object_id); - // if (st == st_idx.end()) { - // - // std::string tx_str = ""; - // - // if (object_id.is()) { - // const auto &idx = database.get_index_type().indices().get(); - // 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 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().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; - //} - } + auto active_sons = gpo.active_sons; + vector wallet_sons = swo->sons; - address_ok = true; - transaction_ok = true; + 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().address == wallet_contract_address); + } + + if (po.proposed_transaction.operations.size() >= 2) { + object_id_type object_id = op_obj_idx_1.get().object_id; + std::string op_tx_str = op_obj_idx_1.get().transaction; + + const auto &st_idx = database.get_index_type().indices().get(); + const auto st = st_idx.find(object_id); + if (st == st_idx.end()) { + + std::string tx_str = ""; + + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swo = idx.find(object_id); + if (swo != idx.end()) { + tx_str = create_primary_wallet_transaction(gpo.active_sons, object_id.operator std::string()); + } + } + + transaction_ok = (op_tx_str == tx_str); + } + } else { + transaction_ok = true; + } + } should_approve = address_ok && transaction_ok; @@ -416,79 +431,62 @@ bool sidechain_net_handler_ethereum::process_proposal(const proposal_object &po) } void sidechain_net_handler_ethereum::process_primary_wallet() { - //const auto &swi = database.get_index_type().indices().get(); - //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::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::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("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::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().indices().get(); + 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::value, active_sw->id)) { + return; + } + + if (!plugin.can_son_participate(chain::operation::tag::value, active_sw->id)) { + return; + } + + 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_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 = wallet_contract_address; + proposal_op.proposed_ops.emplace_back(swu_op); + + std::string tx_str = create_primary_wallet_transaction(gpo.active_sons, active_sw->id.operator std::string()); + if (!tx_str.empty()) { + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = active_sw->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)); + plugin.log_son_proposal_retry(chain::operation::tag::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() { + int temp = 0; } bool sidechain_net_handler_ethereum::process_deposit(const son_wallet_deposit_object &swdo) { @@ -578,19 +576,104 @@ std::string sidechain_net_handler_ethereum::process_sidechain_transaction(const } std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sidechain_transaction_object &sto) { - return send_transaction(sto); + boost::property_tree::ptree pt; + boost::property_tree::ptree pt_array; + for(const auto& signature : sto.signatures) { + const std::string sidechain_transaction = rpc_client->send_transaction(wallet_contract_address, signature.second, sto.transaction); + + std::stringstream ss_tx(sidechain_transaction); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(ss_tx, tx_json); + if( tx_json.count("result") && !tx_json.count("error") ) { + boost::property_tree::ptree node; + node.put("son", signature.second); + node.put("result", tx_json.get("result")); + pt_array.push_back(std::make_pair("", node)); + } + else { + //! Fixme + //! How should we proceed with error in send_transaction + elog("Error in send_transaction for transaction ${id}, signature ${signature}", ("id", sto.id) ("signature", signature.second)); + } + } + pt.add_child("result_array", pt_array); + + std::stringstream ss; + boost::property_tree::json_parser::write_json(ss, pt); + return ss.str(); } bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { - return true; + std::stringstream ss(sto.sidechain_transaction); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if( !json.count("result_array") ) { + return false; + } + + size_t count = 0; + for(const auto &entry : json.get_child("result_array")) { + const std::string receipt = rpc_client->get_transaction_receipt( entry.second.get("result") ); + + std::stringstream ss_receipt(receipt); + boost::property_tree::ptree json_receipt; + boost::property_tree::read_json(ss_receipt, json_receipt); + + if( json_receipt.get("result") == "null" ) { + wlog("Block is not minted yet for transaction ${id}", ("id", sto.id)); + return false; + } + + for(const auto &entry_receipt : json_receipt.get_child("result.logs")) { + if( boost::algorithm::to_lower_copy(wallet_contract_address) == entry_receipt.second.get("address") ) { + count += 1; + //! Fixme - compare data somehow? + //if( sto.transaction == entry_receipt.second.get("data") ) { + //} + } + } + } + + //! Check that we have all transactions + if(count != json.count("result_array")) { + wlog("Not all receipts received for transaction ${id}", ("id", sto.id)); + return false; + } + else + return true; + + return false; } -std::string sidechain_net_handler_ethereum::create_primary_wallet_address(const std::vector &son_pubkeys) { - return "Primary Wallet Address"; -} +std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(const std::vector &son_pubkeys, const std::string& object_id) { + std::vector> owners_weights; + for (auto &son : son_pubkeys) { + FC_ASSERT(son.sidechain_public_keys.contains(sidechain_type::ethereum), "No public keys for son: ${son_id}", ("son_id", son.son_id)); + const std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::ethereum); + owners_weights.emplace_back(std::make_pair(pub_key_str, son.weight)); + } -std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address) { - return "Primary-Wallet-Transaction"; + //! Create data of transaction + const std::string function_hash = "23ab6adf"; //! updateOwners((address,uint256)[],string) + + const std::string data = [&function_hash, &owners_weights, &object_id] { + std::string data = "0x" + function_hash; + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), 64)).str(); + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), ((owners_weights.size() * 2 + 3) * 32))).str(); + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owners_weights.size())).str(); + for(const auto& owner : owners_weights) + { + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.first)).str(); + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.second)).str(); + } + data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), object_id.size())).str(); + data += string_to_hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); + + return data; + }(); + + return data; } std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son_wallet_deposit_object &swdo) { @@ -602,12 +685,11 @@ std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const } std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) { - std::string key = get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain)); - return "Transaction-Signature-" + key; -} + //std::string key = get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain)); -std::string sidechain_net_handler_ethereum::send_transaction(const sidechain_transaction_object &sto) { - return "Transaction-ID"; + const auto& current_son = plugin.get_current_son_object(); + FC_ASSERT(current_son.sidechain_public_keys.contains(sidechain_type::ethereum), "No public keys for current son: ${account_id}", ("account_id", current_son.son_account)); + return "0x" + current_son.sidechain_public_keys.at(sidechain); } void sidechain_net_handler_ethereum::schedule_ethereum_listener() { From 7f3e7e876a83a460ea890b0e31ca5d18432f9344 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Wed, 3 Aug 2022 11:10:30 +0300 Subject: [PATCH 02/17] Replace string_to_hex with boost::algorithm::hex --- .../sidechain_net_handler_ethereum.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index c4f3dd87..10531317 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -23,18 +23,6 @@ namespace graphene { namespace peerplays_sidechain { -std::string string_to_hex(const std::string& in) -{ - std::stringstream ss; - - ss << std::hex << std::setfill('0'); - for (size_t i = 0; in.length() > i; ++i) { - ss << std::setw(2) << static_cast(static_cast(in[i])); - } - - return ss.str(); -} - ethereum_rpc_client::ethereum_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) : rpc_client(url, user_name, password, debug_rpc_calls) { } @@ -91,7 +79,7 @@ std::string ethereum_rpc_client::get_transaction_receipt(const std::string& para data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.second)).str(); } data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), object_id.size())).str(); - data += string_to_hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); + data += boost::algorithm::hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); return data; }(); @@ -668,7 +656,7 @@ std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(co data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.second)).str(); } data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), object_id.size())).str(); - data += string_to_hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); + data += boost::algorithm::hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); return data; }(); From f6614ab122a451da8368121d51968072aa16f58c Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Thu, 4 Aug 2022 10:27:09 +0300 Subject: [PATCH 03/17] base_encoder + update_owners_encoder --- .../peerplays_sidechain/ethereum/encoders.cpp | 40 ++++++++++++++++ .../peerplays_sidechain/ethereum/encoders.hpp | 18 ++++++- .../sidechain_net_handler_ethereum.hpp | 1 - .../sidechain_net_handler_ethereum.cpp | 48 ++----------------- 4 files changed, 59 insertions(+), 48 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp index 4359a605..2b8984f6 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp @@ -1,5 +1,45 @@ #include +#include +#include + namespace graphene { namespace peerplays_sidechain { namespace ethereum { +//! base_encoder +std::string base_encoder::encode_uint256(uint64_t value) +{ + return (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value)).str(); +} + +std::string base_encoder::encode_address(const std::string& value) +{ + return (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value)).str(); +} + +std::string base_encoder::encode_string(const std::string& value) +{ + std::string data = (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value.size())).str(); + data += boost::algorithm::hex(value) + std::string( (64 - value.size() * 2 % 64), '0' ); + return data; +} + + +//! update_owners_encoder +std::string update_owners_encoder::encode(const std::vector>& owners_weights, const std::string& object_id) const +{ + std::string data = "0x" + function_signature; + data += base_encoder::encode_uint256(64); + data += base_encoder::encode_uint256((owners_weights.size() * 2 + 3) * 32); + data += base_encoder::encode_uint256(owners_weights.size()); + for(const auto& owner : owners_weights) + { + data += base_encoder::encode_address(owner.first); + data += base_encoder::encode_uint256(owner.second); + } + data += base_encoder::encode_string(object_id); + + return data; +} + + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp index 43fc38dc..443720c1 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp @@ -5,7 +5,21 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { -class ethereum_function_call_encoder { +class base_encoder { +public: + static std::string encode_uint256(uint64_t value); + static std::string encode_address(const std::string& value); + static std::string encode_string(const std::string& value); +}; + +class update_owners_encoder { +public: + const std::string function_signature = "23ab6adf"; //! updateOwners((address,uint256)[],string) + + std::string encode(const std::vector>& owners_weights, const std::string& object_id) const; +}; + +/*class ethereum_function_call_encoder { public: enum operation_t { OPERATION_CALL, @@ -34,6 +48,6 @@ public: private: ethereum_function_call_encoder m_ethereum_function_call_encoder; -}; +};*/ }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index 1af1ab10..4dc5caff 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -25,7 +25,6 @@ public: std::string send_transaction(const std::string& wallet_contract_address, const std::string& owner_address, const std::string& data); std::string get_transaction_receipt(const std::string& params); - //std::string update_owners(const std::string& wallet_contract_address, const std::string& owner_address, const std::vector>& owners_weights, const std::string& object_id); //std::string withdraw(); }; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 10531317..03778322 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -3,9 +3,7 @@ #include #include -#include #include -#include #include #include @@ -18,8 +16,8 @@ #include #include #include +#include #include -#include namespace graphene { namespace peerplays_sidechain { @@ -65,29 +63,6 @@ std::string ethereum_rpc_client::get_transaction_receipt(const std::string& para return send_post_request("eth_getTransactionReceipt", "[ \"" + params + "\"]", debug_rpc_calls); } -/*std::string ethereum_rpc_client::update_owners(const std::string& wallet_contract_address, const std::string& owner_address, const std::vector>& owners_weights, const std::string& object_id) { - const std::string function_hash = "23ab6adf"; //! updateOwners((address,uint256)[],string) - - const std::string data = [&function_hash, &owners_weights, &object_id] { - std::string data = "0x" + function_hash; - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), 64)).str(); - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), ((owners_weights.size() * 2 + 3) * 32))).str(); - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owners_weights.size())).str(); - for(const auto& owner : owners_weights) - { - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.first)).str(); - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.second)).str(); - } - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), object_id.size())).str(); - data += boost::algorithm::hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); - - return data; - }(); - - const std::string params = "[ { \"from\": \"" + owner_address + "\", \"to\": \"" + wallet_contract_address + "\", \"data\": \"" + data + "\" } ]"; - return send_post_request("eth_sendTransaction", params, debug_rpc_calls); -}*/ - /*std::string ethereum_rpc_client::withdraw() { const std::string params = "[ { \"from\": \"0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12\", \"to\": \"0x3E84f248Cd00A2FDaaDfa0dC5c3ff64D8767Fb01\", \"data\": \"0xe088747b00000000000000000000000009ee460834498a4ee361beb819470061b7381b490000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312e33362e330000000000000000000000000000000000000000000000000000\" } ]"; return send_post_request("eth_sendTransaction", params, debug_rpc_calls); @@ -643,25 +618,8 @@ std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(co } //! Create data of transaction - const std::string function_hash = "23ab6adf"; //! updateOwners((address,uint256)[],string) - - const std::string data = [&function_hash, &owners_weights, &object_id] { - std::string data = "0x" + function_hash; - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), 64)).str(); - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), ((owners_weights.size() * 2 + 3) * 32))).str(); - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owners_weights.size())).str(); - for(const auto& owner : owners_weights) - { - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.first)).str(); - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), owner.second)).str(); - } - data += (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), object_id.size())).str(); - data += boost::algorithm::hex(object_id) + std::string( (64 - object_id.size() * 2 % 64), '0' ); - - return data; - }(); - - return data; + ethereum::update_owners_encoder encoder; + return encoder.encode(owners_weights, object_id); } std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son_wallet_deposit_object &swdo) { From 212e5bc7ad5fdddbb4c56b63253ee2011d220629 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Thu, 4 Aug 2022 13:06:53 +0300 Subject: [PATCH 04/17] Add ethereum::transaction --- .../ethereum/transaction.cpp | 39 ++++++++++++++----- .../ethereum/transaction.hpp | 39 ++++++++++--------- .../sidechain_net_handler_ethereum.hpp | 2 +- .../sidechain_net_handler_ethereum.cpp | 31 ++++++++------- 4 files changed, 69 insertions(+), 42 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp index 9bf3bf02..f2d117b5 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp @@ -1,22 +1,43 @@ #include +#include +#include + namespace graphene { namespace peerplays_sidechain { namespace ethereum { -std::string transaction::sign(std::string private_key) { - v = "signed"; +const transaction& transaction::sign(std::string private_key) const +{ +/* v = "signed"; r = "transaction"; s = "signed-transaction"; - return v + "|" + r + "|" + s; + return v + "|" + r + "|" + s;*/ + return *this; } -std::string transaction::serialize() { - return "serialized-transaction"; +std::string transaction::serialize() const +{ + boost::property_tree::ptree pt; + pt.put("from", from); + pt.put("to", to); + pt.put("data", data); + + std::stringstream ss; + boost::property_tree::json_parser::write_json(ss, pt); + return ss.str(); } -void transaction::deserialize(std::string raw_tx) { - block_hash = "1"; - block_number = "2"; - hash = "3"; +void transaction::deserialize(std::string raw_tx) +{ + std::stringstream ss_tx(raw_tx); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(ss_tx, tx_json); + + if(tx_json.count("from")) + from = tx_json.get("from"); + if(tx_json.count("to")) + to = tx_json.get("to"); + if(tx_json.count("data")) + data = tx_json.get("data"); } }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp index 1ce9497e..7c65b7d2 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp @@ -8,29 +8,30 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { class transaction { public: - std::string block_hash; - std::string block_number; + //std::string block_hash; + //std::string block_number; std::string from; - std::string gas; - std::string gas_price; - std::string max_fee_per_gas; - std::string max_priority_fee_per_gas; - std::string hash; - std::string input; - std::string nonce; + //std::string gas; + //std::string gas_price; + //std::string max_fee_per_gas; + //std::string max_priority_fee_per_gas; + //std::string hash; + //std::string input; + //std::string nonce; std::string to; - std::string transaction_index; - std::string value; - std::string type; - std::vector access_list; - std::string chain_id; - std::string v; - std::string r; - std::string s; + std::string data; + //std::string transaction_index; + //std::string value; + //std::string type; + //std::vector access_list; + //std::string chain_id; + //std::string v; + //std::string r; + //std::string s; - std::string sign(std::string private_key); + const transaction& sign(std::string private_key) const; - std::string serialize(); + std::string serialize() const; void deserialize(std::string raw_tx); }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index 4dc5caff..8606c095 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -23,7 +23,7 @@ public: std::string get_chain_id(); std::string get_network_id(); - std::string send_transaction(const std::string& wallet_contract_address, const std::string& owner_address, const std::string& data); + std::string send_transaction(const std::string& params); std::string get_transaction_receipt(const std::string& params); //std::string withdraw(); }; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 03778322..1553ef50 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -54,13 +54,12 @@ std::string ethereum_rpc_client::get_network_id() { return retrieve_value_from_reply(reply_str, "protocols.eth.network"); } -std::string ethereum_rpc_client::send_transaction(const std::string& wallet_contract_address, const std::string& owner_address, const std::string& data) { - const std::string params = "[ { \"from\": \"" + owner_address + "\", \"to\": \"" + wallet_contract_address + "\", \"data\": \"" + data + "\" } ]"; - return send_post_request("eth_sendTransaction", params, debug_rpc_calls); +std::string ethereum_rpc_client::send_transaction(const std::string& params) { + return send_post_request("eth_sendTransaction", "[" + params + "]", debug_rpc_calls); } std::string ethereum_rpc_client::get_transaction_receipt(const std::string& params) { - return send_post_request("eth_getTransactionReceipt", "[ \"" + params + "\"]", debug_rpc_calls); + return send_post_request("eth_getTransactionReceipt", "[\"" + params + "\"]", debug_rpc_calls); } /*std::string ethereum_rpc_client::withdraw() { @@ -542,21 +541,22 @@ std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sid boost::property_tree::ptree pt; boost::property_tree::ptree pt_array; for(const auto& signature : sto.signatures) { - const std::string sidechain_transaction = rpc_client->send_transaction(wallet_contract_address, signature.second, sto.transaction); + const auto& transaction = signature.second; + const std::string sidechain_transaction = rpc_client->send_transaction(transaction); std::stringstream ss_tx(sidechain_transaction); boost::property_tree::ptree tx_json; boost::property_tree::read_json(ss_tx, tx_json); if( tx_json.count("result") && !tx_json.count("error") ) { boost::property_tree::ptree node; - node.put("son", signature.second); - node.put("result", tx_json.get("result")); + node.put("transaction", transaction); + node.put("transaction_receipt", tx_json.get("result")); pt_array.push_back(std::make_pair("", node)); } else { //! Fixme //! How should we proceed with error in send_transaction - elog("Error in send_transaction for transaction ${id}, signature ${signature}", ("id", sto.id) ("signature", signature.second)); + elog("Error in send_transaction for transaction ${id}, transaction ${transaction}", ("id", sto.id) ("transaction", transaction)); } } pt.add_child("result_array", pt_array); @@ -577,7 +577,7 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai size_t count = 0; for(const auto &entry : json.get_child("result_array")) { - const std::string receipt = rpc_client->get_transaction_receipt( entry.second.get("result") ); + const std::string receipt = rpc_client->get_transaction_receipt( entry.second.get("transaction_receipt") ); std::stringstream ss_receipt(receipt); boost::property_tree::ptree json_receipt; @@ -618,8 +618,10 @@ std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(co } //! Create data of transaction + ethereum::transaction transaction; ethereum::update_owners_encoder encoder; - return encoder.encode(owners_weights, object_id); + transaction.data = encoder.encode(owners_weights, object_id); + return transaction.serialize(); } std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son_wallet_deposit_object &swdo) { @@ -631,11 +633,14 @@ std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const } std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) { - //std::string key = get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain)); - const auto& current_son = plugin.get_current_son_object(); FC_ASSERT(current_son.sidechain_public_keys.contains(sidechain_type::ethereum), "No public keys for current son: ${account_id}", ("account_id", current_son.son_account)); - return "0x" + current_son.sidechain_public_keys.at(sidechain); + + ethereum::transaction sign_transaction; + sign_transaction.deserialize(sto.transaction); + sign_transaction.to = wallet_contract_address; + sign_transaction.from = "0x" + current_son.sidechain_public_keys.at(sidechain); + return sign_transaction.sign(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))).serialize(); } void sidechain_net_handler_ethereum::schedule_ethereum_listener() { From 46ac4d79a3eeac0a2253080cd64db054061ca16d Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Fri, 5 Aug 2022 11:29:21 +0300 Subject: [PATCH 05/17] withdraw transaction --- .../peerplays_sidechain/ethereum/encoders.cpp | 14 +- .../peerplays_sidechain/ethereum/encoders.hpp | 10 +- .../sidechain_net_handler_ethereum.hpp | 1 - .../sidechain_net_handler_ethereum.cpp | 137 +++++++----------- 4 files changed, 72 insertions(+), 90 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp index 2b8984f6..e17bbdfb 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp @@ -6,7 +6,7 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { //! base_encoder -std::string base_encoder::encode_uint256(uint64_t value) +std::string base_encoder::encode_uint256(boost::multiprecision::uint256_t value) { return (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value)).str(); } @@ -41,5 +41,17 @@ std::string update_owners_encoder::encode(const std::vector #include +#include namespace graphene { namespace peerplays_sidechain { namespace ethereum { class base_encoder { public: - static std::string encode_uint256(uint64_t value); + static std::string encode_uint256(boost::multiprecision::uint256_t value); static std::string encode_address(const std::string& value); static std::string encode_string(const std::string& value); }; @@ -19,6 +20,13 @@ public: std::string encode(const std::vector>& owners_weights, const std::string& object_id) const; }; +class withdrawal_encoder { +public: + const std::string function_signature = "e088747b"; //! withdraw(address,uint256,string) + + std::string encode(const std::string& to, boost::multiprecision::uint256_t amount, const std::string& object_id) const; +}; + /*class ethereum_function_call_encoder { public: enum operation_t { diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index 8606c095..af9812d0 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -25,7 +25,6 @@ public: std::string send_transaction(const std::string& params); std::string get_transaction_receipt(const std::string& params); - //std::string withdraw(); }; class sidechain_net_handler_ethereum : public sidechain_net_handler { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 1553ef50..c01ab57d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -62,11 +62,6 @@ std::string ethereum_rpc_client::get_transaction_receipt(const std::string& para return send_post_request("eth_getTransactionReceipt", "[\"" + params + "\"]", debug_rpc_calls); } -/*std::string ethereum_rpc_client::withdraw() { - const std::string params = "[ { \"from\": \"0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12\", \"to\": \"0x3E84f248Cd00A2FDaaDfa0dC5c3ff64D8767Fb01\", \"data\": \"0xe088747b00000000000000000000000009ee460834498a4ee361beb819470061b7381b490000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000006312e33362e330000000000000000000000000000000000000000000000000000\" } ]"; - return send_post_request("eth_sendTransaction", params, debug_rpc_calls); -}*/ - sidechain_net_handler_ethereum::sidechain_net_handler_ethereum(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::ethereum; @@ -275,81 +270,48 @@ bool sidechain_net_handler_ethereum::process_proposal(const proposal_object &po) const auto &idx = database.get_index_type().indices().get(); 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)); - //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(); - // - // price asset_price = database.get(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().object_id; - //std::string op_tx_str = op_obj_idx_1.get().transaction; - // - //const auto &st_idx = database.get_index_type().indices().get(); - //const auto st = st_idx.find(object_id); - //if (st == st_idx.end()) { - // - // std::string tx_str = ""; - // - // if (object_id.is()) { - // const auto &idx = database.get_index_type().indices().get(); - // 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); - //} + 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(); + + price asset_price = database.get(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().object_id; + std::string op_tx_str = op_obj_idx_1.get().transaction; + + const auto &st_idx = database.get_index_type().indices().get(); + const auto st = st_idx.find(object_id); + if (st == st_idx.end()) { + + std::string tx_str = ""; + + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swwo = idx.find(object_id); + if (swwo != idx.end()) { + tx_str = create_withdrawal_transaction(*swwo); + } + } + + transaction_ok = (op_tx_str == tx_str); + } } - process_ok = true; - transaction_ok = true; - should_approve = process_ok && transaction_ok; break; @@ -588,18 +550,17 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai return false; } - for(const auto &entry_receipt : json_receipt.get_child("result.logs")) { - if( boost::algorithm::to_lower_copy(wallet_contract_address) == entry_receipt.second.get("address") ) { - count += 1; - //! Fixme - compare data somehow? - //if( sto.transaction == entry_receipt.second.get("data") ) { - //} - } + if( "0x1" == json_receipt.get("result.status") ) + { + count += 1; + //! Fixme - compare data somehow? + //if( sto.transaction == entry_receipt.second.get("data") ) { + //} } } //! Check that we have all transactions - if(count != json.count("result_array")) { + if(count != json.get_child("result_array").size()) { wlog("Not all receipts received for transaction ${id}", ("id", sto.id)); return false; } @@ -617,7 +578,6 @@ std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(co owners_weights.emplace_back(std::make_pair(pub_key_str, son.weight)); } - //! Create data of transaction ethereum::transaction transaction; ethereum::update_owners_encoder encoder; transaction.data = encoder.encode(owners_weights, object_id); @@ -629,7 +589,10 @@ std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son } std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) { - return "Withdrawal-Transaction"; + ethereum::transaction transaction; + ethereum::withdrawal_encoder encoder; + transaction.data = encoder.encode(swwo.withdraw_address.substr(2), swwo.withdraw_amount.value*10000000000, swwo.id.operator std::string()); + return transaction.serialize(); } std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) { From 1c1ae8848852e50a6a46b030fd4b141330c93c11 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Tue, 16 Aug 2022 10:30:14 +0300 Subject: [PATCH 06/17] Delete submodule SHA3IUF --- .gitmodules | 4 ---- libraries/CMakeLists.txt | 1 - libraries/vendor/CMakeLists.txt | 26 -------------------------- libraries/vendor/SHA3IUF | 1 - 4 files changed, 32 deletions(-) delete mode 100755 libraries/vendor/CMakeLists.txt delete mode 160000 libraries/vendor/SHA3IUF diff --git a/.gitmodules b/.gitmodules index 8a25db68..d9c387a6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,7 +7,3 @@ url = https://gitlab.com/PBSA/tools-libs/peerplays-fc.git branch = develop ignore = dirty -[submodule "libraries/vendor/SHA3IUF"] - path = libraries/vendor/SHA3IUF - url = https://github.com/brainhub/SHA3IUF.git - branch = master diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index dfe3d397..cf2355f1 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -1,4 +1,3 @@ -add_subdirectory( vendor ) add_subdirectory( app ) add_subdirectory( chain ) add_subdirectory( db ) diff --git a/libraries/vendor/CMakeLists.txt b/libraries/vendor/CMakeLists.txt deleted file mode 100755 index 6047e95e..00000000 --- a/libraries/vendor/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -PROJECT( SHA3IUF ) - -include(ExternalProject) - -ExternalProject_Add(project_SHA3IUF - PREFIX ${CMAKE_CURRENT_BINARY_DIR} - SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/SHA3IUF - CONFIGURE_COMMAND cp -R ${CMAKE_CURRENT_LIST_DIR}/SHA3IUF/. ${CMAKE_CURRENT_BINARY_DIR}/src/project_SHA3IUF-build - BUILD_COMMAND make - INSTALL_COMMAND true - BUILD_BYPRODUCTS ${CMAKE_CURRENT_BINARY_DIR}/src/project_SHA3IUF-build/libsha3${CMAKE_STATIC_LIBRARY_SUFFIX} - LOG_BUILD ON -) - -ExternalProject_Get_Property(project_SHA3IUF binary_dir) -add_library(SHA3IUF STATIC IMPORTED) -message(STATUS "Setting up SHA3IUF to ${binary_dir}/libsha3${CMAKE_STATIC_LIBRARY_SUFFIX}") -set_property(TARGET SHA3IUF PROPERTY IMPORTED_LOCATION ${binary_dir}/libsha3${CMAKE_STATIC_LIBRARY_SUFFIX}) -set_property(TARGET SHA3IUF PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/SHA3IUF) - -add_dependencies(SHA3IUF project_SHA3IUF) -install( FILES ${binary_dir}/libsha3${CMAKE_STATIC_LIBRARY_SUFFIX} DESTINATION lib ) - -set(SHA3IUF_libraries sha3 CACHE INTERNAL "") -set(SHA3IUF_include_dirs "${CMAKE_CURRENT_LIST_DIR}/SHA3IUF" CACHE INTERNAL "") -set(SHA3IUF_link_dirs "${CMAKE_CURRENT_BINARY_DIR}/src/project_SHA3IUF-build" CACHE INTERNAL "") diff --git a/libraries/vendor/SHA3IUF b/libraries/vendor/SHA3IUF deleted file mode 160000 index fc850475..00000000 --- a/libraries/vendor/SHA3IUF +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fc8504750a5c2174a1874094dd05e6a0d8797753 From b24b204e79345a5ad29818ca9cffe7188e038f46 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Wed, 17 Aug 2022 07:48:59 +0300 Subject: [PATCH 07/17] Add sha3 library for keccak --- libraries/CMakeLists.txt | 1 + libraries/sha3/CMakeLists.txt | 17 ++ libraries/sha3/include/sha3/memzero.h | 16 ++ libraries/sha3/include/sha3/sha3.h | 88 ++++++ libraries/sha3/memzero.c | 75 +++++ libraries/sha3/sha3.c | 397 ++++++++++++++++++++++++++ 6 files changed, 594 insertions(+) create mode 100644 libraries/sha3/CMakeLists.txt create mode 100644 libraries/sha3/include/sha3/memzero.h create mode 100644 libraries/sha3/include/sha3/sha3.h create mode 100644 libraries/sha3/memzero.c create mode 100644 libraries/sha3/sha3.c diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index cf2355f1..f28a6cee 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory( egenesis ) add_subdirectory( fc ) add_subdirectory( net ) add_subdirectory( plugins ) +add_subdirectory( sha3 ) add_subdirectory( time ) add_subdirectory( utilities ) add_subdirectory( wallet ) diff --git a/libraries/sha3/CMakeLists.txt b/libraries/sha3/CMakeLists.txt new file mode 100644 index 00000000..a54cbba3 --- /dev/null +++ b/libraries/sha3/CMakeLists.txt @@ -0,0 +1,17 @@ +file(GLOB HEADERS "include/sha3/*.h") + +add_library( sha3 + memzero.c + sha3.c +) + +target_include_directories( sha3 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include ) +target_compile_definitions( sha3 PUBLIC USE_KECCAK=1 ) + +install( TARGETS + sha3 + + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib +) diff --git a/libraries/sha3/include/sha3/memzero.h b/libraries/sha3/include/sha3/memzero.h new file mode 100644 index 00000000..1e744c12 --- /dev/null +++ b/libraries/sha3/include/sha3/memzero.h @@ -0,0 +1,16 @@ +#ifndef __MEMZERO_H__ +#define __MEMZERO_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif +void memzero(void* const pnt, const size_t len); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +#endif diff --git a/libraries/sha3/include/sha3/sha3.h b/libraries/sha3/include/sha3/sha3.h new file mode 100644 index 00000000..881e806c --- /dev/null +++ b/libraries/sha3/include/sha3/sha3.h @@ -0,0 +1,88 @@ +/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#ifndef __SHA3_H__ +#define __SHA3_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define sha3_224_hash_size 28 +#define sha3_256_hash_size 32 +#define sha3_384_hash_size 48 +#define sha3_512_hash_size 64 +#define sha3_max_permutation_size 25 +#define sha3_max_rate_in_qwords 24 + +#define SHA3_224_BLOCK_LENGTH 144 +#define SHA3_256_BLOCK_LENGTH 136 +#define SHA3_384_BLOCK_LENGTH 104 +#define SHA3_512_BLOCK_LENGTH 72 + +#define SHA3_224_DIGEST_LENGTH sha3_224_hash_size +#define SHA3_256_DIGEST_LENGTH sha3_256_hash_size +#define SHA3_384_DIGEST_LENGTH sha3_384_hash_size +#define SHA3_512_DIGEST_LENGTH sha3_512_hash_size + +/** + * SHA3 Algorithm context. + */ +typedef struct SHA3_CTX +{ + /* 1600 bits algorithm hashing state */ + uint64_t hash[sha3_max_permutation_size]; + /* 1536-bit buffer for leftovers */ + uint64_t message[sha3_max_rate_in_qwords]; + /* count of bytes in the message[] buffer */ + unsigned rest; + /* size of a message block processed at once */ + unsigned block_size; +} SHA3_CTX; + +/* methods for calculating the hash function */ + +void sha3_224_Init(SHA3_CTX *ctx); +void sha3_256_Init(SHA3_CTX *ctx); +void sha3_384_Init(SHA3_CTX *ctx); +void sha3_512_Init(SHA3_CTX *ctx); +void sha3_Update(SHA3_CTX *ctx, const unsigned char* msg, size_t size); +void sha3_Final(SHA3_CTX *ctx, unsigned char* result); + +#if USE_KECCAK +#define keccak_224_Init sha3_224_Init +#define keccak_256_Init sha3_256_Init +#define keccak_384_Init sha3_384_Init +#define keccak_512_Init sha3_512_Init +#define keccak_Update sha3_Update +void keccak_Final(SHA3_CTX *ctx, unsigned char* result); +void keccak_256(const unsigned char* data, size_t len, unsigned char* digest); +void keccak_512(const unsigned char* data, size_t len, unsigned char* digest); +#endif + +void sha3_256(const unsigned char* data, size_t len, unsigned char* digest); +void sha3_512(const unsigned char* data, size_t len, unsigned char* digest); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* __SHA3_H__ */ diff --git a/libraries/sha3/memzero.c b/libraries/sha3/memzero.c new file mode 100644 index 00000000..32aa140f --- /dev/null +++ b/libraries/sha3/memzero.c @@ -0,0 +1,75 @@ +#ifndef __STDC_WANT_LIB_EXT1__ +#define __STDC_WANT_LIB_EXT1__ 1 // C11's bounds-checking interface. +#endif +#include + +#ifdef _WIN32 +#include +#endif + +#ifdef __unix__ +#include +#include +#endif + +// C11's bounds-checking interface. +#if defined(__STDC_LIB_EXT1__) +#define HAVE_MEMSET_S 1 +#endif + +// GNU C Library version 2.25 or later. +#if defined(__GLIBC__) && \ + (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +#define HAVE_EXPLICIT_BZERO 1 +#endif + +// Newlib +#if defined(__NEWLIB__) +#define HAVE_EXPLICIT_BZERO 1 +#endif + +// FreeBSD version 11.0 or later. +#if defined(__FreeBSD__) && __FreeBSD_version >= 1100037 +#define HAVE_EXPLICIT_BZERO 1 +#endif + +// OpenBSD version 5.5 or later. +#if defined(__OpenBSD__) && OpenBSD >= 201405 +#define HAVE_EXPLICIT_BZERO 1 +#endif + +// NetBSD version 7.2 or later. +#if defined(__NetBSD__) && __NetBSD_Version__ >= 702000000 +#define HAVE_EXPLICIT_MEMSET 1 +#endif + +// Adapted from +// https://github.com/jedisct1/libsodium/blob/1647f0d53ae0e370378a9195477e3df0a792408f/src/libsodium/sodium/utils.c#L102-L130 + +void memzero(void *const pnt, const size_t len) { +#ifdef _WIN32 + SecureZeroMemory(pnt, len); +#elif defined(HAVE_MEMSET_S) + memset_s(pnt, (rsize_t)len, 0, (rsize_t)len); +#elif defined(HAVE_EXPLICIT_BZERO) + explicit_bzero(pnt, len); +#elif defined(HAVE_EXPLICIT_MEMSET) + explicit_memset(pnt, 0, len); +#else + volatile unsigned char *volatile pnt_ = (volatile unsigned char *volatile)pnt; + size_t i = (size_t)0U; + + while (i < len) { + pnt_[i++] = 0U; + } +#endif + + // explicitly mark the memory as overwritten for the Clang MemorySanitizer + // this is only included at compile time if MemorySanitizer is enabled and + // should not come with any downsides during regular builds +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset(pnt, 0, len); +#endif +#endif +} diff --git a/libraries/sha3/sha3.c b/libraries/sha3/sha3.c new file mode 100644 index 00000000..172728eb --- /dev/null +++ b/libraries/sha3/sha3.c @@ -0,0 +1,397 @@ +/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#include +#include + +#include +#include + +#define I64(x) x##LL +#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) +#define le2me_64(x) (x) +#define IS_ALIGNED_64(p) (0 == (7 & ((long)(p)))) // [wallet-core] pointer/numerical type, for MacOS SDK 12.3 +# define me64_to_le_str(to, from, length) memcpy((to), (from), (length)) + +/* constants */ +#define NumberOfRounds 24 + +/* SHA3 (Keccak) constants for 24 rounds */ +uint64_t keccak_round_constants[NumberOfRounds] = { + I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000), + I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009), + I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A), + I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003), + I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A), + I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008) +}; + +/* Initializing a sha3 context for given number of output bits */ +static void keccak_Init(SHA3_CTX *ctx, unsigned bits) +{ + /* NB: The Keccak capacity parameter = bits * 2 */ + unsigned rate = 1600 - bits * 2; + + memzero(ctx, sizeof(SHA3_CTX)); + ctx->block_size = rate / 8; + assert(rate <= 1600 && (rate % 64) == 0); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_224_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 224); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_256_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 256); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_384_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 384); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void sha3_512_Init(SHA3_CTX *ctx) +{ + keccak_Init(ctx, 512); +} + +/* Keccak theta() transformation */ +static void keccak_theta(uint64_t *A) +{ + unsigned int x = 0; + uint64_t C[5] = {0}, D[5] = {0}; + + for (x = 0; x < 5; x++) { + C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20]; + } + D[0] = ROTL64(C[1], 1) ^ C[4]; + D[1] = ROTL64(C[2], 1) ^ C[0]; + D[2] = ROTL64(C[3], 1) ^ C[1]; + D[3] = ROTL64(C[4], 1) ^ C[2]; + D[4] = ROTL64(C[0], 1) ^ C[3]; + + for (x = 0; x < 5; x++) { + A[x] ^= D[x]; + A[x + 5] ^= D[x]; + A[x + 10] ^= D[x]; + A[x + 15] ^= D[x]; + A[x + 20] ^= D[x]; + } +} + +/* Keccak pi() transformation */ +static void keccak_pi(uint64_t *A) +{ + uint64_t A1 = 0; + A1 = A[1]; + A[ 1] = A[ 6]; + A[ 6] = A[ 9]; + A[ 9] = A[22]; + A[22] = A[14]; + A[14] = A[20]; + A[20] = A[ 2]; + A[ 2] = A[12]; + A[12] = A[13]; + A[13] = A[19]; + A[19] = A[23]; + A[23] = A[15]; + A[15] = A[ 4]; + A[ 4] = A[24]; + A[24] = A[21]; + A[21] = A[ 8]; + A[ 8] = A[16]; + A[16] = A[ 5]; + A[ 5] = A[ 3]; + A[ 3] = A[18]; + A[18] = A[17]; + A[17] = A[11]; + A[11] = A[ 7]; + A[ 7] = A[10]; + A[10] = A1; + /* note: A[ 0] is left as is */ +} + +/* Keccak chi() transformation */ +static void keccak_chi(uint64_t *A) +{ + int i = 0; + for (i = 0; i < 25; i += 5) { + uint64_t A0 = A[0 + i], A1 = A[1 + i]; + A[0 + i] ^= ~A1 & A[2 + i]; + A[1 + i] ^= ~A[2 + i] & A[3 + i]; + A[2 + i] ^= ~A[3 + i] & A[4 + i]; + A[3 + i] ^= ~A[4 + i] & A0; + A[4 + i] ^= ~A0 & A1; + } +} + +static void sha3_permutation(uint64_t *state) +{ + int round = 0; + for (round = 0; round < NumberOfRounds; round++) + { + keccak_theta(state); + + /* apply Keccak rho() transformation */ + state[ 1] = ROTL64(state[ 1], 1); + state[ 2] = ROTL64(state[ 2], 62); + state[ 3] = ROTL64(state[ 3], 28); + state[ 4] = ROTL64(state[ 4], 27); + state[ 5] = ROTL64(state[ 5], 36); + state[ 6] = ROTL64(state[ 6], 44); + state[ 7] = ROTL64(state[ 7], 6); + state[ 8] = ROTL64(state[ 8], 55); + state[ 9] = ROTL64(state[ 9], 20); + state[10] = ROTL64(state[10], 3); + state[11] = ROTL64(state[11], 10); + state[12] = ROTL64(state[12], 43); + state[13] = ROTL64(state[13], 25); + state[14] = ROTL64(state[14], 39); + state[15] = ROTL64(state[15], 41); + state[16] = ROTL64(state[16], 45); + state[17] = ROTL64(state[17], 15); + state[18] = ROTL64(state[18], 21); + state[19] = ROTL64(state[19], 8); + state[20] = ROTL64(state[20], 18); + state[21] = ROTL64(state[21], 2); + state[22] = ROTL64(state[22], 61); + state[23] = ROTL64(state[23], 56); + state[24] = ROTL64(state[24], 14); + + keccak_pi(state); + keccak_chi(state); + + /* apply iota(state, round) */ + *state ^= keccak_round_constants[round]; + } +} + +/** + * The core transformation. Process the specified block of data. + * + * @param hash the algorithm state + * @param block the message block to process + * @param block_size the size of the processed block in bytes + */ +static void sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size) +{ + /* expanded loop */ + hash[ 0] ^= le2me_64(block[ 0]); + hash[ 1] ^= le2me_64(block[ 1]); + hash[ 2] ^= le2me_64(block[ 2]); + hash[ 3] ^= le2me_64(block[ 3]); + hash[ 4] ^= le2me_64(block[ 4]); + hash[ 5] ^= le2me_64(block[ 5]); + hash[ 6] ^= le2me_64(block[ 6]); + hash[ 7] ^= le2me_64(block[ 7]); + hash[ 8] ^= le2me_64(block[ 8]); + /* if not sha3-512 */ + if (block_size > 72) { + hash[ 9] ^= le2me_64(block[ 9]); + hash[10] ^= le2me_64(block[10]); + hash[11] ^= le2me_64(block[11]); + hash[12] ^= le2me_64(block[12]); + /* if not sha3-384 */ + if (block_size > 104) { + hash[13] ^= le2me_64(block[13]); + hash[14] ^= le2me_64(block[14]); + hash[15] ^= le2me_64(block[15]); + hash[16] ^= le2me_64(block[16]); + /* if not sha3-256 */ + if (block_size > 136) { + hash[17] ^= le2me_64(block[17]); +#ifdef FULL_SHA3_FAMILY_SUPPORT + /* if not sha3-224 */ + if (block_size > 144) { + hash[18] ^= le2me_64(block[18]); + hash[19] ^= le2me_64(block[19]); + hash[20] ^= le2me_64(block[20]); + hash[21] ^= le2me_64(block[21]); + hash[22] ^= le2me_64(block[22]); + hash[23] ^= le2me_64(block[23]); + hash[24] ^= le2me_64(block[24]); + } +#endif + } + } + } + /* make a permutation of the hash */ + sha3_permutation(hash); +} + +#define SHA3_FINALIZED 0x80000000 + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void sha3_Update(SHA3_CTX *ctx, const unsigned char *msg, size_t size) +{ + size_t idx = (size_t)ctx->rest; + size_t block_size = (size_t)ctx->block_size; + + if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ + ctx->rest = (unsigned)((ctx->rest + size) % block_size); + + /* fill partial block */ + if (idx) { + size_t left = block_size - idx; + memcpy((char*)ctx->message + idx, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + sha3_process_block(ctx->hash, ctx->message, block_size); + msg += left; + size -= left; + } + while (size >= block_size) { + uint64_t *aligned_message_block = NULL; + if (IS_ALIGNED_64(msg)) { + /* the most common case is processing of an already aligned message + without copying it */ + aligned_message_block = (uint64_t*)(void*)msg; + } else { + memcpy(ctx->message, msg, block_size); + aligned_message_block = ctx->message; + } + + sha3_process_block(ctx->hash, aligned_message_block, block_size); + msg += block_size; + size -= block_size; + } + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void sha3_Final(SHA3_CTX *ctx, unsigned char* result) +{ + size_t digest_length = 100 - ctx->block_size / 2; + const size_t block_size = ctx->block_size; + + if (!(ctx->rest & SHA3_FINALIZED)) + { + /* clear the rest of the data queue */ + memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x06; + ((char*)ctx->message)[block_size - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message, block_size); + ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ + } + + assert(block_size > digest_length); + if (result) me64_to_le_str(result, ctx->hash, digest_length); + memzero(ctx, sizeof(SHA3_CTX)); +} + +#if USE_KECCAK +/** +* Store calculated hash into the given array. +* +* @param ctx the algorithm context containing current hashing state +* @param result calculated hash in binary form +*/ +void keccak_Final(SHA3_CTX *ctx, unsigned char* result) +{ + size_t digest_length = 100 - ctx->block_size / 2; + const size_t block_size = ctx->block_size; + + if (!(ctx->rest & SHA3_FINALIZED)) + { + /* clear the rest of the data queue */ + memzero((char*)ctx->message + ctx->rest, block_size - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x01; + ((char*)ctx->message)[block_size - 1] |= 0x80; + + /* process final block */ + sha3_process_block(ctx->hash, ctx->message, block_size); + ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ + } + + assert(block_size > digest_length); + if (result) me64_to_le_str(result, ctx->hash, digest_length); + memzero(ctx, sizeof(SHA3_CTX)); +} + +void keccak_256(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx = {0}; + keccak_256_Init(&ctx); + keccak_Update(&ctx, data, len); + keccak_Final(&ctx, digest); +} + +void keccak_512(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx = {0}; + keccak_512_Init(&ctx); + keccak_Update(&ctx, data, len); + keccak_Final(&ctx, digest); +} +#endif /* USE_KECCAK */ + +void sha3_256(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx = {0}; + sha3_256_Init(&ctx); + sha3_Update(&ctx, data, len); + sha3_Final(&ctx, digest); +} + +void sha3_512(const unsigned char* data, size_t len, unsigned char* digest) +{ + SHA3_CTX ctx = {0}; + sha3_512_Init(&ctx); + sha3_Update(&ctx, data, len); + sha3_Final(&ctx, digest); +} From e6d980d0924ddc3dab8e739f7311a85abd48eeb9 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Thu, 18 Aug 2022 14:54:44 +0300 Subject: [PATCH 08/17] 1) raw_transaction 2) signed_transaction 3) rlp_encoder classes --- .../peerplays_sidechain/CMakeLists.txt | 1 + .../peerplays_sidechain/ethereum/encoders.cpp | 95 ++++++++++++ .../ethereum/transaction.cpp | 146 +++++++++++++++++- .../peerplays_sidechain/ethereum/utils.cpp | 13 ++ .../peerplays_sidechain/ethereum/encoders.hpp | 15 ++ .../ethereum/transaction.hpp | 67 +++++--- .../peerplays_sidechain/ethereum/types.hpp | 2 + .../peerplays_sidechain/ethereum/utils.hpp | 9 ++ 8 files changed, 321 insertions(+), 27 deletions(-) create mode 100644 libraries/plugins/peerplays_sidechain/ethereum/utils.cpp create mode 100644 libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index ca995c10..e3449d93 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -22,6 +22,7 @@ add_library( peerplays_sidechain ethereum/decoders.cpp ethereum/transaction.cpp ethereum/types.cpp + ethereum/utils.cpp hive/asset.cpp hive/operations.cpp hive/transaction.cpp diff --git a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp index e17bbdfb..218f0be5 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -54,4 +55,98 @@ std::string withdrawal_encoder::encode(const std::string& to, boost::multiprecis } +//! rlp_encoder +std::string rlp_encoder::encode(const std::string& s) +{ + return encode_rlp(hex2bytes(s)); +} + +std::string rlp_encoder::encode_length(int len, int offset) +{ + if(len<56) + { + std::string temp; + temp=(char)(len+offset); + return temp; + } + else + { + std::string hexLength = int2Hex(len); + int lLength = hexLength.size()/2; + std::string fByte = int2Hex(offset+55+lLength); + return hex2bytes(fByte+hexLength); + } +} + +std::string rlp_encoder::hex2bytes(const std::string& s) +{ + std::string dest; + dest.resize(s.size()/2); + hex2bin(s.c_str(), &dest[0]); + return dest; +} + +std::string rlp_encoder::bytes2hex(const std::string& s) +{ + std::string dest; + for( const auto& i : s ) + dest += uchar2Hex((unsigned char)i); + + return dest; +} + +std::string rlp_encoder::encode_rlp(const std::string& s) +{ + if(s.size()==1 && (unsigned char)s[0]<128) + return s; + else + return encode_length(s.size(), 128) + s; +} + +std::string rlp_encoder::int2Hex(int n) +{ + std::stringstream stream; + stream << std::hex << n; + std::string result( stream.str() ); + if(result.size() % 2) + result = "0"+result; + return result; +} + +std::string rlp_encoder::uchar2Hex(unsigned char n) +{ + std::string dest; + dest.resize(2); + sprintf(&dest[0], "%X", n); + + if(n < (unsigned char)16) + { + dest[1] = dest[0]; + dest[0] = '0'; + } + + return dest; +} + +int rlp_encoder::char2int(char input) +{ + if(input >= '0' && input <= '9') + return input - '0'; + if(input >= 'A' && input <= 'F') + return input - 'A' + 10; + if(input >= 'a' && input <= 'f') + return input - 'a' + 10; + + return -1; +} + +void rlp_encoder::hex2bin(const char* src, char* target) +{ + while(*src && src[1]) + { + *(target++) = char2int(*src)*16 + char2int(src[1]); + src += 2; + } +} + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp index f2d117b5..8d13a648 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp @@ -1,16 +1,61 @@ #include +#include #include #include +#include +#include + +#include +#include + +#include +#include +#include + namespace graphene { namespace peerplays_sidechain { namespace ethereum { -const transaction& transaction::sign(std::string private_key) const + +namespace +{ + +int is_even(char last_char) +{ + switch (last_char) + { + case '0': + return 1; + case '2': + return 1; + case '4': + return 1; + case '6': + return 1; + case '8': + return 1; + case 'A': + return 1; + case 'C': + return 1; + case 'E': + return 1; + default: + return -1; + } +} + +} + +const secp256k1_context *eth_context() { + static secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); + return ctx; +} + +//! transaction + +const transaction& transaction::sign(const std::string& private_key) const { -/* v = "signed"; - r = "transaction"; - s = "signed-transaction"; - return v + "|" + r + "|" + s;*/ return *this; } @@ -26,7 +71,7 @@ std::string transaction::serialize() const return ss.str(); } -void transaction::deserialize(std::string raw_tx) +void transaction::deserialize(const std::string& raw_tx) { std::stringstream ss_tx(raw_tx); boost::property_tree::ptree tx_json; @@ -40,4 +85,93 @@ void transaction::deserialize(std::string raw_tx) data = tx_json.get("data"); } +//! raw_transaction + +signed_transaction raw_transaction::sign(const std::string& private_key) const +{ + //! Prepare signed transaction + signed_transaction tr; + tr.nonce = nonce; + tr.gas_price = gas_price; + tr.gas_limit = gas_limit; + tr.to = to; + tr.value = value; + tr.data = data; + + //! Calculate keccak hash of transaction + bytes hash; + hash.resize(32); + const auto transaction_string = boost::algorithm::unhex( serialize() ); + keccak_256((const unsigned char *) transaction_string.data(), transaction_string.size(), (unsigned char *) hash.data()); + + const bytes priv_key = parse_hex(private_key); + + secp256k1_ecdsa_signature sign; + FC_ASSERT(secp256k1_ecdsa_sign(eth_context(), &sign, (const unsigned char *)hash.data(), (const unsigned char *)priv_key.data(), secp256k1_nonce_function_rfc6979, nullptr)); + + fc::ecc::compact_signature result; + FC_ASSERT(secp256k1_ecdsa_signature_serialize_compact(eth_context(), (unsigned char*) result.begin() + 1, &sign)); + + bytes r; + for(int i = 1; i < 33; i++) + r.emplace_back((char) result.at(i)); + bytes s; + for(int i = 33; i < 65; i++) + s.emplace_back((char) result.at(i)); + + bytes v; + if(is_even(r.back())) + v = {37}; + else + v = {38}; + + tr.v = fc::to_hex((char *)&v[0], v.size()); + tr.r = fc::to_hex((char *)&r[0], r.size()); + tr.s = fc::to_hex((char *)&s[0], s.size()); + + return tr; +} + +std::string raw_transaction::serialize() const +{ + rlp_encoder encoder; + const std::string serialized = encoder.encode(nonce) + + encoder.encode(gas_price) + + encoder.encode(gas_limit) + + encoder.encode(to) + + encoder.encode(value) + + encoder.encode(data) + + encoder.encode(chain_id) + + encoder.encode("8") + + encoder.encode("0"); + + return encoder.bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); +} + +void raw_transaction::deserialize(const std::string& raw_tx) +{ +} + +//! signed_transaction + +std::string signed_transaction::serialize() const +{ + rlp_encoder encoder; + const std::string serialized = encoder.encode(nonce) + + encoder.encode(gas_price) + + encoder.encode(gas_limit) + + encoder.encode(to) + + encoder.encode(value) + + encoder.encode(data) + + encoder.encode(v) + + encoder.encode(r) + + encoder.encode(s); + + return encoder.bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); +} + +void signed_transaction::deserialize(const std::string& raw_tx) +{ +} + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp new file mode 100644 index 00000000..9d6961bc --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp @@ -0,0 +1,13 @@ +#include + +#include + +namespace graphene { namespace peerplays_sidechain { namespace ethereum { + +bytes parse_hex(const std::string &str) { + bytes vec(str.size() / 2); + fc::from_hex(str, vec.data(), vec.size()); + return vec; +} + +}}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp index 48330aa7..7fcb15ee 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp @@ -27,6 +27,21 @@ public: std::string encode(const std::string& to, boost::multiprecision::uint256_t amount, const std::string& object_id) const; }; +class rlp_encoder { +public: + static std::string encode(const std::string& s); + static std::string encode_length(int len, int offset); + static std::string hex2bytes(const std::string& s); + static std::string bytes2hex(const std::string& s); + +private: + static std::string encode_rlp(const std::string& s); + static std::string int2Hex(int n); + static std::string uchar2Hex(unsigned char n); + static int char2int(char input); + static void hex2bin(const char* src, char* target); +}; + /*class ethereum_function_call_encoder { public: enum operation_t { diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp index 7c65b7d2..50c3e2f7 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp @@ -6,33 +6,58 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { -class transaction { +class base_transaction +{ + virtual std::string serialize() const = 0; + virtual void deserialize(const std::string& raw_tx) = 0; +}; + +class transaction : base_transaction +{ public: - //std::string block_hash; - //std::string block_number; std::string from; - //std::string gas; - //std::string gas_price; - //std::string max_fee_per_gas; - //std::string max_priority_fee_per_gas; - //std::string hash; - //std::string input; - //std::string nonce; std::string to; std::string data; - //std::string transaction_index; - //std::string value; - //std::string type; - //std::vector access_list; - //std::string chain_id; - //std::string v; - //std::string r; - //std::string s; - const transaction& sign(std::string private_key) const; + const transaction& sign(const std::string& private_key) const; - std::string serialize() const; - void deserialize(std::string raw_tx); + virtual std::string serialize() const override; + virtual void deserialize(const std::string& raw_tx) override; +}; + +class signed_transaction; +class raw_transaction : base_transaction +{ +public: + std::string nonce; + std::string gas_price; + std::string gas_limit; + std::string to; + std::string value; + std::string data; + std::string chain_id; + + signed_transaction sign(const std::string& private_key) const; + + virtual std::string serialize() const override; + virtual void deserialize(const std::string& raw_tx) override; +}; + +class signed_transaction : base_transaction +{ +public: + std::string nonce; + std::string gas_price; + std::string gas_limit; + std::string to; + std::string value; + std::string data; + std::string v; + std::string r; + std::string s; + + virtual std::string serialize() const override; + virtual void deserialize(const std::string& raw_tx) override; }; }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/types.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/types.hpp index def91947..963244fa 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/types.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/types.hpp @@ -7,4 +7,6 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { typedef uint64_t chain_id_type; typedef uint64_t network_id_type; +using bytes = std::vector; + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp new file mode 100644 index 00000000..1e2c8802 --- /dev/null +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace graphene { namespace peerplays_sidechain { namespace ethereum { + +bytes parse_hex(const std::string &str); + +}}} // namespace graphene::peerplays_sidechain::ethereum From e3098c3fb64700a0fe213b7c5ddef508b735f234 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Fri, 19 Aug 2022 17:34:57 +0300 Subject: [PATCH 09/17] rlp_decoder class --- .../peerplays_sidechain/ethereum/decoders.cpp | 236 ++++++++++++++++++ .../peerplays_sidechain/ethereum/encoders.cpp | 30 +-- .../ethereum/transaction.cpp | 33 ++- .../peerplays_sidechain/ethereum/utils.cpp | 24 ++ .../peerplays_sidechain/ethereum/decoders.hpp | 21 ++ .../peerplays_sidechain/ethereum/encoders.hpp | 2 - .../peerplays_sidechain/ethereum/utils.hpp | 4 + 7 files changed, 317 insertions(+), 33 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp index fcf468ce..cadb3f65 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp @@ -1,5 +1,241 @@ #include +#include +#include + namespace graphene { namespace peerplays_sidechain { namespace ethereum { +//! rlp_decoder + +namespace +{ +const signed char p_util_hexdigit[256] = + { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; +} + +std::vector rlp_decoder::decode(const std::string& str) +{ + size_t consumed = 0; + const auto raw_vec = parse_hex(str); + const std::vector rlp_array = decode_rlp(raw_vec.data(), raw_vec.size(), consumed); + std::vector result_array; + for(const auto& rlp : decode_rlp(raw_vec.data(), raw_vec.size(), consumed)) + { + result_array.emplace_back( bytes2hex( rlp ) ); + } + return result_array; +} + +std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_t len, size_t& consumed) +{ + std::vector rlp_result; + + consumed = 0; + + const unsigned char* end = raw + len; + const size_t prefixlen = 1; + unsigned char ch = *raw; + + if (len < 1) + { + return rlp_result; + } + + // Case 1: [prefix is 1-byte data buffer] + if (ch <= 0x7f) + { + const unsigned char *tok_start = raw; + const unsigned char *tok_end = tok_start + prefixlen; + FC_ASSERT(tok_end <= end); + + // parsing done; assign data buffer value. + const std::vector buf{tok_start, tok_end}; + rlp_result.emplace_back( buf.cbegin(), buf.cend() ); + + consumed = buf.size(); + } + // Case 2: [prefix, including buffer length][data] + else if ((ch >= 0x80) && (ch <= 0xb7)) + { + const size_t blen = ch - 0x80; + const size_t expected = prefixlen + blen; + + if (len < expected) + return std::vector{}; + + const unsigned char *tok_start = raw + 1; + const unsigned char *tok_end = tok_start + blen; + FC_ASSERT(tok_end <= end); + + // require minimal encoding + if ((blen == 1) && (tok_start[0] <= 0x7f)) + return std::vector{}; + + // parsing done; assign data buffer value. + const std::vector buf{tok_start, tok_end}; + rlp_result.emplace_back( buf.cbegin(), buf.cend() ); + + consumed = expected; + } + // Case 3: [prefix][buffer length][data] + else if ((ch >= 0xb8) && (ch <= 0xbf)) + { + const size_t uintlen = ch - 0xb7; + size_t expected = prefixlen + uintlen; + + if (len < expected) + return std::vector{}; + + FC_ASSERT(uintlen > 0 && uintlen <= RLP_maxUintLen); + + const unsigned char *tok_start = raw + prefixlen; + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + return std::vector{}; + + // read buffer length + const uint64_t slen = to_int(tok_start, uintlen); + + // validate buffer length, including possible addition overflows. + expected = prefixlen + uintlen + slen; + if ((slen < (RLP_listStart - RLP_bufferLenStart - RLP_maxUintLen)) || (expected > len) || (slen > len)) + return std::vector{}; + + // parsing done; assign data buffer value. + tok_start = raw + prefixlen + uintlen; + const unsigned char *tok_end = tok_start + slen; + const std::vector buf{tok_start, tok_end}; + rlp_result.emplace_back( buf.cbegin(), buf.cend() ); + + consumed = expected; + } + // Case 4: [prefix][list] + else if ((ch >= 0xc0) && (ch <= 0xf7)) + { + const size_t payloadlen = ch - 0xc0; + const size_t expected = prefixlen + payloadlen; + + // read list payload + const auto array = decode_array(raw, len, 0, payloadlen); + rlp_result.insert(rlp_result.end(), array.cbegin(), array.cend()); + + consumed = expected; + } + // Case 5: [prefix][list length][list] + else + { + FC_ASSERT((ch >= 0xf8) && (ch <= 0xff)); + + const size_t uintlen = ch - 0xf7; + const size_t expected = prefixlen + uintlen; + + if (len < expected) + return std::vector{}; + + FC_ASSERT(uintlen > 0 && uintlen <= RLP_maxUintLen); + + const unsigned char *tok_start = raw + prefixlen; + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + return std::vector{}; + + // read list length + const size_t payloadlen = to_int(tok_start, uintlen); + + // special requirement for non-immediate length + if (payloadlen < (0x100 - RLP_listStart - RLP_maxUintLen)) + return std::vector{}; + + // read list payload + const auto array = decode_array(raw, len, uintlen, payloadlen); + rlp_result.insert(rlp_result.end(), array.cbegin(), array.cend()); + + consumed = prefixlen + uintlen + payloadlen; + } + + return rlp_result; +} + +std::vector rlp_decoder::decode_array(const unsigned char *raw, size_t len, size_t uintlen, size_t payloadlen) +{ + std::vector rlp_result; + const size_t prefixlen = 1; + + // validate list length, including possible addition overflows. + const size_t expected = prefixlen + uintlen + payloadlen; + if ((expected > len) || (payloadlen > len)) + return std::vector{}; + + size_t child_len = payloadlen; + const unsigned char *list_ent = raw + prefixlen + uintlen; + + // recursively read until payloadlen bytes parsed, or error + while (child_len > 0) + { + size_t child_consumed = 0; + + const auto val = decode_rlp(list_ent, child_len, child_consumed); + rlp_result.insert(rlp_result.end(), val.cbegin(), val.cend()); + + list_ent += child_consumed; + child_len -= child_consumed; + } + + return rlp_result; +} + +uint64_t rlp_decoder::to_int(const unsigned char *raw, size_t len) +{ + if (len == 0) + return 0; + else if (len == 1) + return *raw; + else + return (raw[len - 1]) + (to_int(raw, len - 1) * 256); +} + +std::vector rlp_decoder::parse_hex(const std::string& str) +{ + return parse_hex(str.c_str()); +} + +std::vector rlp_decoder::parse_hex(const char* psz) +{ + // convert hex dump to vector + std::vector vch; + while (true) + { + while (isspace(*psz)) + psz++; + signed char c = hex_digit(*psz++); + if (c == (signed char)-1) + break; + unsigned char n = (c << 4); + c = hex_digit(*psz++); + if (c == (signed char)-1) + break; + n |= c; + vch.push_back(n); + } + return vch; +} + +signed char rlp_decoder::hex_digit(char c) +{ + return p_util_hexdigit[(unsigned char)c]; +} + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp index 218f0be5..456a1be6 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp @@ -71,9 +71,9 @@ std::string rlp_encoder::encode_length(int len, int offset) } else { - std::string hexLength = int2Hex(len); - int lLength = hexLength.size()/2; - std::string fByte = int2Hex(offset+55+lLength); + const std::string hexLength = int2Hex(len); + const int lLength = hexLength.size()/2; + const std::string fByte = int2Hex(offset+55+lLength); return hex2bytes(fByte+hexLength); } } @@ -86,15 +86,6 @@ std::string rlp_encoder::hex2bytes(const std::string& s) return dest; } -std::string rlp_encoder::bytes2hex(const std::string& s) -{ - std::string dest; - for( const auto& i : s ) - dest += uchar2Hex((unsigned char)i); - - return dest; -} - std::string rlp_encoder::encode_rlp(const std::string& s) { if(s.size()==1 && (unsigned char)s[0]<128) @@ -113,21 +104,6 @@ std::string rlp_encoder::int2Hex(int n) return result; } -std::string rlp_encoder::uchar2Hex(unsigned char n) -{ - std::string dest; - dest.resize(2); - sprintf(&dest[0], "%X", n); - - if(n < (unsigned char)16) - { - dest[1] = dest[0]; - dest[0] = '0'; - } - - return dest; -} - int rlp_encoder::char2int(char input) { if(input >= '0' && input <= '9') diff --git a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp index 8d13a648..5ca8c81d 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -142,14 +143,25 @@ std::string raw_transaction::serialize() const encoder.encode(value) + encoder.encode(data) + encoder.encode(chain_id) + - encoder.encode("8") + - encoder.encode("0"); + encoder.encode("") + + encoder.encode(""); - return encoder.bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); + return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); } void raw_transaction::deserialize(const std::string& raw_tx) { + rlp_decoder decoder; + const auto rlp_array = decoder.decode(raw_tx); + FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format"); + + nonce = rlp_array.at(0); + gas_price = rlp_array.at(1); + gas_limit = rlp_array.at(2); + to = rlp_array.at(3); + value = rlp_array.at(4); + data = rlp_array.at(5); + chain_id = rlp_array.at(6); } //! signed_transaction @@ -167,11 +179,24 @@ std::string signed_transaction::serialize() const encoder.encode(r) + encoder.encode(s); - return encoder.bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); + return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); } void signed_transaction::deserialize(const std::string& raw_tx) { + rlp_decoder decoder; + const auto rlp_array = decoder.decode(raw_tx); + FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format"); + + nonce = rlp_array.at(0); + gas_price = rlp_array.at(1); + gas_limit = rlp_array.at(2); + to = rlp_array.at(3); + value = rlp_array.at(4); + data = rlp_array.at(5); + v = rlp_array.at(6); + r = rlp_array.at(7); + s = rlp_array.at(8); } }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp index 9d6961bc..0bfe136a 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp @@ -10,4 +10,28 @@ bytes parse_hex(const std::string &str) { return vec; } +std::string bytes2hex(const std::string& s) +{ + std::string dest; + for( const auto& i : s ) + dest += uchar2Hex((unsigned char)i); + + return dest; +} + +std::string uchar2Hex(unsigned char n) +{ + std::string dest; + dest.resize(2); + sprintf(&dest[0], "%X", n); + + if(n < (unsigned char)16) + { + dest[1] = dest[0]; + dest[0] = '0'; + } + + return dest; +} + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp index b9a7e927..0f30038f 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp @@ -5,4 +5,25 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { +class rlp_decoder { +private: + enum RLP_constants + { + RLP_maxUintLen = 8, + RLP_bufferLenStart = 0x80, + RLP_listStart = 0xc0, + }; + +public: + static std::vector decode(const std::string& str); + +private: + static std::vector decode_rlp(const unsigned char *raw, size_t len, size_t& consumed); + static std::vector decode_array(const unsigned char *raw, size_t len, size_t uintlen, size_t payloadlen); + static uint64_t to_int(const unsigned char *raw, size_t len); + static std::vector parse_hex(const std::string& str); + static std::vector parse_hex(const char* psz); + static signed char hex_digit(char c); +}; + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp index 7fcb15ee..8c92b2fe 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp @@ -32,12 +32,10 @@ public: static std::string encode(const std::string& s); static std::string encode_length(int len, int offset); static std::string hex2bytes(const std::string& s); - static std::string bytes2hex(const std::string& s); private: static std::string encode_rlp(const std::string& s); static std::string int2Hex(int n); - static std::string uchar2Hex(unsigned char n); static int char2int(char input); static void hex2bin(const char* src, char* target); }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp index 1e2c8802..4a2e33d1 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp @@ -6,4 +6,8 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { bytes parse_hex(const std::string &str); +std::string bytes2hex(const std::string& s); + +std::string uchar2Hex(unsigned char n); + }}} // namespace graphene::peerplays_sidechain::ethereum From adc6743ef0e2379d3d244f7dd2bec9470ede13ff Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Mon, 22 Aug 2022 10:43:53 +0300 Subject: [PATCH 10/17] 1) get_nonce 2) get_gas_price 3) get_gas_limit --- .../sidechain_net_handler_ethereum.hpp | 9 +++- .../sidechain_net_handler_ethereum.cpp | 44 ++++++++++++++++--- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index af9812d0..d96d7bd9 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -19,12 +19,17 @@ public: 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 eth_get_transaction_count(const std::string& params); + std::string eth_gas_price(); std::string get_chain_id(); std::string get_network_id(); + std::string get_nonce(const std::string& address); + std::string get_gas_price(); + std::string get_gas_limit(); - std::string send_transaction(const std::string& params); - std::string get_transaction_receipt(const std::string& params); + std::string eth_send_transaction(const std::string& params); + std::string eth_get_transaction_receipt(const std::string& params); }; class sidechain_net_handler_ethereum : public sidechain_net_handler { diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index c01ab57d..36dd2ad3 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -44,6 +44,14 @@ std::string ethereum_rpc_client::net_version() { return send_post_request("net_version", "", debug_rpc_calls); } +std::string ethereum_rpc_client::eth_get_transaction_count(const std::string& params) { + return send_post_request("eth_getTransactionCount", params, debug_rpc_calls); +} + +std::string ethereum_rpc_client::eth_gas_price() { + return send_post_request("eth_gasPrice", "", debug_rpc_calls); +} + std::string ethereum_rpc_client::get_chain_id() { std::string reply_str = net_version(); return retrieve_value_from_reply(reply_str, ""); @@ -54,11 +62,35 @@ std::string ethereum_rpc_client::get_network_id() { return retrieve_value_from_reply(reply_str, "protocols.eth.network"); } -std::string ethereum_rpc_client::send_transaction(const std::string& params) { +std::string ethereum_rpc_client::get_nonce(const std::string& address) { + std::string reply_str = eth_get_transaction_count("[\"" + address + "\", \"latest\"]"); + return retrieve_value_from_reply(reply_str, ""); +} + +std::string ethereum_rpc_client::get_gas_price() { + std::string reply_str = eth_gas_price(); + return retrieve_value_from_reply(reply_str, ""); +} + +std::string ethereum_rpc_client::get_gas_limit() { + std::string reply_str = eth_get_block_by_number("latest", false); + if (!reply_str.empty()) { + std::stringstream ss(reply_str); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + if (json.count("result")) { + std::string gas_limit_s = json.get("result.gasLimit"); + return gas_limit_s; + } + } + return std::string{}; +} + +std::string ethereum_rpc_client::eth_send_transaction(const std::string& params) { return send_post_request("eth_sendTransaction", "[" + params + "]", debug_rpc_calls); } -std::string ethereum_rpc_client::get_transaction_receipt(const std::string& params) { +std::string ethereum_rpc_client::eth_get_transaction_receipt(const std::string& params) { return send_post_request("eth_getTransactionReceipt", "[\"" + params + "\"]", debug_rpc_calls); } @@ -504,7 +536,7 @@ std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sid boost::property_tree::ptree pt_array; for(const auto& signature : sto.signatures) { const auto& transaction = signature.second; - const std::string sidechain_transaction = rpc_client->send_transaction(transaction); + const std::string sidechain_transaction = rpc_client->eth_send_transaction(transaction); std::stringstream ss_tx(sidechain_transaction); boost::property_tree::ptree tx_json; @@ -517,8 +549,8 @@ std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sid } else { //! Fixme - //! How should we proceed with error in send_transaction - elog("Error in send_transaction for transaction ${id}, transaction ${transaction}", ("id", sto.id) ("transaction", transaction)); + //! How should we proceed with error in eth_send_transaction + elog("Error in eth_send_transaction for transaction ${id}, transaction ${transaction}", ("id", sto.id) ("transaction", transaction)); } } pt.add_child("result_array", pt_array); @@ -539,7 +571,7 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai size_t count = 0; for(const auto &entry : json.get_child("result_array")) { - const std::string receipt = rpc_client->get_transaction_receipt( entry.second.get("transaction_receipt") ); + const std::string receipt = rpc_client->eth_get_transaction_receipt( entry.second.get("transaction_receipt") ); std::stringstream ss_receipt(receipt); boost::property_tree::ptree json_receipt; From 6c2bf868c50764b88b68045dd9392ebb570b218c Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Mon, 22 Aug 2022 16:02:58 +0300 Subject: [PATCH 11/17] Fix signing of eth transaction. Calculate `v` value --- .../peerplays_sidechain/ethereum/encoders.cpp | 16 +-- .../ethereum/transaction.cpp | 111 ++++++------------ .../peerplays_sidechain/ethereum/utils.cpp | 20 ++++ .../peerplays_sidechain/ethereum/encoders.hpp | 1 - .../peerplays_sidechain/ethereum/utils.hpp | 26 ++++ 5 files changed, 88 insertions(+), 86 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp index 456a1be6..90b05fd2 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp @@ -4,6 +4,8 @@ #include #include +#include + namespace graphene { namespace peerplays_sidechain { namespace ethereum { //! base_encoder @@ -71,9 +73,9 @@ std::string rlp_encoder::encode_length(int len, int offset) } else { - const std::string hexLength = int2Hex(len); + const std::string hexLength = to_hex(len); const int lLength = hexLength.size()/2; - const std::string fByte = int2Hex(offset+55+lLength); + const std::string fByte = to_hex(offset+55+lLength); return hex2bytes(fByte+hexLength); } } @@ -94,16 +96,6 @@ std::string rlp_encoder::encode_rlp(const std::string& s) return encode_length(s.size(), 128) + s; } -std::string rlp_encoder::int2Hex(int n) -{ - std::stringstream stream; - stream << std::hex << n; - std::string result( stream.str() ); - if(result.size() % 2) - result = "0"+result; - return result; -} - int rlp_encoder::char2int(char input) { if(input >= '0' && input <= '9') diff --git a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp index 5ca8c81d..268256ae 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -18,36 +18,6 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { -namespace -{ - -int is_even(char last_char) -{ - switch (last_char) - { - case '0': - return 1; - case '2': - return 1; - case '4': - return 1; - case '6': - return 1; - case '8': - return 1; - case 'A': - return 1; - case 'C': - return 1; - case 'E': - return 1; - default: - return -1; - } -} - -} - const secp256k1_context *eth_context() { static secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); return ctx; @@ -107,12 +77,13 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const const bytes priv_key = parse_hex(private_key); - secp256k1_ecdsa_signature sign; - FC_ASSERT(secp256k1_ecdsa_sign(eth_context(), &sign, (const unsigned char *)hash.data(), (const unsigned char *)priv_key.data(), secp256k1_nonce_function_rfc6979, nullptr)); - + int recid = 0; + secp256k1_ecdsa_recoverable_signature sig; + FC_ASSERT(secp256k1_ecdsa_sign_recoverable(eth_context(), &sig, (const unsigned char *)hash.data(), (const unsigned char *)priv_key.data(), NULL, NULL)); fc::ecc::compact_signature result; - FC_ASSERT(secp256k1_ecdsa_signature_serialize_compact(eth_context(), (unsigned char*) result.begin() + 1, &sign)); + FC_ASSERT(secp256k1_ecdsa_recoverable_signature_serialize_compact(eth_context(), (unsigned char *)result.begin() + 1, &recid, &sig)); + bytes v = bytes{char(recid + from_hex(chain_id) * 2 + 35)}; bytes r; for(int i = 1; i < 33; i++) r.emplace_back((char) result.at(i)); @@ -120,12 +91,6 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const for(int i = 33; i < 65; i++) s.emplace_back((char) result.at(i)); - bytes v; - if(is_even(r.back())) - v = {37}; - else - v = {38}; - tr.v = fc::to_hex((char *)&v[0], v.size()); tr.r = fc::to_hex((char *)&r[0], r.size()); tr.s = fc::to_hex((char *)&s[0], s.size()); @@ -136,13 +101,13 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const std::string raw_transaction::serialize() const { rlp_encoder encoder; - const std::string serialized = encoder.encode(nonce) + - encoder.encode(gas_price) + - encoder.encode(gas_limit) + - encoder.encode(to) + - encoder.encode(value) + - encoder.encode(data) + - encoder.encode(chain_id) + + const std::string serialized = encoder.encode(remove_0x(nonce)) + + encoder.encode(remove_0x(gas_price)) + + encoder.encode(remove_0x(gas_limit)) + + encoder.encode(remove_0x(to)) + + encoder.encode(remove_0x(value)) + + encoder.encode(remove_0x(data)) + + encoder.encode(remove_0x(chain_id)) + encoder.encode("") + encoder.encode(""); @@ -155,13 +120,13 @@ void raw_transaction::deserialize(const std::string& raw_tx) const auto rlp_array = decoder.decode(raw_tx); FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format"); - nonce = rlp_array.at(0); - gas_price = rlp_array.at(1); - gas_limit = rlp_array.at(2); - to = rlp_array.at(3); - value = rlp_array.at(4); - data = rlp_array.at(5); - chain_id = rlp_array.at(6); + nonce = add_0x(rlp_array.at(0)); + gas_price = add_0x(rlp_array.at(1)); + gas_limit = add_0x(rlp_array.at(2)); + to = add_0x(rlp_array.at(3)); + value = add_0x(rlp_array.at(4)); + data = add_0x(rlp_array.at(5)); + chain_id = add_0x(rlp_array.at(6)); } //! signed_transaction @@ -169,15 +134,15 @@ void raw_transaction::deserialize(const std::string& raw_tx) std::string signed_transaction::serialize() const { rlp_encoder encoder; - const std::string serialized = encoder.encode(nonce) + - encoder.encode(gas_price) + - encoder.encode(gas_limit) + - encoder.encode(to) + - encoder.encode(value) + - encoder.encode(data) + - encoder.encode(v) + - encoder.encode(r) + - encoder.encode(s); + const std::string serialized = encoder.encode(remove_0x(nonce)) + + encoder.encode(remove_0x(gas_price)) + + encoder.encode(remove_0x(gas_limit)) + + encoder.encode(remove_0x(to)) + + encoder.encode(remove_0x(value)) + + encoder.encode(remove_0x(data)) + + encoder.encode(remove_0x(v)) + + encoder.encode(remove_0x(r)) + + encoder.encode(remove_0x(s)); return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); } @@ -188,15 +153,15 @@ void signed_transaction::deserialize(const std::string& raw_tx) const auto rlp_array = decoder.decode(raw_tx); FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format"); - nonce = rlp_array.at(0); - gas_price = rlp_array.at(1); - gas_limit = rlp_array.at(2); - to = rlp_array.at(3); - value = rlp_array.at(4); - data = rlp_array.at(5); - v = rlp_array.at(6); - r = rlp_array.at(7); - s = rlp_array.at(8); + nonce = add_0x(rlp_array.at(0)); + gas_price = add_0x(rlp_array.at(1)); + gas_limit = add_0x(rlp_array.at(2)); + to = add_0x(rlp_array.at(3)); + value = add_0x(rlp_array.at(4)); + data = add_0x(rlp_array.at(5)); + v = add_0x(rlp_array.at(6)); + r = add_0x(rlp_array.at(7)); + s = add_0x(rlp_array.at(8)); } }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp index 0bfe136a..04861b88 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp @@ -34,4 +34,24 @@ std::string uchar2Hex(unsigned char n) return dest; } +std::string add_0x(const std::string& s) +{ + if(s.size() > 1) { + if (s.substr(0, 2) == "0x") + return s; + } + + return "0x" + s; +} + +std::string remove_0x(const std::string& s) +{ + if(s.size() > 1) { + if (s.substr(0, 2) == "0x") + return s.substr(2); + } + + return s; +} + }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp index 8c92b2fe..d3652199 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp @@ -35,7 +35,6 @@ public: private: static std::string encode_rlp(const std::string& s); - static std::string int2Hex(int n); static int char2int(char input); static void hex2bin(const char* src, char* target); }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp index 4a2e33d1..519ed4a1 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp @@ -10,4 +10,30 @@ std::string bytes2hex(const std::string& s); std::string uchar2Hex(unsigned char n); +std::string add_0x(const std::string& s); + +std::string remove_0x(const std::string& s); + +template +std::string to_hex( const T& val ) +{ + std::stringstream stream; + stream << std::hex << val; + std::string result( stream.str() ); + if(result.size() % 2) + result = "0"+result; + return result; +} + +template +T from_hex( const std::string& s ) +{ + T val; + std::stringstream stream; + stream << std::hex << s; + stream >> val; + + return val; +} + }}} // namespace graphene::peerplays_sidechain::ethereum From 34df0c07549e6246146a8777526354b3ad2c754b Mon Sep 17 00:00:00 2001 From: serkixenos Date: Tue, 23 Aug 2022 02:59:03 +0200 Subject: [PATCH 12/17] Fix CI/CD build --- libraries/plugins/peerplays_sidechain/CMakeLists.txt | 8 +++----- libraries/sha3/CMakeLists.txt | 7 +++---- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/CMakeLists.txt b/libraries/plugins/peerplays_sidechain/CMakeLists.txt index e3449d93..687532a1 100755 --- a/libraries/plugins/peerplays_sidechain/CMakeLists.txt +++ b/libraries/plugins/peerplays_sidechain/CMakeLists.txt @@ -42,11 +42,9 @@ endif() unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS) unset(ENABLE_PEERPLAYS_ASSET_DEPOSITS CACHE) -target_link_directories( peerplays_sidechain PUBLIC ${SHA3IUF_link_dirs} ) -target_link_libraries( peerplays_sidechain PRIVATE graphene_plugin zmq ${SHA3IUF_libraries} ) -target_include_directories( peerplays_sidechain PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}/include" - "${SHA3IUF_include_dirs}" ) +target_link_libraries( peerplays_sidechain PRIVATE graphene_plugin sha3 zmq ) +target_include_directories( peerplays_sidechain + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ) install( TARGETS peerplays_sidechain diff --git a/libraries/sha3/CMakeLists.txt b/libraries/sha3/CMakeLists.txt index a54cbba3..c790323e 100644 --- a/libraries/sha3/CMakeLists.txt +++ b/libraries/sha3/CMakeLists.txt @@ -1,16 +1,15 @@ file(GLOB HEADERS "include/sha3/*.h") add_library( sha3 - memzero.c - sha3.c + memzero.c + sha3.c ) target_include_directories( sha3 PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include ) target_compile_definitions( sha3 PUBLIC USE_KECCAK=1 ) install( TARGETS - sha3 - + sha3 RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib From b43d5b4224dc8436537b9fb0e998e968a74941ab Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Wed, 24 Aug 2022 12:51:38 +0300 Subject: [PATCH 13/17] eth_send_raw_transaction + eth_send_transaction --- .../ethereum/transaction.cpp | 10 ++-- .../sidechain_net_handler_ethereum.hpp | 1 + .../sidechain_net_handler_ethereum.cpp | 47 ++++++++++++++----- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp index 268256ae..8a5f7fdf 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp @@ -72,7 +72,7 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const //! Calculate keccak hash of transaction bytes hash; hash.resize(32); - const auto transaction_string = boost::algorithm::unhex( serialize() ); + const auto transaction_string = boost::algorithm::unhex( remove_0x( serialize() ) ); keccak_256((const unsigned char *) transaction_string.data(), transaction_string.size(), (unsigned char *) hash.data()); const bytes priv_key = parse_hex(private_key); @@ -111,13 +111,13 @@ std::string raw_transaction::serialize() const encoder.encode("") + encoder.encode(""); - return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); + return add_0x( bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ) ); } void raw_transaction::deserialize(const std::string& raw_tx) { rlp_decoder decoder; - const auto rlp_array = decoder.decode(raw_tx); + const auto rlp_array = decoder.decode(remove_0x(raw_tx)); FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format"); nonce = add_0x(rlp_array.at(0)); @@ -144,13 +144,13 @@ std::string signed_transaction::serialize() const encoder.encode(remove_0x(r)) + encoder.encode(remove_0x(s)); - return bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ); + return add_0x( bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ) ); } void signed_transaction::deserialize(const std::string& raw_tx) { rlp_decoder decoder; - const auto rlp_array = decoder.decode(raw_tx); + const auto rlp_array = decoder.decode(remove_0x(raw_tx)); FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format"); nonce = add_0x(rlp_array.at(0)); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index d96d7bd9..68ba2c59 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -29,6 +29,7 @@ public: std::string get_gas_limit(); std::string eth_send_transaction(const std::string& params); + std::string eth_send_raw_transaction(const std::string& params); std::string eth_get_transaction_receipt(const std::string& params); }; diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 36dd2ad3..86a162f4 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -18,6 +18,9 @@ #include #include #include +#include + +//#define SEND_RAW_TRANSACTION 1 namespace graphene { namespace peerplays_sidechain { @@ -90,6 +93,10 @@ std::string ethereum_rpc_client::eth_send_transaction(const std::string& params) return send_post_request("eth_sendTransaction", "[" + params + "]", debug_rpc_calls); } +std::string ethereum_rpc_client::eth_send_raw_transaction(const std::string& params) { + return send_post_request("eth_sendRawTransaction", "[ \"" + params + "\" ]", debug_rpc_calls); +} + std::string ethereum_rpc_client::eth_get_transaction_receipt(const std::string& params) { return send_post_request("eth_getTransactionReceipt", "[\"" + params + "\"]", debug_rpc_calls); } @@ -536,7 +543,11 @@ std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sid boost::property_tree::ptree pt_array; for(const auto& signature : sto.signatures) { const auto& transaction = signature.second; - const std::string sidechain_transaction = rpc_client->eth_send_transaction(transaction); + #ifdef SEND_RAW_TRANSACTION + const std::string sidechain_transaction = rpc_client->eth_send_raw_transaction(transaction); + #else + const std::string sidechain_transaction = rpc_client->eth_send_transaction(transaction); + #endif std::stringstream ss_tx(sidechain_transaction); boost::property_tree::ptree tx_json; @@ -610,10 +621,8 @@ std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(co owners_weights.emplace_back(std::make_pair(pub_key_str, son.weight)); } - ethereum::transaction transaction; ethereum::update_owners_encoder encoder; - transaction.data = encoder.encode(owners_weights, object_id); - return transaction.serialize(); + return encoder.encode(owners_weights, object_id); } std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son_wallet_deposit_object &swdo) { @@ -621,21 +630,35 @@ std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son } std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) { - ethereum::transaction transaction; ethereum::withdrawal_encoder encoder; - transaction.data = encoder.encode(swwo.withdraw_address.substr(2), swwo.withdraw_amount.value*10000000000, swwo.id.operator std::string()); - return transaction.serialize(); + return encoder.encode(swwo.withdraw_address.substr(2), swwo.withdraw_amount.value*10000000000, swwo.id.operator std::string()); } std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) { const auto& current_son = plugin.get_current_son_object(); FC_ASSERT(current_son.sidechain_public_keys.contains(sidechain_type::ethereum), "No public keys for current son: ${account_id}", ("account_id", current_son.son_account)); - ethereum::transaction sign_transaction; - sign_transaction.deserialize(sto.transaction); - sign_transaction.to = wallet_contract_address; - sign_transaction.from = "0x" + current_son.sidechain_public_keys.at(sidechain); - return sign_transaction.sign(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))).serialize(); + const auto& public_key = current_son.sidechain_public_keys.at(sidechain); + + #ifdef SEND_RAW_TRANSACTION + ethereum::raw_transaction raw_tr; + raw_tr.nonce = ethereum::to_hex( ethereum::from_hex( rpc_client->get_nonce( ethereum::add_0x(public_key) ) ) + 1 ); + raw_tr.gas_price = rpc_client->get_gas_price(); + raw_tr.gas_limit = rpc_client->get_gas_limit(); + raw_tr.to = wallet_contract_address; + raw_tr.value = ""; + raw_tr.data = sto.transaction; + raw_tr.chain_id = ethereum::add_0x(ethereum::to_hex(chain_id)); + + const auto sign_tr = raw_tr.sign(get_private_key(public_key)); + return sign_tr.serialize(); + #else + ethereum::transaction sign_transaction; + sign_transaction.data = sto.transaction; + sign_transaction.to = wallet_contract_address; + sign_transaction.from = "0x" + public_key; + return sign_transaction.sign(get_private_key(public_key)).serialize(); + #endif } void sidechain_net_handler_ethereum::schedule_ethereum_listener() { From f780fa794f9231404a36f55347e168adb761d583 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Fri, 26 Aug 2022 10:57:18 +0300 Subject: [PATCH 14/17] Fix get_nonce --- .../peerplays_sidechain/sidechain_net_handler_ethereum.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 86a162f4..734a5fcd 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -20,7 +20,7 @@ #include #include -//#define SEND_RAW_TRANSACTION 1 +#define SEND_RAW_TRANSACTION 1 namespace graphene { namespace peerplays_sidechain { @@ -642,7 +642,7 @@ std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_tra #ifdef SEND_RAW_TRANSACTION ethereum::raw_transaction raw_tr; - raw_tr.nonce = ethereum::to_hex( ethereum::from_hex( rpc_client->get_nonce( ethereum::add_0x(public_key) ) ) + 1 ); + raw_tr.nonce = ethereum::add_0x( ethereum::to_hex( ethereum::from_hex( rpc_client->get_nonce( ethereum::add_0x(public_key) ) ) ) ); raw_tr.gas_price = rpc_client->get_gas_price(); raw_tr.gas_limit = rpc_client->get_gas_limit(); raw_tr.to = wallet_contract_address; From ab7bb9e63305bba74d5c9ce5ffc1b3e878fd86e8 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Fri, 26 Aug 2022 11:09:55 +0300 Subject: [PATCH 15/17] clang-format --- .../peerplays_sidechain/ethereum/decoders.cpp | 97 ++++++++----------- .../peerplays_sidechain/ethereum/encoders.cpp | 74 ++++++-------- .../ethereum/transaction.cpp | 49 ++++------ .../peerplays_sidechain/ethereum/utils.cpp | 21 ++-- .../peerplays_sidechain/ethereum/decoders.hpp | 17 ++-- .../peerplays_sidechain/ethereum/encoders.hpp | 18 ++-- .../ethereum/transaction.hpp | 24 ++--- .../peerplays_sidechain/ethereum/utils.hpp | 22 ++--- .../sidechain_net_handler_ethereum.hpp | 12 +-- .../sidechain_net_handler_ethereum.cpp | 91 +++++++++-------- 10 files changed, 183 insertions(+), 242 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp index cadb3f65..02f334f5 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/decoders.cpp @@ -7,71 +7,64 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { //! rlp_decoder -namespace -{ +namespace { const signed char p_util_hexdigit[256] = - { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1, - -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; + {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, + -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; } -std::vector rlp_decoder::decode(const std::string& str) -{ +std::vector rlp_decoder::decode(const std::string &str) { size_t consumed = 0; const auto raw_vec = parse_hex(str); const std::vector rlp_array = decode_rlp(raw_vec.data(), raw_vec.size(), consumed); std::vector result_array; - for(const auto& rlp : decode_rlp(raw_vec.data(), raw_vec.size(), consumed)) - { - result_array.emplace_back( bytes2hex( rlp ) ); + for (const auto &rlp : decode_rlp(raw_vec.data(), raw_vec.size(), consumed)) { + result_array.emplace_back(bytes2hex(rlp)); } return result_array; } -std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_t len, size_t& consumed) -{ +std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_t len, size_t &consumed) { std::vector rlp_result; consumed = 0; - const unsigned char* end = raw + len; + const unsigned char *end = raw + len; const size_t prefixlen = 1; unsigned char ch = *raw; - if (len < 1) - { + if (len < 1) { return rlp_result; } // Case 1: [prefix is 1-byte data buffer] - if (ch <= 0x7f) - { + if (ch <= 0x7f) { const unsigned char *tok_start = raw; const unsigned char *tok_end = tok_start + prefixlen; FC_ASSERT(tok_end <= end); // parsing done; assign data buffer value. const std::vector buf{tok_start, tok_end}; - rlp_result.emplace_back( buf.cbegin(), buf.cend() ); + rlp_result.emplace_back(buf.cbegin(), buf.cend()); consumed = buf.size(); } // Case 2: [prefix, including buffer length][data] - else if ((ch >= 0x80) && (ch <= 0xb7)) - { + else if ((ch >= 0x80) && (ch <= 0xb7)) { const size_t blen = ch - 0x80; const size_t expected = prefixlen + blen; @@ -88,13 +81,12 @@ std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_ // parsing done; assign data buffer value. const std::vector buf{tok_start, tok_end}; - rlp_result.emplace_back( buf.cbegin(), buf.cend() ); + rlp_result.emplace_back(buf.cbegin(), buf.cend()); consumed = expected; } // Case 3: [prefix][buffer length][data] - else if ((ch >= 0xb8) && (ch <= 0xbf)) - { + else if ((ch >= 0xb8) && (ch <= 0xbf)) { const size_t uintlen = ch - 0xb7; size_t expected = prefixlen + uintlen; @@ -104,7 +96,7 @@ std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_ FC_ASSERT(uintlen > 0 && uintlen <= RLP_maxUintLen); const unsigned char *tok_start = raw + prefixlen; - if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes return std::vector{}; // read buffer length @@ -119,13 +111,12 @@ std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_ tok_start = raw + prefixlen + uintlen; const unsigned char *tok_end = tok_start + slen; const std::vector buf{tok_start, tok_end}; - rlp_result.emplace_back( buf.cbegin(), buf.cend() ); + rlp_result.emplace_back(buf.cbegin(), buf.cend()); consumed = expected; } // Case 4: [prefix][list] - else if ((ch >= 0xc0) && (ch <= 0xf7)) - { + else if ((ch >= 0xc0) && (ch <= 0xf7)) { const size_t payloadlen = ch - 0xc0; const size_t expected = prefixlen + payloadlen; @@ -136,8 +127,7 @@ std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_ consumed = expected; } // Case 5: [prefix][list length][list] - else - { + else { FC_ASSERT((ch >= 0xf8) && (ch <= 0xff)); const size_t uintlen = ch - 0xf7; @@ -149,7 +139,7 @@ std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_ FC_ASSERT(uintlen > 0 && uintlen <= RLP_maxUintLen); const unsigned char *tok_start = raw + prefixlen; - if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes + if ((uintlen > 1) && (tok_start[0] == 0)) // no leading zeroes return std::vector{}; // read list length @@ -169,8 +159,7 @@ std::vector rlp_decoder::decode_rlp(const unsigned char *raw, size_ return rlp_result; } -std::vector rlp_decoder::decode_array(const unsigned char *raw, size_t len, size_t uintlen, size_t payloadlen) -{ +std::vector rlp_decoder::decode_array(const unsigned char *raw, size_t len, size_t uintlen, size_t payloadlen) { std::vector rlp_result; const size_t prefixlen = 1; @@ -183,8 +172,7 @@ std::vector rlp_decoder::decode_array(const unsigned char *raw, siz const unsigned char *list_ent = raw + prefixlen + uintlen; // recursively read until payloadlen bytes parsed, or error - while (child_len > 0) - { + while (child_len > 0) { size_t child_consumed = 0; const auto val = decode_rlp(list_ent, child_len, child_consumed); @@ -197,8 +185,7 @@ std::vector rlp_decoder::decode_array(const unsigned char *raw, siz return rlp_result; } -uint64_t rlp_decoder::to_int(const unsigned char *raw, size_t len) -{ +uint64_t rlp_decoder::to_int(const unsigned char *raw, size_t len) { if (len == 0) return 0; else if (len == 1) @@ -207,17 +194,14 @@ uint64_t rlp_decoder::to_int(const unsigned char *raw, size_t len) return (raw[len - 1]) + (to_int(raw, len - 1) * 256); } -std::vector rlp_decoder::parse_hex(const std::string& str) -{ +std::vector rlp_decoder::parse_hex(const std::string &str) { return parse_hex(str.c_str()); } -std::vector rlp_decoder::parse_hex(const char* psz) -{ +std::vector rlp_decoder::parse_hex(const char *psz) { // convert hex dump to vector std::vector vch; - while (true) - { + while (true) { while (isspace(*psz)) psz++; signed char c = hex_digit(*psz++); @@ -233,8 +217,7 @@ std::vector rlp_decoder::parse_hex(const char* psz) return vch; } -signed char rlp_decoder::hex_digit(char c) -{ +signed char rlp_decoder::hex_digit(char c) { return p_util_hexdigit[(unsigned char)c]; } diff --git a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp index 90b05fd2..ad42088b 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/encoders.cpp @@ -1,41 +1,35 @@ #include -#include #include #include +#include #include namespace graphene { namespace peerplays_sidechain { namespace ethereum { //! base_encoder -std::string base_encoder::encode_uint256(boost::multiprecision::uint256_t value) -{ +std::string base_encoder::encode_uint256(boost::multiprecision::uint256_t value) { return (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value)).str(); } -std::string base_encoder::encode_address(const std::string& value) -{ +std::string base_encoder::encode_address(const std::string &value) { return (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value)).str(); } -std::string base_encoder::encode_string(const std::string& value) -{ +std::string base_encoder::encode_string(const std::string &value) { std::string data = (boost::format("%x") % boost::io::group(std::setw(64), std::setfill('0'), value.size())).str(); - data += boost::algorithm::hex(value) + std::string( (64 - value.size() * 2 % 64), '0' ); + data += boost::algorithm::hex(value) + std::string((64 - value.size() * 2 % 64), '0'); return data; } - //! update_owners_encoder -std::string update_owners_encoder::encode(const std::vector>& owners_weights, const std::string& object_id) const -{ +std::string update_owners_encoder::encode(const std::vector> &owners_weights, const std::string &object_id) const { std::string data = "0x" + function_signature; data += base_encoder::encode_uint256(64); data += base_encoder::encode_uint256((owners_weights.size() * 2 + 3) * 32); data += base_encoder::encode_uint256(owners_weights.size()); - for(const auto& owner : owners_weights) - { + for (const auto &owner : owners_weights) { data += base_encoder::encode_address(owner.first); data += base_encoder::encode_uint256(owner.second); } @@ -45,74 +39,62 @@ std::string update_owners_encoder::encode(const std::vector= '0' && input <= '9') +int rlp_encoder::char2int(char input) { + if (input >= '0' && input <= '9') return input - '0'; - if(input >= 'A' && input <= 'F') + if (input >= 'A' && input <= 'F') return input - 'A' + 10; - if(input >= 'a' && input <= 'f') + if (input >= 'a' && input <= 'f') return input - 'a' + 10; return -1; } -void rlp_encoder::hex2bin(const char* src, char* target) -{ - while(*src && src[1]) - { - *(target++) = char2int(*src)*16 + char2int(src[1]); +void rlp_encoder::hex2bin(const char *src, char *target) { + while (*src && src[1]) { + *(target++) = char2int(*src) * 16 + char2int(src[1]); src += 2; } } diff --git a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp index 8a5f7fdf..668e9639 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/transaction.cpp @@ -10,14 +10,13 @@ #include #include -#include #include +#include #include #include namespace graphene { namespace peerplays_sidechain { namespace ethereum { - const secp256k1_context *eth_context() { static secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); return ctx; @@ -25,13 +24,11 @@ const secp256k1_context *eth_context() { //! transaction -const transaction& transaction::sign(const std::string& private_key) const -{ +const transaction &transaction::sign(const std::string &private_key) const { return *this; } -std::string transaction::serialize() const -{ +std::string transaction::serialize() const { boost::property_tree::ptree pt; pt.put("from", from); pt.put("to", to); @@ -42,24 +39,22 @@ std::string transaction::serialize() const return ss.str(); } -void transaction::deserialize(const std::string& raw_tx) -{ +void transaction::deserialize(const std::string &raw_tx) { std::stringstream ss_tx(raw_tx); boost::property_tree::ptree tx_json; boost::property_tree::read_json(ss_tx, tx_json); - if(tx_json.count("from")) + if (tx_json.count("from")) from = tx_json.get("from"); - if(tx_json.count("to")) + if (tx_json.count("to")) to = tx_json.get("to"); - if(tx_json.count("data")) + if (tx_json.count("data")) data = tx_json.get("data"); } //! raw_transaction -signed_transaction raw_transaction::sign(const std::string& private_key) const -{ +signed_transaction raw_transaction::sign(const std::string &private_key) const { //! Prepare signed transaction signed_transaction tr; tr.nonce = nonce; @@ -72,8 +67,8 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const //! Calculate keccak hash of transaction bytes hash; hash.resize(32); - const auto transaction_string = boost::algorithm::unhex( remove_0x( serialize() ) ); - keccak_256((const unsigned char *) transaction_string.data(), transaction_string.size(), (unsigned char *) hash.data()); + const auto transaction_string = boost::algorithm::unhex(remove_0x(serialize())); + keccak_256((const unsigned char *)transaction_string.data(), transaction_string.size(), (unsigned char *)hash.data()); const bytes priv_key = parse_hex(private_key); @@ -85,11 +80,11 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const bytes v = bytes{char(recid + from_hex(chain_id) * 2 + 35)}; bytes r; - for(int i = 1; i < 33; i++) - r.emplace_back((char) result.at(i)); + for (int i = 1; i < 33; i++) + r.emplace_back((char)result.at(i)); bytes s; - for(int i = 33; i < 65; i++) - s.emplace_back((char) result.at(i)); + for (int i = 33; i < 65; i++) + s.emplace_back((char)result.at(i)); tr.v = fc::to_hex((char *)&v[0], v.size()); tr.r = fc::to_hex((char *)&r[0], r.size()); @@ -98,8 +93,7 @@ signed_transaction raw_transaction::sign(const std::string& private_key) const return tr; } -std::string raw_transaction::serialize() const -{ +std::string raw_transaction::serialize() const { rlp_encoder encoder; const std::string serialized = encoder.encode(remove_0x(nonce)) + encoder.encode(remove_0x(gas_price)) + @@ -111,11 +105,10 @@ std::string raw_transaction::serialize() const encoder.encode("") + encoder.encode(""); - return add_0x( bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ) ); + return add_0x(bytes2hex(encoder.encode_length(serialized.size(), 192) + serialized)); } -void raw_transaction::deserialize(const std::string& raw_tx) -{ +void raw_transaction::deserialize(const std::string &raw_tx) { rlp_decoder decoder; const auto rlp_array = decoder.decode(remove_0x(raw_tx)); FC_ASSERT(rlp_array.size() >= 7, "Wrong rlp format"); @@ -131,8 +124,7 @@ void raw_transaction::deserialize(const std::string& raw_tx) //! signed_transaction -std::string signed_transaction::serialize() const -{ +std::string signed_transaction::serialize() const { rlp_encoder encoder; const std::string serialized = encoder.encode(remove_0x(nonce)) + encoder.encode(remove_0x(gas_price)) + @@ -144,11 +136,10 @@ std::string signed_transaction::serialize() const encoder.encode(remove_0x(r)) + encoder.encode(remove_0x(s)); - return add_0x( bytes2hex( encoder.encode_length(serialized.size(), 192) + serialized ) ); + return add_0x(bytes2hex(encoder.encode_length(serialized.size(), 192) + serialized)); } -void signed_transaction::deserialize(const std::string& raw_tx) -{ +void signed_transaction::deserialize(const std::string &raw_tx) { rlp_decoder decoder; const auto rlp_array = decoder.decode(remove_0x(raw_tx)); FC_ASSERT(rlp_array.size() >= 9, "Wrong rlp format"); diff --git a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp index 04861b88..ce64e1ae 100644 --- a/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp +++ b/libraries/plugins/peerplays_sidechain/ethereum/utils.cpp @@ -10,23 +10,20 @@ bytes parse_hex(const std::string &str) { return vec; } -std::string bytes2hex(const std::string& s) -{ +std::string bytes2hex(const std::string &s) { std::string dest; - for( const auto& i : s ) + for (const auto &i : s) dest += uchar2Hex((unsigned char)i); return dest; } -std::string uchar2Hex(unsigned char n) -{ +std::string uchar2Hex(unsigned char n) { std::string dest; dest.resize(2); sprintf(&dest[0], "%X", n); - if(n < (unsigned char)16) - { + if (n < (unsigned char)16) { dest[1] = dest[0]; dest[0] = '0'; } @@ -34,9 +31,8 @@ std::string uchar2Hex(unsigned char n) return dest; } -std::string add_0x(const std::string& s) -{ - if(s.size() > 1) { +std::string add_0x(const std::string &s) { + if (s.size() > 1) { if (s.substr(0, 2) == "0x") return s; } @@ -44,9 +40,8 @@ std::string add_0x(const std::string& s) return "0x" + s; } -std::string remove_0x(const std::string& s) -{ - if(s.size() > 1) { +std::string remove_0x(const std::string &s) { + if (s.size() > 1) { if (s.substr(0, 2) == "0x") return s.substr(2); } diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp index 0f30038f..9edb6ae3 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/decoders.hpp @@ -7,22 +7,21 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { class rlp_decoder { private: - enum RLP_constants - { - RLP_maxUintLen = 8, - RLP_bufferLenStart = 0x80, - RLP_listStart = 0xc0, + enum RLP_constants { + RLP_maxUintLen = 8, + RLP_bufferLenStart = 0x80, + RLP_listStart = 0xc0, }; public: - static std::vector decode(const std::string& str); + static std::vector decode(const std::string &str); private: - static std::vector decode_rlp(const unsigned char *raw, size_t len, size_t& consumed); + static std::vector decode_rlp(const unsigned char *raw, size_t len, size_t &consumed); static std::vector decode_array(const unsigned char *raw, size_t len, size_t uintlen, size_t payloadlen); static uint64_t to_int(const unsigned char *raw, size_t len); - static std::vector parse_hex(const std::string& str); - static std::vector parse_hex(const char* psz); + static std::vector parse_hex(const std::string &str); + static std::vector parse_hex(const char *psz); static signed char hex_digit(char c); }; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp index d3652199..1ff97978 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/encoders.hpp @@ -1,42 +1,42 @@ #pragma once +#include #include #include -#include namespace graphene { namespace peerplays_sidechain { namespace ethereum { class base_encoder { public: static std::string encode_uint256(boost::multiprecision::uint256_t value); - static std::string encode_address(const std::string& value); - static std::string encode_string(const std::string& value); + static std::string encode_address(const std::string &value); + static std::string encode_string(const std::string &value); }; class update_owners_encoder { public: const std::string function_signature = "23ab6adf"; //! updateOwners((address,uint256)[],string) - std::string encode(const std::vector>& owners_weights, const std::string& object_id) const; + std::string encode(const std::vector> &owners_weights, const std::string &object_id) const; }; class withdrawal_encoder { public: const std::string function_signature = "e088747b"; //! withdraw(address,uint256,string) - std::string encode(const std::string& to, boost::multiprecision::uint256_t amount, const std::string& object_id) const; + std::string encode(const std::string &to, boost::multiprecision::uint256_t amount, const std::string &object_id) const; }; class rlp_encoder { public: - static std::string encode(const std::string& s); + static std::string encode(const std::string &s); static std::string encode_length(int len, int offset); - static std::string hex2bytes(const std::string& s); + static std::string hex2bytes(const std::string &s); private: - static std::string encode_rlp(const std::string& s); + static std::string encode_rlp(const std::string &s); static int char2int(char input); - static void hex2bin(const char* src, char* target); + static void hex2bin(const char *src, char *target); }; /*class ethereum_function_call_encoder { diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp index 50c3e2f7..c112206b 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/transaction.hpp @@ -6,28 +6,25 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { -class base_transaction -{ +class base_transaction { virtual std::string serialize() const = 0; - virtual void deserialize(const std::string& raw_tx) = 0; + virtual void deserialize(const std::string &raw_tx) = 0; }; -class transaction : base_transaction -{ +class transaction : base_transaction { public: std::string from; std::string to; std::string data; - const transaction& sign(const std::string& private_key) const; + const transaction &sign(const std::string &private_key) const; virtual std::string serialize() const override; - virtual void deserialize(const std::string& raw_tx) override; + virtual void deserialize(const std::string &raw_tx) override; }; class signed_transaction; -class raw_transaction : base_transaction -{ +class raw_transaction : base_transaction { public: std::string nonce; std::string gas_price; @@ -37,14 +34,13 @@ public: std::string data; std::string chain_id; - signed_transaction sign(const std::string& private_key) const; + signed_transaction sign(const std::string &private_key) const; virtual std::string serialize() const override; - virtual void deserialize(const std::string& raw_tx) override; + virtual void deserialize(const std::string &raw_tx) override; }; -class signed_transaction : base_transaction -{ +class signed_transaction : base_transaction { public: std::string nonce; std::string gas_price; @@ -57,7 +53,7 @@ public: std::string s; virtual std::string serialize() const override; - virtual void deserialize(const std::string& raw_tx) override; + virtual void deserialize(const std::string &raw_tx) override; }; }}} // namespace graphene::peerplays_sidechain::ethereum diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp index 519ed4a1..b4461713 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/ethereum/utils.hpp @@ -6,28 +6,26 @@ namespace graphene { namespace peerplays_sidechain { namespace ethereum { bytes parse_hex(const std::string &str); -std::string bytes2hex(const std::string& s); +std::string bytes2hex(const std::string &s); std::string uchar2Hex(unsigned char n); -std::string add_0x(const std::string& s); +std::string add_0x(const std::string &s); -std::string remove_0x(const std::string& s); +std::string remove_0x(const std::string &s); -template -std::string to_hex( const T& val ) -{ +template +std::string to_hex(const T &val) { std::stringstream stream; stream << std::hex << val; - std::string result( stream.str() ); - if(result.size() % 2) - result = "0"+result; + std::string result(stream.str()); + if (result.size() % 2) + result = "0" + result; return result; } -template -T from_hex( const std::string& s ) -{ +template +T from_hex(const std::string &s) { T val; std::stringstream stream; stream << std::hex << s; diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp index 68ba2c59..3944d0a2 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_ethereum.hpp @@ -19,18 +19,18 @@ public: 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 eth_get_transaction_count(const std::string& params); + std::string eth_get_transaction_count(const std::string ¶ms); std::string eth_gas_price(); std::string get_chain_id(); std::string get_network_id(); - std::string get_nonce(const std::string& address); + std::string get_nonce(const std::string &address); std::string get_gas_price(); std::string get_gas_limit(); - std::string eth_send_transaction(const std::string& params); - std::string eth_send_raw_transaction(const std::string& params); - std::string eth_get_transaction_receipt(const std::string& params); + std::string eth_send_transaction(const std::string ¶ms); + std::string eth_send_raw_transaction(const std::string ¶ms); + std::string eth_get_transaction_receipt(const std::string ¶ms); }; class sidechain_net_handler_ethereum : public sidechain_net_handler { @@ -58,7 +58,7 @@ private: ethereum::chain_id_type chain_id; ethereum::network_id_type network_id; - std::string create_primary_wallet_transaction(const std::vector &son_pubkeys, const std::string& object_id); + std::string create_primary_wallet_transaction(const std::vector &son_pubkeys, const std::string &object_id); std::string create_deposit_transaction(const son_wallet_deposit_object &swdo); std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 734a5fcd..163f2599 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -47,7 +47,7 @@ std::string ethereum_rpc_client::net_version() { return send_post_request("net_version", "", debug_rpc_calls); } -std::string ethereum_rpc_client::eth_get_transaction_count(const std::string& params) { +std::string ethereum_rpc_client::eth_get_transaction_count(const std::string ¶ms) { return send_post_request("eth_getTransactionCount", params, debug_rpc_calls); } @@ -65,7 +65,7 @@ std::string ethereum_rpc_client::get_network_id() { return retrieve_value_from_reply(reply_str, "protocols.eth.network"); } -std::string ethereum_rpc_client::get_nonce(const std::string& address) { +std::string ethereum_rpc_client::get_nonce(const std::string &address) { std::string reply_str = eth_get_transaction_count("[\"" + address + "\", \"latest\"]"); return retrieve_value_from_reply(reply_str, ""); } @@ -89,15 +89,15 @@ std::string ethereum_rpc_client::get_gas_limit() { return std::string{}; } -std::string ethereum_rpc_client::eth_send_transaction(const std::string& params) { +std::string ethereum_rpc_client::eth_send_transaction(const std::string ¶ms) { return send_post_request("eth_sendTransaction", "[" + params + "]", debug_rpc_calls); } -std::string ethereum_rpc_client::eth_send_raw_transaction(const std::string& params) { +std::string ethereum_rpc_client::eth_send_raw_transaction(const std::string ¶ms) { return send_post_request("eth_sendRawTransaction", "[ \"" + params + "\" ]", debug_rpc_calls); } -std::string ethereum_rpc_client::eth_get_transaction_receipt(const std::string& params) { +std::string ethereum_rpc_client::eth_get_transaction_receipt(const std::string ¶ms) { return send_post_request("eth_getTransactionReceipt", "[\"" + params + "\"]", debug_rpc_calls); } @@ -541,27 +541,26 @@ std::string sidechain_net_handler_ethereum::process_sidechain_transaction(const std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sidechain_transaction_object &sto) { boost::property_tree::ptree pt; boost::property_tree::ptree pt_array; - for(const auto& signature : sto.signatures) { - const auto& transaction = signature.second; - #ifdef SEND_RAW_TRANSACTION - const std::string sidechain_transaction = rpc_client->eth_send_raw_transaction(transaction); - #else - const std::string sidechain_transaction = rpc_client->eth_send_transaction(transaction); - #endif + for (const auto &signature : sto.signatures) { + const auto &transaction = signature.second; +#ifdef SEND_RAW_TRANSACTION + const std::string sidechain_transaction = rpc_client->eth_send_raw_transaction(transaction); +#else + const std::string sidechain_transaction = rpc_client->eth_send_transaction(transaction); +#endif std::stringstream ss_tx(sidechain_transaction); boost::property_tree::ptree tx_json; boost::property_tree::read_json(ss_tx, tx_json); - if( tx_json.count("result") && !tx_json.count("error") ) { + if (tx_json.count("result") && !tx_json.count("error")) { boost::property_tree::ptree node; node.put("transaction", transaction); node.put("transaction_receipt", tx_json.get("result")); pt_array.push_back(std::make_pair("", node)); - } - else { + } else { //! Fixme //! How should we proceed with error in eth_send_transaction - elog("Error in eth_send_transaction for transaction ${id}, transaction ${transaction}", ("id", sto.id) ("transaction", transaction)); + elog("Error in eth_send_transaction for transaction ${id}, transaction ${transaction}", ("id", sto.id)("transaction", transaction)); } } pt.add_child("result_array", pt_array); @@ -576,25 +575,24 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai boost::property_tree::ptree json; boost::property_tree::read_json(ss, json); - if( !json.count("result_array") ) { + if (!json.count("result_array")) { return false; } size_t count = 0; - for(const auto &entry : json.get_child("result_array")) { - const std::string receipt = rpc_client->eth_get_transaction_receipt( entry.second.get("transaction_receipt") ); + for (const auto &entry : json.get_child("result_array")) { + const std::string receipt = rpc_client->eth_get_transaction_receipt(entry.second.get("transaction_receipt")); std::stringstream ss_receipt(receipt); boost::property_tree::ptree json_receipt; boost::property_tree::read_json(ss_receipt, json_receipt); - if( json_receipt.get("result") == "null" ) { + if (json_receipt.get("result") == "null") { wlog("Block is not minted yet for transaction ${id}", ("id", sto.id)); return false; } - if( "0x1" == json_receipt.get("result.status") ) - { + if ("0x1" == json_receipt.get("result.status")) { count += 1; //! Fixme - compare data somehow? //if( sto.transaction == entry_receipt.second.get("data") ) { @@ -603,17 +601,16 @@ bool sidechain_net_handler_ethereum::settle_sidechain_transaction(const sidechai } //! Check that we have all transactions - if(count != json.get_child("result_array").size()) { + if (count != json.get_child("result_array").size()) { wlog("Not all receipts received for transaction ${id}", ("id", sto.id)); return false; - } - else + } else return true; return false; } -std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(const std::vector &son_pubkeys, const std::string& object_id) { +std::string sidechain_net_handler_ethereum::create_primary_wallet_transaction(const std::vector &son_pubkeys, const std::string &object_id) { std::vector> owners_weights; for (auto &son : son_pubkeys) { FC_ASSERT(son.sidechain_public_keys.contains(sidechain_type::ethereum), "No public keys for son: ${son_id}", ("son_id", son.son_id)); @@ -631,34 +628,34 @@ std::string sidechain_net_handler_ethereum::create_deposit_transaction(const son std::string sidechain_net_handler_ethereum::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) { ethereum::withdrawal_encoder encoder; - return encoder.encode(swwo.withdraw_address.substr(2), swwo.withdraw_amount.value*10000000000, swwo.id.operator std::string()); + return encoder.encode(swwo.withdraw_address.substr(2), swwo.withdraw_amount.value * 10000000000, swwo.id.operator std::string()); } std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_transaction_object &sto) { - const auto& current_son = plugin.get_current_son_object(); + const auto ¤t_son = plugin.get_current_son_object(); FC_ASSERT(current_son.sidechain_public_keys.contains(sidechain_type::ethereum), "No public keys for current son: ${account_id}", ("account_id", current_son.son_account)); - const auto& public_key = current_son.sidechain_public_keys.at(sidechain); + const auto &public_key = current_son.sidechain_public_keys.at(sidechain); - #ifdef SEND_RAW_TRANSACTION - ethereum::raw_transaction raw_tr; - raw_tr.nonce = ethereum::add_0x( ethereum::to_hex( ethereum::from_hex( rpc_client->get_nonce( ethereum::add_0x(public_key) ) ) ) ); - raw_tr.gas_price = rpc_client->get_gas_price(); - raw_tr.gas_limit = rpc_client->get_gas_limit(); - raw_tr.to = wallet_contract_address; - raw_tr.value = ""; - raw_tr.data = sto.transaction; - raw_tr.chain_id = ethereum::add_0x(ethereum::to_hex(chain_id)); +#ifdef SEND_RAW_TRANSACTION + ethereum::raw_transaction raw_tr; + raw_tr.nonce = ethereum::add_0x(ethereum::to_hex(ethereum::from_hex(rpc_client->get_nonce(ethereum::add_0x(public_key))))); + raw_tr.gas_price = rpc_client->get_gas_price(); + raw_tr.gas_limit = rpc_client->get_gas_limit(); + raw_tr.to = wallet_contract_address; + raw_tr.value = ""; + raw_tr.data = sto.transaction; + raw_tr.chain_id = ethereum::add_0x(ethereum::to_hex(chain_id)); - const auto sign_tr = raw_tr.sign(get_private_key(public_key)); - return sign_tr.serialize(); - #else - ethereum::transaction sign_transaction; - sign_transaction.data = sto.transaction; - sign_transaction.to = wallet_contract_address; - sign_transaction.from = "0x" + public_key; - return sign_transaction.sign(get_private_key(public_key)).serialize(); - #endif + const auto sign_tr = raw_tr.sign(get_private_key(public_key)); + return sign_tr.serialize(); +#else + ethereum::transaction sign_transaction; + sign_transaction.data = sto.transaction; + sign_transaction.to = wallet_contract_address; + sign_transaction.from = "0x" + public_key; + return sign_transaction.sign(get_private_key(public_key)).serialize(); +#endif } void sidechain_net_handler_ethereum::schedule_ethereum_listener() { From fbe263e2cb294816773d7a4fa155e0484e80c2b1 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Mon, 29 Aug 2022 13:52:37 +0300 Subject: [PATCH 16/17] Fix for nonce = 0 --- .../peerplays_sidechain/sidechain_net_handler_ethereum.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 163f2599..8ceb582b 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -67,7 +67,8 @@ std::string ethereum_rpc_client::get_network_id() { std::string ethereum_rpc_client::get_nonce(const std::string &address) { std::string reply_str = eth_get_transaction_count("[\"" + address + "\", \"latest\"]"); - return retrieve_value_from_reply(reply_str, ""); + const auto nonce_val = ethereum::from_hex(retrieve_value_from_reply(reply_str, "")); + return nonce_val == 0 ? ethereum::add_0x("0") : ethereum::add_0x(ethereum::to_hex(nonce_val)); } std::string ethereum_rpc_client::get_gas_price() { @@ -639,7 +640,7 @@ std::string sidechain_net_handler_ethereum::sign_transaction(const sidechain_tra #ifdef SEND_RAW_TRANSACTION ethereum::raw_transaction raw_tr; - raw_tr.nonce = ethereum::add_0x(ethereum::to_hex(ethereum::from_hex(rpc_client->get_nonce(ethereum::add_0x(public_key))))); + raw_tr.nonce = rpc_client->get_nonce(ethereum::add_0x(public_key)); raw_tr.gas_price = rpc_client->get_gas_price(); raw_tr.gas_limit = rpc_client->get_gas_limit(); raw_tr.to = wallet_contract_address; From 1f3beba32acda451e79bd0eae9f2404988d3c833 Mon Sep 17 00:00:00 2001 From: Vlad Dobromyslov Date: Mon, 29 Aug 2022 15:31:42 +0300 Subject: [PATCH 17/17] Don't send transaction that is not signed --- .../peerplays_sidechain/sidechain_net_handler_ethereum.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp index 8ceb582b..52d401cb 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_ethereum.cpp @@ -544,6 +544,11 @@ std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sid boost::property_tree::ptree pt_array; for (const auto &signature : sto.signatures) { const auto &transaction = signature.second; + + //! Check if we have this signed transaction, if not, don't send it + if(transaction.empty()) + continue; + #ifdef SEND_RAW_TRANSACTION const std::string sidechain_transaction = rpc_client->eth_send_raw_transaction(transaction); #else @@ -562,6 +567,7 @@ std::string sidechain_net_handler_ethereum::send_sidechain_transaction(const sid //! Fixme //! How should we proceed with error in eth_send_transaction elog("Error in eth_send_transaction for transaction ${id}, transaction ${transaction}", ("id", sto.id)("transaction", transaction)); + return std::string{}; //! Return empty string, as we have error in sending } } pt.add_child("result_array", pt_array);