diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 5dd7ecbb2e0a2e82008ba8d39cabf5f2e5d36250..af803eef5245e5386a59b5dca48f5f7f4c91e01a 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -490,7 +490,10 @@ struct controller_impl { transaction_context trx_context( self, trx->trx, trx->id ); trace = trx_context.trace; - auto required_delay = limit_delay( authorization.check_authorization( trx->trx.actions, trx->recover_keys() ) ); + fc::microseconds required_delay(0); + if (!implicit) { + required_delay = limit_delay( authorization.check_authorization( trx->trx.actions, trx->recover_keys() ) ); + } trx_context.delay = fc::seconds(trx->trx.delay_sec); EOS_ASSERT( trx_context.delay >= required_delay, transaction_exception, "authorization imposes a delay (${required_delay} sec) greater than the delay specified in transaction header (${specified_delay} sec)", @@ -761,7 +764,41 @@ struct controller_impl { void update_producers_authority() { const auto& producers = pending->_pending_block_state->active_schedule.producers; - //TODO: Complete implementation + + auto update_permission = [&]( auto& permission, auto threshold ) { + auto auth = authority( threshold, {}, {}); + for( auto& p : producers ) { + auth.accounts.push_back({{p.producer_name, config::active_name}, 1}); + } + + if( static_cast(permission.auth) != auth ) { // TODO: use a more efficient way to check that authority has not changed + db.modify(permission, [&]( auto& po ) { + po.auth = auth; + }); + } + }; + + uint32_t num_producers = producers.size(); + auto calculate_threshold = [=]( uint32_t numerator, uint32_t denominator ) { + return ( (num_producers * numerator) / denominator ) + 1; + }; + + update_permission( authorization.get_permission({config::producers_account_name, + config::active_name}), + calculate_threshold( 2, 3 ) /* more than two-thirds */ ); + + update_permission( authorization.get_permission({config::producers_account_name, + config::majority_producers_permission_name}), + calculate_threshold( 1, 2 ) /* more than one-half */ ); + + update_permission( authorization.get_permission({config::producers_account_name, + config::minority_producers_permission_name}), + calculate_threshold( 1, 3 ) /* more than one-third */ ); + + update_permission( authorization.get_permission({config::producers_account_name, + config::any_producer_permission_name}), 1 ); + + //TODO: Add tests } void create_block_summary(const block_id_type& id) { diff --git a/libraries/chain/include/eosio/chain/authority.hpp b/libraries/chain/include/eosio/chain/authority.hpp index 000a3920676edd6c5887f4e8842271dfaa44c246..f933f6e150d23251222a03abcc42cf20fe530d58 100644 --- a/libraries/chain/include/eosio/chain/authority.hpp +++ b/libraries/chain/include/eosio/chain/authority.hpp @@ -56,6 +56,10 @@ struct authority { friend bool operator == ( const authority& lhs, const authority& rhs ) { return tie( lhs.threshold, lhs.delay_sec, lhs.keys, lhs.accounts ) == tie( rhs.threshold, rhs.delay_sec, rhs.keys, rhs.accounts ); } + + friend bool operator != ( const authority& lhs, const authority& rhs ) { + return tie( lhs.threshold, lhs.delay_sec, lhs.keys, lhs.accounts ) != tie( rhs.threshold, rhs.delay_sec, rhs.keys, rhs.accounts ); + } }; diff --git a/libraries/chain/include/eosio/chain/config.hpp b/libraries/chain/include/eosio/chain/config.hpp index bfaa98eef70ece0feca39138fc0d85a04356463f..2704f6dee4f4f7ed9592e9ef330a766fd98b2514 100644 --- a/libraries/chain/include/eosio/chain/config.hpp +++ b/libraries/chain/include/eosio/chain/config.hpp @@ -25,7 +25,6 @@ const static uint64_t majority_producers_permission_name = N(prod.major); // gre const static uint64_t minority_producers_permission_name = N(prod.minor); // greater than 1/3 of producers needed to authorize0 const static uint64_t any_producer_permission_name = N(prod.any); // any producer needed to authorize - const static uint64_t eosio_auth_scope = N(eosio.auth); const static uint64_t eosio_all_scope = N(eosio.all); @@ -66,8 +65,6 @@ const static uint32_t default_max_gen_trx_count = 16; ///< the number of const static uint32_t default_max_trx_delay = 45*24*3600; // 45 days const static uint32_t rate_limiting_precision = 1000*1000; -const static uint32_t producers_authority_threshold_pct = 66 * config::percent_1; - const static uint16_t max_recursion_depth = 6; const static uint32_t default_base_per_transaction_net_usage = 48; // 48 bytes minimum (for misc overhead) diff --git a/unittests/special_accounts_tests.cpp b/unittests/special_accounts_tests.cpp index a266a483a93c547c946719eb1ab351d615564d98..90b521109ee41a578d51385304054099be16ec4a 100644 --- a/unittests/special_accounts_tests.cpp +++ b/unittests/special_accounts_tests.cpp @@ -55,7 +55,7 @@ BOOST_FIXTURE_TEST_CASE(accounts_exists, tester) const auto& active_producers = control->head_block_state()->active_schedule; const auto& producers_active_authority = chain1_db.get(boost::make_tuple(config::producers_account_name, config::active_name)); - auto expected_threshold = EOS_PERCENT_CEIL(active_producers.producers.size(), config::producers_authority_threshold_pct); + auto expected_threshold = (active_producers.producers.size() * 2)/3 + 1; BOOST_CHECK_EQUAL(producers_active_authority.auth.threshold, expected_threshold); BOOST_CHECK_EQUAL(producers_active_authority.auth.accounts.size(), active_producers.producers.size()); BOOST_CHECK_EQUAL(producers_active_authority.auth.keys.size(), 0); @@ -79,6 +79,8 @@ BOOST_FIXTURE_TEST_CASE(accounts_exists, tester) BOOST_CHECK_EQUAL(producers_owner_authority.auth.accounts.size(), 0); BOOST_CHECK_EQUAL(producers_owner_authority.auth.keys.size(), 0); + //TODO: Add checks on the other permissions of the producers account + } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_SUITE_END()