diff --git a/libraries/fc b/libraries/fc index b3816115eb5..4dc8375d7d3 160000 --- a/libraries/fc +++ b/libraries/fc @@ -1 +1 @@ -Subproject commit b3816115eb5452dbce1c62c0cb7c2d98233ae0f2 +Subproject commit 4dc8375d7d3e02ab1177ab5c22835f75b45c845a diff --git a/libraries/wabt b/libraries/wabt index 270e1f9ee63..e7d6948d242 160000 --- a/libraries/wabt +++ b/libraries/wabt @@ -1 +1 @@ -Subproject commit 270e1f9ee63004578c82a2fe594b81afd84c1631 +Subproject commit e7d6948d242a9931436c38275d59a9c6036c4095 diff --git a/plugins/history_plugin/history_plugin.cpp b/plugins/history_plugin/history_plugin.cpp index 2911d4dc240..3c3650b9e59 100644 --- a/plugins/history_plugin/history_plugin.cpp +++ b/plugins/history_plugin/history_plugin.cpp @@ -10,7 +10,7 @@ #include #include -namespace eosio { +namespace eosio { using namespace chain; using boost::signals2::scoped_connection; @@ -51,7 +51,7 @@ namespace eosio { indexed_by< ordered_unique, member>, ordered_unique, member>, - ordered_unique, + ordered_unique, composite_key< action_history_object, member, member @@ -64,7 +64,7 @@ namespace eosio { account_history_object, indexed_by< ordered_unique, member>, - ordered_unique, + ordered_unique, composite_key< account_history_object, member, member @@ -213,7 +213,7 @@ namespace eosio { uint64_t asn = 0; if( itr != idx.begin() ) --itr; - if( itr->account == n ) + if( itr->account == n ) asn = itr->account_sequence_num + 1; //idump((n)(act.receipt.global_sequence)(asn)); @@ -268,7 +268,7 @@ namespace eosio { aho.block_time = chain.pending_block_time(); aho.trx_id = at.trx_id; }); - + auto aset = account_set( at ); for( auto a : aset ) { record_account_action( a, at ); @@ -366,7 +366,7 @@ namespace eosio { - namespace history_apis { + namespace history_apis { read_only::get_actions_result read_only::get_actions( const read_only::get_actions_params& params )const { edump((params)); auto& chain = history->chain_plug->chain(); @@ -388,7 +388,7 @@ namespace eosio { pos = itr->account_sequence_num+1; } else if( itr != idx.begin() ) --itr; - if( itr->account == n ) + if( itr->account == n ) pos = itr->account_sequence_num + 1; } @@ -440,13 +440,31 @@ namespace eosio { read_only::get_transaction_result read_only::get_transaction( const read_only::get_transaction_params& p )const { auto& chain = history->chain_plug->chain(); const auto abi_serializer_max_time = history->chain_plug->get_abi_serializer_max_time(); - auto short_id = fc::variant(p.id).as_string().substr(0,8); + + transaction_id_type input_id; + auto input_id_length = p.id.size(); + try { + FC_ASSERT( input_id_length <= 64, "hex string is too long to represent an actual transaction id" ); + FC_ASSERT( input_id_length >= 8, "hex string representing transaction id should be at least 8 characters long to avoid excessive collisions" ); + input_id = transaction_id_type(p.id); + } EOS_RETHROW_EXCEPTIONS(transaction_id_type_exception, "Invalid transaction ID: ${transaction_id}", ("transaction_id", p.id)) + + auto txn_id_matched = [&input_id, input_id_size = input_id_length/2, no_half_byte_at_end = (input_id_length % 2 == 0)] + ( const transaction_id_type &id ) -> bool // hex prefix comparison + { + bool whole_byte_prefix_matches = memcmp( input_id.data(), id.data(), input_id_size ) == 0; + if( !whole_byte_prefix_matches || no_half_byte_at_end ) + return whole_byte_prefix_matches; + + // check if half byte at end of specified part of input_id matches + return (*(input_id.data() + input_id_size) & 0xF0) == (*(id.data() + input_id_size) & 0xF0); + }; const auto& db = chain.db(); const auto& idx = db.get_index(); - auto itr = idx.lower_bound( boost::make_tuple(p.id) ); + auto itr = idx.lower_bound( boost::make_tuple( input_id ) ); - bool in_history = (itr != idx.end() && fc::variant(itr->trx_id).as_string().substr(0,8) == short_id ); + bool in_history = (itr != idx.end() && txn_id_matched(itr->trx_id) ); if( !in_history && !p.block_num_hint ) { EOS_THROW(tx_not_found, "Transaction ${id} not found in history and no block hint was given", ("id",p.id)); @@ -454,12 +472,9 @@ namespace eosio { get_transaction_result result; - if (in_history) { - result.id = p.id; - result.last_irreversible_block = chain.last_irreversible_block_num(); - - + if( in_history ) { result.id = itr->trx_id; + result.last_irreversible_block = chain.last_irreversible_block_num(); result.block_num = itr->block_num; result.block_time = itr->block_time; @@ -509,7 +524,7 @@ namespace eosio { if (receipt.trx.contains()) { auto& pt = receipt.trx.get(); auto mtrx = transaction_metadata(pt); - if (fc::variant(mtrx.id).as_string().substr(0, 8) == short_id) { + if( txn_id_matched(mtrx.id) ) { result.id = mtrx.id; result.last_irreversible_block = chain.last_irreversible_block_num(); result.block_num = *p.block_num_hint; @@ -522,7 +537,7 @@ namespace eosio { } } else { auto& id = receipt.trx.get(); - if (fc::variant(id).as_string().substr(0, 8) == short_id) { + if( txn_id_matched(id) ) { result.id = id; result.last_irreversible_block = chain.last_irreversible_block_num(); result.block_num = *p.block_num_hint; diff --git a/plugins/history_plugin/include/eosio/history_plugin/history_plugin.hpp b/plugins/history_plugin/include/eosio/history_plugin/history_plugin.hpp index 402c0e3966d..b6801b30a29 100644 --- a/plugins/history_plugin/include/eosio/history_plugin/history_plugin.hpp +++ b/plugins/history_plugin/include/eosio/history_plugin/history_plugin.hpp @@ -30,18 +30,6 @@ class read_only { : history(history) {} - /* - struct get_transaction_params { - chain::transaction_id_type transaction_id; - }; - struct get_transaction_results { - chain::transaction_id_type transaction_id; - fc::variant transaction; - }; - get_transaction_results get_transaction(const get_transaction_params& params) const; - */ - - struct get_actions_params { chain::account_name account_name; optional pos; /// a absolute sequence positon -1 is the end/last action @@ -67,7 +55,7 @@ class read_only { struct get_transaction_params { - transaction_id_type id; + string id; optional block_num_hint; }; @@ -81,7 +69,7 @@ class read_only { }; get_transaction_result get_transaction( const get_transaction_params& )const; - + @@ -120,13 +108,13 @@ class read_only { /** * This plugin tracks all actions and keys associated with a set of configured accounts. It enables - * wallets to paginate queries for history. + * wallets to paginate queries for history. * * An action will be included in the account's history if any of the following: * - receiver * - any account named in auth list * - * A key will be linked to an account if the key is referneced in authorities of updateauth or newaccount + * A key will be linked to an account if the key is referneced in authorities of updateauth or newaccount */ class history_plugin : public plugin { public: diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 49b38d13a37..b4acd6faf72 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -2133,12 +2133,7 @@ int main( int argc, char** argv ) { getTransaction->add_option("id", transaction_id_str, localized("ID of the transaction to retrieve"))->required(); getTransaction->add_option( "-b,--block-hint", block_num_hint, localized("the block number this transaction may be in") ); getTransaction->set_callback([&] { - transaction_id_type transaction_id; - try { - while( transaction_id_str.size() < 64 ) transaction_id_str += "0"; - transaction_id = transaction_id_type(transaction_id_str); - } EOS_RETHROW_EXCEPTIONS(transaction_id_type_exception, "Invalid transaction ID: ${transaction_id}", ("transaction_id", transaction_id_str)) - auto arg= fc::mutable_variant_object( "id", transaction_id); + auto arg= fc::mutable_variant_object( "id", transaction_id_str); if ( block_num_hint > 0 ) { arg = arg("block_num_hint", block_num_hint); }