From 47c98c203a16ce72963ea959d6a59c849406f0e1 Mon Sep 17 00:00:00 2001 From: obucinac Date: Mon, 24 Feb 2020 15:00:59 +0200 Subject: [PATCH] [SON-264] Integrating deposit/withdrawals with bitcoin transactions (feature/SON-260 + SON261 branches) (#291) * Partial integration done, some Bitcoin RPC refactoring * CLang Format config file * CLang Format config file v2.0 * Fix repeating tasks that should be executed by scheduled SON only * Fix withdrawal * Integrate PW wallet fund moving * Resolve conflicts Co-authored-by: gladcow Co-authored-by: satyakoneru --- .clang-format | 127 ++++ .../peerplays_sidechain_plugin.hpp | 1 + .../sidechain_net_handler.hpp | 2 - .../sidechain_net_handler_bitcoin.hpp | 30 +- .../sidechain_net_handler_peerplays.hpp | 2 +- .../peerplays_sidechain_plugin.cpp | 26 +- .../sidechain_net_handler.cpp | 89 +-- .../sidechain_net_handler_bitcoin.cpp | 688 ++++++++---------- .../sidechain_net_handler_peerplays.cpp | 4 +- 9 files changed, 516 insertions(+), 453 deletions(-) create mode 100755 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100755 index 00000000..2fffe7ba --- /dev/null +++ b/.clang-format @@ -0,0 +1,127 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -3 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: None +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: AfterColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 0 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: true +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 6 +ContinuationIndentWidth: 6 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: false +IndentPPDirectives: None +IndentWidth: 3 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 3 +UseTab: Never +... + diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp index e9a868f1..bc1f6d21 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/peerplays_sidechain_plugin.hpp @@ -28,6 +28,7 @@ class peerplays_sidechain_plugin : public graphene::app::plugin std::unique_ptr my; std::set& get_sons(); + son_id_type& get_current_son_id(); son_object get_son_object(son_id_type son_id); bool is_active_son(son_id_type son_id); std::map& get_private_keys(); diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp index 64fea1be..fe042306 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler.hpp @@ -36,8 +36,6 @@ protected: virtual std::string transfer( const std::string& from, const std::string& to, const uint64_t amount ) = 0; virtual std::string sign_transaction( const std::string& transaction ) = 0; virtual std::string send_transaction( const std::string& transaction ) = 0; - //virtual std::string transfer_deposit_to_primary_wallet (const sidechain_event_data& sed) = 0; - //virtual std::string transfer_withdrawal_from_primary_wallet(const std::string& user_address, double sidechain_amount) = 0; private: diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp index 854bac96..1772eef4 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_bitcoin.hpp @@ -7,6 +7,8 @@ #include #include +#include +#include namespace graphene { namespace peerplays_sidechain { @@ -21,20 +23,18 @@ public: class bitcoin_rpc_client { public: bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::string _user, std::string _password) ; - std::string receive_full_block( const std::string& block_hash ); - int32_t receive_confirmations_tx( const std::string& tx_hash ); - bool receive_mempool_entry_tx( const std::string& tx_hash ); - uint64_t receive_estimated_fee(); - void send_btc_tx( const std::string& tx_hex ); - std::string add_multisig_address( const std::vector public_keys ); bool connection_is_not_defined() const; - std::string create_raw_transaction(const std::string& txid, const std::string& vout, const std::string& out_address, double transfer_amount); - std::string sign_raw_transaction_with_wallet(const std::string& tx_hash); - std::string sign_raw_transaction_with_privkey(const std::string& tx_hash, const std::string& private_key); - void import_address( const std::string& address_or_script); - std::vector list_unspent(); - std::vector list_unspent_by_address_and_amount(const std::string& address, double transfer_amount); - std::string prepare_tx(const std::vector& ins, const fc::flat_map outs); + + std::string addmultisigaddress( const std::vector public_keys ); + std::string createrawtransaction(const std::vector& ins, const fc::flat_map outs); + uint64_t estimatesmartfee(); + std::string getblock( const std::string& block_hash, int32_t verbosity = 2 ); + void importaddress( const std::string& address_or_script); + std::vector listunspent(); + std::vector listunspent_by_address_and_amount(const std::string& address, double transfer_amount); + void sendrawtransaction( const std::string& tx_hex ); + std::string signrawtransactionwithkey(const std::string& tx_hash, const std::string& private_key); + std::string signrawtransactionwithwallet(const std::string& tx_hash); private: @@ -86,8 +86,8 @@ public: std::string send_transaction( const std::string& transaction ); std::string sign_and_send_transaction_with_wallet ( const std::string& tx_json ); std::string transfer_all_btc(const std::string& from_address, const std::string& to_address); - std::string transfer_deposit_to_primary_wallet (const sidechain_event_data& sed); - std::string transfer_withdrawal_from_primary_wallet(const std::string& user_address, double sidechain_amount); + std::string transfer_deposit_to_primary_wallet (const son_wallet_deposit_object &swdo); + std::string transfer_withdrawal_from_primary_wallet(const son_wallet_withdraw_object &swwo); private: diff --git a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp index 13d5de52..7de7feb4 100644 --- a/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp +++ b/libraries/plugins/peerplays_sidechain/include/graphene/peerplays_sidechain/sidechain_net_handler_peerplays.hpp @@ -26,7 +26,7 @@ public: private: - void on_block_applied(const signed_block& b); + void on_applied_block(const signed_block& b); }; diff --git a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp index 5af5e5fc..0fa12c4e 100644 --- a/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp +++ b/libraries/plugins/peerplays_sidechain/peerplays_sidechain_plugin.cpp @@ -35,6 +35,7 @@ class peerplays_sidechain_plugin_impl void plugin_startup(); std::set& get_sons(); + son_id_type& get_current_son_id(); son_object get_son_object(son_id_type son_id); bool is_active_son(son_id_type son_id); std::map& get_private_keys(); @@ -55,13 +56,15 @@ class peerplays_sidechain_plugin_impl bool config_ready_bitcoin; bool config_ready_peerplays; + son_id_type current_son_id; + std::unique_ptr net_manager; std::map _private_keys; std::set _sons; fc::future _heartbeat_task; - void on_block_applied( const signed_block& b ); - void on_objects_new(const vector& new_object_ids); + void on_applied_block( const signed_block& b ); + void on_new_objects(const vector& new_object_ids); }; @@ -70,6 +73,7 @@ peerplays_sidechain_plugin_impl::peerplays_sidechain_plugin_impl(peerplays_sidec config_ready_son(false), config_ready_bitcoin(false), config_ready_peerplays(false), + current_son_id(son_id_type(std::numeric_limits().max())), net_manager(nullptr) { } @@ -158,8 +162,8 @@ void peerplays_sidechain_plugin_impl::plugin_initialize(const boost::program_opt throw; } - plugin.database().applied_block.connect( [&] (const signed_block& b) { on_block_applied(b); } ); - plugin.database().new_objects.connect( [&] (const vector& ids, const flat_set& impacted_accounts) { on_objects_new(ids); } ); + plugin.database().applied_block.connect( [&] (const signed_block& b) { on_applied_block(b); } ); + plugin.database().new_objects.connect( [&] (const vector& ids, const flat_set& impacted_accounts) { on_new_objects(ids); } ); net_manager = std::unique_ptr(new sidechain_net_manager(plugin)); @@ -225,6 +229,10 @@ std::set& peerplays_sidechain_plugin_impl::get_sons() return _sons; } +son_id_type& peerplays_sidechain_plugin_impl::get_current_son_id() { + return current_son_id; +} + son_object peerplays_sidechain_plugin_impl::get_son_object(son_id_type son_id) { const auto& idx = plugin.database().get_index_type().indices().get(); @@ -388,7 +396,7 @@ void peerplays_sidechain_plugin_impl::process_withdrawals() net_manager->process_withdrawals(); } -void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b ) +void peerplays_sidechain_plugin_impl::on_applied_block( const signed_block& b ) { chain::database& d = plugin.database(); const chain::global_property_object& gpo = d.get_global_properties(); @@ -403,6 +411,8 @@ void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b ) // check if we control scheduled SON if( _sons.find( next_son_id ) != _sons.end() ) { + current_son_id = next_son_id; + create_son_down_proposals(); recreate_primary_wallet(); @@ -414,7 +424,7 @@ void peerplays_sidechain_plugin_impl::on_block_applied( const signed_block& b ) } } -void peerplays_sidechain_plugin_impl::on_objects_new(const vector& new_object_ids) +void peerplays_sidechain_plugin_impl::on_new_objects(const vector& new_object_ids) { auto approve_proposal = [ & ]( const chain::son_id_type& son_id, const chain::proposal_id_type& proposal_id ) @@ -536,6 +546,10 @@ std::set& peerplays_sidechain_plugin::get_sons() return my->get_sons(); } +son_id_type& peerplays_sidechain_plugin::get_current_son_id() { + return my->get_current_son_id(); +} + son_object peerplays_sidechain_plugin::get_son_object(son_id_type son_id) { return my->get_son_object(son_id); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp index e89bd9c8..062c3094 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler.cpp @@ -87,7 +87,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ 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 ); - ilog("sidechain_net_handler: sending proposal for son wallet deposit create operation by ${son}", ("son", son_id)); + //ilog("sidechain_net_handler: sending proposal for son wallet deposit create operation by ${son}", ("son", son_id)); signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op); try { database.push_transaction(trx, database::validation_steps::skip_block_size_check); @@ -130,7 +130,7 @@ void sidechain_net_handler::sidechain_event_data_received(const sidechain_event_ 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 ); - ilog("sidechain_net_handler: sending proposal for son wallet withdraw create operation by ${son}", ("son", son_id)); + //ilog("sidechain_net_handler: sending proposal for son wallet withdraw create operation by ${son}", ("son", son_id)); signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op); try { database.push_transaction(trx, database::validation_steps::skip_block_size_check); @@ -158,35 +158,30 @@ void sidechain_net_handler::process_deposits() { std::for_each(idx_range.first, idx_range.second, [&] (const son_wallet_deposit_object& swdo) { + ilog("Deposit to process: ${swdo}", ("swdo", swdo)); + process_deposit(swdo); const chain::global_property_object& gpo = plugin.database().get_global_properties(); - for (son_id_type son_id : plugin.get_sons()) { - if (plugin.is_active_son(son_id)) { + son_wallet_deposit_process_operation p_op; + p_op.payer = GRAPHENE_SON_ACCOUNT; + p_op.son_wallet_deposit_id = swdo.id; - son_wallet_deposit_process_operation p_op; - p_op.payer = GRAPHENE_SON_ACCOUNT; - p_op.son_wallet_deposit_id = swdo.id; + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account; + proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) ); + uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; + proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime ); - proposal_create_operation proposal_op; - proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account; - proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) ); - uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; - proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime ); - - ilog("sidechain_net_handler: sending proposal for transfer operation ${swdo} by ${son}", ("swdo", swdo.id) ("son", son_id)); - signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op); - trx.validate(); - ilog("sidechain_net_handler: transaction validated ${swdo} by ${son}", ("swdo", swdo.id) ("son", son_id)); - try { - plugin.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)); - } catch(fc::exception e){ - ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what())); - } - } + signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + trx.validate(); + try { + plugin.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)); + } catch(fc::exception e){ + ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what())); } }); } @@ -198,36 +193,30 @@ void sidechain_net_handler::process_withdrawals() { std::for_each(idx_range.first, idx_range.second, [&] (const son_wallet_withdraw_object& swwo) { + ilog("Withdraw to process: ${swwo}", ("swwo", swwo)); + process_withdrawal(swwo); const chain::global_property_object& gpo = plugin.database().get_global_properties(); - for (son_id_type son_id : plugin.get_sons()) { - if (plugin.is_active_son(son_id)) { + son_wallet_withdraw_process_operation p_op; + p_op.payer = GRAPHENE_SON_ACCOUNT; + p_op.son_wallet_withdraw_id = swwo.id; - ilog("SON ${son_id}: Withdraw to process: ${swwo}", ("son_id", son_id) ("swwo", swwo)); - //son_wallet_withdraw_process_operation p_op; - //p_op.payer = GRAPHENE_SON_ACCOUNT; - //p_op.son_wallet_withdraw_id = swwo.id; - // - //proposal_create_operation proposal_op; - //proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account; - //proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) ); - //uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; - //proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime ); - // - //ilog("sidechain_net_handler: sending proposal for transfer operation ${swwo} by ${son}", ("swwo", swwo.id) ("son", son_id)); - //signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(son_id), proposal_op); - //trx.validate(); - //ilog("sidechain_net_handler: transaction validated ${swwo} by ${son}", ("swwo", swwo.id) ("son", son_id)); - //try { - // plugin.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)); - //} catch(fc::exception e){ - // ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what())); - //} - } + proposal_create_operation proposal_op; + proposal_op.fee_paying_account = plugin.get_son_object(plugin.get_current_son_id()).son_account; + proposal_op.proposed_ops.emplace_back( op_wrapper( p_op ) ); + uint32_t lifetime = ( gpo.parameters.block_interval * gpo.active_witnesses.size() ) * 3; + proposal_op.expiration_time = time_point_sec( plugin.database().head_block_time().sec_since_epoch() + lifetime ); + + signed_transaction trx = plugin.database().create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + trx.validate(); + try { + plugin.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)); + } catch(fc::exception e){ + ilog("sidechain_net_handler: sending proposal for transfer operation failed with exception ${e}",("e", e.what())); } }); } diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp index dd644f3d..b6dd478d 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_bitcoin.cpp @@ -15,8 +15,6 @@ #include #include #include -#include -#include #include namespace graphene { namespace peerplays_sidechain { @@ -30,116 +28,13 @@ bitcoin_rpc_client::bitcoin_rpc_client( std::string _ip, uint32_t _rpc, std::str authorization.val = "Basic " + fc::base64_encode( user + ":" + password ); } -std::string bitcoin_rpc_client::receive_full_block( const std::string& block_hash ) -{ - fc::http::connection conn; - conn.connect_to( fc::ip::endpoint( fc::ip::address( ip ), rpc_port ) ); - - const auto url = "http://" + ip + ":" + std::to_string( rpc_port ) + "/rest/block/" + block_hash + ".json"; - - const auto reply = conn.request( "GET", url ); - if ( reply.status != 200 ) - return ""; - - ilog( "Receive Bitcoin block: ${hash}", ( "hash", block_hash ) ); - return std::string( reply.body.begin(), reply.body.end() ); +bool bitcoin_rpc_client::connection_is_not_defined() const { + return ip.empty() || rpc_port == 0 || user.empty() || password.empty(); } -//int32_t bitcoin_rpc_client::receive_confirmations_tx( const std::string& tx_hash ) -//{ -// const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"getrawtransaction\", \"params\": [") + -// std::string("\"") + tx_hash + std::string("\"") + ", " + "true" + std::string("] }"); -// -// const auto reply = send_post_request( body ); -// -// if ( reply.status != 200 ) -// return 0; -// -// const auto result = std::string( reply.body.begin(), reply.body.end() ); -// -// std::stringstream ss( result ); -// boost::property_tree::ptree tx; -// boost::property_tree::read_json( ss, tx ); -// -// if( tx.count( "result" ) ) { -// if( tx.get_child( "result" ).count( "confirmations" ) ) { -// return tx.get_child( "result" ).get_child( "confirmations" ).get_value(); -// } -// } -// return 0; -//} - -bool bitcoin_rpc_client::receive_mempool_entry_tx( const std::string& tx_hash ) -{ - const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"curltest\", \"method\": \"getmempoolentry\", \"params\": [") + - std::string("\"") + tx_hash + std::string("\"") + std::string("] }"); - - const auto reply = send_post_request( body ); - - if ( reply.status != 200 ) - return false; - - return true; -} - -uint64_t bitcoin_rpc_client::receive_estimated_fee() -{ - static const auto confirmation_target_blocks = 6; - - const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimated_feerate\", \"method\": \"estimatesmartfee\", \"params\": [") + - std::to_string(confirmation_target_blocks) + std::string("] }"); - - const auto reply = send_post_request( body ); - - if( reply.status != 200 ) - return 0; - - std::stringstream ss( std::string( reply.body.begin(), reply.body.end() ) ); - boost::property_tree::ptree json; - boost::property_tree::read_json( ss, json ); - - if( json.count( "result" ) ) - if ( json.get_child( "result" ).count( "feerate" ) ) { - auto feerate_str = json.get_child( "result" ).get_child( "feerate" ).get_value(); - feerate_str.erase( std::remove( feerate_str.begin(), feerate_str.end(), '.' ), feerate_str.end() ); - return std::stoll( feerate_str ); - } - return 0; -} - -void bitcoin_rpc_client::send_btc_tx( const std::string& tx_hex ) -{ - const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"send_tx\", \"method\": \"sendrawtransaction\", \"params\": [") + - std::string("\"") + tx_hex + std::string("\"") + std::string("] }"); - - ilog(body); - - const auto reply = send_post_request( body ); - - if( reply.body.empty() ) - return; - - std::string reply_str( reply.body.begin(), reply.body.end() ); - - std::stringstream ss(reply_str); - boost::property_tree::ptree json; - boost::property_tree::read_json( ss, json ); - - if( reply.status == 200 ) { - idump(( tx_hex )); - return; - } else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) { - const auto error_code = json.get_child( "error" ).get_child( "code" ).get_value(); - if( error_code == -27 ) // transaction already in block chain - return; - - wlog( "BTC tx is not sent! Reply: ${msg}", ("msg", reply_str) ); - } -} - -std::string bitcoin_rpc_client::add_multisig_address( const std::vector public_keys ) -{ - std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"addmultisigaddress\", \"method\": \"addmultisigaddress\", \"params\": ["); +std::string bitcoin_rpc_client::addmultisigaddress(const std::vector public_keys) { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"addmultisigaddress\", " + "\"method\": \"addmultisigaddress\", \"params\": ["); std::string params = "2, ["; std::string pubkeys = ""; for (std::string pubkey : public_keys) { @@ -151,225 +46,42 @@ std::string bitcoin_rpc_client::add_multisig_address( const std::vector bitcoin_rpc_client::list_unspent() -{ - const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"listunspent\", \"params\": [] }"); - - const auto reply = send_post_request( body ); - - std::vector result; - if( reply.body.empty() ) - { - wlog("Failed to list unspent txo"); - return result; - } - - std::string reply_str( reply.body.begin(), reply.body.end() ); - - std::stringstream ss(reply_str); - boost::property_tree::ptree json; - boost::property_tree::read_json( ss, json ); - - if( reply.status == 200 ) { - idump((reply_str)); - if( json.count( "result" ) ) - { - for(auto& entry: json.get_child("result")) - { - btc_txout txo; - txo.txid_ = entry.second.get_child("txid").get_value(); - txo.out_num_ = entry.second.get_child("vout").get_value(); - txo.amount_ = entry.second.get_child("amount").get_value(); - result.push_back(txo); - } - } - } else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) { - wlog( "Failed to list unspent txo! Reply: ${msg}", ("msg", reply_str) ); - } - return result; -} - -std::vector bitcoin_rpc_client::list_unspent_by_address_and_amount(const std::string& address, double minimum_amount) -{ - std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"listunspent\", \"params\": ["); - body += std::string("1,999999,[\""); - body += address; - body += std::string("\"],true,{\"minimumAmount\":"); - body += std::to_string(minimum_amount); - body += std::string("}] }"); - - ilog(body); - - const auto reply = send_post_request( body ); - - std::vector result; - if( reply.body.empty() ) - { - wlog("Failed to list unspent txo"); - return result; - } - - std::string reply_str( reply.body.begin(), reply.body.end() ); - - std::stringstream ss(reply_str); - boost::property_tree::ptree json; - boost::property_tree::read_json( ss, json ); - - if( reply.status == 200 ) { - idump((reply_str)); - if( json.count( "result" ) ) - { - for(auto& entry: json.get_child("result")) - { - btc_txout txo; - txo.txid_ = entry.second.get_child("txid").get_value(); - txo.out_num_ = entry.second.get_child("vout").get_value(); - txo.amount_ = entry.second.get_child("amount").get_value(); - result.push_back(txo); - } - } - } else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) { - wlog( "Failed to list unspent txo! Reply: ${msg}", ("msg", reply_str) ); - } - return result; -} - -std::string bitcoin_rpc_client::prepare_tx(const std::vector &ins, const fc::flat_map outs) -{ - std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": \"createrawtransaction\", \"params\": ["); +std::string bitcoin_rpc_client::createrawtransaction(const std::vector &ins, const fc::flat_map outs) { + std::string body("{\"jsonrpc\": \"1.0\", \"id\":\"createrawtransaction\", " + "\"method\": \"createrawtransaction\", \"params\": ["); body += "["; bool first = true; - for(const auto& entry: ins) - { - if(!first) + for (const auto &entry : ins) { + if (!first) body += ","; body += "{\"txid\":\"" + entry.txid_ + "\",\"vout\":" + std::to_string(entry.out_num_) + "}"; first = false; } body += "],["; first = true; - for(const auto& entry: outs) - { - if(!first) + for (const auto &entry : outs) { + if (!first) body += ","; body += "{\"" + entry.first + "\":" + std::to_string(entry.second) + "}"; first = false; @@ -378,30 +90,237 @@ std::string bitcoin_rpc_client::prepare_tx(const std::vector &ins, co ilog(body); - const auto reply = send_post_request( body ); + const auto reply = send_post_request(body); - if( reply.body.empty() ) - { - wlog("Failed to create raw transaction: [${body}]", ("body", body)); + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); return std::string(); } - std::string reply_str( reply.body.begin(), reply.body.end() ); - - std::stringstream ss(reply_str); + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); boost::property_tree::ptree json; - boost::property_tree::read_json( ss, json ); + boost::property_tree::read_json(ss, json); - if( reply.status == 200 ) { - idump((reply_str)); - if( json.count( "result" ) ) - return reply_str; - } else if( json.count( "error" ) && !json.get_child( "error" ).empty() ) { - wlog( "Failed to create raw transaction: [${body}]! Reply: ${msg}", ("body", body)("msg", reply_str) ); + if (reply.status == 200) { + if (json.count("result")) + return ss.str(); + } else if (json.count("error") && !json.get_child("error").empty()) { + wlog("Failed to create raw transaction: [${body}]! Reply: ${msg}", ("body", body)("msg", ss.str())); } return std::string(); } +uint64_t bitcoin_rpc_client::estimatesmartfee() { + static const auto confirmation_target_blocks = 6; + + const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"estimatesmartfee\", " + "\"method\": \"estimatesmartfee\", \"params\": [") + + std::to_string(confirmation_target_blocks) + std::string("] }"); + + const auto reply = send_post_request(body); + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return 0; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (json.count("result")) + if (json.get_child("result").count("feerate")) { + auto feerate_str = json.get_child("result").get_child("feerate").get_value(); + feerate_str.erase(std::remove(feerate_str.begin(), feerate_str.end(), '.'), feerate_str.end()); + return std::stoll(feerate_str); + } + return 0; +} + +std::string bitcoin_rpc_client::getblock(const std::string &block_hash, int32_t verbosity) { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"getblock\", \"method\": " + "\"getblock\", \"params\": [\"" + + block_hash + "\", " + std::to_string(verbosity) + "] }"); + + const auto reply = send_post_request(body); + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return std::string(); + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + std::stringstream ss; + boost::property_tree::json_parser::write_json(ss, json.get_child("result")); + return ss.str(); + } + + if (json.count("error") && !json.get_child("error").empty()) { + wlog("Bitcoin RPC call ${function} failed with reply '${msg}'", ("function", __FUNCTION__)("msg", ss.str())); + } + return ""; +} + +void bitcoin_rpc_client::importaddress(const std::string &address_or_script) { + const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"importaddress\", " + "\"method\": \"importaddress\", \"params\": [") + + std::string("\"") + address_or_script + std::string("\"") + std::string("] }"); + + const auto reply = send_post_request(body); + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + idump((address_or_script)(ss.str())); + return; + } else if (json.count("error") && !json.get_child("error").empty()) { + wlog("Failed to import address [${addr}]! Reply: ${msg}", ("addr", address_or_script)("msg", ss.str())); + } +} + +std::vector bitcoin_rpc_client::listunspent() { + const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": " + "\"listunspent\", \"params\": [] }"); + + const auto reply = send_post_request(body); + + std::vector result; + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return result; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + if (json.count("result")) { + for (auto &entry : json.get_child("result")) { + btc_txout txo; + txo.txid_ = entry.second.get_child("txid").get_value(); + txo.out_num_ = entry.second.get_child("vout").get_value(); + txo.amount_ = entry.second.get_child("amount").get_value(); + result.push_back(txo); + } + } + } else if (json.count("error") && !json.get_child("error").empty()) { + wlog("Failed to list unspent txo! Reply: ${msg}", ("msg", ss.str())); + } + return result; +} + +std::vector bitcoin_rpc_client::listunspent_by_address_and_amount(const std::string &address, double minimum_amount) { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"pp_plugin\", \"method\": " + "\"listunspent\", \"params\": ["); + body += std::string("1,999999,[\""); + body += address; + body += std::string("\"],true,{\"minimumAmount\":"); + body += std::to_string(minimum_amount); + body += std::string("}] }"); + + const auto reply = send_post_request(body); + + std::vector result; + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return result; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + if (json.count("result")) { + for (auto &entry : json.get_child("result")) { + btc_txout txo; + txo.txid_ = entry.second.get_child("txid").get_value(); + txo.out_num_ = entry.second.get_child("vout").get_value(); + txo.amount_ = entry.second.get_child("amount").get_value(); + result.push_back(txo); + } + } + } else if (json.count("error") && !json.get_child("error").empty()) { + wlog("Failed to list unspent txo! Reply: ${msg}", ("msg", ss.str())); + } + return result; +} + +void bitcoin_rpc_client::sendrawtransaction(const std::string &tx_hex) { + const auto body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"sendrawtransaction\", " + "\"method\": \"sendrawtransaction\", \"params\": [") + + std::string("\"") + tx_hex + std::string("\"") + std::string("] }"); + + ilog(body); + + const auto reply = send_post_request(body); + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return; + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + return; + } else if (json.count("error") && !json.get_child("error").empty()) { + const auto error_code = json.get_child("error").get_child("code").get_value(); + if (error_code == -27) // transaction already in block chain + return; + + wlog("BTC tx is not sent! Reply: ${msg}", ("msg", ss.str())); + } +} + +std::string bitcoin_rpc_client::signrawtransactionwithkey(const std::string &tx_hash, const std::string &private_key) { + return ""; +} + +std::string bitcoin_rpc_client::signrawtransactionwithwallet(const std::string &tx_hash) { + std::string body = std::string("{\"jsonrpc\": \"1.0\", \"id\":\"signrawtransactionwithwallet\", " + "\"method\": \"signrawtransactionwithwallet\", \"params\": ["); + std::string params = "\"" + tx_hash + "\""; + body = body + params + std::string("]}"); + + ilog(body); + + const auto reply = send_post_request(body); + + if (reply.body.empty()) { + wlog("Bitcoin RPC call ${function} failed", ("function", __FUNCTION__)); + return std::string(); + } + + std::stringstream ss(std::string(reply.body.begin(), reply.body.end())); + boost::property_tree::ptree json; + boost::property_tree::read_json(ss, json); + + if (reply.status == 200) { + return ss.str(); + } + + if (json.count("error") && !json.get_child("error").empty()) { + wlog("BTC sign_raw_transaction_with_wallet failed! Reply: ${msg}", ("msg", ss.str())); + } + return ""; +} + fc::http::reply bitcoin_rpc_client::send_post_request( std::string body ) { fc::http::connection conn; @@ -499,12 +418,12 @@ sidechain_net_handler_bitcoin::~sidechain_net_handler_bitcoin() { } void sidechain_net_handler_bitcoin::recreate_primary_wallet() { - const auto& idx_swi = database.get_index_type().indices().get(); - auto obj = idx_swi.rbegin(); - if (obj != idx_swi.rend()) { + const auto& swi = database.get_index_type().indices().get(); + const auto &active_sw = swi.rbegin(); + if (active_sw != swi.rend()) { - if ((obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) || - (obj->addresses.at(sidechain_type::bitcoin).empty())) { + if ((active_sw->addresses.find(sidechain_type::bitcoin) == active_sw->addresses.end()) || + (active_sw->addresses.at(sidechain_type::bitcoin).empty())) { const chain::global_property_object& gpo = database.get_global_properties(); @@ -517,35 +436,46 @@ void sidechain_net_handler_bitcoin::recreate_primary_wallet() { ilog(reply_str); - std::stringstream ss(reply_str); - boost::property_tree::ptree pt; - boost::property_tree::read_json( ss, pt ); - if( pt.count( "error" ) && pt.get_child( "error" ).empty() ) { + 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, pt.get_child("result")); + boost::property_tree::json_parser::write_json(res, active_pw_pt.get_child("result")); son_wallet_update_operation op; op.payer = GRAPHENE_SON_ACCOUNT; - op.son_wallet_id = (*obj).id; + op.son_wallet_id = (*active_sw).id; op.sidechain = sidechain_type::bitcoin; op.address = res.str(); - for (son_id_type son_id : plugin.get_sons()) { - proposal_create_operation proposal_op; - proposal_op.fee_paying_account = plugin.get_son_object(son_id).son_account; - proposal_op.proposed_ops.emplace_back( op_wrapper( op ) ); - 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_son_object(plugin.get_current_son_id()).son_account; + proposal_op.proposed_ops.emplace_back( op_wrapper( op ) ); + 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 ); - signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(son_id), proposal_op); - try { - 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)); - } catch(fc::exception e){ - ilog("sidechain_net_handler: sending proposal for son wallet update operation failed with exception ${e}",("e", e.what())); - } + signed_transaction trx = database.create_signed_transaction(plugin.get_private_key(plugin.get_current_son_id()), proposal_op); + try { + 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)); + } catch(fc::exception e){ + ilog("sidechain_net_handler: 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::stringstream prev_sw_ss(prev_sw->addresses.at(sidechain_type::bitcoin)); + boost::property_tree::ptree prev_sw_pt; + boost::property_tree::read_json( prev_sw_ss, prev_sw_pt ); + + std::string active_pw_address = active_pw_pt.get_child("result").get("address"); + std::string prev_pw_address = prev_sw_pt.get("address"); + + transfer_all_btc(prev_pw_address, active_pw_address); } } } @@ -556,18 +486,22 @@ void sidechain_net_handler_bitcoin::process_deposits() { sidechain_net_handler::process_deposits(); } -void sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_object& swdo) { +void sidechain_net_handler_bitcoin::process_deposit(const son_wallet_deposit_object &swdo) { + ilog(__FUNCTION__); + transfer_deposit_to_primary_wallet(swdo); } void sidechain_net_handler_bitcoin::process_withdrawals() { sidechain_net_handler::process_withdrawals(); } -void sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw_object& swwo) { +void sidechain_net_handler_bitcoin::process_withdrawal(const son_wallet_withdraw_object &swwo) { + ilog(__FUNCTION__); + transfer_withdrawal_from_primary_wallet(swwo); } std::string sidechain_net_handler_bitcoin::create_multisignature_wallet( const std::vector public_keys ) { - return bitcoin_client->add_multisig_address(public_keys); + return bitcoin_client->addmultisigaddress(public_keys); } std::string sidechain_net_handler_bitcoin::transfer( const std::string& from, const std::string& to, const uint64_t amount ) { @@ -598,7 +532,7 @@ std::string sidechain_net_handler_bitcoin::sign_and_send_transaction_with_wallet std::string unsigned_tx_hex = pt.get("result"); - reply_str = bitcoin_client->sign_raw_transaction_with_wallet(unsigned_tx_hex); + reply_str = bitcoin_client->signrawtransactionwithwallet(unsigned_tx_hex); ilog(reply_str); std::stringstream ss_stx(reply_str); boost::property_tree::ptree stx_json; @@ -610,20 +544,20 @@ std::string sidechain_net_handler_bitcoin::sign_and_send_transaction_with_wallet std::string signed_tx_hex = stx_json.get("result.hex"); - bitcoin_client->send_btc_tx(signed_tx_hex); + bitcoin_client->sendrawtransaction(signed_tx_hex); return reply_str; } std::string sidechain_net_handler_bitcoin::transfer_all_btc(const std::string& from_address, const std::string& to_address) { - uint64_t fee_rate = bitcoin_client->receive_estimated_fee(); + uint64_t fee_rate = bitcoin_client->estimatesmartfee(); uint64_t min_fee_rate = 1000; fee_rate = std::max(fee_rate, min_fee_rate); double min_amount = ((double)fee_rate/100000000.0); // Account only for relay fee for now double total_amount = 0.0; - std::vector unspent_utxo= bitcoin_client->list_unspent_by_address_and_amount(from_address, 0); + std::vector unspent_utxo = bitcoin_client->listunspent_by_address_and_amount(from_address, 0); if(unspent_utxo.size() == 0) { @@ -647,16 +581,16 @@ std::string sidechain_net_handler_bitcoin::transfer_all_btc(const std::string& f fc::flat_map outs; outs[to_address] = total_amount - min_amount; - std::string reply_str = bitcoin_client->prepare_tx(unspent_utxo, outs); + std::string reply_str = bitcoin_client->createrawtransaction(unspent_utxo, outs); return sign_and_send_transaction_with_wallet(reply_str); } -std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet ( const sidechain_event_data& sed ) +std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet (const son_wallet_deposit_object &swdo) { const auto& idx = database.get_index_type().indices().get(); auto obj = idx.rbegin(); if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) { - return ""; + return ""; } std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second; @@ -667,11 +601,11 @@ std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet ( std::string pw_address = json.get("address"); - std::string txid = sed.sidechain_transaction_id; - std::string suid = sed.sidechain_uid; + std::string txid = swdo.sidechain_transaction_id; + std::string suid = swdo.sidechain_uid; std::string nvout = suid.substr(suid.find_last_of("-")+1); - uint64_t deposit_amount = sed.sidechain_amount.value; - uint64_t fee_rate = bitcoin_client->receive_estimated_fee(); + uint64_t deposit_amount = swdo.sidechain_amount.value; + uint64_t fee_rate = bitcoin_client->estimatesmartfee(); uint64_t min_fee_rate = 1000; fee_rate = std::max(fee_rate, min_fee_rate); deposit_amount -= fee_rate; // Deduct minimum relay fee @@ -688,16 +622,16 @@ std::string sidechain_net_handler_bitcoin::transfer_deposit_to_primary_wallet ( outs[pw_address] = transfer_amount; - std::string reply_str = bitcoin_client->prepare_tx(ins, outs); + std::string reply_str = bitcoin_client->createrawtransaction(ins, outs); return sign_and_send_transaction_with_wallet(reply_str); } -std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wallet(const std::string& user_address, double sidechain_amount) { +std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wallet(const son_wallet_withdraw_object &swwo) { const auto& idx = database.get_index_type().indices().get(); auto obj = idx.rbegin(); if (obj == idx.rend() || obj->addresses.find(sidechain_type::bitcoin) == obj->addresses.end()) { - return ""; + return ""; } std::string pw_address_json = obj->addresses.find(sidechain_type::bitcoin)->second; @@ -708,13 +642,13 @@ std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wall std::string pw_address = json.get("address"); - uint64_t fee_rate = bitcoin_client->receive_estimated_fee(); + uint64_t fee_rate = bitcoin_client->estimatesmartfee(); uint64_t min_fee_rate = 1000; fee_rate = std::max(fee_rate, min_fee_rate); - double min_amount = sidechain_amount + ((double)fee_rate/100000000.0); // Account only for relay fee for now + double min_amount = ((double)(swwo.withdraw_amount.value + fee_rate) / 100000000.0); // Account only for relay fee for now double total_amount = 0.0; - std::vector unspent_utxo= bitcoin_client->list_unspent_by_address_and_amount(pw_address, 0); + std::vector unspent_utxo = bitcoin_client->listunspent_by_address_and_amount(pw_address, 0); if(unspent_utxo.size() == 0) { @@ -731,23 +665,23 @@ std::string sidechain_net_handler_bitcoin::transfer_withdrawal_from_primary_wall if(min_amount > total_amount) { wlog("Failed not enough BTC to spend for ${pw}",("pw", pw_address)); - return ""; + return ""; } } fc::flat_map outs; - outs[user_address] = sidechain_amount; + outs[swwo.withdraw_address] = swwo.withdraw_amount.value / 100000000.0; if((total_amount - min_amount) > 0.0) { outs[pw_address] = total_amount - min_amount; } - std::string reply_str = bitcoin_client->prepare_tx(unspent_utxo, outs); + std::string reply_str = bitcoin_client->createrawtransaction(unspent_utxo, outs); return sign_and_send_transaction_with_wallet(reply_str); } void sidechain_net_handler_bitcoin::handle_event( const std::string& event_data ) { - std::string block = bitcoin_client->receive_full_block( event_data ); + std::string block = bitcoin_client->getblock(event_data); if( block != "" ) { const auto& vins = extract_info_from_block( block ); diff --git a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp index bfdd5370..f5d47e39 100644 --- a/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp +++ b/libraries/plugins/peerplays_sidechain/sidechain_net_handler_peerplays.cpp @@ -22,7 +22,7 @@ namespace graphene { namespace peerplays_sidechain { sidechain_net_handler_peerplays::sidechain_net_handler_peerplays(peerplays_sidechain_plugin& _plugin, const boost::program_options::variables_map& options) : sidechain_net_handler(_plugin, options) { sidechain = sidechain_type::peerplays; - plugin.database().applied_block.connect( [&] (const signed_block& b) { on_block_applied(b); } ); + plugin.database().applied_block.connect( [&] (const signed_block& b) { on_applied_block(b); } ); } sidechain_net_handler_peerplays::~sidechain_net_handler_peerplays() { @@ -61,7 +61,7 @@ std::string sidechain_net_handler_peerplays::send_transaction( const std::string return ""; } -void sidechain_net_handler_peerplays::on_block_applied(const signed_block& b) { +void sidechain_net_handler_peerplays::on_applied_block(const signed_block& b) { for (const auto& trx: b.transactions) { size_t operation_index = -1; for (auto op: trx.operations) {