GTPH-66-witness_node_crash
This commit is contained in:
parent
e80e9dd401
commit
7ad6050da1
4 changed files with 127 additions and 0 deletions
3
libraries/chain/hardfork.d/1002.hf
Normal file
3
libraries/chain/hardfork.d/1002.hf
Normal 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
|
||||||
|
|
@ -30,6 +30,25 @@
|
||||||
|
|
||||||
namespace graphene { namespace chain {
|
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>
|
class proposal_create_evaluator : public evaluator<proposal_create_evaluator>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -39,6 +58,8 @@ namespace graphene { namespace chain {
|
||||||
object_id_type do_apply( const proposal_create_operation& o );
|
object_id_type do_apply( const proposal_create_operation& o );
|
||||||
|
|
||||||
transaction _proposed_trx;
|
transaction _proposed_trx;
|
||||||
|
|
||||||
|
hardfork_visitor_1002 vtor_1002;
|
||||||
};
|
};
|
||||||
|
|
||||||
class proposal_update_evaluator : public evaluator<proposal_update_evaluator>
|
class proposal_update_evaluator : public evaluator<proposal_update_evaluator>
|
||||||
|
|
|
||||||
|
|
@ -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)
|
void_result proposal_create_evaluator::do_evaluate(const proposal_create_operation& o)
|
||||||
{ try {
|
{ try {
|
||||||
const database& d = db();
|
const database& d = db();
|
||||||
|
|
||||||
proposal_operation_hardfork_visitor vtor( d.head_block_time() );
|
proposal_operation_hardfork_visitor vtor( d.head_block_time() );
|
||||||
vtor( o );
|
vtor( o );
|
||||||
|
vtor_1002( o );
|
||||||
|
|
||||||
const auto& global_parameters = d.get_global_properties().parameters;
|
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(),
|
std::set_difference(required_active.begin(), required_active.end(),
|
||||||
proposal.required_owner_approvals.begin(), proposal.required_owner_approvals.end(),
|
proposal.required_owner_approvals.begin(), proposal.required_owner_approvals.end(),
|
||||||
std::inserter(proposal.required_active_approvals, proposal.required_active_approvals.begin()));
|
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;
|
return proposal.id;
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include <graphene/chain/asset_object.hpp>
|
#include <graphene/chain/asset_object.hpp>
|
||||||
#include <graphene/chain/committee_member_object.hpp>
|
#include <graphene/chain/committee_member_object.hpp>
|
||||||
#include <graphene/chain/proposal_object.hpp>
|
#include <graphene/chain/proposal_object.hpp>
|
||||||
|
#include <graphene/chain/hardfork.hpp>
|
||||||
|
|
||||||
#include <graphene/db/simple_index.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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue