未验证 提交 3b70b575 编写于 作者: D Daniel Larimer 提交者: GitHub

Merge pull request #3164 from EOSIO/system-contract-tests

More producer pay testing, code cleaning
......@@ -155,7 +155,7 @@ namespace eosio { namespace chain {
auto itr = producer_to_last_produced.find(h.producer);
if( itr != producer_to_last_produced.end() ) {
FC_ASSERT( itr->second <= result.block_num - h.confirmed, "producer double-confirming known range" );
FC_ASSERT( itr->second < result.block_num - h.confirmed, "producer double-confirming known range" );
}
// FC_ASSERT( result.header.block_mroot == h.block_mroot, "mismatch block merkle root" );
......
......@@ -160,7 +160,7 @@ namespace eosio { namespace testing {
auto last_produced_block_num = control->last_irreversible_block_num();
auto itr = last_produced_block.find(producer.producer_name);
if (itr != last_produced_block.end()) {
last_produced_block_num = block_header::num_from_id(itr->second);
last_produced_block_num = std::max(control->last_irreversible_block_num(), block_header::num_from_id(itr->second));
}
control->abort_block();
......
......@@ -46,13 +46,27 @@ public:
set_code( N(eosio.token), eosio_token_wast );
set_abi( N(eosio.token), eosio_token_abi );
{
const auto& accnt = control->db().get<account_object,by_name>( N(eosio.token) );
abi_def abi;
BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
token_abi_ser.set_abi(abi);
}
create_currency( N(eosio.token), config::system_account_name, asset::from_string("10000000000.0000 EOS") );
issue(config::system_account_name, "1000000000.0000 EOS");
BOOST_REQUIRE_EQUAL( asset::from_string("1000000000.0000 EOS"), get_balance( "eosio" ) );
set_code( config::system_account_name, eosio_system_wast );
set_abi( config::system_account_name, eosio_system_abi );
{
const auto& accnt = control->db().get<account_object,by_name>( config::system_account_name );
abi_def abi;
BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
abi_ser.set_abi(abi);
}
produce_blocks();
create_account_with_resources( N(alice1111111), N(eosio), asset::from_string("1.0000 EOS"), false );
......@@ -60,26 +74,9 @@ public:
create_account_with_resources( N(carol1111111), N(eosio), asset::from_string("1.0000 EOS"), false );
BOOST_REQUIRE_EQUAL( asset::from_string("1000000000.0000 EOS"), get_balance( "eosio" ) );
// eosio pays it self for these...
//BOOST_REQUIRE_EQUAL( asset::from_string("999999998.5000 EOS"), get_balance( "eosio" ) );
produce_blocks();
{
const auto& accnt = control->db().get<account_object,by_name>( config::system_account_name );
abi_def abi;
BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
abi_ser.set_abi(abi);
}
{
const auto& accnt = control->db().get<account_object,by_name>( N(eosio.token) );
abi_def abi;
BOOST_REQUIRE_EQUAL(abi_serializer::to_abi(accnt.abi, abi), true);
token_abi_ser.set_abi(abi);
}
}
void create_accounts_with_resources( vector<account_name> accounts, account_name creator = N(eosio) ) {
for( auto a : accounts ) {
create_account_with_resources( a, creator );
......@@ -290,7 +287,6 @@ public:
("max_authority_depth", 6 + n)
("max_generated_transaction_count", 10 + n)
("max_ram_size", (n % 10 + 1) * 1024 * 1024)
("percent_of_max_inflation_rate", 50 + n)
("ram_reserve_ratio", 100 + n);
}
......@@ -310,23 +306,8 @@ public:
}
asset get_balance( const account_name& act ) {
//return get_currency_balance( config::system_account_name, symbol(SY(4,EOS)), act );
//temporary code. current get_currency_balancy uses table name N(accounts) from currency.h
//generic_currency table name is N(account).
const auto& db = control->db();
const auto* tbl = db.find<table_id_object, by_code_scope_table>(boost::make_tuple(N(eosio.token), act, N(accounts)));
share_type result = 0;
// the balance is implied to be 0 if either the table or row does not exist
if (tbl) {
const auto *obj = db.find<key_value_object, by_scope_primary>(boost::make_tuple(tbl->id, symbol(SY(4,EOS)).to_symbol_code()));
if (obj) {
// balance is the first field in the serialization
fc::datastream<const char *> ds(obj->value.data(), obj->value.size());
fc::raw::unpack(ds, result);
}
}
return asset( result, symbol(SY(4,EOS)) );
vector<char> data = get_row_by_account( N(eosio.token), act, N(accounts), symbol(SY(4,EOS)).to_symbol_code().value );
return data.empty() ? asset(0, symbol(SY(4,EOS))) : token_abi_ser.binary_to_variant("account", data)["balance"].as<asset>();
}
fc::variant get_total_stake( const account_name& act ) {
......@@ -1415,11 +1396,12 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t
const double secs_per_year = 52 * 7 * 24 * 3600;
const asset large_asset = asset::from_string("80.0000 EOS");
create_account_with_resources( N(defproducera), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(defproducerb), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(defproducera), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(defproducerb), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(defproducerc), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvotera), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvoterb), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvotera), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvoterb), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
BOOST_REQUIRE_EQUAL(success(), regproducer(N(defproducera)));
auto prod = get_producer_info( N(defproducera) );
......@@ -1584,6 +1566,27 @@ BOOST_FIXTURE_TEST_CASE(producer_pay, eosio_system_tester, * boost::unit_test::t
push_action(N(defproducerb), N(claimrewards), mvo()("owner", "defproducerb")));
}
// test stability over a year
{
regproducer(N(defproducerb));
regproducer(N(defproducerc));
const asset initial_supply = get_token_supply();
const int64_t initial_savings = get_global_state()["savings"].as<int64_t>();
for (uint32_t i = 0; i < 7 * 52; ++i) {
produce_block(fc::seconds(8 * 3600));
BOOST_REQUIRE_EQUAL(success(), push_action(N(defproducerc), N(claimrewards), mvo()("owner", "defproducerc")));
produce_block(fc::seconds(8 * 3600));
BOOST_REQUIRE_EQUAL(success(), push_action(N(defproducerb), N(claimrewards), mvo()("owner", "defproducerb")));
produce_block(fc::seconds(8 * 3600));
BOOST_REQUIRE_EQUAL(success(), push_action(N(defproducera), N(claimrewards), mvo()("owner", "defproducera")));
}
const asset supply = get_token_supply();
const int64_t savings = get_global_state()["savings"].as<int64_t>();
// Amount issued per year is very close to the 5% inflation target. Small difference (500 tokens out of 50'000'000 issued)
// is due to compounding every 8 hours in this test as opposed to theoretical continuous compounding
BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.amount) * double(0.05)) - (supply.amount - initial_supply.amount));
BOOST_REQUIRE(500 * 10000 > int64_t(double(initial_supply.amount) * double(0.04)) - (savings - initial_savings));
}
} FC_LOG_AND_RETHROW()
......@@ -1592,13 +1595,13 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
const int64_t secs_per_year = 52 * 7 * 24 * 3600;
const double usecs_per_year = secs_per_year * 1000000;
const double cont_rate = 4.879/100.;
const double cont_rate = 4.879/100.;
const asset net = asset::from_string("80.0000 EOS");
const asset cpu = asset::from_string("80.0000 EOS");
create_account_with_resources( N(producvotera), N(eosio), asset::from_string("1.0000 EOS"), false, net, cpu );
create_account_with_resources( N(producvoterb), N(eosio), asset::from_string("1.0000 EOS"), false, net, cpu );
create_account_with_resources( N(producvoterc), N(eosio), asset::from_string("1.0000 EOS"), false, net, cpu );
create_account_with_resources( N(producvotera), config::system_account_name, asset::from_string("1.0000 EOS"), false, net, cpu );
create_account_with_resources( N(producvoterb), config::system_account_name, asset::from_string("1.0000 EOS"), false, net, cpu );
create_account_with_resources( N(producvoterc), config::system_account_name, asset::from_string("1.0000 EOS"), false, net, cpu );
// create accounts {defproducera, defproducerb, ..., defproducerz} and register as producers
std::vector<account_name> producer_names;
......@@ -1616,7 +1619,6 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
wdump((p));
BOOST_TEST(0 == get_producer_info(p)["total_votes"].as<double>());
}
}
{
......@@ -1700,6 +1702,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
vote_shares[i] = get_producer_info(producer_names[i])["total_votes"].as<double>();
total_votes += vote_shares[i];
}
BOOST_TEST(total_votes == get_global_state()["total_producer_vote_weight"].as<double>());
std::for_each(vote_shares.begin(), vote_shares.end(), [total_votes](double& x) { x /= total_votes; });
BOOST_TEST(double(1) == std::accumulate(vote_shares.begin(), vote_shares.end(), double(0)));
......@@ -1720,7 +1723,6 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
const uint32_t initial_tot_unpaid_blocks = initial_global_state["total_unpaid_blocks"].as<uint32_t>();
const asset initial_supply = get_token_supply();
const asset initial_balance = get_balance(prod_name);
const uint32_t initial_unpaid_blocks = get_producer_info(prod_name)["unpaid_blocks"].as<uint32_t>();
BOOST_REQUIRE_EQUAL(success(), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name)));
......@@ -1733,10 +1735,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
const uint32_t tot_unpaid_blocks = global_state["total_unpaid_blocks"].as<uint32_t>();
const asset supply = get_token_supply();
const asset balance = get_balance(prod_name);
const uint32_t unpaid_blocks = get_producer_info(prod_name)["unpaid_blocks"].as<uint32_t>();
const uint64_t usecs_between_fills = claim_time - initial_claim_time;
const int32_t secs_between_fills = static_cast<int32_t>(usecs_between_fills / 1000000);
......@@ -1795,7 +1794,6 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
const uint32_t initial_tot_unpaid_blocks = initial_global_state["total_unpaid_blocks"].as<uint32_t>();
const asset initial_supply = get_token_supply();
const asset initial_balance = get_balance(prod_name);
const uint32_t initial_unpaid_blocks = get_producer_info(prod_name)["unpaid_blocks"].as<uint32_t>();
BOOST_REQUIRE_EQUAL(success(), push_action(prod_name, N(claimrewards), mvo()("owner", prod_name)));
......@@ -1808,19 +1806,18 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
const uint32_t tot_unpaid_blocks = global_state["total_unpaid_blocks"].as<uint32_t>();
const asset supply = get_token_supply();
const asset balance = get_balance(prod_name);
const uint32_t unpaid_blocks = get_producer_info(prod_name)["unpaid_blocks"].as<uint32_t>();
const uint64_t usecs_between_fills = claim_time - initial_claim_time;
const double expected_supply_growth = initial_supply.amount * double(usecs_between_fills) * cont_rate / usecs_per_year;
BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth), supply.amount - initial_supply.amount );
BOOST_REQUIRE_EQUAL( int64_t(expected_supply_growth) - int64_t(expected_supply_growth)/5, savings - initial_savings );
const int64_t expected_perblock_bucket = int64_t( initial_supply.amount * double(usecs_between_fills) * (0.25 * cont_rate/ 5.) / usecs_per_year ) + initial_perblock_bucket;
const int64_t expected_pervote_bucket = int64_t( initial_supply.amount * double(usecs_between_fills) * (0.75 * cont_rate/ 5.) / usecs_per_year ) + initial_pervote_bucket;
const int64_t expected_perblock_bucket = int64_t( initial_supply.amount * double(usecs_between_fills) * (0.25 * cont_rate/ 5.) / usecs_per_year )
+ initial_perblock_bucket;
const int64_t expected_pervote_bucket = int64_t( initial_supply.amount * double(usecs_between_fills) * (0.75 * cont_rate/ 5.) / usecs_per_year )
+ initial_pervote_bucket;
const int64_t from_perblock_bucket = initial_unpaid_blocks * expected_perblock_bucket / initial_tot_unpaid_blocks ;
const int64_t from_pervote_bucket = int64_t( vote_shares[prod_index] * expected_pervote_bucket);
......@@ -1852,7 +1849,6 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
// wait two more hours, now most producers haven't produced in a day and will
// be deactivated
produce_block(fc::seconds(2 * 3600));
produce_blocks(8 * 21 * 12);
{
......@@ -1882,6 +1878,15 @@ BOOST_FIXTURE_TEST_CASE(multiple_producer_pay, eosio_system_tester, * boost::uni
BOOST_REQUIRE_EQUAL(0, inactive_prod_info["time_became_active"].as<uint32_t>());
BOOST_REQUIRE_EQUAL(error("condition: assertion failed: producer does not have an active key"),
push_action(producer_names[one_inactive_index], N(claimrewards), mvo()("owner", producer_names[one_inactive_index])));
// re-register deactivated producer and let him produce blocks again
const uint32_t initial_unpaid_blocks = inactive_prod_info["unpaid_blocks"].as<uint32_t>();
regproducer(producer_names[one_inactive_index]);
produce_blocks(21 * 12);
auto reactivated_prod_info = get_producer_info(producer_names[one_inactive_index]);
const uint32_t unpaid_blocks = reactivated_prod_info["unpaid_blocks"].as<uint32_t>();
BOOST_REQUIRE(initial_unpaid_blocks + 12 <= unpaid_blocks);
BOOST_REQUIRE_EQUAL(success(),
push_action(producer_names[one_inactive_index], N(claimrewards), mvo()("owner", producer_names[one_inactive_index])));
}
} FC_LOG_AND_RETHROW()
......@@ -2067,12 +2072,10 @@ BOOST_FIXTURE_TEST_CASE(producers_upgrade_system_contract, eosio_system_tester)
BOOST_FIXTURE_TEST_CASE(producer_onblock_check, eosio_system_tester) try {
const auto tol = boost::test_tools::tolerance(0.0000000001);
const asset large_asset = asset::from_string("80.0000 EOS");
create_account_with_resources( N(producvotera), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvoterb), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvoterc), N(eosio), asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvotera), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvoterb), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
create_account_with_resources( N(producvoterc), config::system_account_name, asset::from_string("1.0000 EOS"), false, large_asset, large_asset );
// create accounts {defproducera, defproducerb, ..., defproducerz} and register as producers
std::vector<account_name> producer_names;
......@@ -2086,11 +2089,12 @@ BOOST_FIXTURE_TEST_CASE(producer_onblock_check, eosio_system_tester) try {
for (auto a:producer_names)
regproducer(a);
BOOST_REQUIRE_EQUAL(0, get_producer_info( N(defproducera) )["total_votes"].as<double>());
BOOST_REQUIRE_EQUAL(0, get_producer_info( N(defproducerz) )["total_votes"].as<double>());
BOOST_REQUIRE_EQUAL(0, get_producer_info( producer_names.front() )["total_votes"].as<double>());
BOOST_REQUIRE_EQUAL(0, get_producer_info( producer_names.back() )["total_votes"].as<double>());
issue( "producvotera", "100000000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvotera", "30000000.0000 EOS", "30000000.0000 EOS"));
transfer(config::system_account_name, "producvotera", "200000000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvotera", "70000000.0000 EOS", "70000000.0000 EOS"));
BOOST_REQUIRE_EQUAL(success(), push_action(N(producvotera), N(voteproducer), mvo()
("voter", "producvotera")
("proxy", name(0).to_string())
......@@ -2116,11 +2120,11 @@ BOOST_FIXTURE_TEST_CASE(producer_onblock_check, eosio_system_tester) try {
BOOST_REQUIRE_EQUAL(true, rest_didnt_produce);
}
// issue across 15% boundary
issue( "producvoterb", "100000000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvoterb", "30000000.0000 EOS", "30000000.0000 EOS"));
issue( "producvoterc", "100000000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvoterc", "30000000.0000 EOS", "30000000.0000 EOS"));
// stake across 15% boundary
transfer(config::system_account_name, "producvoterb", "100000000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvoterb", "4000000.0000 EOS", "4000000.0000 EOS"));
transfer(config::system_account_name, "producvoterc", "100000000.0000 EOS", config::system_account_name);
BOOST_REQUIRE_EQUAL(success(), stake("producvoterc", "2000000.0000 EOS", "2000000.0000 EOS"));
BOOST_REQUIRE_EQUAL(success(), push_action(N(producvoterb), N(voteproducer), mvo()
("voter", "producvoterb")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册