Skip to content

Commit

Permalink
Merge pull request #1484 from bitshares/release
Browse files Browse the repository at this point in the history
Bugfix release
  • Loading branch information
pmconrad authored Dec 21, 2018
2 parents 3aeb5aa + 3eb2cfa commit 58c0c49
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 1 deletion.
4 changes: 4 additions & 0 deletions libraries/chain/hardfork.d/CORE_1479.hf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// bitshares-core issue #1479 nodes crashing on self-approving proposal
#ifndef HARDFORK_CORE_1479_TIME
#define HARDFORK_CORE_1479_TIME (fc::time_point_sec( 1545436800 )) // 2018-12-22T00:00:00Z
#endif
2 changes: 1 addition & 1 deletion libraries/chain/include/graphene/chain/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
#define GRAPHENE_RECENTLY_MISSED_COUNT_INCREMENT 4
#define GRAPHENE_RECENTLY_MISSED_COUNT_DECREMENT 3

#define GRAPHENE_CURRENT_DB_VERSION "BTS2.181127"
#define GRAPHENE_CURRENT_DB_VERSION "BTS2.181221"

#define GRAPHENE_IRREVERSIBLE_THRESHOLD (70 * GRAPHENE_1_PERCENT)

Expand Down
21 changes: 21 additions & 0 deletions libraries/chain/include/graphene/chain/proposal_evaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@

namespace graphene { namespace chain {

class hardfork_visitor_1479
{
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:
Expand All @@ -37,6 +56,8 @@ namespace graphene { namespace chain {
object_id_type do_apply( const proposal_create_operation& o );

transaction _proposed_trx;

hardfork_visitor_1479 vtor_1479;
};

class proposal_update_evaluator : public evaluator<proposal_update_evaluator>
Expand Down
36 changes: 36 additions & 0 deletions libraries/chain/proposal_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,27 @@ struct hardfork_visitor_214 // non-recursive proposal visitor
}
};

void hardfork_visitor_1479::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_1479::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_1479::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();
Expand All @@ -128,6 +149,7 @@ void_result proposal_create_evaluator::do_evaluate(const proposal_create_operati
for (const op_wrapper &op : o.proposed_ops)
op.op.visit( hf214 );
}
vtor_1479( o );

const auto& global_parameters = d.get_global_properties().parameters;

Expand Down Expand Up @@ -199,6 +221,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_CORE_1479_TIME )
FC_ASSERT( vtor_1479.nested_update_count == 0 || proposal.id.instance() > vtor_1479.max_update_instance,
"Cannot update/delete a proposal with a future id!" );
else if( vtor_1479.nested_update_count > 0 && proposal.id.instance() <= vtor_1479.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: ${p}", ("p",proposal) );
}
});

return proposal.id;
Expand Down
66 changes: 66 additions & 0 deletions tests/tests/authority_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1677,4 +1677,70 @@ BOOST_AUTO_TEST_CASE( issue_214 )
BOOST_CHECK_EQUAL( top.amount.amount.value, get_balance( bob_id, top.amount.asset_id ) );
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_CASE( self_approving_proposal )
{ try {
ACTORS( (alice) );
fund( alice );

generate_blocks( HARDFORK_CORE_1479_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_CORE_1479_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 exists
db.get<proposal_object>(pid1);
} FC_LOG_AND_RETHROW() }

BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 58c0c49

Please sign in to comment.