Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #7043 from EOSIO/sign-key-future-dev
Browse files Browse the repository at this point in the history
Use shared_future - develop
  • Loading branch information
heifner authored Apr 2, 2019
2 parents 0c68d50 + bdce0de commit 91c7806
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 49 deletions.
7 changes: 4 additions & 3 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -994,9 +994,10 @@ struct controller_impl {
auto start = fc::time_point::now();
const bool check_auth = !self.skip_auth_check() && !trx->implicit;
// call recover keys so that trx->sig_cpu_usage is set correctly
const flat_set<public_key_type>& recovered_keys = check_auth ? trx->recover_keys( chain_id ) : flat_set<public_key_type>();
const fc::microseconds sig_cpu_usage = check_auth ? std::get<0>( trx->recover_keys( chain_id ) ) : fc::microseconds();
const flat_set<public_key_type>& recovered_keys = check_auth ? std::get<1>( trx->recover_keys( chain_id ) ) : flat_set<public_key_type>();
if( !explicit_billed_cpu_time ) {
fc::microseconds already_consumed_time( EOS_PERCENT(trx->sig_cpu_usage.count(), conf.sig_cpu_bill_pct) );
fc::microseconds already_consumed_time( EOS_PERCENT(sig_cpu_usage.count(), conf.sig_cpu_bill_pct) );

if( start.time_since_epoch() < already_consumed_time ) {
start = fc::time_point();
Expand Down Expand Up @@ -1194,7 +1195,7 @@ struct controller_impl {
auto& pt = receipt.trx.get<packed_transaction>();
auto mtrx = std::make_shared<transaction_metadata>( std::make_shared<packed_transaction>( pt ) );
if( !self.skip_auth_check() ) {
transaction_metadata::create_signing_keys_future( mtrx, thread_pool, chain_id, microseconds::maximum() );
transaction_metadata::start_recover_keys( mtrx, thread_pool, chain_id, microseconds::maximum() );
}
packed_transactions.emplace_back( std::move( mtrx ) );
}
Expand Down
19 changes: 12 additions & 7 deletions libraries/chain/include/eosio/chain/transaction_metadata.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ namespace eosio { namespace chain {

class transaction_metadata;
using transaction_metadata_ptr = std::shared_ptr<transaction_metadata>;
using signing_keys_future_value_type = std::tuple<chain_id_type, fc::microseconds, flat_set<public_key_type>>;
using signing_keys_future_type = std::shared_future<signing_keys_future_value_type>;
using recovery_keys_type = std::pair<fc::microseconds, const flat_set<public_key_type>&>;

/**
* This data structure should store context-free cached data about a transaction such as
* packed/unpacked/compressed and recovered keys
Expand All @@ -24,10 +28,7 @@ class transaction_metadata {
transaction_id_type id;
transaction_id_type signed_id;
packed_transaction_ptr packed_trx;
fc::microseconds sig_cpu_usage;
optional<pair<chain_id_type, flat_set<public_key_type>>> signing_keys;
std::future<std::tuple<chain_id_type, fc::microseconds, flat_set<public_key_type>>>
signing_keys_future;
signing_keys_future_type signing_keys_future;
bool accepted = false;
bool implicit = false;
bool scheduled = false;
Expand All @@ -50,10 +51,14 @@ class transaction_metadata {
signed_id = digest_type::hash(*packed_trx);
}

const flat_set<public_key_type>& recover_keys( const chain_id_type& chain_id );
// must be called from main application thread
static signing_keys_future_type
start_recover_keys( const transaction_metadata_ptr& mtrx, boost::asio::thread_pool& thread_pool,
const chain_id_type& chain_id, fc::microseconds time_limit );

// start_recover_keys must be called first
recovery_keys_type recover_keys( const chain_id_type& chain_id );

static void create_signing_keys_future( const transaction_metadata_ptr& mtrx, boost::asio::thread_pool& thread_pool,
const chain_id_type& chain_id, fc::microseconds time_limit );

};

Expand Down
45 changes: 26 additions & 19 deletions libraries/chain/transaction_metadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,39 @@

namespace eosio { namespace chain {


const flat_set<public_key_type>& transaction_metadata::recover_keys( const chain_id_type& chain_id ) {
recovery_keys_type transaction_metadata::recover_keys( const chain_id_type& chain_id ) {
// Unlikely for more than one chain_id to be used in one nodeos instance
if( !signing_keys || signing_keys->first != chain_id ) {
if( signing_keys_future.valid() ) {
std::tuple<chain_id_type, fc::microseconds, flat_set<public_key_type>> sig_keys = signing_keys_future.get();
if( std::get<0>( sig_keys ) == chain_id ) {
sig_cpu_usage = std::get<1>( sig_keys );
signing_keys.emplace( std::get<0>( sig_keys ), std::move( std::get<2>( sig_keys )));
return signing_keys->second;
}
if( signing_keys_future.valid() ) {
const std::tuple<chain_id_type, fc::microseconds, flat_set<public_key_type>>& sig_keys = signing_keys_future.get();
if( std::get<0>( sig_keys ) == chain_id ) {
return std::make_pair( std::get<1>( sig_keys ), std::cref( std::get<2>( sig_keys ) ) );
}
flat_set<public_key_type> recovered_pub_keys;
sig_cpu_usage = packed_trx->get_signed_transaction().get_signature_keys( chain_id, fc::time_point::maximum(), recovered_pub_keys );
signing_keys.emplace( chain_id, std::move( recovered_pub_keys ));
}
return signing_keys->second;

// shared_keys_future not created or different chain_id
std::promise<signing_keys_future_value_type> p;
flat_set<public_key_type> recovered_pub_keys;
const signed_transaction& trn = packed_trx->get_signed_transaction();
fc::microseconds cpu_usage = trn.get_signature_keys( chain_id, fc::time_point::maximum(), recovered_pub_keys );
p.set_value( std::make_tuple( chain_id, cpu_usage, std::move( recovered_pub_keys ) ) );
signing_keys_future = p.get_future().share();

const std::tuple<chain_id_type, fc::microseconds, flat_set<public_key_type>>& sig_keys = signing_keys_future.get();
return std::make_pair( std::get<1>( sig_keys ), std::cref( std::get<2>( sig_keys ) ) );
}

void transaction_metadata::create_signing_keys_future( const transaction_metadata_ptr& mtrx,
boost::asio::thread_pool& thread_pool, const chain_id_type& chain_id, fc::microseconds time_limit ) {
if( mtrx->signing_keys_future.valid() || mtrx->signing_keys.valid() ) // already created
return;
signing_keys_future_type transaction_metadata::start_recover_keys( const transaction_metadata_ptr& mtrx,
boost::asio::thread_pool& thread_pool,
const chain_id_type& chain_id,
fc::microseconds time_limit )
{
if( mtrx->signing_keys_future.valid() && std::get<0>( mtrx->signing_keys_future.get() ) == chain_id ) // already created
return mtrx->signing_keys_future;

std::weak_ptr<transaction_metadata> mtrx_wp = mtrx;
mtrx->signing_keys_future = async_thread_pool( thread_pool, [time_limit, chain_id, mtrx_wp]() {
fc::time_point deadline = time_limit == fc::microseconds::maximum() ?
fc::time_point::maximum() : fc::time_point::now() + time_limit;
fc::time_point::maximum() : fc::time_point::now() + time_limit;
auto mtrx = mtrx_wp.lock();
fc::microseconds cpu_usage;
flat_set<public_key_type> recovered_pub_keys;
Expand All @@ -41,6 +46,8 @@ void transaction_metadata::create_signing_keys_future( const transaction_metadat
}
return std::make_tuple( chain_id, cpu_usage, std::move( recovered_pub_keys ));
} );

return mtrx->signing_keys_future;
}


Expand Down
15 changes: 13 additions & 2 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,13 @@ namespace eosio { namespace testing {
{ try {
if( !control->pending_block_state() )
_start_block(control->head_block_time() + fc::microseconds(config::block_interval_us));
auto r = control->push_transaction( std::make_shared<transaction_metadata>(std::make_shared<packed_transaction>(trx)), deadline, billed_cpu_time_us );

auto mtrx = std::make_shared<transaction_metadata>( std::make_shared<packed_transaction>(trx) );
auto time_limit = deadline == fc::time_point::maximum() ?
fc::microseconds::maximum() :
fc::microseconds( deadline - fc::time_point::now() );
transaction_metadata::start_recover_keys( mtrx, control->get_thread_pool(), control->get_chain_id(), time_limit );
auto r = control->push_transaction( mtrx, deadline, billed_cpu_time_us );
if( r->except_ptr ) std::rethrow_exception( r->except_ptr );
if( r->except ) throw *r->except;
return r;
Expand All @@ -365,7 +371,12 @@ namespace eosio { namespace testing {
c = packed_transaction::zlib;
}

auto r = control->push_transaction( std::make_shared<transaction_metadata>(trx,c), deadline, billed_cpu_time_us );
auto time_limit = deadline == fc::time_point::maximum() ?
fc::microseconds::maximum() :
fc::microseconds( deadline - fc::time_point::now() );
auto mtrx = std::make_shared<transaction_metadata>(trx, c);
transaction_metadata::start_recover_keys( mtrx, control->get_thread_pool(), control->get_chain_id(), time_limit );
auto r = control->push_transaction( mtrx, deadline, billed_cpu_time_us );
if( r->except_ptr ) std::rethrow_exception( r->except_ptr );
if( r->except) throw *r->except;
return r;
Expand Down
4 changes: 2 additions & 2 deletions plugins/mongo_db_plugin/mongo_db_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -780,8 +780,8 @@ void mongo_db_plugin_impl::_process_accepted_transaction( const chain::transacti
}

string signing_keys_json;
if( t->signing_keys.valid() ) {
signing_keys_json = fc::json::to_string( t->signing_keys->second );
if( t->signing_keys_future.valid() ) {
signing_keys_json = fc::json::to_string( std::get<2>( t->signing_keys_future.get() ) );
} else {
flat_set<public_key_type> keys;
trx.get_signature_keys( *chain_id, fc::time_point::maximum(), keys, false );
Expand Down
9 changes: 5 additions & 4 deletions plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,10 +351,11 @@ class producer_plugin_impl : public std::enable_shared_from_this<producer_plugin
void on_incoming_transaction_async(const transaction_metadata_ptr& trx, bool persist_until_expired, next_function<transaction_trace_ptr> next) {
chain::controller& chain = chain_plug->chain();
const auto& cfg = chain.get_global_properties().configuration;
transaction_metadata::create_signing_keys_future( trx, *_thread_pool, chain.get_chain_id(), fc::microseconds( cfg.max_transaction_cpu_usage ) );
boost::asio::post( *_thread_pool, [self = this, trx, persist_until_expired, next]() {
if( trx->signing_keys_future.valid() )
trx->signing_keys_future.wait();
signing_keys_future_type future = transaction_metadata::start_recover_keys( trx, *_thread_pool,
chain.get_chain_id(), fc::microseconds( cfg.max_transaction_cpu_usage ) );
boost::asio::post( *_thread_pool, [self = this, future, trx, persist_until_expired, next]() {
if( future.valid() )
future.wait();
app().post(priority::low, [self, trx, persist_until_expired, next]() {
self->process_incoming_transaction_async( trx, persist_until_expired, next );
});
Expand Down
35 changes: 23 additions & 12 deletions unittests/misc_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -834,29 +834,40 @@ BOOST_AUTO_TEST_CASE(transaction_metadata_test) { try {
BOOST_CHECK( !mtrx->signing_keys_future.valid() );
BOOST_CHECK( !mtrx2->signing_keys_future.valid() );

transaction_metadata::create_signing_keys_future( mtrx, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );
transaction_metadata::create_signing_keys_future( mtrx2, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );
transaction_metadata::start_recover_keys( mtrx, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );
transaction_metadata::start_recover_keys( mtrx2, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );

BOOST_CHECK( mtrx->signing_keys_future.valid() );
BOOST_CHECK( mtrx2->signing_keys_future.valid() );

// no-op
transaction_metadata::create_signing_keys_future( mtrx, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );
transaction_metadata::create_signing_keys_future( mtrx2, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );
transaction_metadata::start_recover_keys( mtrx, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );
transaction_metadata::start_recover_keys( mtrx2, thread_pool, test.control->get_chain_id(), fc::microseconds::maximum() );

auto keys = mtrx->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys.size());
BOOST_CHECK_EQUAL(public_key, *keys.begin());
BOOST_CHECK_EQUAL(1u, keys.second.size());
BOOST_CHECK_EQUAL(public_key, *keys.second.begin());

// again
keys = mtrx->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys.size());
BOOST_CHECK_EQUAL(public_key, *keys.begin());
auto keys2 = mtrx->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys2.second.size());
BOOST_CHECK_EQUAL(public_key, *keys2.second.begin());

auto keys2 = mtrx2->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys.size());
BOOST_CHECK_EQUAL(public_key, *keys.begin());
auto keys3 = mtrx2->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys3.second.size());
BOOST_CHECK_EQUAL(public_key, *keys3.second.begin());

// recover keys without first calling start_recover_keys
transaction_metadata_ptr mtrx4 = std::make_shared<transaction_metadata>( std::make_shared<packed_transaction>( trx, packed_transaction::none) );
transaction_metadata_ptr mtrx5 = std::make_shared<transaction_metadata>( std::make_shared<packed_transaction>( trx, packed_transaction::zlib) );

auto keys4 = mtrx4->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys4.second.size());
BOOST_CHECK_EQUAL(public_key, *keys4.second.begin());

auto keys5 = mtrx5->recover_keys( test.control->get_chain_id() );
BOOST_CHECK_EQUAL(1u, keys5.second.size());
BOOST_CHECK_EQUAL(public_key, *keys5.second.begin());

} FC_LOG_AND_RETHROW() }

Expand Down

0 comments on commit 91c7806

Please sign in to comment.