remove hardcodes, implementation build_transaction safe_transaction_encoder

This commit is contained in:
Pavel Baykov 2022-06-15 09:16:55 -03:00
parent 647a5369fc
commit 6e213fcfad
2 changed files with 1139 additions and 1097 deletions

View file

@ -21,19 +21,19 @@
namespace graphene { namespace peerplays_sidechain { namespace graphene { namespace peerplays_sidechain {
typedef websocketpp::client<websocketpp::config::asio_client> client; typedef websocketpp::client<websocketpp::config::asio_client> client;
using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2; using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind; using websocketpp::lib::bind;
// pull out the type of messages sent by our config // pull out the type of messages sent by our config
typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr; typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr;
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr; typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
typedef client::connection_ptr connection_ptr; typedef client::connection_ptr connection_ptr;
class eth_rpc_client { class eth_rpc_client {
public: public:
typedef eth_rpc_client type; typedef eth_rpc_client type;
enum req_t { enum req_t {
@ -123,9 +123,16 @@ public:
std::string chain_id;//256 bit value std::string chain_id;//256 bit value
std::vector<std::string> owners; std::vector<std::string> owners;
std::string safe_account_addr; std::string safe_account_addr;
private: private:
class ethereum_function_call_encoder { class ethereum_function_call_encoder {
public: public:
enum operation_t {
OPERATION_CALL,
OPERATION_DELEGATE_CALL
};
static constexpr const char*const default_prev_addr = "0000000000000000000000000000000000000001";
std::string encode_function_signature(const std::string& function_signature); std::string encode_function_signature(const std::string& function_signature);
std::string encode_address(const std::string& addr); std::string encode_address(const std::string& addr);
std::string encode_uint256(const std::string& value); std::string encode_uint256(const std::string& value);
@ -133,7 +140,23 @@ private:
std::string encode_bytes(const std::string& values); std::string encode_bytes(const std::string& values);
}; };
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";
std::string create_safe_address(const std::vector<std::string> 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);
private:
ethereum_function_call_encoder m_ethereum_function_call_encoder; 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;
std::shared_ptr<fc::thread> _thread; std::shared_ptr<fc::thread> _thread;
std::string signature; std::string signature;
@ -158,12 +181,12 @@ private:
client m_endpoint; client m_endpoint;
websocketpp::connection_hdl m_hdl; websocketpp::connection_hdl m_hdl;
}; };
// ============================================================================= // =============================================================================
class sidechain_net_handler_eth : public sidechain_net_handler { class sidechain_net_handler_eth : public sidechain_net_handler {
public: public:
sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options); sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options);
virtual ~sidechain_net_handler_eth(); virtual ~sidechain_net_handler_eth();
@ -176,7 +199,7 @@ public:
std::string send_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); bool settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount);
private: private:
std::string url; std::string url;
uint32_t rpc_port; uint32_t rpc_port;
@ -209,6 +232,6 @@ private:
std::vector<char> parse_hex(const std::string &str); std::vector<char> parse_hex(const std::string &str);
fc::ecc::public_key_data create_public_key_data(const std::vector<char> &public_key); fc::ecc::public_key_data create_public_key_data(const std::vector<char> &public_key);
}; };
}} // namespace graphene::peerplays_sidechain }} // namespace graphene::peerplays_sidechain

View file

@ -28,8 +28,8 @@ extern "C" {
} }
namespace graphene { namespace peerplays_sidechain { namespace graphene { namespace peerplays_sidechain {
// ============================================================================= // =============================================================================
std::string eth_rpc_client::ethereum_function_call_encoder::encode_function_signature(const std::string& function_signature) { std::string eth_rpc_client::ethereum_function_call_encoder::encode_function_signature(const std::string& function_signature) {
sha3_context c; sha3_context c;
char *hash; char *hash;
@ -41,33 +41,63 @@ std::string eth_rpc_client::ethereum_function_call_encoder::encode_function_sign
output = output.substr(0,8); output = output.substr(0,8);
return output; return output;
}; };
std::string eth_rpc_client::ethereum_function_call_encoder::encode_address(const std::string& addr) { std::string eth_rpc_client::ethereum_function_call_encoder::encode_address(const std::string& addr) {
FC_ASSERT(20 == addr.length()); FC_ASSERT(40 == addr.length());
std::string output = str(boost::format("%012u") % 0) + addr; std::string output = str(boost::format("%024u") % 0) + addr;
return output; return output;
} }
std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint256(const std::string& value) { std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint256(const std::string& value) {
FC_ASSERT(value.length() <= 64); FC_ASSERT(value.length() <= 64);
std::string output = std::string(64 - value.length(), '0') + value; std::string output = std::string(64 - value.length(), '0') + value;
return output; return output;
} }
std::string eth_rpc_client::ethereum_function_call_encoder::encode_uint8(uint8_t value) { 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'); std::string output = str(boost::format("%02X") % value) + std::string(62, '0');
return output; return output;
} }
std::string eth_rpc_client::ethereum_function_call_encoder::encode_bytes(const std::string& values) { std::string eth_rpc_client::ethereum_function_call_encoder::encode_bytes(const std::string& values) {
size_t len = values.length(); size_t len = values.length();
std::string output = encode_uint256((boost::format("%x") % len).str()) + values + std::string(64 - len, '0'); std::string output = encode_uint256((boost::format("%x") % len).str()) + values + std::string(64 - len, '0');
return output; return output;
} }
std::string eth_rpc_client::safe_transaction_encoder::create_safe_address(const std::vector<std::string> 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);
//"<checksummed address>"
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);
//"<checksummed address>", 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);
//"<checksummed address>", 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<fc::thread>("eth_rpc_client")){ 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<fc::thread>("eth_rpc_client")){
geth_url = url; geth_url = url;
user = user_name; user = user_name;
this->password = password; this->password = password;
@ -89,9 +119,9 @@ eth_rpc_client::eth_rpc_client(const std::string &url, const std::string &user_n
m_endpoint.set_open_handler(bind(&type::on_open,this,::_1)); 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_close_handler(bind(&type::on_close,this,::_1));
m_endpoint.set_fail_handler(bind(&type::on_fail,this,::_1)); m_endpoint.set_fail_handler(bind(&type::on_fail,this,::_1));
} }
void eth_rpc_client::start() { void eth_rpc_client::start() {
ilog("### eth_rpc_client::start uri: ${uri}", ("uri", geth_url)); ilog("### eth_rpc_client::start uri: ${uri}", ("uri", geth_url));
auto future = _thread->async([this] auto future = _thread->async([this]
{ {
@ -109,16 +139,16 @@ void eth_rpc_client::start() {
// Start the ASIO io_service run loop // Start the ASIO io_service run loop
m_endpoint.run(); m_endpoint.run();
}); });
} }
void eth_rpc_client::stop() { void eth_rpc_client::stop() {
m_endpoint.close(m_hdl,websocketpp::close::status::normal,""); m_endpoint.close(m_hdl,websocketpp::close::status::normal,"");
} }
void eth_rpc_client::on_socket_init(websocketpp::connection_hdl) { void eth_rpc_client::on_socket_init(websocketpp::connection_hdl) {
} }
void eth_rpc_client::on_fail(websocketpp::connection_hdl hdl) { void eth_rpc_client::on_fail(websocketpp::connection_hdl hdl) {
client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl); client::connection_ptr con = m_endpoint.get_con_from_hdl(hdl);
elog("Ethereum websocket fail"); elog("Ethereum websocket fail");
@ -128,9 +158,9 @@ void eth_rpc_client::on_fail(websocketpp::connection_hdl hdl) {
elog("get_remote_close_code: ${close}", ("close", con->get_remote_close_code())); 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_remote_close_reason: ${close}", ("close", con->get_remote_close_reason()));
elog("get_ec().message(): ${ec}", ("ec", con->get_ec().message())); elog("get_ec().message(): ${ec}", ("ec", con->get_ec().message()));
} }
void eth_rpc_client::on_open(websocketpp::connection_hdl hdl) { void eth_rpc_client::on_open(websocketpp::connection_hdl hdl) {
std::string str = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":84}"; std::string str = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":84}";
ilog("on_open: ${str}", ("str", str)); ilog("on_open: ${str}", ("str", str));
m_endpoint.send(hdl, str.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(hdl, str.c_str(), websocketpp::frame::opcode::text);
@ -138,9 +168,9 @@ void eth_rpc_client::on_open(websocketpp::connection_hdl hdl) {
vector<std::string> owner_addresses; vector<std::string> owner_addresses;
std::string private_key = ""; std::string private_key = "";
createmultisig(5, owner_addresses, private_key); createmultisig(5, owner_addresses, private_key);
} }
void eth_rpc_client::on_message(websocketpp::connection_hdl hdl, message_ptr msg) { void eth_rpc_client::on_message(websocketpp::connection_hdl hdl, message_ptr msg) {
ilog("on_message: ${msg}", ("msg", msg->get_payload())); ilog("on_message: ${msg}", ("msg", msg->get_payload()));
@ -199,121 +229,116 @@ void eth_rpc_client::on_message(websocketpp::connection_hdl hdl, message_ptr msg
case REMOVE_OWNER: case REMOVE_OWNER:
break; break;
} }
} }
void eth_rpc_client::on_close(websocketpp::connection_hdl) { void eth_rpc_client::on_close(websocketpp::connection_hdl) {
ilog("Ethereum websocket close"); ilog("Ethereum websocket close");
} }
uint64_t eth_rpc_client::get_chain_id() { 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); 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())); ilog("get_chain_id: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_CHAIN_ID; m_requests[t_id] = req_t::ETH_CHAIN_ID;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_getTransactionReceipt(const std::string& tx_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); 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())); ilog("eth_getTransactionReceipt: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_GET_TRANSACTION_RECEIPT; m_requests[t_id] = req_t::ETH_GET_TRANSACTION_RECEIPT;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_call(const std::string& to, const std::string& data) { 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); 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())); ilog("eth_call: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_CALL; m_requests[t_id] = req_t::ETH_CALL;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_sendTransaction(const std::string& from, const std::string& to, const std::string& data) { 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); 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())); ilog("eth_sendTransaction: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_SEND_TRANSACTION; m_requests[t_id] = req_t::ETH_SEND_TRANSACTION;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_sendRawTransaction(const std::string& params) { 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); 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())); ilog("eth_sendRawTransaction: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_SEND_RAW_TRANSACTION; m_requests[t_id] = req_t::ETH_SEND_RAW_TRANSACTION;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_getCode(const std::string& addr) { 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); 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())); ilog("eth_getCode: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_GET_CODE; m_requests[t_id] = req_t::ETH_GET_CODE;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_getBalance(const std::string& addr) { 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); 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())); ilog("eth_getBalance: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_GET_BALANCE; m_requests[t_id] = req_t::ETH_GET_BALANCE;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_sign(const string& addr, const string& message) { 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); 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())); ilog("eth_sign: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_SIGN; m_requests[t_id] = req_t::ETH_SIGN;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::eth_coinbase() { uint64_t eth_rpc_client::eth_coinbase() {
std::string req = str(boost::format("{\"jsonrpc\":\"2.0\",\"method\":\"eth_coinbase\",\"params\":[],\"id\":%1%}") % t_id); 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())); ilog("eth_coinbase: ${req}", ("req", req.c_str()));
m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text); m_endpoint.send(m_hdl, req.c_str(), websocketpp::frame::opcode::text);
m_requests[t_id] = req_t::ETH_COINBASE; m_requests[t_id] = req_t::ETH_COINBASE;
return t_id++; return t_id++;
} }
uint64_t eth_rpc_client::get_list_owners(const std::string& safe_account) { uint64_t eth_rpc_client::get_list_owners(const std::string& safe_account) {
return eth_call(safe_account.c_str(), "0xa0e67e2b"); //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 ) { uint64_t eth_rpc_client::add_owner(const std::string& addr ) {
if (std::count(owners.begin(), owners.end(), addr)){ if (std::count(owners.begin(), owners.end(), addr)){
FC_THROW_EXCEPTION(fc::exception, "Owners allready have addr: ${addr}", ("addr", 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)"); 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); //addOwnerWithThreshold(address,uint256)
std::string address = safe_account_addr; std::string data_method_id = m_ethereum_function_call_encoder.encode_function_signature("addOwnerWithThreshold(address,uint256)");
std::string value = str(boost::format("%020u") % 0); FC_ASSERT("0d582f13" == data_method_id);
std::string data = "f8dc5dd9000000000000000000000000" + owners[0] + "000000000000000000000000" + addr + str(boost::format("%032u") % threshold); 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 operation = "0";
std::string safeTxGas = str(boost::format("%032u") % 0); 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);
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); uint64_t id = eth_sign(account_address, message);
m_requests[t_id] = req_t::ADD_OWNER; m_requests[t_id] = req_t::ADD_OWNER;
return 0; return 0;
} }
uint64_t eth_rpc_client::remove_owner(const std::string& addr, uint32_t threshold) { uint64_t eth_rpc_client::remove_owner(const std::string& addr, uint32_t threshold) {
if (!std::count(owners.begin(), owners.end(), addr)){ if (!std::count(owners.begin(), owners.end(), addr)){
FC_THROW_EXCEPTION(fc::exception, "Owners does not have addr: ${addr}", ("addr", addr)); FC_THROW_EXCEPTION(fc::exception, "Owners does not have addr: ${addr}", ("addr", addr));
} }
@ -322,147 +347,141 @@ uint64_t eth_rpc_client::remove_owner(const std::string& addr, uint32_t threshol
FC_THROW_EXCEPTION(fc::exception, "Owners size does not meet threshold: ${th}", ("th", threshold)); FC_THROW_EXCEPTION(fc::exception, "Owners size does not meet threshold: ${th}", ("th", threshold));
} }
//It's require to execute //removeOwner(address,address,uint256)
//execTransaction method of smart contract , using safe-account address std::string data_method_id = m_ethereum_function_call_encoder.encode_function_signature("removeOwner(address,address,uint256)");
//execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) FC_ASSERT("f8dc5dd9" == data_method_id);
std::string method_id = m_ethereum_function_call_encoder.encode_function_signature("execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"); 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());
FC_ASSERT("6a761202" == method_id);
std::string address = safe_account_addr; 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);
std::string value = str(boost::format("%032u") % 0);
std::string data = "f8dc5dd90000000000000000000000000000000000000000000000000000000000000001000000000000000000000000" + addr + str(boost::format("%032u") % threshold); uint64_t id = eth_sign(account_address, message);
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; m_requests[t_id] = req_t::REMOVE_OWNER;
return 0; return 0;
} }
std::string eth_rpc_client::addmultisigaddress(const uint32_t nrequired, const std::vector<std::string> public_keys) { std::string eth_rpc_client::addmultisigaddress(const uint32_t nrequired, const std::vector<std::string> public_keys) {
return ""; return "";
} }
std::string eth_rpc_client::combinepsbt(const vector<std::string> &psbts) { std::string eth_rpc_client::combinepsbt(const vector<std::string> &psbts) {
return ""; return "";
} }
uint64_t eth_rpc_client::createmultisig(const uint32_t nrequired, const std::vector<std::string> owner_addresses, const std::string &private_key) { uint64_t eth_rpc_client::createmultisig(const uint32_t nrequired, const std::vector<std::string> owner_addresses, const std::string &private_key) {
ilog("createmultisig: ${key}", ("key", private_key.c_str())); ilog("createmultisig: ${key}", ("key", private_key.c_str()));
//That's will create //That's will create
//0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12 //0x5FbBb31BE52608D2F52247E8400B7fCaA9E0bC12
//0x76ce31BD03f601c3fC13732deF921c5Bac282676 //0x76ce31BD03f601c3fC13732deF921c5Bac282676
//0x09EE460834498a4ee361beB819470061B7381B49 //0x09EE460834498a4ee361beB819470061B7381B49
//0x6AEFbd09209e1eE2e0a589d31e732F69B77713D2 //0x6AEFbd09209e1eE2e0a589d31e732F69B77713D2
//0x631e128b16f9aDCF1bB6385112B1519C917D77a7 //0x631e128b16f9aDCF1bB6385112B1519C917D77a7
//0xcD5C788e84220E8b8934Ea4F1dC6a12009bCc91D //0xcD5C788e84220E8b8934Ea4F1dC6a12009bCc91D
//0x3627C1B31525887CB9441130C831e35887650305 //0x3627C1B31525887CB9441130C831e35887650305
//0x03A13a989AF30C92AD7ABD1E6210308A6c96f373 //0x03A13a989AF30C92AD7ABD1E6210308A6c96f373
std::string from = "0xeE52b70e8D7AB5Fe661311D47e81228EAD6B06B9"; std::string from = "0xeE52b70e8D7AB5Fe661311D47e81228EAD6B06B9";
std::string to = "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2"; std::string to = "0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2";
std::string data = "0x1688f0b9000000000000000000000000d9db270c1b5e3bd161e8c8503c55ceabee70955200000000000000000000000000000000000000000000000000000000000000604fa262bd05cdef2e3d5261787ee66d9447a4036324990e04380339bec83b4c7a0000000000000000000000000000000000000000000000000000000000000264b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000f48f2b2d2a534e402487b3ee7c18c33aec0fe5e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC1200000000000000000000000076ce31BD03f601c3fC13732deF921c5Bac28267600000000000000000000000009EE460834498a4ee361beB819470061B7381B490000000000000000000000006AEFbd09209e1eE2e0a589d31e732F69B77713D2000000000000000000000000631e128b16f9aDCF1bB6385112B1519C917D77a7000000000000000000000000cD5C788e84220E8b8934Ea4F1dC6a12009bCc91D0000000000000000000000003627C1B31525887CB9441130C831e3588765030500000000000000000000000003A13a989AF30C92AD7ABD1E6210308A6c96f3730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; std::string data = "0x1688f0b9000000000000000000000000d9db270c1b5e3bd161e8c8503c55ceabee70955200000000000000000000000000000000000000000000000000000000000000604fa262bd05cdef2e3d5261787ee66d9447a4036324990e04380339bec83b4c7a0000000000000000000000000000000000000000000000000000000000000264b63e800d0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220000000000000000000000000f48f2b2d2a534e402487b3ee7c18c33aec0fe5e400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000005FbBb31BE52608D2F52247E8400B7fCaA9E0bC1200000000000000000000000076ce31BD03f601c3fC13732deF921c5Bac28267600000000000000000000000009EE460834498a4ee361beB819470061B7381B490000000000000000000000006AEFbd09209e1eE2e0a589d31e732F69B77713D2000000000000000000000000631e128b16f9aDCF1bB6385112B1519C917D77a7000000000000000000000000cD5C788e84220E8b8934Ea4F1dC6a12009bCc91D0000000000000000000000003627C1B31525887CB9441130C831e3588765030500000000000000000000000003A13a989AF30C92AD7ABD1E6210308A6c96f3730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
return eth_sendTransaction(from, to, data); return eth_sendTransaction(from, to, data);
} }
std::string eth_rpc_client::createpsbt() { std::string eth_rpc_client::createpsbt() {
} }
std::string eth_rpc_client::createrawtransaction() { std::string eth_rpc_client::createrawtransaction() {
return ""; return "";
} }
std::string eth_rpc_client::createwallet(const std::string &wallet_name) { std::string eth_rpc_client::createwallet(const std::string &wallet_name) {
return ""; return "";
} }
std::string eth_rpc_client::decodepsbt(std::string const &tx_psbt) { std::string eth_rpc_client::decodepsbt(std::string const &tx_psbt) {
return ""; return "";
} }
std::string eth_rpc_client::decoderawtransaction(std::string const &tx_hex) { std::string eth_rpc_client::decoderawtransaction(std::string const &tx_hex) {
return ""; return "";
} }
std::string eth_rpc_client::encryptwallet(const std::string &passphrase) { std::string eth_rpc_client::encryptwallet(const std::string &passphrase) {
return ""; return "";
} }
uint64_t eth_rpc_client::estimatesmartfee(uint16_t conf_target) { uint64_t eth_rpc_client::estimatesmartfee(uint16_t conf_target) {
return 20000; return 20000;
} }
std::string eth_rpc_client::finalizepsbt(std::string const &tx_psbt) { std::string eth_rpc_client::finalizepsbt(std::string const &tx_psbt) {
return ""; return "";
} }
std::string eth_rpc_client::getaddressinfo(const std::string &address) { std::string eth_rpc_client::getaddressinfo(const std::string &address) {
return ""; return "";
} }
std::string eth_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) { std::string eth_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) {
return ""; return "";
} }
std::string eth_rpc_client::getnetworkinfo() { std::string eth_rpc_client::getnetworkinfo() {
return ""; return "";
} }
std::string eth_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) { std::string eth_rpc_client::getrawtransaction(const std::string &txid, const bool verbose) {
return ""; return "";
} }
std::string eth_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) { std::string eth_rpc_client::gettransaction(const std::string &txid, const bool include_watch_only) {
return ""; return "";
} }
std::string eth_rpc_client::getblockchaininfo() { std::string eth_rpc_client::getblockchaininfo() {
return ""; return "";
} }
void eth_rpc_client::importaddress(const std::string &address_or_script, const std::string &label, const bool rescan, const bool p2sh) { void eth_rpc_client::importaddress(const std::string &address_or_script, const std::string &label, const bool rescan, const bool p2sh) {
return; return;
} }
void eth_rpc_client::importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan) { void eth_rpc_client::importmulti(const std::vector<multi_params> &address_or_script_array, const bool rescan) {
} }
std::string eth_rpc_client::loadwallet(const std::string &filename) { std::string eth_rpc_client::loadwallet(const std::string &filename) {
return ""; return "";
} }
std::string eth_rpc_client::sendrawtransaction(const std::string &tx_hex) { std::string eth_rpc_client::sendrawtransaction(const std::string &tx_hex) {
return ""; return "";
} }
std::string eth_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) { std::string eth_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) {
return ""; return "";
} }
std::string eth_rpc_client::unloadwallet(const std::string &filename) { std::string eth_rpc_client::unloadwallet(const std::string &filename) {
return ""; return "";
} }
std::string eth_rpc_client::walletlock() { std::string eth_rpc_client::walletlock() {
return ""; return "";
} }
std::string eth_rpc_client::walletprocesspsbt(std::string const &tx_psbt) { std::string eth_rpc_client::walletprocesspsbt(std::string const &tx_psbt) {
return ""; return "";
} }
bool eth_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) { bool eth_rpc_client::walletpassphrase(const std::string &passphrase, uint32_t timeout) {
return false; return false;
} }
// ============================================================================= // =============================================================================
sidechain_net_handler_eth::sidechain_net_handler_eth(peerplays_sidechain_plugin &_plugin, const boost::program_options::variables_map &options) : 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_net_handler(_plugin, options) {
sidechain = sidechain_type::ethereum; sidechain = sidechain_type::ethereum;
@ -473,7 +492,7 @@ sidechain_net_handler_eth::sidechain_net_handler_eth(peerplays_sidechain_plugin
url = options.at("ethereum-node-rpc-url").as<std::string>(); url = options.at("ethereum-node-rpc-url").as<std::string>();
eth_client = std::unique_ptr<eth_rpc_client>(new eth_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls)); eth_client = std::unique_ptr<eth_rpc_client>(new eth_rpc_client(url, rpc_user, rpc_password, debug_rpc_calls));
eth_client->start(); eth_client->start();
/* /*
if (!wallet.empty()) { if (!wallet.empty()) {
eth_client->loadwallet(wallet); eth_client->loadwallet(wallet);
} }
@ -485,7 +504,7 @@ sidechain_net_handler_eth::sidechain_net_handler_eth(peerplays_sidechain_plugin
database.changed_objects.connect([this](const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) { database.changed_objects.connect([this](const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
on_changed_objects(ids, accounts); on_changed_objects(ids, accounts);
}); });
*/ */
} }
sidechain_net_handler_eth::~sidechain_net_handler_eth() { sidechain_net_handler_eth::~sidechain_net_handler_eth() {
@ -503,7 +522,7 @@ sidechain_net_handler_eth::~sidechain_net_handler_eth() {
bool sidechain_net_handler_eth::process_proposal(const proposal_object &po) { 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())); ilog("Proposal to process: ${po}, SON id ${son_id}", ("po", po.id)("son_id", plugin.get_current_son_id()));
/* /*
bool should_approve = false; bool should_approve = false;
const chain::global_property_object &gpo = database.get_global_properties(); const chain::global_property_object &gpo = database.get_global_properties();
@ -588,17 +607,17 @@ bool sidechain_net_handler_eth::process_proposal(const proposal_object &po) {
transaction_ok = (op_tx_str == tx_str); transaction_ok = (op_tx_str == tx_str);
} }
} else { } else {
transaction_ok = true; transaction_ok = true;
} }
} }
should_approve = address_ok && should_approve = address_ok &&
transaction_ok; transaction_ok;
break; break;
} }
case chain::operation::tag<chain::son_wallet_deposit_process_operation>::value: { case chain::operation::tag<chain::son_wallet_deposit_process_operation>::value: {
bool process_ok = false; bool process_ok = false;
bool transaction_ok = false; bool transaction_ok = false;
son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get<son_wallet_deposit_process_operation>().son_wallet_deposit_id; son_wallet_deposit_id_type swdo_id = op_obj_idx_0.get<son_wallet_deposit_process_operation>().son_wallet_deposit_id;
@ -681,7 +700,7 @@ bool sidechain_net_handler_eth::process_proposal(const proposal_object &po) {
break; break;
} }
case chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value: { case chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value: {
bool process_ok = false; bool process_ok = false;
bool transaction_ok = false; bool transaction_ok = false;
son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get<son_wallet_withdraw_process_operation>().son_wallet_withdraw_id; son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get<son_wallet_withdraw_process_operation>().son_wallet_withdraw_id;
@ -736,7 +755,7 @@ bool sidechain_net_handler_eth::process_proposal(const proposal_object &po) {
break; break;
} }
case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: { case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: {
using namespace bitcoin; using namespace bitcoin;
should_approve = true; should_approve = true;
son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer; son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer;
@ -771,22 +790,22 @@ bool sidechain_net_handler_eth::process_proposal(const proposal_object &po) {
break; break;
} }
case chain::operation::tag<chain::sidechain_transaction_settle_operation>::value: { case chain::operation::tag<chain::sidechain_transaction_settle_operation>::value: {
should_approve = true; should_approve = true;
break; break;
} }
default: default:
should_approve = false; should_approve = false;
elog("=================================================="); elog("==================================================");
elog("Proposal not considered for approval ${po}", ("po", po)); elog("Proposal not considered for approval ${po}", ("po", po));
elog("=================================================="); elog("==================================================");
} }
return should_approve; return should_approve;
*/ */
return true; return true;
} }
void sidechain_net_handler_eth::process_primary_wallet() { void sidechain_net_handler_eth::process_primary_wallet() {
@ -867,7 +886,7 @@ void sidechain_net_handler_eth::process_primary_wallet() {
} }
void sidechain_net_handler_eth::process_sidechain_addresses() { void sidechain_net_handler_eth::process_sidechain_addresses() {
/* /*
const chain::global_property_object &gpo = database.get_global_properties(); const chain::global_property_object &gpo = database.get_global_properties();
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkeys; std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkeys;
for (auto &son : gpo.active_sons) { for (auto &son : gpo.active_sons) {
@ -920,7 +939,7 @@ void sidechain_net_handler_eth::process_sidechain_addresses() {
} }
return retval; return retval;
}); });
*/ */
} }
bool sidechain_net_handler_eth::process_deposit(const son_wallet_deposit_object &swdo) { bool sidechain_net_handler_eth::process_deposit(const son_wallet_deposit_object &swdo) {