From 56a6f8b7327a96f01abf9896acdceeb7897115e0 Mon Sep 17 00:00:00 2001 From: abitmore Date: Wed, 22 Aug 2018 18:00:05 -0400 Subject: [PATCH] Extract public keys before pushing a transaction --- libraries/app/api.cpp | 14 +++++++++----- libraries/app/application.cpp | 1 + .../graphene/chain/protocol/transaction.hpp | 19 +++++++++++++++++-- libraries/chain/protocol/transaction.cpp | 9 +++++++++ tests/common/database_fixture.cpp | 2 +- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/libraries/app/api.cpp b/libraries/app/api.cpp index 318ad821..ee1ba043 100644 --- a/libraries/app/api.cpp +++ b/libraries/app/api.cpp @@ -169,9 +169,11 @@ namespace graphene { namespace app { void network_broadcast_api::broadcast_transaction(const signed_transaction& trx) { trx.validate(); - _app.chain_database()->check_tansaction_for_duplicated_operations(trx); - _app.chain_database()->push_transaction(trx); - _app.p2p_node()->broadcast_transaction(trx); + const auto& chain_db = _app.chain_database(); + chain_db->check_tansaction_for_duplicated_operations(trx); + chain_db->push_transaction( signed_transaction( trx, chain_db->get_chain_id() ) ); + if( _app.p2p_node() != nullptr ) + _app.p2p_node()->broadcast_transaction(trx); } fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx) @@ -196,8 +198,10 @@ namespace graphene { namespace app { { trx.validate(); _callbacks[trx.id()] = cb; - _app.chain_database()->push_transaction(trx); - _app.p2p_node()->broadcast_transaction(trx); + const auto& chain_db = _app.chain_database(); + chain_db->push_transaction( signed_transaction( trx, chain_db->get_chain_id() ) ); + if( _app.p2p_node() != nullptr ) + _app.p2p_node()->broadcast_transaction(trx); } network_node_api::network_node_api( application& a ) : _app( a ) diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index 75cb95fd..a2f75a28 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -506,6 +506,7 @@ namespace detail { } } + _chain_db->push_transaction( signed_transaction( transaction_message.trx, get_chain_id() ) ); return result; } catch ( const graphene::chain::unlinkable_block_exception& e ) { // translate to a graphene::net exception diff --git a/libraries/chain/include/graphene/chain/protocol/transaction.hpp b/libraries/chain/include/graphene/chain/protocol/transaction.hpp index 4d529a27..a2864df6 100644 --- a/libraries/chain/include/graphene/chain/protocol/transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/transaction.hpp @@ -123,6 +123,13 @@ namespace graphene { namespace chain { signed_transaction( const transaction& trx = transaction() ) : transaction(trx){} + /** Extract public keys from signatures when initializing with another signed transaction and a chain ID */ + signed_transaction( const signed_transaction& trx, const chain_id_type& chain_id ) + : signed_transaction(trx) + { + signees = _get_signature_keys( chain_id ); + } + /** signs and appends to signatures */ const signature_type& sign( const private_key_type& key, const chain_id_type& chain_id ); @@ -169,8 +176,15 @@ namespace graphene { namespace chain { vector signatures; - /// Removes all operations and signatures - void clear() { operations.clear(); signatures.clear(); } + /** Extracted public keys from signatures if this object was initialized with a chain ID. */ + flat_set signees; + + /// Removes all operations, signatures and signees + void clear() { operations.clear(); signatures.clear(); signees.clear(); } + + private: + /// To be used by constructor and get_signature_keys() function + flat_set _get_signature_keys( const chain_id_type& chain_id )const; }; void verify_authority( const vector& ops, const flat_set& sigs, @@ -209,5 +223,6 @@ namespace graphene { namespace chain { } } // graphene::chain FC_REFLECT( graphene::chain::transaction, (ref_block_num)(ref_block_prefix)(expiration)(operations)(extensions) ) +// Note: not reflecting signees field for backward compatibility; in addition, it should not be in p2p messages FC_REFLECT_DERIVED( graphene::chain::signed_transaction, (graphene::chain::transaction), (signatures) ) FC_REFLECT_DERIVED( graphene::chain::processed_transaction, (graphene::chain::signed_transaction), (operation_results) ) diff --git a/libraries/chain/protocol/transaction.cpp b/libraries/chain/protocol/transaction.cpp index 5faf1c0a..ae7695f4 100644 --- a/libraries/chain/protocol/transaction.cpp +++ b/libraries/chain/protocol/transaction.cpp @@ -298,6 +298,15 @@ void verify_authority( const vector& ops, const flat_set signed_transaction::get_signature_keys( const chain_id_type& chain_id )const +{ + // Strictly we should check whether the given chain ID is same as the one used to initialize the object. + // However, we don't pass in another chain ID so far, for better performance, we skip the check. + if( !signees.empty() || signatures.empty() ) + return signees; + return _get_signature_keys( chain_id ); +} + +flat_set signed_transaction::_get_signature_keys( const chain_id_type& chain_id )const { try { auto d = sig_digest( chain_id ); flat_set result; diff --git a/tests/common/database_fixture.cpp b/tests/common/database_fixture.cpp index a2691c09..32731785 100644 --- a/tests/common/database_fixture.cpp +++ b/tests/common/database_fixture.cpp @@ -1564,7 +1564,7 @@ bool _push_block( database& db, const signed_block& b, uint32_t skip_flags /* = processed_transaction _push_transaction( database& db, const signed_transaction& tx, uint32_t skip_flags /* = 0 */ ) { try { - auto pt = db.push_transaction( tx, skip_flags ); + auto pt = db.push_transaction( signed_transaction( tx, db.get_chain_id() ), skip_flags ); database_fixture::verify_asset_supplies(db); return pt; } FC_CAPTURE_AND_RETHROW((tx)) }