diff --git a/libraries/app/database_api.cpp b/libraries/app/database_api.cpp index e95ccff7..fd8779f5 100644 --- a/libraries/app/database_api.cpp +++ b/libraries/app/database_api.cpp @@ -1723,6 +1723,9 @@ set database_api_impl::get_potential_signatures( const signed_t set
database_api_impl::get_potential_address_signatures( const signed_transaction& trx )const { + auto chain_time = _db.head_block_time(); + bool allow_non_immediate_owner = ( chain_time >= HARDFORK_1002_TIME ); + set
result; trx.get_required_signatures( _db.get_chain_id(), @@ -1741,6 +1744,7 @@ set
database_api_impl::get_potential_address_signatures( const signed_t result.insert(k); return &auth; }, + allow_non_immediate_owner, _db.get_global_properties().parameters.max_authority_depth ); return result; diff --git a/libraries/chain/include/graphene/chain/protocol/transaction.hpp b/libraries/chain/include/graphene/chain/protocol/transaction.hpp index d9d0eefb..049b2496 100644 --- a/libraries/chain/include/graphene/chain/protocol/transaction.hpp +++ b/libraries/chain/include/graphene/chain/protocol/transaction.hpp @@ -188,6 +188,9 @@ namespace graphene { namespace chain { /// Removes all operations and signatures void clear() { operations.clear(); signatures.clear(); } + + /** Removes all signatures */ + void clear_signatures() { signatures.clear(); } }; /** diff --git a/libraries/chain/protocol/transaction.cpp b/libraries/chain/protocol/transaction.cpp index fd398b75..70ec4395 100644 --- a/libraries/chain/protocol/transaction.cpp +++ b/libraries/chain/protocol/transaction.cpp @@ -341,22 +341,23 @@ set signed_transaction::get_required_signatures( vector other; get_required_authorities( required_active, required_owner, other ); - - sign_state s( get_signature_keys( chain_id ), get_active, get_owner, allow_non_immediate_owner, max_recursion_depth, available_keys ); + const flat_set& signature_keys = get_signature_keys(chain_id); + sign_state s( signature_keys, get_active, get_owner, allow_non_immediate_owner, max_recursion_depth, available_keys ); for( const auto& auth : other ) s.check_authority(&auth); for( auto& owner : required_owner ) s.check_authority( get_owner( owner ) ); for( auto& active : required_active ) - s.check_authority( active ); + s.check_authority( active ) || s.check_authority( get_owner( active ) ); s.remove_unused_signatures(); set result; for( auto& provided_sig : s.provided_signatures ) - if( available_keys.find( provided_sig.first ) != available_keys.end() ) + if( available_keys.find( provided_sig.first ) != available_keys.end() + && signature_keys.find( provided_sig.first ) == signature_keys.end() ) result.insert( provided_sig.first ); return result; diff --git a/tests/tests/authority_tests.cpp b/tests/tests/authority_tests.cpp index 984189cd..d754e661 100644 --- a/tests/tests/authority_tests.cpp +++ b/tests/tests/authority_tests.cpp @@ -1398,7 +1398,7 @@ BOOST_FIXTURE_TEST_CASE( parent_owner_test, database_fixture ) { //wdump( (tx)(available_keys) ); set result_set = tx.get_required_signatures(db.get_chain_id(), available_keys, - get_active, get_owner, after_hf_584, false); + get_active, get_owner, after_hf_584); //wdump( (result_set)(ref_set) ); return result_set == ref_set; } ; @@ -1514,87 +1514,87 @@ BOOST_FIXTURE_TEST_CASE( parent_owner_test, database_fixture ) BOOST_CHECK( chk( tx, true, { gavin_active_pub, gavin_owner_pub }, { gavin_active_pub } ) ); sign( tx, alice_owner_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false ), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, alice_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, false); PUSH_TX( db, tx, database::skip_transaction_dupe_check ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, bob_owner_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, false); PUSH_TX( db, tx, database::skip_transaction_dupe_check ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, bob_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, false); PUSH_TX( db, tx, database::skip_transaction_dupe_check ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, cindy_owner_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, cindy_active_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, daisy_owner_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, daisy_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, false); PUSH_TX( db, tx, database::skip_transaction_dupe_check ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, edwin_owner_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, edwin_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, false); PUSH_TX( db, tx, database::skip_transaction_dupe_check ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, frank_owner_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, frank_active_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, gavin_owner_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), fc::exception ); + GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false), fc::exception ); GRAPHENE_REQUIRE_THROW( PUSH_TX( db, tx, database::skip_transaction_dupe_check ), fc::exception ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); sign( tx, gavin_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, false); PUSH_TX( db, tx, database::skip_transaction_dupe_check ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); + tx.verify_authority( db.get_chain_id(), get_active, get_owner, true); tx.clear_signatures(); // proposal tests @@ -1823,120 +1823,4 @@ BOOST_FIXTURE_TEST_CASE( parent_owner_test, database_fixture ) } } -/// This test case reproduces https://github.com/bitshares/bitshares-core/issues/944 -/// and https://github.com/bitshares/bitshares-core/issues/580 -BOOST_FIXTURE_TEST_CASE( missing_owner_auth_test, database_fixture ) -{ - try - { - ACTORS( - (alice) - ); - - auto set_auth = [&]( - account_id_type aid, - const authority& active, - const authority& owner - ) - { - signed_transaction tx; - account_update_operation op; - op.account = aid; - op.active = active; - op.owner = owner; - tx.operations.push_back( op ); - set_expiration( db, tx ); - PUSH_TX( db, tx, database::skip_transaction_signatures ); - } ; - - auto get_active = [&]( - account_id_type aid - ) -> const authority* - { - return &(aid(db).active); - } ; - - auto get_owner = [&]( - account_id_type aid - ) -> const authority* - { - return &(aid(db).owner); - } ; - - fc::ecc::private_key alice_active_key = fc::ecc::private_key::regenerate(fc::digest("alice_active")); - fc::ecc::private_key alice_owner_key = fc::ecc::private_key::regenerate(fc::digest("alice_owner")); - public_key_type alice_active_pub( alice_active_key.get_public_key() ); - public_key_type alice_owner_pub( alice_owner_key.get_public_key() ); - set_auth( alice_id, authority( 1, alice_active_pub, 1 ), authority( 1, alice_owner_pub, 1 ) ); - - // creating a transaction that needs owner permission - signed_transaction tx; - account_update_operation op; - op.account = alice_id; - op.owner = authority( 1, alice_active_pub, 1 ); - tx.operations.push_back( op ); - - // not signed, should throw tx_missing_owner_auth - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), - graphene::chain::tx_missing_owner_auth ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ), - graphene::chain::tx_missing_owner_auth ); - - // signed with alice's active key, should throw tx_missing_owner_auth - sign( tx, alice_active_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), - graphene::chain::tx_missing_owner_auth ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ), - graphene::chain::tx_missing_owner_auth ); - - // signed with alice's owner key, should not throw - tx.clear_signatures(); - sign( tx, alice_owner_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); - - // signed with both alice's owner key and active key, - // it does not throw due to https://github.com/bitshares/bitshares-core/issues/580 - sign( tx, alice_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); - - // creating a transaction that needs active permission - tx.clear(); - op.owner.reset(); - op.active = authority( 1, alice_owner_pub, 1 ); - tx.operations.push_back( op ); - - // not signed, should throw tx_missing_active_auth - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), - graphene::chain::tx_missing_active_auth ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ), - graphene::chain::tx_missing_active_auth ); - - // signed with alice's active key, should not throw - sign( tx, alice_active_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); - - // signed with alice's owner key, should not throw - tx.clear_signatures(); - sign( tx, alice_owner_key ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ); - tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ); - - // signed with both alice's owner key and active key, should throw tx_irrelevant_sig - sign( tx, alice_active_key ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, false, false ), - graphene::chain::tx_irrelevant_sig ); - GRAPHENE_REQUIRE_THROW( tx.verify_authority( db.get_chain_id(), get_active, get_owner, true, false ), - graphene::chain::tx_irrelevant_sig ); - - } - catch(fc::exception& e) - { - edump((e.to_detail_string())); - throw; - } -} - BOOST_AUTO_TEST_SUITE_END() diff --git a/tests/tests/database_api_tests.cpp b/tests/tests/database_api_tests.cpp index 41b3a9d3..67a1dbfc 100644 --- a/tests/tests/database_api_tests.cpp +++ b/tests/tests/database_api_tests.cpp @@ -27,6 +27,8 @@ #include #include +#include + #include "../common/database_fixture.hpp" using namespace graphene::chain;