sidechain_net_handler_eth, eth_rpc_client
This commit is contained in:
parent
3980512543
commit
bb976816af
5 changed files with 968 additions and 11 deletions
|
|
@ -6,6 +6,7 @@ add_library( peerplays_sidechain
|
|||
sidechain_net_manager.cpp
|
||||
sidechain_net_handler.cpp
|
||||
sidechain_net_handler_bitcoin.cpp
|
||||
sidechain_net_handler_eth.cpp
|
||||
sidechain_net_handler_hive.cpp
|
||||
sidechain_net_handler_peerplays.cpp
|
||||
bitcoin/bech32.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
#pragma once
|
||||
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <zmq_addon.hpp>
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <fc/network/http/connection.hpp>
|
||||
#include <graphene/peerplays_sidechain/bitcoin/bitcoin_address.hpp>
|
||||
|
||||
#include <fc/api.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/rpc/api_connection.hpp>
|
||||
#include <fc/rpc/websocket_api.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
class eth_rpc_client {
|
||||
public:
|
||||
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;
|
||||
};
|
||||
|
||||
public:
|
||||
eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls);
|
||||
|
||||
void connect();
|
||||
std::string get_chain_id();
|
||||
|
||||
std::string addmultisigaddress(const uint32_t nrequired, const std::vector<std::string> public_keys);
|
||||
std::string combinepsbt(const vector<std::string> &psbts);
|
||||
std::string createmultisig(const uint32_t nrequired, const std::vector<std::string> public_keys);
|
||||
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<multi_params> &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);
|
||||
|
||||
private:
|
||||
std::string geth_url;
|
||||
std::string ip;
|
||||
uint32_t rpc_port;
|
||||
std::string user;
|
||||
std::string password;
|
||||
std::string wallet;
|
||||
std::string wallet_password;
|
||||
bool debug_rpc_calls;
|
||||
|
||||
fc::http::header authorization;
|
||||
|
||||
fc::http::websocket_client client;
|
||||
std::shared_ptr<fc::rpc::websocket_api_connection> client_connection;
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
std::string url;
|
||||
uint32_t rpc_port;
|
||||
|
||||
std::string rpc_user;
|
||||
std::string rpc_password;
|
||||
std::string wallet;
|
||||
std::string wallet_password;
|
||||
|
||||
std::unique_ptr<eth_rpc_client> eth_client;
|
||||
|
||||
fc::future<void> on_changed_objects_task;
|
||||
bitcoin::bitcoin_address::network network_type;
|
||||
|
||||
std::mutex event_handler_mutex;
|
||||
typedef std::lock_guard<decltype(event_handler_mutex)> scoped_lock;
|
||||
|
||||
std::string create_primary_wallet_address(const std::vector<son_info> &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::string get_redeemscript_for_userdeposit(const std::string &user_address);
|
||||
std::vector<info_for_vin> extract_info_from_block(const std::string &_block);
|
||||
void on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||
void on_changed_objects_cb(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts);
|
||||
};
|
||||
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -157,6 +157,9 @@ void peerplays_sidechain_plugin_impl::plugin_set_program_options(
|
|||
cli.add_options()("bitcoin-private-key", bpo::value<vector<string>>()->composing()->multitoken()->DEFAULT_VALUE_VECTOR(std::make_pair("02d0f137e717fb3aab7aff99904001d49a0a636c5e1342f8927a4ba2eaee8e9772", "cVN31uC9sTEr392DLVUEjrtMgLA8Yb3fpYmTRj7bomTm6nn2ANPr")),
|
||||
"Tuple of [Bitcoin public key, Bitcoin private key] (may specify multiple times)");
|
||||
|
||||
cli.add_options()("ethereum-sidechain-enabled", bpo::value<bool>()->default_value(true), "Hive sidechain handler enabled");
|
||||
cli.add_options()("ethereum-node-rpc-url", bpo::value<string>()->default_value("ws://127.0.0.1:8546/"), "Ethereum node RPC WS URL [ws[s]://]host[:port]");
|
||||
|
||||
cli.add_options()("hive-sidechain-enabled", bpo::value<bool>()->default_value(false), "Hive sidechain handler enabled");
|
||||
cli.add_options()("hive-node-rpc-url", bpo::value<string>()->default_value("127.0.0.1:28090"), "Hive node RPC URL [http[s]://]host[:port]");
|
||||
cli.add_options()("hive-node-rpc-user", bpo::value<string>(), "Hive node RPC user");
|
||||
|
|
@ -217,13 +220,13 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt
|
|||
wlog("Haven't set up Bitcoin sidechain parameters");
|
||||
}
|
||||
|
||||
//sidechain_enabled_ethereum = options.at("ethereum-sidechain-enabled").as<bool>();
|
||||
//config_ready_ethereum = options.count("ethereum-node-ip") &&
|
||||
// options.count("ethereum-address") &&
|
||||
// options.count("ethereum-public-key") && options.count("ethereum-private-key");
|
||||
//if (!config_ready_ethereum) {
|
||||
// wlog("Haven't set up Ethereum sidechain parameters");
|
||||
//}
|
||||
sidechain_enabled_ethereum = options.at("ethereum-sidechain-enabled").as<bool>();
|
||||
config_ready_ethereum = options.count("ethereum-node-rpc-url");
|
||||
//options.count("ethereum-address") &&
|
||||
//options.count("ethereum-public-key") && options.count("ethereum-private-key");
|
||||
if (!config_ready_ethereum) {
|
||||
wlog("Haven't set up Ethereum sidechain parameters");
|
||||
}
|
||||
|
||||
sidechain_enabled_hive = options.at("hive-sidechain-enabled").as<bool>();
|
||||
config_ready_hive = options.count("hive-node-rpc-url") &&
|
||||
|
|
@ -269,10 +272,10 @@ void peerplays_sidechain_plugin_impl::plugin_startup() {
|
|||
ilog("Bitcoin sidechain handler running");
|
||||
}
|
||||
|
||||
//if (sidechain_enabled_ethereum && config_ready_ethereum) {
|
||||
// net_manager->create_handler(sidechain_type::ethereum, options);
|
||||
// ilog("Ethereum sidechain handler running");
|
||||
//}
|
||||
if (sidechain_enabled_ethereum && config_ready_ethereum) {
|
||||
net_manager->create_handler(sidechain_type::ethereum, options);
|
||||
ilog("Ethereum sidechain handler running");
|
||||
}
|
||||
|
||||
if (sidechain_enabled_hive && config_ready_hive) {
|
||||
net_manager->create_handler(sidechain_type::hive, options);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,807 @@
|
|||
#include <graphene/peerplays_sidechain/sidechain_net_handler_eth.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
#include <fc/crypto/base64.hpp>
|
||||
#include <fc/log/logger.hpp>
|
||||
#include <fc/network/ip.hpp>
|
||||
|
||||
#include <graphene/chain/account_object.hpp>
|
||||
#include <graphene/chain/protocol/son_wallet.hpp>
|
||||
#include <graphene/chain/sidechain_transaction_object.hpp>
|
||||
#include <graphene/chain/son_info.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/utilities/key_conversion.hpp>
|
||||
|
||||
namespace graphene { namespace peerplays_sidechain {
|
||||
|
||||
// =============================================================================
|
||||
|
||||
eth_rpc_client::eth_rpc_client(const std::string &url, const std::string &user_name, const std::string &password, bool debug_rpc_calls) {
|
||||
geth_url = url;
|
||||
user = user_name;
|
||||
this->password = password;
|
||||
this->debug_rpc_calls = debug_rpc_calls;
|
||||
|
||||
ilog("eth_rpc_client");
|
||||
ilog("### Geth URL: ${url}", ("url", url));
|
||||
}
|
||||
|
||||
void eth_rpc_client::connect() {
|
||||
client_connection = std::make_shared<fc::rpc::websocket_api_connection>(client.connect(geth_url), GRAPHENE_MAX_NESTED_OBJECTS);
|
||||
}
|
||||
|
||||
std::string eth_rpc_client::get_chain_id() {
|
||||
//std::string reply_str = database_api_get_version();
|
||||
return "";//retrieve_value_from_reply(reply_str, "chain_id");
|
||||
}
|
||||
|
||||
std::string eth_rpc_client::addmultisigaddress(const uint32_t nrequired, const std::vector<std::string> public_keys) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string eth_rpc_client::combinepsbt(const vector<std::string> &psbts) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string eth_rpc_client::createmultisig(const uint32_t nrequired, const std::vector<std::string> public_keys) {
|
||||
return "";
|
||||
}
|
||||
|
||||
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<multi_params> &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<bool>();
|
||||
}
|
||||
|
||||
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->connect();
|
||||
/*
|
||||
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<object_id_type> &ids, const flat_set<account_id_type> &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()));
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
int32_t op_idx_0 = -1;
|
||||
chain::operation op_obj_idx_0;
|
||||
|
||||
if (po.proposed_transaction.operations.size() >= 1) {
|
||||
op_idx_0 = po.proposed_transaction.operations[0].which();
|
||||
op_obj_idx_0 = po.proposed_transaction.operations[0];
|
||||
}
|
||||
|
||||
int32_t op_idx_1 = -1;
|
||||
chain::operation op_obj_idx_1;
|
||||
(void)op_idx_1;
|
||||
|
||||
if (po.proposed_transaction.operations.size() >= 2) {
|
||||
op_idx_1 = po.proposed_transaction.operations[1].which();
|
||||
op_obj_idx_1 = po.proposed_transaction.operations[1];
|
||||
}
|
||||
|
||||
switch (op_idx_0) {
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_update_operation>::value: {
|
||||
bool address_ok = false;
|
||||
bool transaction_ok = false;
|
||||
std::string new_pw_address = "";
|
||||
son_wallet_id_type swo_id = op_obj_idx_0.get<son_wallet_update_operation>().son_wallet_id;
|
||||
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
const auto swo = idx.find(swo_id);
|
||||
if (swo != idx.end()) {
|
||||
|
||||
auto active_sons = gpo.active_sons;
|
||||
vector<son_info> wallet_sons = swo->sons;
|
||||
|
||||
bool son_sets_equal = (active_sons.size() == wallet_sons.size());
|
||||
|
||||
if (son_sets_equal) {
|
||||
for (size_t i = 0; i < active_sons.size(); i++) {
|
||||
son_sets_equal = son_sets_equal && active_sons.at(i) == wallet_sons.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (son_sets_equal) {
|
||||
auto active_sons = gpo.active_sons;
|
||||
vector<string> 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);
|
||||
|
||||
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<std::string>("result.address");
|
||||
|
||||
address_ok = (op_obj_idx_0.get<son_wallet_update_operation>().address == res.str());
|
||||
}
|
||||
}
|
||||
|
||||
if (po.proposed_transaction.operations.size() >= 2) {
|
||||
object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
|
||||
std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
|
||||
|
||||
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
|
||||
const auto st = st_idx.find(object_id);
|
||||
if (st == st_idx.end()) {
|
||||
|
||||
std::string tx_str = "";
|
||||
|
||||
if (object_id.is<son_wallet_id_type>()) {
|
||||
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
const auto swo = idx.find(object_id);
|
||||
if (swo != idx.end()) {
|
||||
tx_str = create_primary_wallet_transaction(*swo, new_pw_address);
|
||||
}
|
||||
}
|
||||
|
||||
transaction_ok = (op_tx_str == tx_str);
|
||||
}
|
||||
} else {
|
||||
transaction_ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
should_approve = address_ok &&
|
||||
transaction_ok;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_deposit_process_operation>::value: {
|
||||
bool process_ok = false;
|
||||
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;
|
||||
const auto &idx = database.get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
|
||||
const auto swdo = idx.find(swdo_id);
|
||||
if (swdo != idx.end()) {
|
||||
|
||||
std::string swdo_txid = swdo->sidechain_transaction_id;
|
||||
std::string swdo_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);
|
||||
|
||||
if (tx_json.count("error") && tx_json.get_child("error").empty()) {
|
||||
|
||||
std::string tx_txid = tx_json.get<std::string>("result.txid");
|
||||
uint32_t tx_confirmations = tx_json.get<uint32_t>("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<std::string>("n");
|
||||
tx_vout = std::stoll(tx_vout_s);
|
||||
if (tx_vout == swdo_vout) {
|
||||
if (bitcoin_major_version > 21) {
|
||||
std::string address = input.second.get<std::string>("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<std::string>("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);
|
||||
}
|
||||
|
||||
object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
|
||||
std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
|
||||
|
||||
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
|
||||
const auto st = st_idx.find(object_id);
|
||||
if (st == st_idx.end()) {
|
||||
|
||||
std::string tx_str = "";
|
||||
|
||||
if (object_id.is<son_wallet_deposit_id_type>()) {
|
||||
const auto &idx = database.get_index_type<son_wallet_deposit_index>().indices().get<by_id>();
|
||||
const auto swdo = idx.find(object_id);
|
||||
if (swdo != idx.end()) {
|
||||
tx_str = create_deposit_transaction(*swdo);
|
||||
}
|
||||
}
|
||||
|
||||
transaction_ok = (op_tx_str == tx_str);
|
||||
}
|
||||
}
|
||||
|
||||
should_approve = process_ok &&
|
||||
transaction_ok;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value: {
|
||||
bool process_ok = false;
|
||||
bool transaction_ok = false;
|
||||
son_wallet_withdraw_id_type swwo_id = op_obj_idx_0.get<son_wallet_withdraw_process_operation>().son_wallet_withdraw_id;
|
||||
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
|
||||
const auto swwo = idx.find(swwo_id);
|
||||
if (swwo != idx.end()) {
|
||||
|
||||
uint32_t swwo_block_num = swwo->block_num;
|
||||
std::string swwo_peerplays_transaction_id = swwo->peerplays_transaction_id;
|
||||
uint32_t swwo_op_idx = std::stoll(swwo->peerplays_uid.substr(swwo->peerplays_uid.find_last_of("-") + 1));
|
||||
|
||||
const auto &block = database.fetch_block_by_number(swwo_block_num);
|
||||
|
||||
for (const auto &tx : block->transactions) {
|
||||
if (tx.id().str() == swwo_peerplays_transaction_id) {
|
||||
operation op = tx.operations[swwo_op_idx];
|
||||
transfer_operation t_op = op.get<transfer_operation>();
|
||||
|
||||
price asset_price = database.get<asset_object>(t_op.amount.asset_id).options.core_exchange_rate;
|
||||
asset peerplays_asset = asset(t_op.amount.amount * asset_price.base.amount / asset_price.quote.amount);
|
||||
|
||||
process_ok = (t_op.to == gpo.parameters.son_account()) &&
|
||||
(swwo->peerplays_from == t_op.from) &&
|
||||
(swwo->peerplays_asset == peerplays_asset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
object_id_type object_id = op_obj_idx_1.get<sidechain_transaction_create_operation>().object_id;
|
||||
std::string op_tx_str = op_obj_idx_1.get<sidechain_transaction_create_operation>().transaction;
|
||||
|
||||
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_object_id>();
|
||||
const auto st = st_idx.find(object_id);
|
||||
if (st == st_idx.end()) {
|
||||
|
||||
std::string tx_str = "";
|
||||
|
||||
if (object_id.is<son_wallet_withdraw_id_type>()) {
|
||||
const auto &idx = database.get_index_type<son_wallet_withdraw_index>().indices().get<by_id>();
|
||||
const auto swwo = idx.find(object_id);
|
||||
if (swwo != idx.end()) {
|
||||
tx_str = create_withdrawal_transaction(*swwo);
|
||||
}
|
||||
}
|
||||
|
||||
transaction_ok = (op_tx_str == tx_str);
|
||||
}
|
||||
}
|
||||
|
||||
should_approve = process_ok &&
|
||||
transaction_ok;
|
||||
break;
|
||||
}
|
||||
|
||||
case chain::operation::tag<chain::sidechain_transaction_sign_operation>::value: {
|
||||
using namespace bitcoin;
|
||||
should_approve = true;
|
||||
son_id_type signer = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signer;
|
||||
std::string signature = op_obj_idx_0.get<sidechain_transaction_sign_operation>().signature;
|
||||
sidechain_transaction_id_type sidechain_transaction_id = op_obj_idx_0.get<sidechain_transaction_sign_operation>().sidechain_transaction_id;
|
||||
std::vector<uint64_t> in_amounts;
|
||||
std::string tx_hex;
|
||||
std::string redeem_script;
|
||||
const auto &st_idx = database.get_index_type<sidechain_transaction_index>().indices().get<by_id>();
|
||||
const auto sto = st_idx.find(sidechain_transaction_id);
|
||||
if (sto == st_idx.end()) {
|
||||
should_approve = false;
|
||||
break;
|
||||
}
|
||||
|
||||
const auto &s_idx = database.get_index_type<son_index>().indices().get<by_id>();
|
||||
const auto son = s_idx.find(signer);
|
||||
if (son == s_idx.end()) {
|
||||
should_approve = false;
|
||||
break;
|
||||
}
|
||||
|
||||
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<bitcoin::bytes> 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<int64_t>(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<chain::sidechain_transaction_settle_operation>::value: {
|
||||
should_approve = true;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
should_approve = false;
|
||||
elog("==================================================");
|
||||
elog("Proposal not considered for approval ${po}", ("po", po));
|
||||
elog("==================================================");
|
||||
}
|
||||
|
||||
return should_approve;
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_eth::process_primary_wallet() {
|
||||
const auto &swi = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
const auto &active_sw = swi.rbegin();
|
||||
if (active_sw != swi.rend()) {
|
||||
|
||||
if ((active_sw->addresses.find(sidechain_type::bitcoin) == active_sw->addresses.end()) ||
|
||||
(active_sw->addresses.at(sidechain_type::bitcoin).empty())) {
|
||||
|
||||
if (proposal_exists(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
auto active_sons = gpo.active_sons;
|
||||
string reply_str = create_primary_wallet_address(active_sons);
|
||||
|
||||
std::stringstream active_pw_ss(reply_str);
|
||||
boost::property_tree::ptree active_pw_pt;
|
||||
boost::property_tree::read_json(active_pw_ss, active_pw_pt);
|
||||
if (active_pw_pt.count("error") && active_pw_pt.get_child("error").empty()) {
|
||||
if (!plugin.can_son_participate(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
std::stringstream res;
|
||||
boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result"));
|
||||
|
||||
son_wallet_update_operation swu_op;
|
||||
swu_op.payer = gpo.parameters.son_account();
|
||||
swu_op.son_wallet_id = active_sw->id;
|
||||
swu_op.sidechain = sidechain_type::bitcoin;
|
||||
swu_op.address = res.str();
|
||||
|
||||
proposal_op.proposed_ops.emplace_back(swu_op);
|
||||
|
||||
const auto &prev_sw = std::next(active_sw);
|
||||
if (prev_sw != swi.rend()) {
|
||||
std::string new_pw_address = active_pw_pt.get<std::string>("result.address");
|
||||
std::string tx_str = create_primary_wallet_transaction(*prev_sw, new_pw_address);
|
||||
if (!tx_str.empty()) {
|
||||
sidechain_transaction_create_operation stc_op;
|
||||
stc_op.payer = gpo.parameters.son_account();
|
||||
stc_op.object_id = prev_sw->id;
|
||||
stc_op.sidechain = sidechain;
|
||||
stc_op.transaction = tx_str;
|
||||
stc_op.signers = prev_sw->sons;
|
||||
proposal_op.proposed_ops.emplace_back(stc_op);
|
||||
}
|
||||
}
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
plugin.log_son_proposal_retry(chain::operation::tag<chain::son_wallet_update_operation>::value, active_sw->id);
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for son wallet update operation failed with exception ${e}", ("e", e.what()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sidechain_net_handler_eth::process_sidechain_addresses() {
|
||||
using namespace bitcoin;
|
||||
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkeys;
|
||||
for (auto &son : gpo.active_sons) {
|
||||
std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::bitcoin);
|
||||
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<sidechain_address_index>();
|
||||
const auto &sidechain_addresses_by_sidechain_idx = sidechain_addresses_idx.indices().get<by_sidechain>();
|
||||
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()) + "\" }";
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_eth::process_deposit(const son_wallet_deposit_object &swdo) {
|
||||
|
||||
if (proposal_exists(chain::operation::tag<chain::son_wallet_deposit_process_operation>::value, swdo.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tx_str = create_deposit_transaction(swdo);
|
||||
|
||||
if (!tx_str.empty()) {
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
son_wallet_deposit_process_operation swdp_op;
|
||||
swdp_op.payer = gpo.parameters.son_account();
|
||||
swdp_op.son_wallet_deposit_id = swdo.id;
|
||||
proposal_op.proposed_ops.emplace_back(swdp_op);
|
||||
|
||||
sidechain_transaction_create_operation stc_op;
|
||||
stc_op.payer = gpo.parameters.son_account();
|
||||
stc_op.object_id = swdo.id;
|
||||
stc_op.sidechain = sidechain;
|
||||
stc_op.transaction = tx_str;
|
||||
stc_op.signers = gpo.active_sons;
|
||||
proposal_op.proposed_ops.emplace_back(stc_op);
|
||||
|
||||
signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op);
|
||||
try {
|
||||
trx.validate();
|
||||
database.push_transaction(trx, database::validation_steps::skip_block_size_check);
|
||||
if (plugin.app().p2p_node())
|
||||
plugin.app().p2p_node()->broadcast(net::trx_message(trx));
|
||||
return true;
|
||||
} catch (fc::exception &e) {
|
||||
elog("Sending proposal for deposit sidechain transaction create operation failed with exception ${e}", ("e", e.what()));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_eth::process_withdrawal(const son_wallet_withdraw_object &swwo) {
|
||||
|
||||
if (proposal_exists(chain::operation::tag<chain::son_wallet_withdraw_process_operation>::value, swwo.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tx_str = create_withdrawal_transaction(swwo);
|
||||
|
||||
if (!tx_str.empty()) {
|
||||
const chain::global_property_object &gpo = database.get_global_properties();
|
||||
|
||||
proposal_create_operation proposal_op;
|
||||
proposal_op.fee_paying_account = plugin.get_current_son_object().son_account;
|
||||
uint32_t lifetime = (gpo.parameters.block_interval * gpo.active_witnesses.size()) * 3;
|
||||
proposal_op.expiration_time = time_point_sec(database.head_block_time().sec_since_epoch() + lifetime);
|
||||
|
||||
son_wallet_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);
|
||||
|
||||
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) {
|
||||
return sign_transaction(sto);
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_eth::send_sidechain_transaction(const sidechain_transaction_object &sto) {
|
||||
return send_transaction(sto);
|
||||
}
|
||||
|
||||
bool sidechain_net_handler_eth::settle_sidechain_transaction(const sidechain_transaction_object &sto, asset &settle_amount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_eth::create_primary_wallet_address(const std::vector<son_info> &son_pubkeys) {
|
||||
using namespace bitcoin;
|
||||
|
||||
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
|
||||
for (auto &son : son_pubkeys) {
|
||||
std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::bitcoin);
|
||||
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
|
||||
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
|
||||
}
|
||||
|
||||
btc_weighted_multisig_address addr(pubkey_weights, network_type);
|
||||
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "{\"result\": {\"address\": \"" << addr.get_address() << "\", \"redeemScript\": \"" << fc::to_hex(addr.get_redeem_script()) << "\""
|
||||
<< "}, \"error\":null}";
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_eth::create_deposit_transaction(const son_wallet_deposit_object &swdo) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 sidechain_net_handler_eth::sign_transaction(const sidechain_transaction_object &sto) {
|
||||
std::string tx_signature;// = write_transaction_signatures(sigs);
|
||||
|
||||
return tx_signature;
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_eth::send_transaction(const sidechain_transaction_object &sto) {
|
||||
std::string res;// = eth_client->sendrawtransaction(final_tx_hex);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_eth::handle_event(const std::string &event_data) {
|
||||
}
|
||||
|
||||
std::string sidechain_net_handler_eth::get_redeemscript_for_userdeposit(const std::string &user_address) {
|
||||
using namespace bitcoin;
|
||||
const auto &sidechain_addresses_idx = database.get_index_type<sidechain_address_index>().indices().get<by_sidechain_and_deposit_address_and_expires>();
|
||||
const auto &addr_itr = sidechain_addresses_idx.find(std::make_tuple(sidechain, user_address, time_point_sec::maximum()));
|
||||
if (addr_itr == sidechain_addresses_idx.end()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const auto &idx = database.get_index_type<son_wallet_index>().indices().get<by_id>();
|
||||
auto obj = idx.rbegin();
|
||||
if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<std::pair<fc::ecc::public_key, uint16_t>> pubkey_weights;
|
||||
for (auto &son : obj->sons) {
|
||||
std::string pub_key_str = son.sidechain_public_keys.at(sidechain_type::bitcoin);
|
||||
auto pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(pub_key_str)));
|
||||
pubkey_weights.push_back(std::make_pair(pub_key, son.weight));
|
||||
}
|
||||
auto user_pub_key = fc::ecc::public_key(create_public_key_data(parse_hex(addr_itr->deposit_public_key)));
|
||||
btc_one_or_weighted_multisig_address deposit_addr(user_pub_key, pubkey_weights, network_type);
|
||||
return fc::to_hex(deposit_addr.get_redeem_script());
|
||||
}
|
||||
|
||||
std::vector<info_for_vin> 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::vector<info_for_vin> result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void sidechain_net_handler_eth::on_changed_objects(const vector<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
|
||||
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));
|
||||
|
||||
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<object_id_type> &ids, const flat_set<account_id_type> &accounts) {
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
}} // namespace graphene::peerplays_sidechain
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include <fc/log/logger.hpp>
|
||||
#include <graphene/chain/son_wallet_object.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_eth.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_hive.hpp>
|
||||
#include <graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp>
|
||||
|
||||
|
|
@ -31,6 +32,12 @@ bool sidechain_net_manager::create_handler(sidechain_type sidechain, const boost
|
|||
ret_val = true;
|
||||
break;
|
||||
}
|
||||
case sidechain_type::ethereum: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_eth(plugin, options));
|
||||
net_handlers.push_back(std::move(h));
|
||||
ret_val = true;
|
||||
break;
|
||||
}
|
||||
case sidechain_type::hive: {
|
||||
std::unique_ptr<sidechain_net_handler> h = std::unique_ptr<sidechain_net_handler>(new sidechain_net_handler_hive(plugin, options));
|
||||
net_handlers.push_back(std::move(h));
|
||||
|
|
|
|||
Loading…
Reference in a new issue