From 12c5ec3f3ffcfeb6bcf3219813d8f34618b9300a Mon Sep 17 00:00:00 2001 From: Alexander Suslikov Date: Thu, 24 Jan 2019 14:22:17 +0300 Subject: [PATCH] Added finalize_bitcoin_transaction, changed bitcoin_transaction_object and bitcoin_transaction_send_operation --- .../chain/bitcoin_transaction_evaluator.cpp | 45 ++++++++++++++++--- libraries/chain/db_init.cpp | 2 + libraries/chain/db_management.cpp | 6 +++ .../chain/bitcoin_transaction_evaluator.hpp | 2 + .../chain/bitcoin_transaction_object.hpp | 4 +- .../chain/include/graphene/chain/database.hpp | 5 +++ .../chain/info_for_used_vin_object.hpp | 39 ++++++++++++++++ .../chain/protocol/bitcoin_transaction.hpp | 16 +++---- .../include/graphene/chain/protocol/types.hpp | 5 +++ .../sidechain/input_withdrawal_info.hpp | 2 + .../sidechain/sign_bitcoin_transaction.hpp | 2 +- .../sidechain/sign_bitcoin_transaction.cpp | 6 +-- tests/tests/bitcoin_sign_tests.cpp | 2 +- .../primary_wallet_vout_manager_tests.cpp | 2 +- 14 files changed, 115 insertions(+), 23 deletions(-) create mode 100644 libraries/chain/include/graphene/chain/info_for_used_vin_object.hpp diff --git a/libraries/chain/bitcoin_transaction_evaluator.cpp b/libraries/chain/bitcoin_transaction_evaluator.cpp index eb0da7ae..0b90a8e2 100644 --- a/libraries/chain/bitcoin_transaction_evaluator.cpp +++ b/libraries/chain/bitcoin_transaction_evaluator.cpp @@ -2,6 +2,9 @@ #include #include #include +#include + +#include namespace graphene { namespace chain { @@ -12,19 +15,34 @@ void_result bitcoin_transaction_send_evaluator::do_evaluate( const bitcoin_trans } object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_transaction_send_operation& op ) -{ +{ + bitcoin_transaction_send_operation& mutable_op = const_cast( op ); database& d = db(); + std::vector< info_for_used_vin_id_type > new_vins; sidechain::prev_out new_pw_vout = { "", 0, 0 }; sidechain::bytes wit_script; + finalize_bitcoin_transaction( mutable_op ); + + for( auto itr : op.vins ){ + auto itr_id = d.create< info_for_used_vin_object >( [&]( info_for_used_vin_object& obj ) + { + obj.identifier = itr.identifier; + obj.out = itr.out; + obj.address = itr.address; + obj.script = itr.script; + }).get_id(); + new_vins.push_back( itr_id ); + } + const bitcoin_transaction_object& btc_tx = d.create< bitcoin_transaction_object >( [&]( bitcoin_transaction_object& obj ) { - obj.pw_vin = op.pw_vin; - obj.vins = op.vins; - obj.vouts = op.vouts; - obj.transaction = op.transaction; - obj.transaction_id = op.transaction.get_txid(); - obj.fee_for_size = op.fee_for_size; + obj.pw_vin = mutable_op.pw_vin; + obj.vins = new_vins; + obj.vouts = mutable_op.vouts; + obj.transaction = mutable_op.transaction; + obj.transaction_id = mutable_op.transaction.get_txid(); + obj.fee_for_size = mutable_op.fee_for_size; obj.confirm = false; }); @@ -37,6 +55,19 @@ object_id_type bitcoin_transaction_send_evaluator::do_apply( const bitcoin_trans return btc_tx.id; } +void bitcoin_transaction_send_evaluator::finalize_bitcoin_transaction( bitcoin_transaction_send_operation& op ) +{ + database& d = db(); + + std::vector> new_stacks( sidechain::sort_sigs( op.transaction, op.vins, d.context_verify ) ); + + for( size_t i = 0; i < new_stacks.size(); i++ ) { + op.transaction.vin[i].scriptWitness = new_stacks[i]; + } + + sidechain::sign_witness_transaction_finalize( op.transaction, op.vins ); +} + void bitcoin_transaction_send_evaluator::send_bitcoin_transaction( const bitcoin_transaction_object& btc_tx ) { database& d = db(); diff --git a/libraries/chain/db_init.cpp b/libraries/chain/db_init.cpp index 4554fe83..0fab1944 100644 --- a/libraries/chain/db_init.cpp +++ b/libraries/chain/db_init.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -315,6 +316,7 @@ void database::initialize_indexes() add_index< primary_index >(); add_index< primary_index >(); + add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); add_index< primary_index >(); diff --git a/libraries/chain/db_management.cpp b/libraries/chain/db_management.cpp index ce8041a9..95a7125b 100644 --- a/libraries/chain/db_management.cpp +++ b/libraries/chain/db_management.cpp @@ -40,11 +40,17 @@ database::database() : { initialize_indexes(); initialize_evaluators(); + context_sign = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + context_verify = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); } database::~database() { clear_pending(); + secp256k1_context_destroy(context_sign); + context_sign = nullptr; + secp256k1_context_destroy(context_verify); + context_verify = nullptr; } void database::reindex(fc::path data_dir, const genesis_state_type& initial_allocation) diff --git a/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp b/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp index 6013294c..c402b503 100644 --- a/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/bitcoin_transaction_evaluator.hpp @@ -13,6 +13,8 @@ public: object_id_type do_apply( const bitcoin_transaction_send_operation& op ); + void finalize_bitcoin_transaction( bitcoin_transaction_send_operation& op ); + void send_bitcoin_transaction( const bitcoin_transaction_object& btc_tx ); }; diff --git a/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp b/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp index 3f70fdf5..b2adc786 100644 --- a/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp +++ b/libraries/chain/include/graphene/chain/bitcoin_transaction_object.hpp @@ -14,9 +14,9 @@ class bitcoin_transaction_object : public abstract_object pw_vin; - std::vector< fc::sha256 > vins; + std::vector< info_for_used_vin_id_type > vins; std::vector< info_for_vout_id_type > vouts; sidechain::bitcoin_transaction transaction; diff --git a/libraries/chain/include/graphene/chain/database.hpp b/libraries/chain/include/graphene/chain/database.hpp index 511dfefd..48411d06 100644 --- a/libraries/chain/include/graphene/chain/database.hpp +++ b/libraries/chain/include/graphene/chain/database.hpp @@ -46,6 +46,7 @@ #include #include +#include namespace graphene { namespace chain { using graphene::db::abstract_object; @@ -516,6 +517,10 @@ namespace graphene { namespace chain { fc::signal send_btc_tx; + secp256k1_context_t* context_sign; + + secp256k1_context_t* context_verify; + private: vector< processed_transaction > _pending_tx; diff --git a/libraries/chain/include/graphene/chain/info_for_used_vin_object.hpp b/libraries/chain/include/graphene/chain/info_for_used_vin_object.hpp new file mode 100644 index 00000000..abd4ff67 --- /dev/null +++ b/libraries/chain/include/graphene/chain/info_for_used_vin_object.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include +#include + +namespace graphene { namespace chain { + +class info_for_used_vin_object : public abstract_object +{ + public: + static const uint8_t space_id = protocol_ids; + static const uint8_t type_id = info_for_used_vin_object_type; + + info_for_used_vin_id_type get_id()const { return id; } + + fc::sha256 identifier; + + sidechain::prev_out out; + std::string address; + sidechain::bytes script; +}; + +struct by_id; +struct by_identifier; + +typedef boost::multi_index_container< + info_for_used_vin_object, + indexed_by< + ordered_unique< tag< by_id >, member< object, object_id_type, &object::id > >, + ordered_unique, member> + > +> info_for_used_vin_multi_index_container; +typedef generic_index info_for_used_vin_index; + +} } // graphene::chain + +FC_REFLECT_DERIVED( graphene::chain::info_for_used_vin_object, (graphene::chain::object), (identifier)(out)(address)(script) ) diff --git a/libraries/chain/include/graphene/chain/protocol/bitcoin_transaction.hpp b/libraries/chain/include/graphene/chain/protocol/bitcoin_transaction.hpp index f216a7be..ca444952 100644 --- a/libraries/chain/include/graphene/chain/protocol/bitcoin_transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/bitcoin_transaction.hpp @@ -1,5 +1,6 @@ #pragma once #include +#include #include namespace graphene { namespace chain { @@ -11,16 +12,15 @@ namespace graphene { namespace chain { uint32_t price_per_kbyte = 0; }; - asset fee; - account_id_type payer; + asset fee; + account_id_type payer; - fc::sha256 pw_vin; + fc::optional< fc::sha256 > pw_vin; + std::vector< sidechain::info_for_vin > vins; + std::vector< info_for_vout_id_type > vouts; - std::vector< fc::sha256 > vins; - std::vector< info_for_vout_id_type > vouts; - - sidechain::bitcoin_transaction transaction; - uint64_t fee_for_size; + sidechain::bitcoin_transaction transaction; + uint64_t fee_for_size; account_id_type fee_payer()const { return payer; } void validate()const {} diff --git a/libraries/chain/include/graphene/chain/protocol/types.hpp b/libraries/chain/include/graphene/chain/protocol/types.hpp index 69c17669..4b7b2b30 100644 --- a/libraries/chain/include/graphene/chain/protocol/types.hpp +++ b/libraries/chain/include/graphene/chain/protocol/types.hpp @@ -146,6 +146,7 @@ namespace graphene { namespace chain { betting_market_object_type, bet_object_type, info_for_vout_object_type, + info_for_used_vin_object_type, bitcoin_address_object_type, primary_wallet_vout_object_type, sidechain_proposal_object_type, @@ -208,6 +209,7 @@ namespace graphene { namespace chain { class betting_market_object; class bet_object; class info_for_vout_object; + class info_for_used_vin_object; class bitcoin_address_object; class primary_wallet_vout_object; class sidechain_proposal_object; @@ -239,6 +241,7 @@ namespace graphene { namespace chain { typedef object_id< protocol_ids, betting_market_object_type, betting_market_object> betting_market_id_type; typedef object_id< protocol_ids, bet_object_type, bet_object> bet_id_type; typedef object_id< protocol_ids, info_for_vout_object_type, info_for_vout_object> info_for_vout_id_type; + typedef object_id< protocol_ids, info_for_used_vin_object_type, info_for_used_vin_object> info_for_used_vin_id_type; typedef object_id< protocol_ids, bitcoin_address_object_type, bitcoin_address_object> bitcoin_address_id_type; typedef object_id< protocol_ids, primary_wallet_vout_object_type, primary_wallet_vout_object> primary_wallet_vout_id_type; typedef object_id< protocol_ids, sidechain_proposal_object_type, sidechain_proposal_object> sidechain_proposal_id_type; @@ -418,6 +421,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type, (betting_market_object_type) (bet_object_type) (info_for_vout_object_type) + (info_for_used_vin_object_type) (bitcoin_address_object_type) (primary_wallet_vout_object_type) (sidechain_proposal_object_type) @@ -474,6 +478,7 @@ FC_REFLECT_TYPENAME( graphene::chain::betting_market_id_type ) FC_REFLECT_TYPENAME( graphene::chain::bet_id_type ) FC_REFLECT_TYPENAME( graphene::chain::tournament_id_type ) FC_REFLECT_TYPENAME( graphene::chain::info_for_vout_id_type ) +FC_REFLECT_TYPENAME( graphene::chain::info_for_used_vin_id_type ) FC_REFLECT_TYPENAME( graphene::chain::bitcoin_address_id_type ) FC_REFLECT_TYPENAME( graphene::chain::primary_wallet_vout_id_type ) FC_REFLECT_TYPENAME( graphene::chain::sidechain_proposal_id_type ) diff --git a/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp b/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp index c1955158..57724028 100644 --- a/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp +++ b/libraries/sidechain/include/sidechain/input_withdrawal_info.hpp @@ -103,3 +103,5 @@ private: }; } + +FC_REFLECT( sidechain::info_for_vin, (identifier)(out)(address)(script)(created) ) \ No newline at end of file diff --git a/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp b/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp index fc045f7c..11b6e4c4 100644 --- a/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp +++ b/libraries/sidechain/include/sidechain/sign_bitcoin_transaction.hpp @@ -16,7 +16,7 @@ std::vector privkey_sign( const bytes& privkey, const fc::sha256 &hash, co std::vector< bytes > sign_witness_transaction_part( const bitcoin_transaction& tx, const std::vector& info_vins, const bytes& privkey, const secp256k1_context_t* context_sign = nullptr, int hash_type = 1 ); -void sign_witness_transaction_finalize( bitcoin_transaction& tx, const std::vector< bytes >& redeemScripts ); +void sign_witness_transaction_finalize( bitcoin_transaction& tx, const std::vector& info_vins ); bool verify_sig( const bytes& sig, const bytes& pubkey, const bytes& msg, const secp256k1_context_t* context ); diff --git a/libraries/sidechain/sign_bitcoin_transaction.cpp b/libraries/sidechain/sign_bitcoin_transaction.cpp index 75b8a13c..bc282946 100644 --- a/libraries/sidechain/sign_bitcoin_transaction.cpp +++ b/libraries/sidechain/sign_bitcoin_transaction.cpp @@ -61,13 +61,13 @@ std::vector sign_witness_transaction_part( const bitcoin_transaction& tx, return signatures; } -void sign_witness_transaction_finalize( bitcoin_transaction& tx, const std::vector& redeemScripts ) +void sign_witness_transaction_finalize( bitcoin_transaction& tx, const std::vector& info_vins ) { - FC_ASSERT( tx.vin.size() == redeemScripts.size() ); + FC_ASSERT( tx.vin.size() == info_vins.size() ); for( size_t i = 0; i < tx.vin.size(); i++ ) { tx.vin[i].scriptWitness.insert( tx.vin[i].scriptWitness.begin(), bytes() ); // Bitcoin workaround CHECKMULTISIG bug - tx.vin[i].scriptWitness.push_back( redeemScripts[i] ); + tx.vin[i].scriptWitness.push_back( info_vins[i].script ); } } diff --git a/tests/tests/bitcoin_sign_tests.cpp b/tests/tests/bitcoin_sign_tests.cpp index f3094551..c524d0f3 100644 --- a/tests/tests/bitcoin_sign_tests.cpp +++ b/tests/tests/bitcoin_sign_tests.cpp @@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE( btc_tx_witness_signature_test ) secp256k1_context_t* context_sign = secp256k1_context_create( SECP256K1_CONTEXT_SIGN ); tx.vin[0].scriptWitness.push_back( sign_witness_transaction_part( tx, { vin }, privkey_1, context_sign, hash_type)[0] ); tx.vin[0].scriptWitness.push_back( sign_witness_transaction_part( tx, { vin }, privkey_2, context_sign, hash_type)[0] ); - sign_witness_transaction_finalize( tx, { redeemScript } ); + sign_witness_transaction_finalize( tx, { vin } ); BOOST_CHECK( fc::to_hex( pack( tx ) ) == "0100000000010145310e878941a1b2bc2d33797ee4d89d95eaaf2e13488063a2aa9a74490f510a0100000023220020b6744de4f6ec63cc92f7c220cdefeeb1b1bed2b66c8e5706d80ec247d37e65a1ffffffff01002d3101000000001976a9143ebc40e411ed3c76f86711507ab952300890397288ac0400473044022001dd489a5d4e2fbd8a3ade27177f6b49296ba7695c40dbbe650ea83f106415fd02200b23a0602d8ff1bdf79dee118205fc7e9b40672bf31563e5741feb53fb86388501483045022100f88f040e90cc5dc6c6189d04718376ac19ed996bf9e4a3c29c3718d90ffd27180220761711f16c9e3a44f71aab55cbc0634907a1fa8bb635d971a9a01d368727bea10169522103b3623117e988b76aaabe3d63f56a4fc88b228a71e64c4cc551d1204822fe85cb2103dd823066e096f72ed617a41d3ca56717db335b1ea47a1b4c5c9dbdd0963acba621033d7c89bd9da29fa8d44db7906a9778b53121f72191184a9fee785c39180e4be153ae00000000" ); diff --git a/tests/tests/primary_wallet_vout_manager_tests.cpp b/tests/tests/primary_wallet_vout_manager_tests.cpp index 30dcca58..27d4d29f 100644 --- a/tests/tests/primary_wallet_vout_manager_tests.cpp +++ b/tests/tests/primary_wallet_vout_manager_tests.cpp @@ -125,11 +125,11 @@ BOOST_AUTO_TEST_CASE( use_pw_vout_objects ) { const auto& idx = db.get_index_type().indices().get< graphene::chain::by_id >(); primary_wallet_vout_manager pw_vout_manager( db ); - auto itr = idx.begin(); create_primary_wallet_vouts( pw_vout_manager, db, 1 ); pw_vout_manager.use_latest_vout( fc::sha256::hash( "0" + std::to_string( 0 ))); + auto itr = idx.begin(); BOOST_CHECK( !pw_vout_manager.get_latest_unused_vout().valid() ); BOOST_CHECK( itr->used == true );