From f78c6fe3b1608796fea41828884a9b068409ca46 Mon Sep 17 00:00:00 2001 From: Anton Perkov Date: Thu, 24 May 2018 14:52:42 -0400 Subject: [PATCH] action setparams added to system contract, unit-test of producers changing parameters using multi-sig #3390 --- contracts/eosio.system/eosio.system.abi | 10 ++ contracts/eosio.system/eosio.system.cpp | 8 ++ contracts/eosio.system/eosio.system.hpp | 2 + libraries/chain/chain_config.cpp | 5 +- unittests/eosio.system_tests.cpp | 174 ++++++++++++++---------- unittests/eosio_system_tester.hpp | 93 +++++++++++++ 6 files changed, 217 insertions(+), 75 deletions(-) diff --git a/contracts/eosio.system/eosio.system.abi b/contracts/eosio.system/eosio.system.abi index dcf903eba..e559ad30e 100644 --- a/contracts/eosio.system/eosio.system.abi +++ b/contracts/eosio.system/eosio.system.abi @@ -378,6 +378,12 @@ "fields": [ {"name":"from", "type":"account_name"} ] + },{ + "name": "setparams", + "base": "", + "fields": [ + {"name":"params", "type":"eosio_parameters"} + ] } ], "actions": [{ @@ -488,6 +494,10 @@ "name": "reqauth", "type": "require_auth", "ricardian_contract": "" + },{ + "name": "setparams", + "type": "setparams", + "ricardian_contract": "" }], "tables": [{ "name": "producers", diff --git a/contracts/eosio.system/eosio.system.cpp b/contracts/eosio.system/eosio.system.cpp index 667a22794..9bfa0d34b 100644 --- a/contracts/eosio.system/eosio.system.cpp +++ b/contracts/eosio.system/eosio.system.cpp @@ -165,6 +165,13 @@ namespace eosiosystem { set_resource_limits( newact, 0, 0, 0 ); } + void system_contract::setparams( const eosio_parameters& params ) { + require_auth( N(eosio) ); + (eosiosystem::eosio_parameters&)(_gstate) = params; + eosio_assert( 3 <= _gstate.max_authority_depth, "max_authority_depth should be at least 3" ); + set_blockchain_parameters( params ); + } + } /// eosio.system @@ -183,4 +190,5 @@ EOSIO_ABI( eosiosystem::system_contract, //this file (bidname) (setpriv) + (setparams) ) diff --git a/contracts/eosio.system/eosio.system.hpp b/contracts/eosio.system/eosio.system.hpp index 70e0778f1..b2120247c 100644 --- a/contracts/eosio.system/eosio.system.hpp +++ b/contracts/eosio.system/eosio.system.hpp @@ -215,6 +215,8 @@ namespace eosiosystem { void regproxy( const account_name proxy, bool isproxy ); + void setparams( const eosio_parameters& params ); + // functions defined in producer_pay.cpp void claimrewards( const account_name& owner ); diff --git a/libraries/chain/chain_config.cpp b/libraries/chain/chain_config.cpp index b62d4c177..974675749 100644 --- a/libraries/chain/chain_config.cpp +++ b/libraries/chain/chain_config.cpp @@ -38,6 +38,9 @@ namespace eosio { namespace chain { "min transaction cpu usage cannot exceed max transaction cpu usage" ); EOS_ASSERT( max_transaction_cpu_usage < (max_block_cpu_usage - min_transaction_cpu_usage), action_validate_exception, "max transaction cpu usage must be at less than the difference between the max block cpu usage and the min transaction cpu usage" ); - } + + EOS_ASSERT( 1 <= max_authority_depth, action_validate_exception, + "max authority depth should be at least 1" ); +} } } // namespace eosio::chain diff --git a/unittests/eosio.system_tests.cpp b/unittests/eosio.system_tests.cpp index fe8013c97..415968092 100644 --- a/unittests/eosio.system_tests.cpp +++ b/unittests/eosio.system_tests.cpp @@ -10,6 +10,12 @@ using namespace eosio_system; +struct eosio_parameters : eosio::chain::chain_config { + uint64_t max_ram_size; +}; + +FC_REFLECT_DERIVED(eosio_parameters, (eosio::chain::chain_config), (max_ram_size)); + BOOST_AUTO_TEST_SUITE(eosio_system_tests) BOOST_FIXTURE_TEST_CASE( buysell, eosio_system_tester ) try { @@ -1588,79 +1594,8 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni BOOST_FIXTURE_TEST_CASE(producers_upgrade_system_contract, eosio_system_tester) try { //install multisig contract - abi_serializer msig_abi_ser; - { - create_account_with_resources( N(eosio.msig), config::system_account_name ); - BOOST_REQUIRE_EQUAL( success(), buyram( "eosio", "eosio.msig", core_from_string("5000.0000") ) ); - produce_block(); - - auto trace = base_tester::push_action(config::system_account_name, N(setpriv), - config::system_account_name, mutable_variant_object() - ("account", "eosio.msig") - ("is_priv", 1) - ); - - set_code( N(eosio.msig), eosio_msig_wast ); - set_abi( N(eosio.msig), eosio_msig_abi ); - - produce_blocks(); - const auto& accnt = control->db().get( N(eosio.msig) ); - abi_def msig_abi; - BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, msig_abi), true); - msig_abi_ser.set_abi(msig_abi); - } - - //stake more than 15% of total EOS supply to activate chain - transfer( "eosio", "alice1111111", core_from_string("650000000.0000"), "eosio" ); - BOOST_REQUIRE_EQUAL( success(), stake( "alice1111111", "alice1111111", core_from_string("300000000.0000"), core_from_string("300000000.0000") ) ); - - // create accounts {defproducera, defproducerb, ..., defproducerz} and register as producers - std::vector producer_names; - { - producer_names.reserve('z' - 'a' + 1); - const std::string root("defproducer"); - for ( char c = 'a'; c < 'a'+21; ++c ) { - producer_names.emplace_back(root + std::string(1, c)); - } - setup_producer_accounts(producer_names); - for (const auto& p: producer_names) { - - BOOST_REQUIRE_EQUAL( success(), regproducer(p) ); - } - } - produce_blocks( 250); - - //BOOST_REQUIRE_EQUAL( name("defproducer2"), producer_keys[1].producer_name ); - - auto trace_auth = TESTER::push_action(config::system_account_name, updateauth::get_name(), config::system_account_name, mvo() - ("account", name(config::system_account_name).to_string()) - ("permission", name(config::active_name).to_string()) - ("parent", name(config::owner_name).to_string()) - ("auth", authority(1, {key_weight{get_public_key( config::system_account_name, "active" ), 1}}, { - permission_level_weight{{config::system_account_name, config::eosio_code_name}, 1}, - permission_level_weight{{config::producers_account_name, config::active_name}, 1} - } - )) - ); - BOOST_REQUIRE_EQUAL(transaction_receipt::executed, trace_auth->receipt->status); - - //vote for producers - { - transfer( config::system_account_name, "alice1111111", core_from_string("100000000.0000"), config::system_account_name ); - BOOST_REQUIRE_EQUAL(success(), stake( "alice1111111", core_from_string("30000000.0000"), core_from_string("30000000.0000") ) ); - BOOST_REQUIRE_EQUAL(success(), buyram( "alice1111111", "alice1111111", core_from_string("30000000.0000") ) ); - BOOST_REQUIRE_EQUAL(success(), push_action(N(alice1111111), N(voteproducer), mvo() - ("voter", "alice1111111") - ("proxy", name(0).to_string()) - ("producers", vector(producer_names.begin(), producer_names.begin()+21)) - ) - ); - } - produce_blocks( 250 ); - - auto producer_keys = control->head_block_state()->active_schedule.producers; - BOOST_REQUIRE_EQUAL( 21, producer_keys.size() ); - BOOST_REQUIRE_EQUAL( name("defproducera"), producer_keys[0].producer_name ); + abi_serializer msig_abi_ser = initialize_multisig(); + auto producer_names = active_and_vote_producers(); //helper function auto push_action_msig = [&]( const account_name& signer, const action_name &name, const variant_object &data, bool auth = true ) -> action_result { @@ -1673,7 +1608,6 @@ BOOST_FIXTURE_TEST_CASE(producers_upgrade_system_contract, eosio_system_tester) return base_tester::push_action( std::move(act), auth ? uint64_t(signer) : signer == N(bob111111111) ? N(alice1111111) : N(bob111111111) ); }; - // test begins vector prod_perms; for ( auto& x : producer_names ) { @@ -2426,4 +2360,96 @@ BOOST_FIXTURE_TEST_CASE( multiple_namebids, eosio_system_tester ) try { } FC_LOG_AND_RETHROW() +BOOST_FIXTURE_TEST_CASE( setparams, eosio_system_tester ) try { + //install multisig contract + abi_serializer msig_abi_ser = initialize_multisig(); + auto producer_names = active_and_vote_producers(); + + //helper function + auto push_action_msig = [&]( const account_name& signer, const action_name &name, const variant_object &data, bool auth = true ) -> action_result { + string action_type_name = msig_abi_ser.get_action_type(name); + + action act; + act.account = N(eosio.msig); + act.name = name; + act.data = msig_abi_ser.variant_to_binary( action_type_name, data ); + + return base_tester::push_action( std::move(act), auth ? uint64_t(signer) : signer == N(bob111111111) ? N(alice1111111) : N(bob111111111) ); + }; + + // test begins + vector prod_perms; + for ( auto& x : producer_names ) { + prod_perms.push_back( { name(x), config::active_name } ); + } + + eosio_parameters params; + (eosio::chain::chain_config&)params = control->get_global_properties().configuration; + params.max_ram_size = 65ll*1024 * 1024 * 1024; + //change some values + params.max_block_net_usage += 10; + params.max_transaction_lifetime += 1; + + transaction trx; + { + variant pretty_trx = fc::mutable_variant_object() + ("expiration", "2020-01-01T00:30") + ("ref_block_num", 2) + ("ref_block_prefix", 3) + ("max_net_usage_words", 0) + ("max_cpu_usage_ms", 0) + ("delay_sec", 0) + ("actions", fc::variants({ + fc::mutable_variant_object() + ("account", name(config::system_account_name)) + ("name", "setparams") + ("authorization", vector{ { config::system_account_name, config::active_name } }) + ("data", fc::mutable_variant_object() + ("params", params) + ) + }) + ); + abi_serializer::from_variant(pretty_trx, trx, get_resolver()); + } + + BOOST_REQUIRE_EQUAL(success(), push_action_msig( N(alice1111111), N(propose), mvo() + ("proposer", "alice1111111") + ("proposal_name", "setparams1") + ("trx", trx) + ("requested", prod_perms) + ) + ); + + // get 16 approvals + for ( size_t i = 0; i < 15; ++i ) { + BOOST_REQUIRE_EQUAL(success(), push_action_msig( name(producer_names[i]), N(approve), mvo() + ("proposer", "alice1111111") + ("proposal_name", "setparams1") + ("level", permission_level{ name(producer_names[i]), config::active_name }) + ) + ); + } + + transaction_trace_ptr trace; + control->applied_transaction.connect([&]( const transaction_trace_ptr& t) { if (t->scheduled) { trace = t; } } ); + BOOST_REQUIRE_EQUAL(success(), push_action_msig( N(alice1111111), N(exec), mvo() + ("proposer", "alice1111111") + ("proposal_name", "setparams1") + ("executer", "alice1111111") + ) + ); + + BOOST_REQUIRE( bool(trace) ); + BOOST_REQUIRE_EQUAL( 1, trace->action_traces.size() ); + BOOST_REQUIRE_EQUAL( transaction_receipt::executed, trace->receipt->status ); + + produce_blocks( 250 ); + + // make sure that changed parameters were applied + auto active_params = control->get_global_properties().configuration; + BOOST_REQUIRE_EQUAL( params.max_block_net_usage, active_params.max_block_net_usage ); + BOOST_REQUIRE_EQUAL( params.max_transaction_lifetime, active_params.max_transaction_lifetime ); + +} FC_LOG_AND_RETHROW() + BOOST_AUTO_TEST_SUITE_END() diff --git a/unittests/eosio_system_tester.hpp b/unittests/eosio_system_tester.hpp index 36606dd3e..ea676617d 100644 --- a/unittests/eosio_system_tester.hpp +++ b/unittests/eosio_system_tester.hpp @@ -398,6 +398,99 @@ public: return data.empty() ? fc::variant() : abi_ser.binary_to_variant( "refund_request", data ); } + abi_serializer initialize_multisig() { + abi_serializer msig_abi_ser; + { + create_account_with_resources( N(eosio.msig), config::system_account_name ); + BOOST_REQUIRE_EQUAL( success(), buyram( "eosio", "eosio.msig", core_from_string("5000.0000") ) ); + produce_block(); + + auto trace = base_tester::push_action(config::system_account_name, N(setpriv), + config::system_account_name, mutable_variant_object() + ("account", "eosio.msig") + ("is_priv", 1) + ); + + set_code( N(eosio.msig), eosio_msig_wast ); + set_abi( N(eosio.msig), eosio_msig_abi ); + + produce_blocks(); + const auto& accnt = control->db().get( N(eosio.msig) ); + abi_def msig_abi; + BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, msig_abi), true); + msig_abi_ser.set_abi(msig_abi); + } + return msig_abi_ser; + } + + //helper function + /* + action_result push_action_msig( const account_name& signer, const action_name &name, const variant_object &data ) { + string action_type_name = msig_abi_ser.get_action_type(name); + + action act; + act.account = N(eosio.msig); + act.name = name; + act.data = msig_abi_ser.variant_to_binary( action_type_name, data ); + + return base_tester::push_action( std::move(act), signer ); + }; + */ + + vector active_and_vote_producers() { + //stake more than 15% of total EOS supply to activate chain + transfer( "eosio", "alice1111111", core_from_string("650000000.0000"), "eosio" ); + BOOST_REQUIRE_EQUAL( success(), stake( "alice1111111", "alice1111111", core_from_string("300000000.0000"), core_from_string("300000000.0000") ) ); + + // create accounts {defproducera, defproducerb, ..., defproducerz} and register as producers + std::vector producer_names; + { + producer_names.reserve('z' - 'a' + 1); + const std::string root("defproducer"); + for ( char c = 'a'; c < 'a'+21; ++c ) { + producer_names.emplace_back(root + std::string(1, c)); + } + setup_producer_accounts(producer_names); + for (const auto& p: producer_names) { + + BOOST_REQUIRE_EQUAL( success(), regproducer(p) ); + } + } + produce_blocks( 250); + + auto trace_auth = TESTER::push_action(config::system_account_name, updateauth::get_name(), config::system_account_name, mvo() + ("account", name(config::system_account_name).to_string()) + ("permission", name(config::active_name).to_string()) + ("parent", name(config::owner_name).to_string()) + ("auth", authority(1, {key_weight{get_public_key( config::system_account_name, "active" ), 1}}, { + permission_level_weight{{config::system_account_name, config::eosio_code_name}, 1}, + permission_level_weight{{config::producers_account_name, config::active_name}, 1} + } + )) + ); + BOOST_REQUIRE_EQUAL(transaction_receipt::executed, trace_auth->receipt->status); + + //vote for producers + { + transfer( config::system_account_name, "alice1111111", core_from_string("100000000.0000"), config::system_account_name ); + BOOST_REQUIRE_EQUAL(success(), stake( "alice1111111", core_from_string("30000000.0000"), core_from_string("30000000.0000") ) ); + BOOST_REQUIRE_EQUAL(success(), buyram( "alice1111111", "alice1111111", core_from_string("30000000.0000") ) ); + BOOST_REQUIRE_EQUAL(success(), push_action(N(alice1111111), N(voteproducer), mvo() + ("voter", "alice1111111") + ("proxy", name(0).to_string()) + ("producers", vector(producer_names.begin(), producer_names.begin()+21)) + ) + ); + } + produce_blocks( 250 ); + + auto producer_keys = control->head_block_state()->active_schedule.producers; + BOOST_REQUIRE_EQUAL( 21, producer_keys.size() ); + BOOST_REQUIRE_EQUAL( name("defproducera"), producer_keys[0].producer_name ); + + return producer_names; + } + abi_serializer abi_ser; abi_serializer token_abi_ser; }; -- GitLab