From 5b22f2e7226a641d3711e4b91c1a5eccfb093da4 Mon Sep 17 00:00:00 2001 From: Nathan Hourt Date: Tue, 1 Aug 2017 17:13:05 -0500 Subject: [PATCH] Ref #7: Implement require_authorization, fix tests Require_authorization is now implemented so as the contract executes and asserts that a particular account approved the transaction, the chain asserts that this is so and throws if not. Also, update the tests, since the auth checks now bring to bear the rule that an account cannot be used in the same block that creates it. The tests now comply with this rule. TODO: - Check that all declared authorizations get required by the contract - Implement the mapping from user permissions to message types - Use mapping of permission to message type in lookup_minimum_permission --- libraries/chain/chain_controller.cpp | 1 - libraries/chain/message_handling_contexts.cpp | 4 ++- tests/common/macro_support.hpp | 32 +++++++++---------- tests/tests/native_contract_tests.cpp | 17 +++++----- tests/tests/special_accounts_tests.cpp | 12 ++++--- 5 files changed, 36 insertions(+), 30 deletions(-) diff --git a/libraries/chain/chain_controller.cpp b/libraries/chain/chain_controller.cpp index 917cd645924..db2a7e28af8 100644 --- a/libraries/chain/chain_controller.cpp +++ b/libraries/chain/chain_controller.cpp @@ -504,7 +504,6 @@ void chain_controller::check_transaction_authorization(const SignedTransaction& ("auth", declaredAuthority)); } } - ilog("Auth check passed"); } ProcessedTransaction chain_controller::apply_transaction(const SignedTransaction& trx, uint32_t skip) diff --git a/libraries/chain/message_handling_contexts.cpp b/libraries/chain/message_handling_contexts.cpp index acab6c6c8dc..2ae94f459dc 100644 --- a/libraries/chain/message_handling_contexts.cpp +++ b/libraries/chain/message_handling_contexts.cpp @@ -10,7 +10,9 @@ namespace eos { namespace chain { void message_validate_context::require_authorization(const types::AccountName& account) { -#warning TODO + auto itr = boost::find_if(msg.authorization, [&account](const auto& auth) { return auth.account == account; }); + EOS_ASSERT(itr != msg.authorization.end(), tx_missing_auth, + "Transaction is missing required authorization from ${acct}", ("acct", account)); } void message_validate_context::require_scope(const types::AccountName& account)const { diff --git a/tests/common/macro_support.hpp b/tests/common/macro_support.hpp index 48670b4965b..be43fc958c3 100644 --- a/tests/common/macro_support.hpp +++ b/tests/common/macro_support.hpp @@ -35,11 +35,11 @@ inline std::vector sort_names( std::vector&& names ) { eos::chain::SignedTransaction trx; \ trx.scope = sort_names({ #creator, "eos" }); \ trx.emplaceMessage(config::EosContractName, \ - vector{}, \ + vector{{#creator, "active"}}, \ "newaccount", types::newaccount{#creator, #name, owner, active, recovery, deposit}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Created account " << #name); \ } #define MKACCT2(chain, name) \ @@ -80,11 +80,11 @@ inline std::vector sort_names( std::vector&& names ) { { \ eos::chain::SignedTransaction trx; \ trx.scope = sort_names( { #sender, #recipient } ); \ - trx.emplaceMessage(config::EosContractName, \ - vector{}, "lock", types::lock{#sender, #recipient, amount}); \ + trx.emplaceMessage(config::EosContractName, vector{{#sender, "active"}}, \ + "lock", types::lock{#sender, #recipient, amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Staked " << amount << " to " << #recipient); \ } #define STAKE3(chain, account, amount) STAKE4(chain, account, account, amount) @@ -94,11 +94,11 @@ inline std::vector sort_names( std::vector&& names ) { eos::chain::SignedTransaction trx; \ trx.scope = sort_names( { "eos" } ); \ trx.emplaceMessage(config::EosContractName, \ - vector{}, \ + vector{{#account, "active"}}, \ "unlock", types::unlock{#account, amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Begin unstake " << amount << " to " << #account); \ } @@ -106,11 +106,11 @@ inline std::vector sort_names( std::vector&& names ) { { \ eos::chain::SignedTransaction trx; \ trx.scope = sort_names( { "eos", #account } ); \ - trx.emplaceMessage(config::EosContractName, \ - vector{}, "claim", types::claim{#account, amount}); \ + trx.emplaceMessage(config::EosContractName, vector{{#account, "active"}}, \ + "claim", types::claim{#account, amount}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Finish unstake " << amount << " to " << #account); \ } @@ -119,11 +119,11 @@ inline std::vector sort_names( std::vector&& names ) { eos::chain::SignedTransaction trx; \ trx.scope = sort_names( {#owner, "eos"} ); \ trx.emplaceMessage(config::EosContractName, \ - vector{}, \ + vector{{#owner, "active"}}, \ "setproducer", types::setproducer{#owner, key, cfg}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Create producer " << #owner); \ } #define MKPDCR3(chain, owner, key) MKPDCR4(chain, owner, key, BlockchainConfiguration{}); @@ -136,11 +136,11 @@ inline std::vector sort_names( std::vector&& names ) { eos::chain::SignedTransaction trx; \ trx.scope = sort_names( {#voter, "eos"} ); \ trx.emplaceMessage(config::EosContractName, \ - vector{}, \ + vector{{#voter, "active"}}, \ "okproducer", types::okproducer{#voter, #producer, approved? 1 : 0}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Set producer approval from " << #voter << " for " << #producer << " to " << approved); \ } @@ -149,11 +149,11 @@ inline std::vector sort_names( std::vector&& names ) { eos::chain::SignedTransaction trx; \ trx.scope = sort_names( {owner, "eos"} ); \ trx.emplaceMessage(config::EosContractName, \ - vector{}, \ + vector{{owner, "active"}}, \ "setproducer", types::setproducer{owner, key, cfg}); \ trx.expiration = chain.head_block_time() + 100; \ trx.set_reference_block(chain.head_block_id()); \ - chain.push_transaction(trx); \ + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); \ BOOST_TEST_CHECKPOINT("Update producer " << owner); \ } #define UPPDCR3(chain, owner, key) UPPDCR4(chain, owner, key, chain.get_producer(owner).configuration) diff --git a/tests/tests/native_contract_tests.cpp b/tests/tests/native_contract_tests.cpp index 2a58af116af..963eccc3503 100644 --- a/tests/tests/native_contract_tests.cpp +++ b/tests/tests/native_contract_tests.cpp @@ -99,9 +99,10 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture) auto unpacked = fc::raw::unpack(packed); BOOST_CHECK_EQUAL( value, unpacked ); trx.messages[0].type = "transfer"; + trx.messages[0].authorization = {{"inita", "active"}}; trx.messages[0].code = config::EosContractName; trx.setMessage(0, "transfer", trans); - chain.push_transaction(trx); + chain.push_transaction(trx, chain_controller::skip_transaction_signatures); BOOST_CHECK_EQUAL(chain.get_liquid_balance("inita"), Asset(100000 - 100)); BOOST_CHECK_EQUAL(chain.get_liquid_balance("initb"), Asset(100000 + 100)); @@ -118,10 +119,10 @@ BOOST_FIXTURE_TEST_CASE(transfer, testing_fixture) BOOST_FIXTURE_TEST_CASE(producer_creation, testing_fixture) { try { Make_Blockchain(chain) + Make_Account(chain, producer); chain.produce_blocks(); BOOST_CHECK_EQUAL(chain.head_block_num(), 1); - Make_Account(chain, producer); Make_Producer(chain, producer, producer_public_key); while (chain.head_block_num() < 3) { @@ -237,10 +238,10 @@ BOOST_FIXTURE_TEST_CASE(producer_voting_parameters_2, testing_fixture) BOOST_FIXTURE_TEST_CASE(producer_voting_1, testing_fixture) { try { Make_Blockchain(chain) - chain.produce_blocks(); - Make_Account(chain, joe); Make_Account(chain, bob); + chain.produce_blocks(); + Make_Producer(chain, joe); Approve_Producer(chain, bob, joe, true); // Produce blocks up to, but not including, the last block in the round @@ -274,10 +275,10 @@ BOOST_FIXTURE_TEST_CASE(producer_voting_1, testing_fixture) { BOOST_FIXTURE_TEST_CASE(producer_voting_2, testing_fixture) { try { Make_Blockchain(chain) - chain.produce_blocks(); - Make_Account(chain, joe); Make_Account(chain, bob); + chain.produce_blocks(); + Make_Producer(chain, joe); Approve_Producer(chain, bob, joe, true); chain.produce_blocks(); @@ -332,11 +333,11 @@ BOOST_FIXTURE_TEST_CASE(producer_proxy_voting, testing_fixture) { auto run = [this](std::vector actions) { Make_Blockchain(chain) - chain.produce_blocks(); - Make_Account(chain, stakeholder); Make_Account(chain, proxy); Make_Account(chain, producer); + chain.produce_blocks(); + Make_Producer(chain, producer); for (auto& action : actions) diff --git a/tests/tests/special_accounts_tests.cpp b/tests/tests/special_accounts_tests.cpp index 31f554e1b1f..52e1e25add5 100644 --- a/tests/tests/special_accounts_tests.cpp +++ b/tests/tests/special_accounts_tests.cpp @@ -86,15 +86,19 @@ BOOST_FIXTURE_TEST_CASE(producers_authority, testing_fixture) { try { Make_Blockchain(chain) - chain.produce_blocks(); Make_Account(chain, alice); Make_Account(chain, bob); Make_Account(chain, charlie); - Make_Account(chain, newproducer1); Make_Producer(chain, newproducer1); - Make_Account(chain, newproducer2); Make_Producer(chain, newproducer2); - Make_Account(chain, newproducer3); Make_Producer(chain, newproducer3); + Make_Account(chain, newproducer1); + Make_Account(chain, newproducer2); + Make_Account(chain, newproducer3); + chain.produce_blocks(); + + Make_Producer(chain, newproducer1); + Make_Producer(chain, newproducer2); + Make_Producer(chain, newproducer3); Approve_Producer(chain, alice, newproducer1, true); Approve_Producer(chain, bob, newproducer2, true);