From 7ad6050da187f6f7862dcff342a13732630206b8 Mon Sep 17 00:00:00 2001 From: satyakoneru Date: Wed, 28 Aug 2019 01:47:28 +0000 Subject: [PATCH] GTPH-66-witness_node_crash --- libraries/chain/hardfork.d/1002.hf | 3 + .../graphene/chain/proposal_evaluator.hpp | 21 ++++++ libraries/chain/proposal_evaluator.cpp | 36 ++++++++++ tests/tests/authority_tests.cpp | 67 +++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 libraries/chain/hardfork.d/1002.hf diff --git a/libraries/chain/hardfork.d/1002.hf b/libraries/chain/hardfork.d/1002.hf new file mode 100644 index 00000000..b1511cc0 --- /dev/null +++ b/libraries/chain/hardfork.d/1002.hf @@ -0,0 +1,3 @@ +#ifndef HARDFORK_1002_TIME +#define HARDFORK_1002_TIME (fc::time_point_sec( 1566927111 )) // 08/27/2019 5:31pm (UTC) +#endif diff --git a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp index bf6fc547..3221f63d 100644 --- a/libraries/chain/include/graphene/chain/proposal_evaluator.hpp +++ b/libraries/chain/include/graphene/chain/proposal_evaluator.hpp @@ -30,6 +30,25 @@ namespace graphene { namespace chain { + class hardfork_visitor_1002 + { + public: + typedef void result_type; + + uint64_t max_update_instance = 0; + uint64_t nested_update_count = 0; + + template + void operator()(const T &v) const {} + + void operator()(const proposal_update_operation &v); + + void operator()(const proposal_delete_operation &v); + + // loop and self visit in proposals + void operator()(const graphene::chain::proposal_create_operation &v); + }; + class proposal_create_evaluator : public evaluator { public: @@ -39,6 +58,8 @@ namespace graphene { namespace chain { object_id_type do_apply( const proposal_create_operation& o ); transaction _proposed_trx; + + hardfork_visitor_1002 vtor_1002; }; class proposal_update_evaluator : public evaluator diff --git a/libraries/chain/proposal_evaluator.cpp b/libraries/chain/proposal_evaluator.cpp index a6640ea4..c6fad1a6 100644 --- a/libraries/chain/proposal_evaluator.cpp +++ b/libraries/chain/proposal_evaluator.cpp @@ -142,12 +142,34 @@ struct proposal_operation_hardfork_visitor } }; +void hardfork_visitor_1002::operator()(const proposal_update_operation &v) +{ + if( nested_update_count == 0 || v.proposal.instance.value > max_update_instance ) + max_update_instance = v.proposal.instance.value; + nested_update_count++; +} + +void hardfork_visitor_1002::operator()(const proposal_delete_operation &v) +{ + if( nested_update_count == 0 || v.proposal.instance.value > max_update_instance ) + max_update_instance = v.proposal.instance.value; + nested_update_count++; +} + +// loop and self visit in proposals +void hardfork_visitor_1002::operator()(const graphene::chain::proposal_create_operation &v) +{ + for (const op_wrapper &op : v.proposed_ops) + op.op.visit(*this); +} + void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o) { try { const database& d = db(); proposal_operation_hardfork_visitor vtor( d.head_block_time() ); vtor( o ); + vtor_1002( o ); const auto& global_parameters = d.get_global_properties().parameters; @@ -218,6 +240,20 @@ object_id_type proposal_create_evaluator::do_apply(const proposal_create_operati std::set_difference(required_active.begin(), required_active.end(), proposal.required_owner_approvals.begin(), proposal.required_owner_approvals.end(), std::inserter(proposal.required_active_approvals, proposal.required_active_approvals.begin())); + + if( d.head_block_time() > HARDFORK_1002_TIME ) + FC_ASSERT( vtor_1002.nested_update_count == 0 || proposal.id.instance() > vtor_1002.max_update_instance, + "Cannot update/delete a proposal with a future id!" ); + else if( vtor_1002.nested_update_count > 0 && proposal.id.instance() <= vtor_1002.max_update_instance ) + { + // prevent approval + transfer_operation top; + top.from = GRAPHENE_NULL_ACCOUNT; + top.to = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT; + top.amount = asset( GRAPHENE_MAX_SHARE_SUPPLY ); + proposal.proposed_transaction.operations.emplace_back( top ); + wlog( "Issue 1479 on BitShares: ${p}", ("p",proposal) ); + } }); return proposal.id; diff --git a/tests/tests/authority_tests.cpp b/tests/tests/authority_tests.cpp index f5efbb9d..b9b5ba07 100644 --- a/tests/tests/authority_tests.cpp +++ b/tests/tests/authority_tests.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -1316,4 +1317,70 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture ) } } +BOOST_AUTO_TEST_CASE( self_approving_proposal ) +{ try { + ACTORS( (alice) ); + fund( alice ); + + generate_blocks( HARDFORK_1002_TIME ); + trx.clear(); + set_expiration( db, trx ); + + proposal_update_operation pup; + pup.fee_paying_account = alice_id; + pup.proposal = proposal_id_type(0); + pup.active_approvals_to_add.insert( alice_id ); + + proposal_create_operation pop; + pop.proposed_ops.emplace_back(pup); + pop.fee_paying_account = alice_id; + pop.expiration_time = db.head_block_time() + fc::days(1); + trx.operations.push_back(pop); + const proposal_id_type pid1 = PUSH_TX( db, trx, ~0 ).operation_results[0].get(); + trx.clear(); + BOOST_REQUIRE_EQUAL( 0, pid1.instance.value ); + db.get(pid1); + + trx.operations.push_back(pup); + PUSH_TX( db, trx, ~0 ); + + // Proposal failed and still exists + db.get(pid1); +} FC_LOG_AND_RETHROW() } + +BOOST_AUTO_TEST_CASE( self_deleting_proposal ) +{ try { + ACTORS( (alice) ); + fund( alice ); + + generate_blocks( HARDFORK_1002_TIME ); + trx.clear(); + set_expiration( db, trx ); + + proposal_delete_operation pdo; + pdo.fee_paying_account = alice_id; + pdo.proposal = proposal_id_type(0); + pdo.using_owner_authority = false; + + proposal_create_operation pop; + pop.proposed_ops.emplace_back( pdo ); + pop.fee_paying_account = alice_id; + pop.expiration_time = db.head_block_time() + fc::days(1); + trx.operations.push_back( pop ); + const proposal_id_type pid1 = PUSH_TX( db, trx, ~0 ).operation_results[0].get(); + trx.clear(); + BOOST_REQUIRE_EQUAL( 0, pid1.instance.value ); + db.get(pid1); + + proposal_update_operation pup; + pup.fee_paying_account = alice_id; + pup.proposal = proposal_id_type(0); + pup.active_approvals_to_add.insert( alice_id ); + trx.operations.push_back(pup); + PUSH_TX( db, trx, ~0 ); + + // Proposal failed and still exist + db.get(pid1); +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_SUITE_END()