GRPH-60 Added Recursion guard to be 2*witness_node_count

This commit is contained in:
satyakoneru 2019-08-27 02:53:23 +00:00
parent dea5a973ba
commit 31d8e68d89
4 changed files with 79 additions and 2 deletions

View file

@ -325,6 +325,24 @@ processed_transaction database::validate_transaction( const signed_transaction&
return _apply_transaction( trx );
}
class push_proposal_nesting_guard {
public:
push_proposal_nesting_guard( uint32_t& nesting_counter, const database& db )
: orig_value(nesting_counter), counter(nesting_counter)
{
FC_ASSERT( counter < db.get_global_properties().active_witnesses.size() * 2, "Max proposal nesting depth exceeded!" );
counter++;
}
~push_proposal_nesting_guard()
{
if( --counter != orig_value )
elog( "Unexpected proposal nesting count value: ${n} != ${o}", ("n",counter)("o",orig_value) );
}
private:
const uint32_t orig_value;
uint32_t& counter;
};
processed_transaction database::push_proposal(const proposal_object& proposal)
{ try {
transaction_evaluation_state eval_state(this);
@ -336,6 +354,9 @@ processed_transaction database::push_proposal(const proposal_object& proposal)
size_t old_applied_ops_size = _applied_ops.size();
try {
push_proposal_nesting_guard guard( _push_proposal_nesting_depth, *this );
if( _undo_db.size() >= _undo_db.max_size() )
_undo_db.set_max_size( _undo_db.size() + 1 );
auto session = _undo_db.start_undo_session(true);
for( auto& op : proposal.proposed_transaction.operations )
eval_state.operation_results.emplace_back(apply_operation(eval_state, op));

View file

@ -544,6 +544,8 @@ namespace graphene { namespace chain {
node_property_object _node_property_object;
fc::hash_ctr_rng<secret_hash_type, 20> _random_number_generator;
bool _slow_replays = false;
// Counts nested proposal updates
uint32_t _push_proposal_nesting_depth = 0;
};
namespace detail

View file

@ -89,7 +89,8 @@ void proposal_update_operation::get_required_authorities( vector<authority>& o )
auth.key_auths[k] = 1;
auth.weight_threshold = auth.key_auths.size();
o.emplace_back( std::move(auth) );
if( auth.weight_threshold > 0 )
o.emplace_back( std::move(auth) );
}
void proposal_update_operation::get_required_active_authorities( flat_set<account_id_type>& a )const

View file

@ -894,7 +894,6 @@ BOOST_FIXTURE_TEST_CASE( max_authority_membership, database_fixture )
});
transaction tx;
processed_transaction ptx;
private_key_type committee_key = init_account_priv_key;
// Sam is the creator of accounts
@ -1313,4 +1312,58 @@ BOOST_FIXTURE_TEST_CASE( nonminimal_sig_test, database_fixture )
}
}
BOOST_AUTO_TEST_CASE( nested_execution )
{ try {
ACTORS( (alice)(bob) );
fund( alice );
generate_blocks( fc::time_point::now() + fc::hours(1) );
set_expiration( db, trx );
const auto& gpo = db.get_global_properties();
proposal_create_operation pco;
pco.expiration_time = db.head_block_time() + fc::minutes(1);
pco.fee_paying_account = alice_id;
proposal_id_type inner;
{
transfer_operation top;
top.from = alice_id;
top.to = bob_id;
top.amount = asset( 10 );
pco.proposed_ops.emplace_back( top );
trx.operations.push_back( pco );
inner = PUSH_TX( db, trx, ~0 ).operation_results.front().get<object_id_type>();
trx.clear();
pco.proposed_ops.clear();
}
std::vector<proposal_id_type> nested;
nested.push_back( inner );
for( size_t i = 0; i < gpo.active_witnesses.size() * 2; i++ )
{
proposal_update_operation pup;
pup.fee_paying_account = alice_id;
pup.proposal = nested.back();
pup.active_approvals_to_add.insert( alice_id );
pco.proposed_ops.emplace_back( pup );
trx.operations.push_back( pco );
nested.push_back( PUSH_TX( db, trx, ~0 ).operation_results.front().get<object_id_type>() );
trx.clear();
pco.proposed_ops.clear();
}
proposal_update_operation pup;
pup.fee_paying_account = alice_id;
pup.proposal = nested.back();
pup.active_approvals_to_add.insert( alice_id );
trx.operations.push_back( pup );
PUSH_TX( db, trx, ~0 );
for( size_t i = 1; i < nested.size(); i++ )
BOOST_CHECK_THROW( db.get<proposal_object>( nested[i] ), fc::assert_exception ); // executed successfully -> object removed
db.get<proposal_object>( inner ); // asn't executed -> object exists, doesn't throw
} FC_LOG_AND_RETHROW() }
BOOST_AUTO_TEST_SUITE_END()