SON126 - Witness proposal tests and related fixes
This commit is contained in:
parent
a4b3fae15c
commit
517afc2d19
4 changed files with 225 additions and 1 deletions
|
|
@ -183,6 +183,7 @@ fc::optional<operation> database::create_son_deregister_proposal(const son_id_ty
|
||||||
{
|
{
|
||||||
son_delete_operation son_dereg_op;
|
son_delete_operation son_dereg_op;
|
||||||
son_dereg_op.payer = current_witness.witness_account;
|
son_dereg_op.payer = current_witness.witness_account;
|
||||||
|
son_dereg_op.son_id = son_id;
|
||||||
|
|
||||||
proposal_create_operation proposal_op;
|
proposal_create_operation proposal_op;
|
||||||
proposal_op.fee_paying_account = current_witness.witness_account;
|
proposal_op.fee_paying_account = current_witness.witness_account;
|
||||||
|
|
@ -245,4 +246,14 @@ void database::remove_son_proposal( const proposal_object& proposal )
|
||||||
}
|
}
|
||||||
} FC_CAPTURE_AND_RETHROW( (proposal) ) }
|
} FC_CAPTURE_AND_RETHROW( (proposal) ) }
|
||||||
|
|
||||||
|
bool database::is_son_dereg_valid( const son_id_type& son_id )
|
||||||
|
{
|
||||||
|
const auto& son_idx = get_index_type<son_index>().indices().get< by_id >();
|
||||||
|
auto son = son_idx.find( son_id );
|
||||||
|
FC_ASSERT( son != son_idx.end() );
|
||||||
|
bool ret = ( son->status == son_status::in_maintenance &&
|
||||||
|
(head_block_time() - son->statistics(*this).last_down_timestamp >= fc::hours(SON_DEREGISTER_TIME)));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,7 @@ namespace graphene { namespace chain {
|
||||||
signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op );
|
signed_transaction create_signed_transaction( const fc::ecc::private_key& signing_private_key, const operation& op );
|
||||||
void process_son_proposals( const witness_object& current_witness, const fc::ecc::private_key& private_key );
|
void process_son_proposals( const witness_object& current_witness, const fc::ecc::private_key& private_key );
|
||||||
void remove_son_proposal( const proposal_object& proposal );
|
void remove_son_proposal( const proposal_object& proposal );
|
||||||
|
bool is_son_dereg_valid( const son_id_type& son_id );
|
||||||
|
|
||||||
time_point_sec head_block_time()const;
|
time_point_sec head_block_time()const;
|
||||||
uint32_t head_block_num()const;
|
uint32_t head_block_num()const;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <graphene/chain/database.hpp>
|
#include <graphene/chain/database.hpp>
|
||||||
#include <graphene/chain/son_object.hpp>
|
#include <graphene/chain/son_object.hpp>
|
||||||
|
#include <graphene/chain/witness_object.hpp>
|
||||||
#include <graphene/chain/hardfork.hpp>
|
#include <graphene/chain/hardfork.hpp>
|
||||||
#include <graphene/chain/vesting_balance_object.hpp>
|
#include <graphene/chain/vesting_balance_object.hpp>
|
||||||
|
|
||||||
|
|
@ -63,7 +64,11 @@ object_id_type update_son_evaluator::do_apply(const son_update_operation& op)
|
||||||
void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op)
|
void_result delete_son_evaluator::do_evaluate(const son_delete_operation& op)
|
||||||
{ try {
|
{ try {
|
||||||
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass
|
FC_ASSERT(db().head_block_time() >= HARDFORK_SON_TIME, "Not allowed until SON_HARDFORK"); // can be removed after HF date pass
|
||||||
FC_ASSERT(db().get(op.son_id).son_account == op.owner_account);
|
// Get the current block witness signatory
|
||||||
|
witness_id_type wit_id = db().get_scheduled_witness(1);
|
||||||
|
const witness_object& current_witness = wit_id(db());
|
||||||
|
// Either owner can remove or witness
|
||||||
|
FC_ASSERT(db().get(op.son_id).son_account == op.owner_account || (db().is_son_dereg_valid(op.son_id) && op.payer == current_witness.witness_account));
|
||||||
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
|
const auto& idx = db().get_index_type<son_index>().indices().get<by_id>();
|
||||||
FC_ASSERT( idx.find(op.son_id) != idx.end() );
|
FC_ASSERT( idx.find(op.son_id) != idx.end() );
|
||||||
return void_result();
|
return void_result();
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
#include <graphene/chain/hardfork.hpp>
|
#include <graphene/chain/hardfork.hpp>
|
||||||
#include <graphene/chain/son_object.hpp>
|
#include <graphene/chain/son_object.hpp>
|
||||||
|
#include <graphene/chain/proposal_object.hpp>
|
||||||
|
#include <graphene/chain/son_proposal_object.hpp>
|
||||||
#include <graphene/chain/son_evaluator.hpp>
|
#include <graphene/chain/son_evaluator.hpp>
|
||||||
#include <graphene/chain/vesting_balance_object.hpp>
|
#include <graphene/chain/vesting_balance_object.hpp>
|
||||||
|
|
||||||
|
|
@ -444,4 +446,209 @@ BOOST_AUTO_TEST_CASE( son_pay_test )
|
||||||
BOOST_CHECK( dpo.witness_budget.value == 0);
|
BOOST_CHECK( dpo.witness_budget.value == 0);
|
||||||
}FC_LOG_AND_RETHROW()
|
}FC_LOG_AND_RETHROW()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( son_witness_proposal_test )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
const dynamic_global_property_object& dpo = db.get_dynamic_global_properties();
|
||||||
|
generate_blocks(HARDFORK_SON_TIME);
|
||||||
|
generate_block();
|
||||||
|
generate_block();
|
||||||
|
set_expiration(db, trx);
|
||||||
|
|
||||||
|
ACTORS((alice)(bob));
|
||||||
|
|
||||||
|
upgrade_to_lifetime_member(alice);
|
||||||
|
upgrade_to_lifetime_member(bob);
|
||||||
|
|
||||||
|
transfer( committee_account, alice_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) );
|
||||||
|
transfer( committee_account, bob_id, asset( 1000*GRAPHENE_BLOCKCHAIN_PRECISION ) );
|
||||||
|
|
||||||
|
set_expiration(db, trx);
|
||||||
|
generate_block();
|
||||||
|
// Now create SONs
|
||||||
|
std::string test_url1 = "https://create_son_test1";
|
||||||
|
std::string test_url2 = "https://create_son_test2";
|
||||||
|
|
||||||
|
// create deposit vesting
|
||||||
|
vesting_balance_id_type deposit1;
|
||||||
|
{
|
||||||
|
vesting_balance_create_operation op;
|
||||||
|
op.creator = alice_id;
|
||||||
|
op.owner = alice_id;
|
||||||
|
op.amount = asset(50*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||||
|
op.balance_type = vesting_balance_type::son;
|
||||||
|
op.policy = dormant_vesting_policy_initializer {};
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||||
|
set_expiration(db, trx);
|
||||||
|
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||||
|
trx.clear();
|
||||||
|
deposit1 = ptx.operation_results[0].get<object_id_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create payment vesting
|
||||||
|
vesting_balance_id_type payment1;
|
||||||
|
{
|
||||||
|
vesting_balance_create_operation op;
|
||||||
|
op.creator = alice_id;
|
||||||
|
op.owner = alice_id;
|
||||||
|
op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||||
|
op.balance_type = vesting_balance_type::normal;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||||
|
set_expiration(db, trx);
|
||||||
|
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||||
|
trx.clear();
|
||||||
|
payment1 = ptx.operation_results[0].get<object_id_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create deposit vesting
|
||||||
|
vesting_balance_id_type deposit2;
|
||||||
|
{
|
||||||
|
vesting_balance_create_operation op;
|
||||||
|
op.creator = bob_id;
|
||||||
|
op.owner = bob_id;
|
||||||
|
op.amount = asset(50*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||||
|
op.balance_type = vesting_balance_type::son;
|
||||||
|
op.policy = dormant_vesting_policy_initializer {};
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||||
|
set_expiration(db, trx);
|
||||||
|
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||||
|
trx.clear();
|
||||||
|
deposit2 = ptx.operation_results[0].get<object_id_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create payment vesting
|
||||||
|
vesting_balance_id_type payment2;
|
||||||
|
{
|
||||||
|
vesting_balance_create_operation op;
|
||||||
|
op.creator = bob_id;
|
||||||
|
op.owner = bob_id;
|
||||||
|
op.amount = asset(1*GRAPHENE_BLOCKCHAIN_PRECISION);
|
||||||
|
op.balance_type = vesting_balance_type::normal;
|
||||||
|
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||||
|
set_expiration(db, trx);
|
||||||
|
processed_transaction ptx = PUSH_TX(db, trx, ~0);
|
||||||
|
trx.clear();
|
||||||
|
payment2 = ptx.operation_results[0].get<object_id_type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// alice becomes son
|
||||||
|
{
|
||||||
|
son_create_operation op;
|
||||||
|
op.owner_account = alice_id;
|
||||||
|
op.url = test_url1;
|
||||||
|
op.deposit = deposit1;
|
||||||
|
op.pay_vb = payment1;
|
||||||
|
op.fee = asset(0);
|
||||||
|
op.signing_key = alice_public_key;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||||
|
sign(trx, alice_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
trx.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// bob becomes son
|
||||||
|
{
|
||||||
|
son_create_operation op;
|
||||||
|
op.owner_account = bob_id;
|
||||||
|
op.url = test_url2;
|
||||||
|
op.deposit = deposit2;
|
||||||
|
op.pay_vb = payment2;
|
||||||
|
op.fee = asset(0);
|
||||||
|
op.signing_key = bob_public_key;
|
||||||
|
trx.operations.push_back(op);
|
||||||
|
for( auto& op : trx.operations ) db.current_fee_schedule().set_fee(op);
|
||||||
|
sign(trx, bob_private_key);
|
||||||
|
PUSH_TX(db, trx, ~0);
|
||||||
|
trx.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
// Check if SONs are created properly
|
||||||
|
const auto& idx = db.get_index_type<son_index>().indices().get<by_account>();
|
||||||
|
BOOST_REQUIRE( idx.size() == 2 );
|
||||||
|
// Alice's SON
|
||||||
|
auto obj1 = idx.find( alice_id );
|
||||||
|
BOOST_REQUIRE( obj1 != idx.end() );
|
||||||
|
BOOST_CHECK( obj1->url == test_url1 );
|
||||||
|
BOOST_CHECK( obj1->signing_key == alice_public_key );
|
||||||
|
BOOST_CHECK( obj1->deposit.instance == deposit1.instance.value );
|
||||||
|
BOOST_CHECK( obj1->pay_vb.instance == payment1.instance.value );
|
||||||
|
// Bob's SON
|
||||||
|
auto obj2 = idx.find( bob_id );
|
||||||
|
BOOST_REQUIRE( obj2 != idx.end() );
|
||||||
|
BOOST_CHECK( obj2->url == test_url2 );
|
||||||
|
BOOST_CHECK( obj2->signing_key == bob_public_key );
|
||||||
|
BOOST_CHECK( obj2->deposit.instance == deposit2.instance.value );
|
||||||
|
BOOST_CHECK( obj2->pay_vb.instance == payment2.instance.value );
|
||||||
|
// Get the statistics object for the SONs
|
||||||
|
const auto& sidx = db.get_index_type<son_stats_index>().indices().get<by_id>();
|
||||||
|
BOOST_REQUIRE( sidx.size() == 2 );
|
||||||
|
auto son_stats_obj1 = sidx.find( obj1->statistics );
|
||||||
|
auto son_stats_obj2 = sidx.find( obj2->statistics );
|
||||||
|
BOOST_REQUIRE( son_stats_obj1 != sidx.end() );
|
||||||
|
BOOST_REQUIRE( son_stats_obj2 != sidx.end() );
|
||||||
|
|
||||||
|
|
||||||
|
// Modify SON's status to in_maintenance
|
||||||
|
db.modify( *obj1, [&]( son_object& _s)
|
||||||
|
{
|
||||||
|
_s.status = son_status::in_maintenance;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modify the transaction signed statistics of Alice's SON
|
||||||
|
db.modify( *son_stats_obj1, [&]( son_statistics_object& _s)
|
||||||
|
{
|
||||||
|
_s.last_down_timestamp = fc::time_point_sec(db.head_block_time() - fc::hours(12));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modify SON's status to in_maintenance
|
||||||
|
db.modify( *obj2, [&]( son_object& _s)
|
||||||
|
{
|
||||||
|
_s.status = son_status::in_maintenance;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modify the transaction signed statistics of Alice's SON
|
||||||
|
db.modify( *son_stats_obj2, [&]( son_statistics_object& _s)
|
||||||
|
{
|
||||||
|
_s.last_down_timestamp = fc::time_point_sec(db.head_block_time() - fc::hours(12));
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto& son_proposal_idx = db.get_index_type<son_proposal_index>().indices().get<by_id>();
|
||||||
|
const auto& proposal_idx = db.get_index_type<proposal_index>().indices().get<by_id>();
|
||||||
|
|
||||||
|
BOOST_CHECK( son_proposal_idx.size() == 0 && proposal_idx.size() == 0 );
|
||||||
|
|
||||||
|
generate_block();
|
||||||
|
witness_id_type proposal_initiator = dpo.current_witness;
|
||||||
|
|
||||||
|
BOOST_CHECK( son_proposal_idx.size() == 2 && proposal_idx.size() == 2 );
|
||||||
|
|
||||||
|
for(size_t i = 0 ; i < 3 * db.get_global_properties().active_witnesses.size() ; i++ )
|
||||||
|
{
|
||||||
|
generate_block();
|
||||||
|
if( dpo.current_witness != proposal_initiator)
|
||||||
|
{
|
||||||
|
BOOST_CHECK( son_proposal_idx.size() == 2 && proposal_idx.size() == 2 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BOOST_CHECK( son_proposal_idx.size() == 0 && proposal_idx.size() == 0 );
|
||||||
|
BOOST_REQUIRE( idx.size() == 0 );
|
||||||
|
} FC_LOG_AND_RETHROW()
|
||||||
|
|
||||||
} BOOST_AUTO_TEST_SUITE_END()
|
} BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue