GTPH-66-witness_node_crash

This commit is contained in:
satyakoneru 2019-08-28 01:47:28 +00:00
parent e80e9dd401
commit 7ad6050da1
4 changed files with 127 additions and 0 deletions

View file

@ -0,0 +1,3 @@
#ifndef HARDFORK_1002_TIME
#define HARDFORK_1002_TIME (fc::time_point_sec( 1566927111 )) // 08/27/2019 5:31pm (UTC)
#endif

View file

@ -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<typename T>
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<proposal_create_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<proposal_update_evaluator>

View file

@ -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;

View file

@ -32,6 +32,7 @@
#include <graphene/chain/asset_object.hpp>
#include <graphene/chain/committee_member_object.hpp>
#include <graphene/chain/proposal_object.hpp>
#include <graphene/chain/hardfork.hpp>
#include <graphene/db/simple_index.hpp>
@ -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<object_id_type>();
trx.clear();
BOOST_REQUIRE_EQUAL( 0, pid1.instance.value );
db.get<proposal_object>(pid1);
trx.operations.push_back(pup);
PUSH_TX( db, trx, ~0 );
// Proposal failed and still exists
db.get<proposal_object>(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<object_id_type>();
trx.clear();
BOOST_REQUIRE_EQUAL( 0, pid1.instance.value );
db.get<proposal_object>(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<proposal_object>(pid1);
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()