diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_eth.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_eth.hpp index 11df4cb8..705b40b0 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_eth.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_eth.hpp @@ -21,194 +21,217 @@ namespace graphene { namespace peerplays_sidechain { -typedef websocketpp::client client; + typedef websocketpp::client client; -using websocketpp::lib::placeholders::_1; -using websocketpp::lib::placeholders::_2; -using websocketpp::lib::bind; + using websocketpp::lib::placeholders::_1; + using websocketpp::lib::placeholders::_2; + using websocketpp::lib::bind; -// pull out the type of messages sent by our config -typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr; -typedef websocketpp::lib::shared_ptr context_ptr; -typedef client::connection_ptr connection_ptr; + // pull out the type of messages sent by our config + typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr; + typedef websocketpp::lib::shared_ptr context_ptr; + typedef client::connection_ptr connection_ptr; -class eth_rpc_client { -public: - typedef eth_rpc_client type; + class eth_rpc_client { + public: + typedef eth_rpc_client type; - enum req_t { - ETH_CHAIN_ID, - ETH_GET_TRANSACTION_RECEIPT, - ETH_CALL, - ETH_SEND_TRANSACTION, - ETH_SEND_RAW_TRANSACTION, - ETH_GET_CODE, - ETH_GET_BALANCE, - ETH_SIGN, - ETH_COINBASE, - GET_LIST_OWNERS, - ADD_OWNER, - REMOVE_OWNER - }; + enum req_t { + ETH_CHAIN_ID, + ETH_GET_TRANSACTION_RECEIPT, + ETH_CALL, + ETH_SEND_TRANSACTION, + ETH_SEND_RAW_TRANSACTION, + ETH_GET_CODE, + ETH_GET_BALANCE, + ETH_SIGN, + ETH_COINBASE, + GET_LIST_OWNERS, + ADD_OWNER, + REMOVE_OWNER + }; - enum class multi_type { - script, - address - }; - struct multi_params { - multi_params(multi_type _type, const std::string &_address_or_script, const std::string &_label = "") : - type{_type}, - address_or_script{_address_or_script}, - label{_label} { - } + enum class multi_type { + script, + address + }; + struct multi_params { + multi_params(multi_type _type, const std::string &_address_or_script, const std::string &_label = "") : + type{_type}, + address_or_script{_address_or_script}, + label{_label} { + } - multi_type type; - std::string address_or_script; - std::string label; - }; + multi_type type; + std::string address_or_script; + std::string label; + }; - eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls); + eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls); - void start(); - void stop(); - void on_socket_init(websocketpp::connection_hdl); - void on_fail(websocketpp::connection_hdl hdl); - void on_open(websocketpp::connection_hdl hdl); - void on_message(websocketpp::connection_hdl hdl, message_ptr msg); - void on_close(websocketpp::connection_hdl); + void start(); + void stop(); + void on_socket_init(websocketpp::connection_hdl); + void on_fail(websocketpp::connection_hdl hdl); + void on_open(websocketpp::connection_hdl hdl); + void on_message(websocketpp::connection_hdl hdl, message_ptr msg); + void on_close(websocketpp::connection_hdl); - uint64_t get_chain_id(); - uint64_t eth_getTransactionReceipt(const std::string& tx_id); - uint64_t eth_call(const std::string& to, const std::string& data); - uint64_t eth_sendTransaction(const std::string& from, const std::string& to, const std::string& data); - uint64_t eth_sendRawTransaction(const std::string& params); - uint64_t eth_getCode(const std::string& addr); - uint64_t eth_getBalance(const std::string& addr); - uint64_t eth_sign(const string& addr, const string& message); - uint64_t eth_coinbase(); + uint64_t get_chain_id(); + uint64_t eth_getTransactionReceipt(const std::string& tx_id); + uint64_t eth_call(const std::string& to, const std::string& data); + uint64_t eth_sendTransaction(const std::string& from, const std::string& to, const std::string& data); + uint64_t eth_sendRawTransaction(const std::string& params); + uint64_t eth_getCode(const std::string& addr); + uint64_t eth_getBalance(const std::string& addr); + uint64_t eth_sign(const string& addr, const string& message); + uint64_t eth_coinbase(); - uint64_t get_list_owners(const std::string& safe_account); - uint64_t add_owner(const std::string& addr ); - uint64_t remove_owner(const std::string& addr, uint32_t threshold); + uint64_t get_list_owners(const std::string& safe_account); + uint64_t add_owner(const std::string& addr ); + uint64_t remove_owner(const std::string& addr, uint32_t threshold); - std::string addmultisigaddress(const uint32_t nrequired, const std::vector public_keys); - std::string combinepsbt(const vector &psbts); + std::string addmultisigaddress(const uint32_t nrequired, const std::vector public_keys); + std::string combinepsbt(const vector &psbts); - uint64_t createmultisig(const uint32_t nrequired, const std::vector owner_addresses, const std::string &private_key); + uint64_t createmultisig(const uint32_t nrequired, const std::vector owner_addresses, const std::string &private_key); - std::string createpsbt(); - std::string createrawtransaction(); - std::string createwallet(const std::string &wallet_name); - std::string decodepsbt(std::string const &tx_psbt); - std::string decoderawtransaction(std::string const &tx_hex); - std::string encryptwallet(const std::string &passphrase); - uint64_t estimatesmartfee(uint16_t conf_target = 128); - std::string finalizepsbt(std::string const &tx_psbt); - std::string getaddressinfo(const std::string &address); - std::string getblock(const std::string &block_hash, int32_t verbosity = 2); - std::string getrawtransaction(const std::string &txid, const bool verbose = false); - std::string getnetworkinfo(); - std::string gettransaction(const std::string &txid, const bool include_watch_only = false); - std::string getblockchaininfo(); - void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false); - void importmulti(const std::vector &address_or_script_array, const bool rescan = true); - std::string loadwallet(const std::string &filename); - std::string sendrawtransaction(const std::string &tx_hex); - std::string signrawtransactionwithwallet(const std::string &tx_hash); - std::string unloadwallet(const std::string &filename); - std::string walletlock(); - std::string walletprocesspsbt(std::string const &tx_psbt); - bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60); + std::string createpsbt(); + std::string createrawtransaction(); + std::string createwallet(const std::string &wallet_name); + std::string decodepsbt(std::string const &tx_psbt); + std::string decoderawtransaction(std::string const &tx_hex); + std::string encryptwallet(const std::string &passphrase); + uint64_t estimatesmartfee(uint16_t conf_target = 128); + std::string finalizepsbt(std::string const &tx_psbt); + std::string getaddressinfo(const std::string &address); + std::string getblock(const std::string &block_hash, int32_t verbosity = 2); + std::string getrawtransaction(const std::string &txid, const bool verbose = false); + std::string getnetworkinfo(); + std::string gettransaction(const std::string &txid, const bool include_watch_only = false); + std::string getblockchaininfo(); + void importaddress(const std::string &address_or_script, const std::string &label = "", const bool rescan = true, const bool p2sh = false); + void importmulti(const std::vector &address_or_script_array, const bool rescan = true); + std::string loadwallet(const std::string &filename); + std::string sendrawtransaction(const std::string &tx_hex); + std::string signrawtransactionwithwallet(const std::string &tx_hash); + std::string unloadwallet(const std::string &filename); + std::string walletlock(); + std::string walletprocesspsbt(std::string const &tx_psbt); + bool walletpassphrase(const std::string &passphrase, uint32_t timeout = 60); - std::string chain_id;//256 bit value - std::vector owners; - std::string safe_account_addr; -private: - class ethereum_function_call_encoder { - public: - std::string encode_function_signature(const std::string& function_signature); - std::string encode_address(const std::string& addr); - std::string encode_uint256(const std::string& value); - std::string encode_uint8(uint8_t value); - std::string encode_bytes(const std::string& values); - }; + std::string chain_id;//256 bit value + std::vector owners; + std::string safe_account_addr; + private: + class ethereum_function_call_encoder { + public: + enum operation_t { + OPERATION_CALL, + OPERATION_DELEGATE_CALL + }; - ethereum_function_call_encoder m_ethereum_function_call_encoder; + static constexpr const char*const default_prev_addr = "0000000000000000000000000000000000000001"; - std::shared_ptr _thread; - std::string signature; - std::string geth_url; - uint64_t t_id; - std::string account_address; - std::string transaction_id; - uint32_t threshold; - std::unordered_map m_requests; - std::string balance; - std::string code; + std::string encode_function_signature(const std::string& function_signature); + std::string encode_address(const std::string& addr); + std::string encode_uint256(const std::string& value); + std::string encode_uint8(uint8_t value); + std::string encode_bytes(const std::string& values); + }; - std::string ip; - uint32_t rpc_port; - std::string user; - std::string password; - std::string wallet; - std::string wallet_password; - bool debug_rpc_calls; + class safe_transaction_encoder { + public: + static constexpr const char*const default_safe_tx_gas = "0"; + static constexpr const char*const default_data_gas = "0"; + static constexpr const char*const default_gas_price = "0"; + static constexpr const char*const default_gas_token = "0000000000000000000000000000000000000000"; + static constexpr const char*const default_refund_receiver = "0000000000000000000000000000000000000000"; - fc::http::header authorization; + std::string create_safe_address(const std::vector owner_addresses, uint32_t threshold); + std::string build_transaction(const std::string& safe_account_addr, const std::string& value, const std::string& data, uint8_t operation, const std::string& safeTxGas, const std::string& dataGas, const std::string& gasPrice, const std::string& gasToken, const std::string& refundReceiver); - client m_endpoint; - websocketpp::connection_hdl m_hdl; -}; + private: + ethereum_function_call_encoder m_ethereum_function_call_encoder; + }; -// ============================================================================= + ethereum_function_call_encoder m_ethereum_function_call_encoder; + safe_transaction_encoder m_safe_transaction_encoder; -class sidechain_net_handler_eth : public sidechain_net_handler { -public: - sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options); - virtual ~sidechain_net_handler_eth(); + std::shared_ptr _thread; + std::string signature; + std::string geth_url; + uint64_t t_id; + std::string account_address; + std::string transaction_id; + uint32_t threshold; + std::unordered_map m_requests; + std::string balance; + std::string code; - bool process_proposal(const proposal_object &po); - void process_primary_wallet(); - void process_sidechain_addresses(); - bool process_deposit(const son_wallet_deposit_object &swdo); - bool process_withdrawal(const son_wallet_withdraw_object &swwo); - std::string process_sidechain_transaction(const sidechain_transaction_object &sto); - std::string send_sidechain_transaction(const sidechain_transaction_object &sto); - bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); + std::string ip; + uint32_t rpc_port; + std::string user; + std::string password; + std::string wallet; + std::string wallet_password; + bool debug_rpc_calls; -private: - std::string url; - uint32_t rpc_port; + fc::http::header authorization; - std::string rpc_user; - std::string rpc_password; - std::string wallet; - std::string wallet_password; + client m_endpoint; + websocketpp::connection_hdl m_hdl; + }; - std::unique_ptr eth_client; + // ============================================================================= - fc::future on_changed_objects_task; + class sidechain_net_handler_eth : public sidechain_net_handler { + public: + sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options); + virtual ~sidechain_net_handler_eth(); - std::mutex event_handler_mutex; - typedef std::lock_guard scoped_lock; + bool process_proposal(const proposal_object &po); + void process_primary_wallet(); + void process_sidechain_addresses(); + bool process_deposit(const son_wallet_deposit_object &swdo); + bool process_withdrawal(const son_wallet_withdraw_object &swwo); + std::string process_sidechain_transaction(const sidechain_transaction_object &sto); + std::string send_sidechain_transaction(const sidechain_transaction_object &sto); + bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount); - std::string create_primary_wallet_address(const std::vector &son_pubkeys); + private: + std::string url; + uint32_t rpc_port; - std::string create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address); - std::string create_deposit_transaction(const son_wallet_deposit_object &swdo); - std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); + std::string rpc_user; + std::string rpc_password; + std::string wallet; + std::string wallet_password; - std::string create_transaction(); - std::string sign_transaction(const sidechain_transaction_object &sto); - std::string send_transaction(const sidechain_transaction_object &sto); + std::unique_ptr eth_client; - void handle_event(const std::string &event_data); - std::vector extract_info_from_block(const std::string &_block); - void on_changed_objects(const vector &ids, const flat_set &accounts); - void on_changed_objects_cb(const vector &ids, const flat_set &accounts); + fc::future on_changed_objects_task; - std::vector parse_hex(const std::string &str); - fc::ecc::public_key_data create_public_key_data(const std::vector &public_key); -}; + std::mutex event_handler_mutex; + typedef std::lock_guard scoped_lock; + + 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_deposit_transaction(const son_wallet_deposit_object &swdo); + std::string create_withdrawal_transaction(const son_wallet_withdraw_object &swwo); + + std::string create_transaction(); + std::string sign_transaction(const sidechain_transaction_object &sto); + std::string send_transaction(const sidechain_transaction_object &sto); + + void handle_event(const std::string &event_data); + std::vector extract_info_from_block(const std::string &_block); + void on_changed_objects(const vector &ids, const flat_set &accounts); + void on_changed_objects_cb(const vector &ids, const flat_set &accounts); + + std::vector parse_hex(const std::string &str); + fc::ecc::public_key_data create_public_key_data(const std::vector &public_key); + }; }} // namespace graphene::peerplays_sidechain diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_eth.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_eth.cpp index 3cc7ec43..1c333811 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_eth.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_eth.cpp @@ -28,1115 +28,1134 @@ extern "C" { } namespace graphene { namespace peerplays_sidechain { -// ============================================================================= -std::string eth_rpc_client::ethereum_function_call_encoder::encode_function_signature(const std::string& function_signature) { - sha3_context c; - char *hash; - - sha3_Init256(static_cast(&c)); - sha3_SetFlags(&c, SHA3_FLAGS_KECCAK); - sha3_Update(&c, "abc", 3); - hash = (char*)sha3_Finalize(&c); - std::string output(hash); - output = output.substr(0,8); - - return output; -}; - -std::string eth_rpc_client::ethereum_function_call_encoder::encode_address(const std::string& addr) { - FC_ASSERT(20 == addr.length()); - std::string output = str(boost::format("%012u") % 0) + addr; - return output; -} - -std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint256(const std::string& value) { - FC_ASSERT(value.length() <= 64); - std::string output = std::string(64 - value.length(), '0') + value; - return output; -} - -std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint8(uint8_t value) { - std::string output = str(boost::format("%02X") % value) + std::string(62, '0'); - return output; -} - -std::string eth_rpc_client::ethereum_function_call_encoder::encode_bytes(const std::string& values) { - size_t len = values.length(); - std::string output = encode_uint256((boost::format("%x") % len).str()) + values + std::string(64 - len, '0'); - return output; -} - - -eth_rpc_client::eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) : _thread(std::make_shared("eth_rpc_client")){ - geth_url = url; - user = user_name; - this->password = password; - this->debug_rpc_calls = debug_rpc_calls; - t_id = 1; - - ilog("eth_rpc_client"); - ilog("### Geth URL: ${url}", ("url", url)); - - m_endpoint.set_access_channels(websocketpp::log::alevel::none); - m_endpoint.set_error_channels(websocketpp::log::elevel::none); - - // Initialize ASIO - m_endpoint.init_asio(); - - // Register our handlers - m_endpoint.set_socket_init_handler(bind(&type::on_socket_init,this,::_1)); - m_endpoint.set_message_handler(bind(&type::on_message,this,::_1,::_2)); - m_endpoint.set_open_handler(bind(&type::on_open,this,::_1)); - m_endpoint.set_close_handler(bind(&type::on_close,this,::_1)); - m_endpoint.set_fail_handler(bind(&type::on_fail,this,::_1)); -} - -void eth_rpc_client::start() { - ilog("### eth_rpc_client::start uri: ${uri}", ("uri", geth_url)); - auto future = _thread->async([this] - { - websocketpp::lib::error_code ec; - client::connection_ptr con = m_endpoint.get_connection(this->geth_url, ec); - m_hdl = con->get_handle(); - - if (ec) { - m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message()); - return; - } - - m_endpoint.connect(con); - - // Start the ASIO io_service run loop - m_endpoint.run(); - }); -} - -void eth_rpc_client::stop() { - m_endpoint.close(m_hdl,websocketpp::close::status::normal,""); -} - -void eth_rpc_client::on_socket_init(websocketpp::connection_hdl) { -} - -void eth_rpc_client::on_fail(websocketpp::connection_hdl hdl) { - client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl); - - elog("Ethereum websocket fail"); - //elog("get_state: ${state}", ("state", con->get_state() ) ); - elog("get_local_close_code: ${code}", ("code", con->get_local_close_code())); - elog("get_local_close_reason: ${close}", ("close",con->get_local_close_reason())); - elog("get_remote_close_code: ${close}", ("close", con->get_remote_close_code())); - elog("get_remote_close_reason: ${close}", ("close", con->get_remote_close_reason())); - elog("get_ec().message(): ${ec}", ("ec", con->get_ec().message())); -} - -void eth_rpc_client::on_open(websocketpp::connection_hdl hdl) { - std::string str = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":84}"; - ilog("on_open: ${str}", ("str", str)); - m_endpoint.send(hdl, str.c_str(), websocketpp::frame::opcode::text); - - vector owner_addresses; - std::string private_key = ""; - createmultisig(5, owner_addresses, private_key); -} - -void eth_rpc_client::on_message(websocketpp::connection_hdl hdl, message_ptr msg) { - - ilog("on_message: ${msg}", ("msg", msg->get_payload())); - - fc::variants list = fc::json::variants_from_string( msg->get_payload() ); - - ilog("json reposnse: ${list}", ("list", list)); - - const auto& b_obj = list[0].get_object().find( "id" ); - - if (true == list[0].get_object().contains( "error" )){ - elog("error in json reposnse: ${list}", ("list", list)); - return; - } - - std::string result_str = list[0].get_object().find( "result" )->value().as(1); - uint32_t num_owners = 0; - uint32_t i = 0; - fc::variant v; - switch(b_obj->value().as(1)){ - case ETH_CHAIN_ID: - chain_id = result_str; - break; - case ETH_GET_TRANSACTION_RECEIPT: - list = fc::json::variants_from_string( result_str ); - v = list[0].get_object().find( "logs" )->value(); - safe_account_addr = v.get_object().find( "address" )->value().as(1); - break; - case ETH_CALL: - break; - case ETH_SEND_TRANSACTION: - transaction_id = result_str; - break; - case ETH_SEND_RAW_TRANSACTION: - break; - case ETH_GET_CODE: - code = result_str; - break; - case ETH_GET_BALANCE: - balance = result_str; - break; - case ETH_SIGN: - signature = result_str; - break; - case ETH_COINBASE: - account_address = result_str; - break; - case GET_LIST_OWNERS: - num_owners = (uint32_t)strtol(result_str.substr(2 + 32 + 32 - 4, 4).c_str(), NULL, 16); - owners.clear(); - for (i = 0; i < num_owners; ++i){ - owners.push_back("0x" + result_str.substr(2 + 32 + 32 + 12 + 32 * i,20)); - } - break; - case ADD_OWNER: - break; - case REMOVE_OWNER: - break; - } -} - -void eth_rpc_client::on_close(websocketpp::connection_hdl) { - ilog("Ethereum websocket close"); -} - -uint64_t eth_rpc_client::get_chain_id() { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":%1%}") % t_id); - ilog("get_chain_id: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_CHAIN_ID; - return t_id++; -} - -uint64_t eth_rpc_client::eth_getTransactionReceipt(const std::string& tx_id) { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"%1%\"],\"id\":%2%}") % tx_id.c_str() % t_id); - ilog("eth_getTransactionReceipt: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_GET_TRANSACTION_RECEIPT; - return t_id++; -} - -uint64_t eth_rpc_client::eth_call(const std::string& to, const std::string& data) { - std::string req = str(boost::format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_call\", \"params\": [{\"to\": \"%1%\", \"data\": \"%2%\"}, \"latest\"], \"id\": %3%}") % to.c_str() % data.c_str() % t_id); - ilog("eth_call: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_CALL; - - return t_id++; -} - -uint64_t eth_rpc_client::eth_sendTransaction(const std::string& from, const std::string& to, const std::string& data) { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_sendTransaction\", \"params\": [{\"from\": \"%1%\", \"to\": \"%2%\", \"data\": \"%3%\"}], \"id\": %4%}") % from.c_str() % to.c_str() % data.c_str() % t_id); - ilog("eth_sendTransaction: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_SEND_TRANSACTION; - - return t_id++; -} - -uint64_t eth_rpc_client::eth_sendRawTransaction(const std::string& params) { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":[\"%1%\"],\"id\":%2%}") % params.c_str() % t_id); - ilog("eth_sendRawTransaction: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_SEND_RAW_TRANSACTION; - - return t_id++; -} - -uint64_t eth_rpc_client::eth_getCode(const std::string& addr) { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_getCode\", \"params\": [\"%1%\",\"latest\"], \"id\": %2%}") % addr.c_str() % t_id); - ilog("eth_getCode: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_GET_CODE; - return t_id++; -} - -uint64_t eth_rpc_client::eth_getBalance(const std::string& addr) { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_getBalance\", \"params\": [\"%1%\",\"latest\"], \"id\": %2%}") % addr.c_str() % t_id); - ilog("eth_getBalance: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_GET_BALANCE; - return t_id++; -} - -uint64_t eth_rpc_client::eth_sign(const string& addr, const string& message) { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_sign\", \"params\": [\"%1%\",\"%2%\"], \"id\": %2%}") % addr.c_str() % message.c_str() % t_id); - ilog("eth_sign: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_SIGN; - - return t_id++; -} - -uint64_t eth_rpc_client::eth_coinbase() { - std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_coinbase\",\"params\":[],\"id\":%1%}") % t_id); - ilog("eth_coinbase: ${req}", ("req", req.c_str())); - m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); - m_requests[t_id] = req_t::ETH_COINBASE; - return t_id++; -} - -uint64_t eth_rpc_client::get_list_owners(const std::string& safe_account) { - return eth_call(safe_account.c_str(), "0xa0e67e2b"); -} - -uint64_t eth_rpc_client::add_owner(const std::string& addr ) { - if (std::count(owners.begin(), owners.end(), addr)){ - FC_THROW_EXCEPTION(fc::exception, "Owners allready have addr: ${addr}", ("addr", addr)); - } - - //It's require to execute - //execTransaction method of smart contract , using safe-account address - //execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) - std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); - FC_ASSERT("6a761202" == method_id); - std::string address = safe_account_addr; - std::string value = str(boost::format("%020u") % 0); - std::string data = "f8dc5dd9000000000000000000000000" + owners[0] + "000000000000000000000000" + addr + str(boost::format("%032u") % threshold); - std::string operation = "0"; - std::string safeTxGas = str(boost::format("%032u") % 0); - std::string dataGas = str(boost::format("%032u") % 0); - std::string gasPrice = str(boost::format("%032u") % 0); - std::string gasToken = "0000000000000000000000000000000000000000"; - std::string refundReceiver = "0000000000000000000000000000000000000000"; - - std::string message = method_id + address + value + data + operation + safeTxGas + dataGas + gasPrice + gasToken + refundReceiver; - uint64_t id = eth_sign(account_address, message); - - m_requests[t_id] = req_t::ADD_OWNER; - - return 0; -} - -uint64_t eth_rpc_client::remove_owner(const std::string& addr, uint32_t threshold) { - if (!std::count(owners.begin(), owners.end(), addr)){ - FC_THROW_EXCEPTION(fc::exception, "Owners does not have addr: ${addr}", ("addr", addr)); - } - - if (threshold == owners.size()){ - FC_THROW_EXCEPTION(fc::exception, "Owners size does not meet threshold: ${th}", ("th", threshold)); - } - - //It's require to execute - //execTransaction method of smart contract , using safe-account address - //execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) - std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); - FC_ASSERT("6a761202" == method_id); - std::string address = safe_account_addr; - std::string value = str(boost::format("%032u") % 0); - std::string data = "f8dc5dd90000000000000000000000000000000000000000000000000000000000000001000000000000000000000000" + addr + str(boost::format("%032u") % threshold); - std::string operatio = "0"; - std::string safeTxGas = str(boost::format("%032u") % 0); - std::string dataGas = str(boost::format("%032u") % 0); - std::string gasPrice = str(boost::format("%032u") % 0); - std::string gasToken = "0000000000000000000000000000000000000000"; - std::string refundReceiver = "0000000000000000000000000000000000000000"; - - m_requests[t_id] = req_t::REMOVE_OWNER; - - return 0; -} - -std::string eth_rpc_client::addmultisigaddress(const uint32_t nrequired, const std::vector public_keys) { - return ""; -} - -std::string eth_rpc_client::combinepsbt(const vector &psbts) { - return ""; -} - -uint64_t eth_rpc_client::createmultisig(const uint32_t nrequired, const std::vector owner_addresses, const std::string &private_key) { - ilog("createmultisig: ${key}", ("key", private_key.c_str())); - -//That's will create -//0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12 -//0x76ce31BD03f601c3fC13732deF921c5Bac282676 -//0x09EE460834498a4ee361beB819470061B7381B49 -//0x6AEFbd09209e1eE2e0a589d31e732F69B77713D2 -//0x631e128b16f9aDCF1bB6385112B1519C917D77a7 -//0xcD5C788e84220E8b8934Ea4F1dC6a12009bCc91D -//0x3627C1B31525887CB9441130C831e35887650305 -//0x03A13a989AF30C92AD7ABD1E6210308A6c96f373 - - - std::string from = "0xeE52b70e8D7AB5Fe661311D47e81228EAD6B06B9"; - std::string to = "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2"; - std::string data = "0x1688f0b9000000000000000000000000d9db270c1b5e3bd161e8c8503c55ceabee70955200000000000000000000000000000000000000000000000000000000000000604fa262bd05cdef2e3d5261787ee66d9447a4036324990e04380339bec83b4c7a0000000000000000000000000000000000000000000000000000000000000264b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000f48f2b2d2a534e402487b3ee7c18c33aec0fe5e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC1200000000000000000000000076ce31BD03f601c3fC13732deF921c5Bac28267600000000000000000000000009EE460834498a4ee361beB819470061B7381B490000000000000000000000006AEFbd09209e1eE2e0a589d31e732F69B77713D2000000000000000000000000631e128b16f9aDCF1bB6385112B1519C917D77a7000000000000000000000000cD5C788e84220E8b8934Ea4F1dC6a12009bCc91D0000000000000000000000003627C1B31525887CB9441130C831e3588765030500000000000000000000000003A13a989AF30C92AD7ABD1E6210308A6c96f3730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; - return eth_sendTransaction(from, to, data); -} - -std::string eth_rpc_client::createpsbt() { -} - -std::string eth_rpc_client::createrawtransaction() { - return ""; -} - -std::string eth_rpc_client::createwallet(const std::string &wallet_name) { - return ""; -} - -std::string eth_rpc_client::decodepsbt(std::string const &tx_psbt) { - return ""; -} - -std::string eth_rpc_client::decoderawtransaction(std::string const &tx_hex) { - return ""; -} - -std::string eth_rpc_client::encryptwallet(const std::string &passphrase) { - return ""; -} - -uint64_t eth_rpc_client::estimatesmartfee(uint16_t conf_target) { - return 20000; -} - -std::string eth_rpc_client::finalizepsbt(std::string const &tx_psbt) { - return ""; -} - -std::string eth_rpc_client::getaddressinfo(const std::string &address) { - return ""; -} - -std::string eth_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) { - return ""; -} - -std::string eth_rpc_client::getnetworkinfo() { - return ""; -} - -std::string eth_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { - return ""; -} - -std::string eth_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) { - return ""; -} - -std::string eth_rpc_client::getblockchaininfo() { - return ""; -} - -void eth_rpc_client::importaddress(const std::string &address_or_script, const std::string &label, const bool rescan, const bool p2sh) { - return; -} - -void eth_rpc_client::importmulti(const std::vector &address_or_script_array, const bool rescan) { -} - -std::string eth_rpc_client::loadwallet(const std::string &filename) { - return ""; -} + // ============================================================================= + std::string eth_rpc_client::ethereum_function_call_encoder::encode_function_signature(const std::string& function_signature) { + sha3_context c; + char *hash; + + sha3_Init256(static_cast(&c)); + sha3_SetFlags(&c, SHA3_FLAGS_KECCAK); + sha3_Update(&c, "abc", 3); + hash = (char*)sha3_Finalize(&c); + std::string output(hash); + output = output.substr(0,8); + + return output; + }; + + std::string eth_rpc_client::ethereum_function_call_encoder::encode_address(const std::string& addr) { + FC_ASSERT(40 == addr.length()); + std::string output = str(boost::format("%024u") % 0) + addr; + return output; + } + + std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint256(const std::string& value) { + FC_ASSERT(value.length() <= 64); + std::string output = std::string(64 - value.length(), '0') + value; + return output; + } + + std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint8(uint8_t value) { + std::string output = str(boost::format("%02X") % value) + std::string(62, '0'); + return output; + } + + std::string eth_rpc_client::ethereum_function_call_encoder::encode_bytes(const std::string& values) { + size_t len = values.length(); + std::string output = encode_uint256((boost::format("%x") % len).str()) + values + std::string(64 - len, '0'); + return output; + } + + std::string eth_rpc_client::safe_transaction_encoder::create_safe_address(const std::vector owner_addresses, uint32_t threshold) { + } + + std::string eth_rpc_client::safe_transaction_encoder::build_transaction(const std::string& safe_account_addr, const std::string& value, const std::string& data, uint8_t operation, const std::string& safeTxGas, const std::string& dataGas, const std::string& gasPrice, const std::string& gasToken, const std::string& refundReceiver){ + //execTransaction method of smart contract , using safe-account address + //execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) + std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); + FC_ASSERT("6a761202" == method_id); + //"" + std::string to = m_ethereum_function_call_encoder.encode_address(safe_account_addr); + // Value in wei + std::string value_encoded = m_ethereum_function_call_encoder.encode_uint256(value); + // 0 CALL, 1 DELEGATE_CALL + std::string operation_encoded = m_ethereum_function_call_encoder.encode_uint8(operation); + // Max gas to use in the transaction + std::string safeTxGas_encoded = m_ethereum_function_call_encoder.encode_uint256(safeTxGas); + // Gas costs not related to the transaction execution (signature check, refund payment...) + std::string dataGas_encoded = m_ethereum_function_call_encoder.encode_uint256(dataGas); + // Gas price used for the refund calculation + std::string gasPrice_encoded = m_ethereum_function_call_encoder.encode_uint256(gasPrice); + //"", Token address (hold by the Safe) to be used as a refund to the sender, if `null` is Ether + std::string gasToken_encoded = m_ethereum_function_call_encoder.encode_address(gasToken); + //"", Address of receiver of gas payment (or `null` if tx.origin) + std::string refundReceiver_encoded = m_ethereum_function_call_encoder.encode_address(refundReceiver); + + std::string message = method_id + to + value_encoded + data + operation_encoded + safeTxGas_encoded + dataGas_encoded + gasPrice_encoded + gasToken_encoded + refundReceiver_encoded; + + return message; + } + + + eth_rpc_client::eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) : _thread(std::make_shared("eth_rpc_client")){ + geth_url = url; + user = user_name; + this->password = password; + this->debug_rpc_calls = debug_rpc_calls; + t_id = 1; + + ilog("eth_rpc_client"); + ilog("### Geth URL: ${url}", ("url", url)); + + m_endpoint.set_access_channels(websocketpp::log::alevel::none); + m_endpoint.set_error_channels(websocketpp::log::elevel::none); + + // Initialize ASIO + m_endpoint.init_asio(); + + // Register our handlers + m_endpoint.set_socket_init_handler(bind(&type::on_socket_init,this,::_1)); + m_endpoint.set_message_handler(bind(&type::on_message,this,::_1,::_2)); + m_endpoint.set_open_handler(bind(&type::on_open,this,::_1)); + m_endpoint.set_close_handler(bind(&type::on_close,this,::_1)); + m_endpoint.set_fail_handler(bind(&type::on_fail,this,::_1)); + } + + void eth_rpc_client::start() { + ilog("### eth_rpc_client::start uri: ${uri}", ("uri", geth_url)); + auto future = _thread->async([this] + { + websocketpp::lib::error_code ec; + client::connection_ptr con = m_endpoint.get_connection(this->geth_url, ec); + m_hdl = con->get_handle(); + + if (ec) { + m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message()); + return; + } + + m_endpoint.connect(con); + + // Start the ASIO io_service run loop + m_endpoint.run(); + }); + } + + void eth_rpc_client::stop() { + m_endpoint.close(m_hdl,websocketpp::close::status::normal,""); + } + + void eth_rpc_client::on_socket_init(websocketpp::connection_hdl) { + } + + void eth_rpc_client::on_fail(websocketpp::connection_hdl hdl) { + client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl); + + elog("Ethereum websocket fail"); + //elog("get_state: ${state}", ("state", con->get_state() ) ); + elog("get_local_close_code: ${code}", ("code", con->get_local_close_code())); + elog("get_local_close_reason: ${close}", ("close",con->get_local_close_reason())); + elog("get_remote_close_code: ${close}", ("close", con->get_remote_close_code())); + elog("get_remote_close_reason: ${close}", ("close", con->get_remote_close_reason())); + elog("get_ec().message(): ${ec}", ("ec", con->get_ec().message())); + } + + void eth_rpc_client::on_open(websocketpp::connection_hdl hdl) { + std::string str = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":84}"; + ilog("on_open: ${str}", ("str", str)); + m_endpoint.send(hdl, str.c_str(), websocketpp::frame::opcode::text); + + vector owner_addresses; + std::string private_key = ""; + createmultisig(5, owner_addresses, private_key); + } + + void eth_rpc_client::on_message(websocketpp::connection_hdl hdl, message_ptr msg) { + + ilog("on_message: ${msg}", ("msg", msg->get_payload())); + + fc::variants list = fc::json::variants_from_string( msg->get_payload() ); + + ilog("json reposnse: ${list}", ("list", list)); + + const auto& b_obj = list[0].get_object().find( "id" ); + + if (true == list[0].get_object().contains( "error" )){ + elog("error in json reposnse: ${list}", ("list", list)); + return; + } + + std::string result_str = list[0].get_object().find( "result" )->value().as(1); + uint32_t num_owners = 0; + uint32_t i = 0; + fc::variant v; + switch(b_obj->value().as(1)){ + case ETH_CHAIN_ID: + chain_id = result_str; + break; + case ETH_GET_TRANSACTION_RECEIPT: + list = fc::json::variants_from_string( result_str ); + v = list[0].get_object().find( "logs" )->value(); + safe_account_addr = v.get_object().find( "address" )->value().as(1); + break; + case ETH_CALL: + break; + case ETH_SEND_TRANSACTION: + transaction_id = result_str; + break; + case ETH_SEND_RAW_TRANSACTION: + break; + case ETH_GET_CODE: + code = result_str; + break; + case ETH_GET_BALANCE: + balance = result_str; + break; + case ETH_SIGN: + signature = result_str; + break; + case ETH_COINBASE: + account_address = result_str; + break; + case GET_LIST_OWNERS: + num_owners = (uint32_t)strtol(result_str.substr(2 + 32 + 32 - 4, 4).c_str(), NULL, 16); + owners.clear(); + for (i = 0; i < num_owners; ++i){ + owners.push_back("0x" + result_str.substr(2 + 32 + 32 + 12 + 32 * i,20)); + } + break; + case ADD_OWNER: + break; + case REMOVE_OWNER: + break; + } + } + + void eth_rpc_client::on_close(websocketpp::connection_hdl) { + ilog("Ethereum websocket close"); + } + + uint64_t eth_rpc_client::get_chain_id() { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":%1%}") % t_id); + ilog("get_chain_id: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_CHAIN_ID; + return t_id++; + } + + uint64_t eth_rpc_client::eth_getTransactionReceipt(const std::string& tx_id) { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_getTransactionReceipt\",\"params\":[\"%1%\"],\"id\":%2%}") % tx_id.c_str() % t_id); + ilog("eth_getTransactionReceipt: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_GET_TRANSACTION_RECEIPT; + return t_id++; + } + + uint64_t eth_rpc_client::eth_call(const std::string& to, const std::string& data) { + std::string req = str(boost::format("{\"jsonrpc\": \"2.0\", \"method\": \"eth_call\", \"params\": [{\"to\": \"%1%\", \"data\": \"%2%\"}, \"latest\"], \"id\": %3%}") % to.c_str() % data.c_str() % t_id); + ilog("eth_call: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_CALL; + + return t_id++; + } + + uint64_t eth_rpc_client::eth_sendTransaction(const std::string& from, const std::string& to, const std::string& data) { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_sendTransaction\", \"params\": [{\"from\": \"%1%\", \"to\": \"%2%\", \"data\": \"%3%\"}], \"id\": %4%}") % from.c_str() % to.c_str() % data.c_str() % t_id); + ilog("eth_sendTransaction: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_SEND_TRANSACTION; + + return t_id++; + } + + uint64_t eth_rpc_client::eth_sendRawTransaction(const std::string& params) { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_sendRawTransaction\",\"params\":[\"%1%\"],\"id\":%2%}") % params.c_str() % t_id); + ilog("eth_sendRawTransaction: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_SEND_RAW_TRANSACTION; + + return t_id++; + } + + uint64_t eth_rpc_client::eth_getCode(const std::string& addr) { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_getCode\", \"params\": [\"%1%\",\"latest\"], \"id\": %2%}") % addr.c_str() % t_id); + ilog("eth_getCode: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_GET_CODE; + return t_id++; + } + + uint64_t eth_rpc_client::eth_getBalance(const std::string& addr) { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_getBalance\", \"params\": [\"%1%\",\"latest\"], \"id\": %2%}") % addr.c_str() % t_id); + ilog("eth_getBalance: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_GET_BALANCE; + return t_id++; + } + + uint64_t eth_rpc_client::eth_sign(const string& addr, const string& message) { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\": \"eth_sign\", \"params\": [\"%1%\",\"%2%\"], \"id\": %2%}") % addr.c_str() % message.c_str() % t_id); + ilog("eth_sign: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_SIGN; + + return t_id++; + } + + uint64_t eth_rpc_client::eth_coinbase() { + std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_coinbase\",\"params\":[],\"id\":%1%}") % t_id); + ilog("eth_coinbase: ${req}", ("req", req.c_str())); + m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); + m_requests[t_id] = req_t::ETH_COINBASE; + return t_id++; + } + + uint64_t eth_rpc_client::get_list_owners(const std::string& safe_account) { + //getOwners() + std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("getOwners()"); + FC_ASSERT("a0e67e2b" == method_id); + return eth_call(safe_account.c_str(), method_id); + } + + uint64_t eth_rpc_client::add_owner(const std::string& addr ) { + if (std::count(owners.begin(), owners.end(), addr)){ + FC_THROW_EXCEPTION(fc::exception, "Owners allready have addr: ${addr}", ("addr", addr)); + } + + std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); + //addOwnerWithThreshold(address,uint256) + std::string data_method_id = m_ethereum_function_call_encoder.encode_function_signature("addOwnerWithThreshold(address,uint256)"); + FC_ASSERT("0d582f13" == data_method_id); + std::string data = data_method_id + m_ethereum_function_call_encoder.encode_address(addr) + m_ethereum_function_call_encoder.encode_uint256((boost::format("%x") % threshold).str()); + + std::string message = m_safe_transaction_encoder.build_transaction(safe_account_addr, "0", data, ethereum_function_call_encoder::operation_t::OPERATION_CALL, m_safe_transaction_encoder.default_safe_tx_gas, m_safe_transaction_encoder.default_data_gas, m_safe_transaction_encoder.default_gas_price, m_safe_transaction_encoder.default_gas_token, m_safe_transaction_encoder.default_refund_receiver); + + uint64_t id = eth_sign(account_address, message); + + m_requests[t_id] = req_t::ADD_OWNER; + + return 0; + } + + uint64_t eth_rpc_client::remove_owner(const std::string& addr, uint32_t threshold) { + if (!std::count(owners.begin(), owners.end(), addr)){ + FC_THROW_EXCEPTION(fc::exception, "Owners does not have addr: ${addr}", ("addr", addr)); + } + + if (threshold == owners.size()){ + FC_THROW_EXCEPTION(fc::exception, "Owners size does not meet threshold: ${th}", ("th", threshold)); + } + + //removeOwner(address,address,uint256) + std::string data_method_id = m_ethereum_function_call_encoder.encode_function_signature("removeOwner(address,address,uint256)"); + FC_ASSERT("f8dc5dd9" == data_method_id); + std::string data = data_method_id + m_ethereum_function_call_encoder.encode_address(m_ethereum_function_call_encoder.default_prev_addr) + m_ethereum_function_call_encoder.encode_address(addr) + m_ethereum_function_call_encoder.encode_uint256((boost::format("%x") % threshold).str()); + + std::string message = m_safe_transaction_encoder.build_transaction(safe_account_addr, "0", data, ethereum_function_call_encoder::operation_t::OPERATION_CALL, m_safe_transaction_encoder.default_safe_tx_gas, m_safe_transaction_encoder.default_data_gas, m_safe_transaction_encoder.default_gas_price, m_safe_transaction_encoder.default_gas_token, m_safe_transaction_encoder.default_refund_receiver); + + uint64_t id = eth_sign(account_address, message); + + m_requests[t_id] = req_t::REMOVE_OWNER; + + return 0; + } + + std::string eth_rpc_client::addmultisigaddress(const uint32_t nrequired, const std::vector public_keys) { + return ""; + } + + std::string eth_rpc_client::combinepsbt(const vector &psbts) { + return ""; + } + + uint64_t eth_rpc_client::createmultisig(const uint32_t nrequired, const std::vector owner_addresses, const std::string &private_key) { + ilog("createmultisig: ${key}", ("key", private_key.c_str())); + + //That's will create + //0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12 + //0x76ce31BD03f601c3fC13732deF921c5Bac282676 + //0x09EE460834498a4ee361beB819470061B7381B49 + //0x6AEFbd09209e1eE2e0a589d31e732F69B77713D2 + //0x631e128b16f9aDCF1bB6385112B1519C917D77a7 + //0xcD5C788e84220E8b8934Ea4F1dC6a12009bCc91D + //0x3627C1B31525887CB9441130C831e35887650305 + //0x03A13a989AF30C92AD7ABD1E6210308A6c96f373 + + + std::string from = "0xeE52b70e8D7AB5Fe661311D47e81228EAD6B06B9"; + std::string to = "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2"; + std::string data = "0x1688f0b9000000000000000000000000d9db270c1b5e3bd161e8c8503c55ceabee70955200000000000000000000000000000000000000000000000000000000000000604fa262bd05cdef2e3d5261787ee66d9447a4036324990e04380339bec83b4c7a0000000000000000000000000000000000000000000000000000000000000264b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000f48f2b2d2a534e402487b3ee7c18c33aec0fe5e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC1200000000000000000000000076ce31BD03f601c3fC13732deF921c5Bac28267600000000000000000000000009EE460834498a4ee361beB819470061B7381B490000000000000000000000006AEFbd09209e1eE2e0a589d31e732F69B77713D2000000000000000000000000631e128b16f9aDCF1bB6385112B1519C917D77a7000000000000000000000000cD5C788e84220E8b8934Ea4F1dC6a12009bCc91D0000000000000000000000003627C1B31525887CB9441130C831e3588765030500000000000000000000000003A13a989AF30C92AD7ABD1E6210308A6c96f3730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + return eth_sendTransaction(from, to, data); + } + + std::string eth_rpc_client::createpsbt() { + } + + std::string eth_rpc_client::createrawtransaction() { + return ""; + } + + std::string eth_rpc_client::createwallet(const std::string &wallet_name) { + return ""; + } -std::string eth_rpc_client::sendrawtransaction(const std::string &tx_hex) { - return ""; -} - -std::string eth_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) { - return ""; -} - -std::string eth_rpc_client::unloadwallet(const std::string &filename) { - return ""; -} - -std::string eth_rpc_client::walletlock() { - return ""; -} - -std::string eth_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { - return ""; -} - -bool eth_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) { - return false; -} + std::string eth_rpc_client::decodepsbt(std::string const &tx_psbt) { + return ""; + } + + std::string eth_rpc_client::decoderawtransaction(std::string const &tx_hex) { + return ""; + } -// ============================================================================= + std::string eth_rpc_client::encryptwallet(const std::string &passphrase) { + return ""; + } -sidechain_net_handler_eth::sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : - sidechain_net_handler(_plugin, options) { - sidechain = sidechain_type::ethereum; - - if (options.count("debug-rpc-calls")) { - debug_rpc_calls = options.at("debug-rpc-calls").as(); - } + uint64_t eth_rpc_client::estimatesmartfee(uint16_t conf_target) { + return 20000; + } - url = options.at("ethereum-node-rpc-url").as(); - eth_client = std::unique_ptr(new eth_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls)); - eth_client->start(); -/* - if (!wallet.empty()) { - eth_client->loadwallet(wallet); - } - - - std::thread(&sidechain_net_handler_eth::handle_event, this, event_data).detach(); - }); - - database.changed_objects.connect([this](const vector &ids, const flat_set &accounts) { - on_changed_objects(ids, accounts); - }); -*/ + std::string eth_rpc_client::finalizepsbt(std::string const &tx_psbt) { + return ""; + } + + std::string eth_rpc_client::getaddressinfo(const std::string &address) { + return ""; + } + + std::string eth_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) { + return ""; + } + + std::string eth_rpc_client::getnetworkinfo() { + return ""; + } + + std::string eth_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { + return ""; + } + + std::string eth_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) { + return ""; + } + + std::string eth_rpc_client::getblockchaininfo() { + return ""; + } + + void eth_rpc_client::importaddress(const std::string &address_or_script, const std::string &label, const bool rescan, const bool p2sh) { + return; + } + + void eth_rpc_client::importmulti(const std::vector &address_or_script_array, const bool rescan) { + } + + std::string eth_rpc_client::loadwallet(const std::string &filename) { + return ""; + } + + std::string eth_rpc_client::sendrawtransaction(const std::string &tx_hex) { + return ""; + } + + std::string eth_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) { + return ""; + } + + std::string eth_rpc_client::unloadwallet(const std::string &filename) { + return ""; + } + + std::string eth_rpc_client::walletlock() { + return ""; + } + + std::string eth_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { + return ""; + } + + bool eth_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) { + return false; + } + + // ============================================================================= + + sidechain_net_handler_eth::sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : + sidechain_net_handler(_plugin, options) { + sidechain = sidechain_type::ethereum; + + if (options.count("debug-rpc-calls")) { + debug_rpc_calls = options.at("debug-rpc-calls").as(); + } + + url = options.at("ethereum-node-rpc-url").as(); + eth_client = std::unique_ptr(new eth_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls)); + eth_client->start(); + /* + if (!wallet.empty()) { + eth_client->loadwallet(wallet); + } + + + std::thread(&sidechain_net_handler_eth::handle_event, this, event_data).detach(); + }); + + database.changed_objects.connect([this](const vector &ids, const flat_set &accounts) { + on_changed_objects(ids, accounts); + }); + */ } sidechain_net_handler_eth::~sidechain_net_handler_eth() { - try { - if (on_changed_objects_task.valid()) { - on_changed_objects_task.cancel_and_wait(__FUNCTION__); - } - } catch (fc::canceled_exception &) { - //Expected exception. Move along. - } catch (fc::exception &e) { - edump((e.to_detail_string())); - } + try { + if (on_changed_objects_task.valid()) { + on_changed_objects_task.cancel_and_wait(__FUNCTION__); + } + } catch (fc::canceled_exception &) { + //Expected exception. Move along. + } catch (fc::exception &e) { + edump((e.to_detail_string())); + } } bool sidechain_net_handler_eth::process_proposal(const proposal_object &po) { - ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); -/* - bool should_approve = false; + ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id())); + /* + bool should_approve = false; - const chain::global_property_object &gpo = database.get_global_properties(); + const chain::global_property_object &gpo = database.get_global_properties(); - int32_t op_idx_0 = -1; - chain::operation op_obj_idx_0; + int32_t op_idx_0 = -1; + chain::operation op_obj_idx_0; - if (po.proposed_transaction.operations.size() >= 1) { - op_idx_0 = po.proposed_transaction.operations[0].which(); - op_obj_idx_0 = po.proposed_transaction.operations[0]; - } + if (po.proposed_transaction.operations.size() >= 1) { + op_idx_0 = po.proposed_transaction.operations[0].which(); + op_obj_idx_0 = po.proposed_transaction.operations[0]; + } - int32_t op_idx_1 = -1; - chain::operation op_obj_idx_1; - (void)op_idx_1; + int32_t op_idx_1 = -1; + chain::operation op_obj_idx_1; + (void)op_idx_1; - if (po.proposed_transaction.operations.size() >= 2) { - op_idx_1 = po.proposed_transaction.operations[1].which(); - op_obj_idx_1 = po.proposed_transaction.operations[1]; - } + if (po.proposed_transaction.operations.size() >= 2) { + op_idx_1 = po.proposed_transaction.operations[1].which(); + op_obj_idx_1 = po.proposed_transaction.operations[1]; + } - switch (op_idx_0) { + switch (op_idx_0) { - case chain::operation::tag::value: { - bool address_ok = false; - bool transaction_ok = false; - std::string new_pw_address = ""; - son_wallet_id_type swo_id = op_obj_idx_0.get().son_wallet_id; - const auto &idx = database.get_index_type().indices().get(); - const auto swo = idx.find(swo_id); - if (swo != idx.end()) { + case chain::operation::tag::value: { + bool address_ok = false; + bool transaction_ok = false; + std::string new_pw_address = ""; + son_wallet_id_type swo_id = op_obj_idx_0.get().son_wallet_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swo = idx.find(swo_id); + if (swo != idx.end()) { - auto active_sons = gpo.active_sons; - vector wallet_sons = swo->sons; + auto active_sons = gpo.active_sons; + vector wallet_sons = swo->sons; - bool son_sets_equal = (active_sons.size() == wallet_sons.size()); + 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) { + 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) { - auto active_sons = gpo.active_sons; - vector son_pubkeys_bitcoin; - for (const son_info &si : active_sons) { - son_pubkeys_bitcoin.push_back(si.sidechain_public_keys.at(sidechain_type::bitcoin)); - } + if (son_sets_equal) { + auto active_sons = gpo.active_sons; + vector son_pubkeys_bitcoin; + for (const son_info &si : active_sons) { + son_pubkeys_bitcoin.push_back(si.sidechain_public_keys.at(sidechain_type::bitcoin)); + } - string reply_str = create_primary_wallet_address(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()) { - std::stringstream res; - boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); - new_pw_address = active_pw_pt.get("result.address"); + 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()) { + std::stringstream res; + boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); + new_pw_address = active_pw_pt.get("result.address"); - address_ok = (op_obj_idx_0.get().address == res.str()); - } - } + address_ok = (op_obj_idx_0.get().address == res.str()); + } + } - 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; + 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()) { + 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 = ""; + 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(*swo, new_pw_address); - } - } + 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(*swo, new_pw_address); + } + } - transaction_ok = (op_tx_str == tx_str); - } - } else { - transaction_ok = true; - } - } + transaction_ok = (op_tx_str == tx_str); + } +} else { + transaction_ok = true; +} +} - should_approve = address_ok && - transaction_ok; - break; - } +should_approve = address_ok && +transaction_ok; +break; +} - case chain::operation::tag::value: { - bool process_ok = false; - bool transaction_ok = false; - son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; - const auto &idx = database.get_index_type().indices().get(); - const auto swdo = idx.find(swdo_id); - if (swdo != idx.end()) { +case chain::operation::tag::value: { + bool process_ok = false; + bool transaction_ok = false; + son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get().son_wallet_deposit_id; + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(swdo_id); + if (swdo != idx.end()) { - std::string swdo_txid = swdo->sidechain_transaction_id; - std::string swdo_address = swdo->sidechain_from; - uint64_t swdo_amount = swdo->sidechain_amount.value; - uint64_t swdo_vout = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1)); + std::string swdo_txid = swdo->sidechain_transaction_id; + std::string swdo_address = swdo->sidechain_from; + uint64_t swdo_amount = swdo->sidechain_amount.value; + uint64_t swdo_vout = std::stoll(swdo->sidechain_uid.substr(swdo->sidechain_uid.find_last_of("-") + 1)); - std::string tx_str = eth_client->getrawtransaction(swdo_txid, true); - std::stringstream tx_ss(tx_str); - boost::property_tree::ptree tx_json; - boost::property_tree::read_json(tx_ss, tx_json); + std::string tx_str = eth_client->getrawtransaction(swdo_txid, true); + std::stringstream tx_ss(tx_str); + boost::property_tree::ptree tx_json; + boost::property_tree::read_json(tx_ss, tx_json); - if (tx_json.count("error") && tx_json.get_child("error").empty()) { + if (tx_json.count("error") && tx_json.get_child("error").empty()) { - std::string tx_txid = tx_json.get("result.txid"); - uint32_t tx_confirmations = tx_json.get("result.confirmations"); - std::string tx_address = ""; - uint64_t tx_amount = -1; - uint64_t tx_vout = -1; + std::string tx_txid = tx_json.get("result.txid"); + uint32_t tx_confirmations = tx_json.get("result.confirmations"); + std::string tx_address = ""; + uint64_t tx_amount = -1; + uint64_t tx_vout = -1; - for (auto &input : tx_json.get_child("result.vout")) { - std::string tx_vout_s = input.second.get("n"); - tx_vout = std::stoll(tx_vout_s); - if (tx_vout == swdo_vout) { - if (bitcoin_major_version > 21) { - std::string address = input.second.get("scriptPubKey.address"); - if (address == swdo_address) { - tx_address = address; - } - } else { - for (auto &address : input.second.get_child("scriptPubKey.addresses")) { - if (address.second.data() == swdo_address) { - tx_address = address.second.data(); - break; - } - } - } - std::string tx_amount_s = input.second.get("value"); - tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); - tx_amount = std::stoll(tx_amount_s); - break; - } - } + for (auto &input : tx_json.get_child("result.vout")) { + std::string tx_vout_s = input.second.get("n"); + tx_vout = std::stoll(tx_vout_s); + if (tx_vout == swdo_vout) { + if (bitcoin_major_version > 21) { + std::string address = input.second.get("scriptPubKey.address"); + if (address == swdo_address) { + tx_address = address; + } + } else { + for (auto &address : input.second.get_child("scriptPubKey.addresses")) { + if (address.second.data() == swdo_address) { + tx_address = address.second.data(); + break; + } + } + } + std::string tx_amount_s = input.second.get("value"); + tx_amount_s.erase(std::remove(tx_amount_s.begin(), tx_amount_s.end(), '.'), tx_amount_s.end()); + tx_amount = std::stoll(tx_amount_s); + break; + } + } - process_ok = (swdo_txid == tx_txid) && - (swdo_address == tx_address) && - (swdo_amount == tx_amount) && - (swdo_vout == tx_vout) && - (gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations); - } + process_ok = (swdo_txid == tx_txid) && + (swdo_address == tx_address) && + (swdo_amount == tx_amount) && + (swdo_vout == tx_vout) && + (gpo.parameters.son_bitcoin_min_tx_confirmations() <= tx_confirmations); + } - object_id_type object_id = op_obj_idx_1.get().object_id; - std::string op_tx_str = op_obj_idx_1.get().transaction; + 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()) { + 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 = ""; + std::string tx_str = ""; - if (object_id.is()) { - const auto &idx = database.get_index_type().indices().get(); - const auto swdo = idx.find(object_id); - if (swdo != idx.end()) { - tx_str = create_deposit_transaction(*swdo); - } - } + if (object_id.is()) { + const auto &idx = database.get_index_type().indices().get(); + const auto swdo = idx.find(object_id); + if (swdo != idx.end()) { + tx_str = create_deposit_transaction(*swdo); + } + } - transaction_ok = (op_tx_str == tx_str); - } - } + transaction_ok = (op_tx_str == tx_str); + } + } - should_approve = process_ok && - transaction_ok; - break; - } + should_approve = process_ok && + transaction_ok; + break; + } - case chain::operation::tag::value: { - bool process_ok = false; - bool transaction_ok = false; - son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get().son_wallet_withdraw_id; - const auto &idx = database.get_index_type().indices().get(); - const auto swwo = idx.find(swwo_id); - if (swwo != idx.end()) { +case chain::operation::tag::value: { + bool process_ok = false; + bool transaction_ok = false; + son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get().son_wallet_withdraw_id; + 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); + 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(); + 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); + 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; - } - } + 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; + 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()) { + 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 = ""; + 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); - } - } + 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); - } - } + transaction_ok = (op_tx_str == tx_str); + } + } - should_approve = process_ok && - transaction_ok; - break; - } + should_approve = process_ok && + transaction_ok; + break; + } - case chain::operation::tag::value: { - using namespace bitcoin; - should_approve = true; - son_id_type signer = op_obj_idx_0.get().signer; - std::string signature = op_obj_idx_0.get().signature; - sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get().sidechain_transaction_id; - std::vector in_amounts; - std::string tx_hex; - std::string redeem_script; - const auto &st_idx = database.get_index_type().indices().get(); - const auto sto = st_idx.find(sidechain_transaction_id); - if (sto == st_idx.end()) { - should_approve = false; - break; - } +case chain::operation::tag::value: { + using namespace bitcoin; + should_approve = true; + son_id_type signer = op_obj_idx_0.get().signer; + std::string signature = op_obj_idx_0.get().signature; + sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get().sidechain_transaction_id; + std::vector in_amounts; + std::string tx_hex; + std::string redeem_script; + const auto &st_idx = database.get_index_type().indices().get(); + const auto sto = st_idx.find(sidechain_transaction_id); + if (sto == st_idx.end()) { + should_approve = false; + break; + } - const auto &s_idx = database.get_index_type().indices().get(); - const auto son = s_idx.find(signer); - if (son == s_idx.end()) { - should_approve = false; - break; - } + const auto &s_idx = database.get_index_type().indices().get(); + const auto son = s_idx.find(signer); + if (son == s_idx.end()) { + should_approve = false; + break; + } - read_transaction_data(sto->transaction, tx_hex, in_amounts, redeem_script); - bitcoin_transaction tx = unpack(parse_hex(tx_hex)); - bitcoin::bytes pubkey = parse_hex(son->sidechain_public_keys.at(sidechain_type::bitcoin)); - vector sigs = read_byte_arrays_from_string(signature); - for (size_t i = 0; i < tx.vin.size(); i++) { - const auto &sighash_str = get_signature_hash(tx, parse_hex(redeem_script), static_cast(in_amounts[i]), i, 1, true).str(); - const bitcoin::bytes &sighash_hex = parse_hex(sighash_str); - should_approve = should_approve && verify_sig(sigs[i], pubkey, sighash_hex, btc_context()); - } - break; - } + read_transaction_data(sto->transaction, tx_hex, in_amounts, redeem_script); + bitcoin_transaction tx = unpack(parse_hex(tx_hex)); + bitcoin::bytes pubkey = parse_hex(son->sidechain_public_keys.at(sidechain_type::bitcoin)); + vector sigs = read_byte_arrays_from_string(signature); + for (size_t i = 0; i < tx.vin.size(); i++) { + const auto &sighash_str = get_signature_hash(tx, parse_hex(redeem_script), static_cast(in_amounts[i]), i, 1, true).str(); + const bitcoin::bytes &sighash_hex = parse_hex(sighash_str); + should_approve = should_approve && verify_sig(sigs[i], pubkey, sighash_hex, btc_context()); + } + break; + } - case chain::operation::tag::value: { - should_approve = true; - break; - } +case chain::operation::tag::value: { + should_approve = true; + break; + } - default: - should_approve = false; - elog("=================================================="); - elog("Proposal not considered for approval ${po}", ("po", po)); - elog("=================================================="); - } +default: +should_approve = false; +elog("=================================================="); +elog("Proposal not considered for approval ${po}", ("po", po)); +elog("=================================================="); +} - return should_approve; - */ +return should_approve; +*/ - return true; +return true; } void sidechain_net_handler_eth::process_primary_wallet() { - ilog("### process_primary_wallet:"); - - const auto &swi = database.get_index_type().indices().get(); - const auto &active_sw = swi.rbegin(); - if (active_sw != swi.rend()) { + ilog("### process_primary_wallet:"); - if ((active_sw->addresses.find(sidechain_type::ethereum) == active_sw->addresses.end()) || - (active_sw->addresses.at(sidechain_type::ethereum).empty())) { + const auto &swi = database.get_index_type().indices().get(); + const auto &active_sw = swi.rbegin(); + if (active_sw != swi.rend()) { - if (proposal_exists(chain::operation::tag::value, active_sw->id)) { - return; - } + if ((active_sw->addresses.find(sidechain_type::ethereum) == active_sw->addresses.end()) || + (active_sw->addresses.at(sidechain_type::ethereum).empty())) { - const chain::global_property_object &gpo = database.get_global_properties(); + if (proposal_exists(chain::operation::tag::value, active_sw->id)) { + return; + } - auto active_sons = gpo.active_sons; - string reply_str = create_primary_wallet_address(active_sons); + const chain::global_property_object &gpo = database.get_global_properties(); - std::stringstream active_pw_ss(reply_str); + auto active_sons = gpo.active_sons; + string reply_str = create_primary_wallet_address(active_sons); - ilog("### process_primary_wallet: ${reply}", ("reply", reply_str)); + 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; - } + ilog("### process_primary_wallet: ${reply}", ("reply", reply_str)); - 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); + 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; + } - std::stringstream res; - boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); + 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 = res.str(); + std::stringstream res; + boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); - proposal_op.proposed_ops.emplace_back(swu_op); + 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(); - 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); - } - } + proposal_op.proposed_ops.emplace_back(swu_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 &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; + } + } + } + } } void sidechain_net_handler_eth::process_sidechain_addresses() { -/* - const chain::global_property_object &gpo = database.get_global_properties(); - std::vector> pubkeys; - for (auto &son : gpo.active_sons) { - std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::ethereum); - auto pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str))); - pubkeys.push_back(std::make_pair(pubkey, son.weight)); - } + /* + const chain::global_property_object &gpo = database.get_global_properties(); + std::vector> pubkeys; + for (auto &son : gpo.active_sons) { + std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::ethereum); + auto pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str))); + pubkeys.push_back(std::make_pair(pubkey, son.weight)); + } - const auto &sidechain_addresses_idx = database.get_index_type(); - const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get(); - const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain); - std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second, - [&](const sidechain_address_object &sao) { - bool retval = true; - try { - if (sao.expires == time_point_sec::maximum()) { - auto usr_pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(sao.deposit_public_key))); + const auto &sidechain_addresses_idx = database.get_index_type(); + const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get(); + const auto &sidechain_addresses_by_sidechain_range = sidechain_addresses_by_sidechain_idx.equal_range(sidechain); + std::for_each(sidechain_addresses_by_sidechain_range.first, sidechain_addresses_by_sidechain_range.second, + [&](const sidechain_address_object &sao) { + bool retval = true; + try { + if (sao.expires == time_point_sec::maximum()) { + auto usr_pubkey = fc::ecc::public_key(create_public_key_data(parse_hex(sao.deposit_public_key))); - btc_one_or_weighted_multisig_address addr(usr_pubkey, pubkeys, network_type); - std::string address_data = "{ \"redeemScript\": \"" + fc::to_hex(addr.get_redeem_script()) + - "\", \"witnessScript\": \"" + fc::to_hex(addr.get_witness_script()) + "\" }"; + btc_one_or_weighted_multisig_address addr(usr_pubkey, pubkeys, network_type); + std::string address_data = "{ \"redeemScript\": \"" + fc::to_hex(addr.get_redeem_script()) + + "\", \"witnessScript\": \"" + fc::to_hex(addr.get_witness_script()) + "\" }"; - if (addr.get_address() != sao.deposit_address) { - sidechain_address_update_operation op; - op.payer = plugin.get_current_son_object().son_account; - op.sidechain_address_id = sao.id; - op.sidechain_address_account = sao.sidechain_address_account; - op.sidechain = sao.sidechain; - op.deposit_public_key = sao.deposit_public_key; - op.deposit_address = addr.get_address(); - op.deposit_address_data = address_data; - op.withdraw_public_key = sao.withdraw_public_key; - op.withdraw_address = sao.withdraw_address; + if (addr.get_address() != sao.deposit_address) { + sidechain_address_update_operation op; + op.payer = plugin.get_current_son_object().son_account; + op.sidechain_address_id = sao.id; + op.sidechain_address_account = sao.sidechain_address_account; + op.sidechain = sao.sidechain; + op.deposit_public_key = sao.deposit_public_key; + op.deposit_address = addr.get_address(); + op.deposit_address_data = address_data; + op.withdraw_public_key = sao.withdraw_public_key; + op.withdraw_address = sao.withdraw_address; - signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), 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)); - retval = true; - } catch (fc::exception &e) { - elog("Sending transaction for sidechain address update operation failed with exception ${e}", ("e", e.what())); - retval = false; - } - } - } - } catch (fc::exception &e) { - retval = false; - } - return retval; - }); -*/ + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), 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)); + retval = true; + } catch (fc::exception &e) { + elog("Sending transaction for sidechain address update operation failed with exception ${e}", ("e", e.what())); + retval = false; + } + } + } + } catch (fc::exception &e) { + retval = false; + } + return retval; + }); + */ } bool sidechain_net_handler_eth::process_deposit(const son_wallet_deposit_object &swdo) { - ilog("### process_deposit:"); + ilog("### process_deposit:"); - if (proposal_exists(chain::operation::tag::value, swdo.id)) { - return false; - } + if (proposal_exists(chain::operation::tag::value, swdo.id)) { + return false; + } - std::string tx_str = create_deposit_transaction(swdo); + std::string tx_str = create_deposit_transaction(swdo); - if (!tx_str.empty()) { - const chain::global_property_object &gpo = database.get_global_properties(); + if (!tx_str.empty()) { + const chain::global_property_object &gpo = database.get_global_properties(); - proposal_create_operation proposal_op; - proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; - uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; - proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; + uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; + proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); - son_wallet_deposit_process_operation swdp_op; - swdp_op.payer = gpo.parameters.son_account(); - swdp_op.son_wallet_deposit_id = swdo.id; - proposal_op.proposed_ops.emplace_back(swdp_op); + son_wallet_deposit_process_operation swdp_op; + swdp_op.payer = gpo.parameters.son_account(); + swdp_op.son_wallet_deposit_id = swdo.id; + proposal_op.proposed_ops.emplace_back(swdp_op); - sidechain_transaction_create_operation stc_op; - stc_op.payer = gpo.parameters.son_account(); - stc_op.object_id = swdo.id; - stc_op.sidechain = sidechain; - stc_op.transaction = tx_str; - stc_op.signers = gpo.active_sons; - proposal_op.proposed_ops.emplace_back(stc_op); + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = swdo.id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + proposal_op.proposed_ops.emplace_back(stc_op); - signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); - try { - trx.validate(); - database.push_transaction(trx, database::validation_steps::skip_block_size_check); - if (plugin.app().p2p_node()) - plugin.app().p2p_node()->broadcast(net::trx_message(trx)); - return true; - } catch (fc::exception &e) { - elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); - return false; - } - } - return false; + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return true; + } catch (fc::exception &e) { + elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + return false; + } + } + return false; } bool sidechain_net_handler_eth::process_withdrawal(const son_wallet_withdraw_object &swwo) { - ilog("### process_withdrawal:"); + ilog("### process_withdrawal:"); - if (proposal_exists(chain::operation::tag::value, swwo.id)) { - return false; - } + if (proposal_exists(chain::operation::tag::value, swwo.id)) { + return false; + } - std::string tx_str = create_withdrawal_transaction(swwo); + std::string tx_str = create_withdrawal_transaction(swwo); - if (!tx_str.empty()) { - const chain::global_property_object &gpo = database.get_global_properties(); + if (!tx_str.empty()) { + const chain::global_property_object &gpo = database.get_global_properties(); - proposal_create_operation proposal_op; - proposal_op.fee_paying_account = plugin.get_current_son_object().son_account; - uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3; - proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime); + 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_withdraw_process_operation swwp_op; - swwp_op.payer = gpo.parameters.son_account(); - swwp_op.son_wallet_withdraw_id = swwo.id; - proposal_op.proposed_ops.emplace_back(swwp_op); + son_wallet_withdraw_process_operation swwp_op; + swwp_op.payer = gpo.parameters.son_account(); + swwp_op.son_wallet_withdraw_id = swwo.id; + proposal_op.proposed_ops.emplace_back(swwp_op); - sidechain_transaction_create_operation stc_op; - stc_op.payer = gpo.parameters.son_account(); - stc_op.object_id = swwo.id; - stc_op.sidechain = sidechain; - stc_op.transaction = tx_str; - stc_op.signers = gpo.active_sons; - proposal_op.proposed_ops.emplace_back(stc_op); + sidechain_transaction_create_operation stc_op; + stc_op.payer = gpo.parameters.son_account(); + stc_op.object_id = swwo.id; + stc_op.sidechain = sidechain; + stc_op.transaction = tx_str; + stc_op.signers = gpo.active_sons; + proposal_op.proposed_ops.emplace_back(stc_op); - signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); - try { - trx.validate(); - database.push_transaction(trx, database::validation_steps::skip_block_size_check); - if (plugin.app().p2p_node()) - plugin.app().p2p_node()->broadcast(net::trx_message(trx)); - return true; - } catch (fc::exception &e) { - elog("Sending proposal for withdraw sidechain transaction create operation failed with exception ${e}", ("e", e.what())); - return false; - } - } - return false; + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + try { + trx.validate(); + database.push_transaction(trx, database::validation_steps::skip_block_size_check); + if (plugin.app().p2p_node()) + plugin.app().p2p_node()->broadcast(net::trx_message(trx)); + return true; + } catch (fc::exception &e) { + elog("Sending proposal for withdraw sidechain transaction create operation failed with exception ${e}", ("e", e.what())); + return false; + } + } + return false; } std::string sidechain_net_handler_eth::process_sidechain_transaction(const sidechain_transaction_object &sto) { - ilog("### process_sidechain_transaction: "); - return sign_transaction(sto); + ilog("### process_sidechain_transaction: "); + return sign_transaction(sto); } std::string sidechain_net_handler_eth::send_sidechain_transaction(const sidechain_transaction_object &sto) { - ilog("### send_sidechain_transaction: "); - return send_transaction(sto); + ilog("### send_sidechain_transaction: "); + return send_transaction(sto); } bool sidechain_net_handler_eth::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) { - return false; + return false; } std::vector sidechain_net_handler_eth::parse_hex(const std::string &str) { - std::vector vec(str.size() / 2); - fc::from_hex(str, vec.data(), vec.size()); - return vec; + std::vector vec(str.size() / 2); + fc::from_hex(str, vec.data(), vec.size()); + return vec; } std::string sidechain_net_handler_eth::create_primary_wallet_address(const std::vector &son_pubkeys) { - std::stringstream ss; + std::stringstream ss; - ss << "{\"result\": {\"address\": \"" << eth_client->safe_account_addr << "\"" << "}, "; - ss << "\"onwers\": ["; - for (auto &owner : eth_client->owners){ - ss << "\"" << owner << "\","; - } - ss.seekp(-1, std::ios_base::end); - ss << "], keys: ["; + ss << "{\"result\": {\"address\": \"" << eth_client->safe_account_addr << "\"" << "}, "; + ss << "\"onwers\": ["; + for (auto &owner : eth_client->owners){ + ss << "\"" << owner << "\","; + } + ss.seekp(-1, std::ios_base::end); + ss << "], keys: ["; - for (auto &son : son_pubkeys) { - std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::ethereum); - ss << "\"" << pub_key_str << "\","; - } - ss.seekp(-1, std::ios_base::end); - ss << "], "; + for (auto &son : son_pubkeys) { + std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::ethereum); + ss << "\"" << pub_key_str << "\","; + } + ss.seekp(-1, std::ios_base::end); + ss << "], "; - ss << "\"error\":null}"; + ss << "\"error\":null}"; - std::string res = ss.str(); - return res; + std::string res = ss.str(); + return res; } std::string sidechain_net_handler_eth::create_primary_wallet_transaction(const son_wallet_object &prev_swo, std::string new_sw_address) { - return "";//create_transaction(inputs, outputs, prev_redeem_script); + return "";//create_transaction(inputs, outputs, prev_redeem_script); } std::string sidechain_net_handler_eth::create_deposit_transaction(const son_wallet_deposit_object &swdo) { - return "";//create_transaction(inputs, outputs, redeem_script); + return "";//create_transaction(inputs, outputs, redeem_script); } std::string sidechain_net_handler_eth::create_withdrawal_transaction(const son_wallet_withdraw_object &swwo) { - return "";//create_transaction(inputs, outputs, redeem_script); + return "";//create_transaction(inputs, outputs, redeem_script); } std::string sidechain_net_handler_eth::create_transaction() { - std::string tx_raw;// = write_transaction_data(hex_tx, in_amounts, redeem_script); - return tx_raw; + std::string tx_raw;// = write_transaction_data(hex_tx, in_amounts, redeem_script); + return tx_raw; } std::string sidechain_net_handler_eth::sign_transaction(const sidechain_transaction_object &sto) { - ilog("### sign_transaction: "); + ilog("### sign_transaction: "); - std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); - ethereum::signed_transaction htrx; - fc::raw::unpack(ss_trx, htrx, 1000); + std::stringstream ss_trx(boost::algorithm::unhex(sto.transaction)); + ethereum::signed_transaction htrx; + fc::raw::unpack(ss_trx, htrx, 1000); - std::string chain_id_str = eth_client->chain_id;//eth_rpc_client->get_chain_id(); - const ethereum::chain_id_type chain_id(chain_id_str); + std::string chain_id_str = eth_client->chain_id;//eth_rpc_client->get_chain_id(); + const ethereum::chain_id_type chain_id(chain_id_str); - fc::optional privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))); - signature_type st = htrx.sign(*privkey, chain_id); + fc::optional privkey = graphene::utilities::wif_to_key(get_private_key(plugin.get_current_son_object().sidechain_public_keys.at(sidechain))); + signature_type st = htrx.sign(*privkey, chain_id); - std::stringstream ss_st; - fc::raw::pack(ss_st, st, 1000); - std::string st_str = boost::algorithm::hex(ss_st.str()); - return st_str; + std::stringstream ss_st; + fc::raw::pack(ss_st, st, 1000); + std::string st_str = boost::algorithm::hex(ss_st.str()); + return st_str; } std::string sidechain_net_handler_eth::send_transaction(const sidechain_transaction_object &sto) { - std::string res;// = eth_client->sendrawtransaction(final_tx_hex); + std::string res;// = eth_client->sendrawtransaction(final_tx_hex); - return res; + return res; } void sidechain_net_handler_eth::handle_event(const std::string &event_data) { } std::vector sidechain_net_handler_eth::extract_info_from_block(const std::string &_block) { - std::stringstream ss(_block); - boost::property_tree::ptree block; - boost::property_tree::read_json(ss, block); + std::stringstream ss(_block); + boost::property_tree::ptree block; + boost::property_tree::read_json(ss, block); - std::vector result; + std::vector result; - return result; + return result; } void sidechain_net_handler_eth::on_changed_objects(const vector &ids, const flat_set &accounts) { - ilog("### on_changed_objects: "); + ilog("### on_changed_objects: "); - fc::time_point now = fc::time_point::now(); - int64_t time_to_next_changed_objects_processing = 5000; + fc::time_point now = fc::time_point::now(); + int64_t time_to_next_changed_objects_processing = 5000; - fc::time_point next_wakeup(now + fc::microseconds(time_to_next_changed_objects_processing)); + fc::time_point next_wakeup(now + fc::microseconds(time_to_next_changed_objects_processing)); - on_changed_objects_task = fc::schedule([this, ids, accounts] { - on_changed_objects_cb(ids, accounts); - }, - next_wakeup, "SON Processing"); + on_changed_objects_task = fc::schedule([this, ids, accounts] { + on_changed_objects_cb(ids, accounts); + }, + next_wakeup, "SON Processing"); } void sidechain_net_handler_eth::on_changed_objects_cb(const vector &ids, const flat_set &accounts) { } fc::ecc::public_key_data sidechain_net_handler_eth::create_public_key_data(const std::vector &public_key) { - FC_ASSERT(public_key.size() == 33); - fc::ecc::public_key_data key; - for (size_t i = 0; i < 33; i++) { - key.at(i) = public_key[i]; - } - return key; + FC_ASSERT(public_key.size() == 33); + fc::ecc::public_key_data key; + for (size_t i = 0; i < 33; i++) { + key.at(i) = public_key[i]; + } + return key; } // =============================================================================