Fix the overflow test for fee and block_reward in blocks (#869)

This commit is contained in:
Doyle 2019-10-04 15:01:03 +10:00 committed by GitHub
parent a3ebf5eba6
commit 11e6f7affe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 238 additions and 198 deletions

View File

@ -111,6 +111,48 @@ std::shared_ptr<const service_nodes::testing_quorum> loki_chain_generator::get_t
return result;
}
loki_blockchain_entry &loki_chain_generator::add_block(loki_blockchain_entry const &entry, bool can_be_added_to_blockchain, std::string const &fail_msg)
{
crypto::hash block_hash = get_block_hash(entry.block);
if (can_be_added_to_blockchain)
{
blocks_.push_back(entry);
assert(block_table_.count(block_hash) == 0);
block_table_[block_hash] = blocks_.back();
}
else
{
assert(block_table_.count(block_hash) == 0);
block_table_[block_hash] = entry;
}
loki_blockchain_entry &result = (can_be_added_to_blockchain) ? blocks_.back() : block_table_[block_hash];
for (cryptonote::transaction &tx : result.txs)
{
crypto::hash tx_hash = get_transaction_hash(tx);
assert(tx_table_.count(tx_hash) == 0);
tx_table_[tx_hash] = tx;
}
// TODO(loki): State history culling and alt states
state_history_.emplace_hint(state_history_.end(), result.service_node_state);
if (result.checkpointed)
{
loki_block_with_checkpoint data = {};
data.has_checkpoint = true;
data.block = result.block;
data.checkpoint = result.checkpoint;
events_.push_back(loki_blockchain_addable<loki_block_with_checkpoint>(data, can_be_added_to_blockchain, fail_msg));
}
else
{
events_.push_back(loki_blockchain_addable<cryptonote::block>(result.block, can_be_added_to_blockchain, fail_msg));
}
return result;
}
cryptonote::account_base loki_chain_generator::add_account()
{
cryptonote::account_base account;
@ -119,51 +161,6 @@ cryptonote::account_base loki_chain_generator::add_account()
return account;
}
loki_blockchain_entry &loki_chain_generator::add_block(const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const *checkpoint, bool can_be_added_to_blockchain, std::string const &fail_msg)
{
blocks_.push_back({});
loki_blockchain_entry &result = blocks_.back(); // NOTE: important to use blocks_ storage as we take references to the contents in create_loki_blockchain_entry
loki_blockchain_entry &prev = blocks_[blocks_.size() - 2];
{
const auto new_height = get_block_height(prev.block) + 1;
uint8_t desired_hf = hard_forks_[0].first;
for (std::pair<uint8_t, uint64_t> const &hf_pair : hard_forks_)
{
uint8_t version = hf_pair.first;
uint64_t height = hf_pair.second;
if (new_height >= height) desired_hf = version;
else break;
}
service_nodes::block_winner winner = prev.service_node_state.get_block_winner();
std::vector<uint64_t> block_weights = last_n_block_weights(new_height - 1, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
create_loki_blockchain_entry(result,
desired_hf,
prev,
first_miner_,
prev.block.timestamp + DIFFICULTY_TARGET_V2,
block_weights,
txs,
winner);
if (checkpoint)
{
loki_block_with_checkpoint data = {};
data.has_checkpoint = true;
data.block = result.block;
data.checkpoint = *checkpoint;
events_.push_back(loki_blockchain_addable<loki_block_with_checkpoint>(data, can_be_added_to_blockchain, fail_msg));
}
else
{
events_.push_back(loki_blockchain_addable<cryptonote::block>(result.block, can_be_added_to_blockchain, fail_msg));
}
}
hf_version_ = result.block.major_version;
return result;
}
void loki_chain_generator::add_blocks_until_version(uint8_t hf_version)
{
assert(hard_forks_.size());
@ -171,7 +168,7 @@ void loki_chain_generator::add_blocks_until_version(uint8_t hf_version)
assert(blocks_.size() >= 1); // NOTE: We must have genesis block
for (;;)
{
loki_blockchain_entry entry = add_block();
loki_blockchain_entry &entry = create_and_add_next_block();
if (entry.block.major_version == hf_version) return;
}
}
@ -179,7 +176,7 @@ void loki_chain_generator::add_blocks_until_version(uint8_t hf_version)
void loki_chain_generator::add_n_blocks(int n)
{
for (auto i = 0; i < n; ++i) {
add_block();
create_and_add_next_block();
}
}
@ -192,7 +189,7 @@ void loki_chain_generator::add_blocks_until_next_checkpointable_height()
else
{
while (height() % service_nodes::CHECKPOINT_INTERVAL != 0)
add_block();
create_and_add_next_block();
}
}
@ -222,7 +219,7 @@ cryptonote::transaction loki_chain_generator::create_and_add_tx(const cryptonote
uint64_t fee,
bool kept_by_block)
{
cryptonote::transaction t;
cryptonote::transaction t = create_tx(src, dest, amount, fee, kept_by_block);
loki_tx_builder(events_, t, blocks_.back().block, src, dest, amount, hf_version_).with_fee(fee).build();
add_tx(t, true /*can_be_added_to_blockchain*/, ""/*fail_msg*/, kept_by_block);
return t;
@ -242,6 +239,26 @@ cryptonote::transaction loki_chain_generator::create_and_add_registration_tx(con
return result;
}
loki_blockchain_entry &loki_chain_generator::create_and_add_next_block(const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const *checkpoint, bool can_be_added_to_blockchain, std::string const &fail_msg)
{
loki_blockchain_entry entry = create_next_block(txs, checkpoint);
loki_blockchain_entry &result = add_block(entry, can_be_added_to_blockchain, fail_msg);
return result;
}
cryptonote::transaction loki_chain_generator::create_tx(const cryptonote::account_base &src,
const cryptonote::account_base &dest,
uint64_t amount,
uint64_t fee,
bool kept_by_block,
bool can_be_added_by_block,
std::string const &fail_msg) const
{
cryptonote::transaction t;
loki_tx_builder(events_, t, blocks_.back().block, src, dest, amount, hf_version_).with_fee(fee).build();
return t;
}
cryptonote::transaction loki_chain_generator::create_registration_tx(const cryptonote::account_base &src, const cryptonote::keypair &service_node_keys) const
{
uint64_t new_height = get_block_height(top().block) + 1;
@ -441,14 +458,14 @@ loki_blockchain_entry loki_chain_generator::create_genesis_block(const cryptonot
return result;
}
bool loki_chain_generator::create_loki_blockchain_entry(loki_blockchain_entry &entry,
uint8_t hf_version,
loki_blockchain_entry &prev,
const cryptonote::account_base &miner_acc,
uint64_t timestamp,
std::vector<uint64_t> &block_weights,
const std::vector<cryptonote::transaction> &tx_list,
const service_nodes::block_winner &block_winner)
bool loki_chain_generator::create_block(loki_blockchain_entry &entry,
uint8_t hf_version,
loki_blockchain_entry const &prev,
const cryptonote::account_base &miner_acc,
uint64_t timestamp,
std::vector<uint64_t> &block_weights,
const std::vector<cryptonote::transaction> &tx_list,
const service_nodes::block_winner &block_winner) const
{
assert(hf_version >= prev.block.major_version);
uint64_t height = get_block_height(prev.block) + 1;
@ -546,21 +563,7 @@ bool loki_chain_generator::create_loki_blockchain_entry(loki_blockchain_entry &e
fill_nonce(blk, TEST_DEFAULT_DIFFICULTY, height);
entry.txs = tx_list;
crypto::hash block_hash = get_block_hash(blk);
assert(block_table_.count(block_hash) == 0);
block_table_[block_hash] = &entry;
for (cryptonote::transaction &tx : entry.txs)
{
crypto::hash tx_hash = get_transaction_hash(tx);
assert(tx_table_.count(tx_hash) == 0);
tx_table_[tx_hash] = tx;
}
entry.service_node_state = prev.service_node_state;
// TODO(loki): State history culling
state_history_.emplace_hint(state_history_.end(), entry.service_node_state);
entry.service_node_state.update_from_block(db_, cryptonote::FAKECHAIN, state_history_, {} /*alt_states*/, entry.block, entry.txs, nullptr);
uint64_t block_reward, block_reward_unpenalized;
@ -569,6 +572,34 @@ bool loki_chain_generator::create_loki_blockchain_entry(loki_blockchain_entry &e
return true;
}
loki_blockchain_entry loki_chain_generator::create_next_block(const std::vector<cryptonote::transaction>& txs, cryptonote::checkpoint_t const *checkpoint)
{
loki_blockchain_entry result = {};
loki_blockchain_entry const &prev = top();
{
uint64_t new_height = height() + 1;
uint8_t desired_hf = get_hf_version_at(new_height);
service_nodes::block_winner winner = prev.service_node_state.get_block_winner();
std::vector<uint64_t> block_weights = last_n_block_weights(new_height - 1, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
create_block(result,
desired_hf,
prev,
first_miner_,
prev.block.timestamp + DIFFICULTY_TARGET_V2,
block_weights,
txs,
winner);
if (checkpoint)
{
result.checkpoint = *checkpoint;
result.checkpointed = true;
}
}
hf_version_ = result.block.major_version;
return result;
}
uint8_t loki_chain_generator::get_hf_version_at(uint64_t height) const {
uint8_t cur_hf_ver = 0;

View File

@ -752,7 +752,7 @@ public:
log_event("loki_blockchain_addable<cryptonote::checkpoint_t>");
cryptonote::Blockchain &blockchain = m_c.get_blockchain_storage();
bool added = blockchain.update_checkpoint(entry.data);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, entry.fail_msg);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, (entry.fail_msg.size() ? entry.fail_msg : "Failed to add checkpoint (no reason given)"));
return true;
}
@ -761,7 +761,7 @@ public:
log_event("loki_blockchain_addable<service_nodes::quorum_vote_t>");
cryptonote::vote_verification_context vvc = {};
bool added = m_c.add_service_node_vote(entry.data, vvc);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, entry.fail_msg);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, (entry.fail_msg.size() ? entry.fail_msg : "Failed to add service node vote (no reason given)"));
return true;
}
@ -786,7 +786,7 @@ public:
bvc.m_verifivation_failed = true;
bool added = !bvc.m_verifivation_failed;
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, entry.fail_msg);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, (entry.fail_msg.size() ? entry.fail_msg : "Failed to add block with checkpoint (no reason given)"));
return true;
}
@ -807,7 +807,7 @@ public:
bvc.m_verifivation_failed = true;
bool added = !bvc.m_verifivation_failed;
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, entry.fail_msg);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, (entry.fail_msg.size() ? entry.fail_msg : "Failed to add block (no reason given)"));
return true;
}
@ -819,7 +819,7 @@ public:
m_c.handle_incoming_tx(t_serializable_object_to_blob(entry.data.tx), tvc, entry.data.kept_by_block, false, false);
bool added = (pool_size + 1) == m_c.get_pool_transactions_count();
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, entry.fail_msg);
CHECK_AND_NO_ASSERT_MES(added == entry.can_be_added_to_blockchain, false, (entry.fail_msg.size() ? entry.fail_msg : "Failed to add transaction (no reason given)"));
return true;
}
@ -1331,11 +1331,11 @@ struct loki_chain_generator_db : public cryptonote::BaseTestDB
{
std::vector<loki_blockchain_entry> &blockchain;
std::unordered_map<crypto::hash, cryptonote::transaction> &tx_table; // TODO(loki): I want to store pointers to transactions but I get some memory corruption somewhere. Pls fix.
std::unordered_map<crypto::hash, loki_blockchain_entry *> &block_table;
std::unordered_map<crypto::hash, loki_blockchain_entry> &block_table;
loki_chain_generator_db(std::vector<loki_blockchain_entry> &blockchain,
std::unordered_map<crypto::hash, cryptonote::transaction> &tx_table,
std::unordered_map<crypto::hash, loki_blockchain_entry *> &block_table)
std::unordered_map<crypto::hash, loki_blockchain_entry> &block_table)
: blockchain(blockchain)
, tx_table(tx_table)
, block_table(block_table)
@ -1354,7 +1354,7 @@ struct loki_chain_generator
// TODO(loki): I want to store pointers to transactions but I get some memory corruption somewhere. Pls fix.
// We already store blockchain_entries in block_ vector which stores the actual backing transaction entries.
std::unordered_map<crypto::hash, cryptonote::transaction> tx_table_;
std::unordered_map<crypto::hash, loki_blockchain_entry *> block_table_;
std::unordered_map<crypto::hash, loki_blockchain_entry> block_table_; // TODO(loki): Hmm takes a copy. But its easier to work this way, particularly for storing alt blocks
std::vector<loki_blockchain_entry> blocks_;
loki_chain_generator_db db_;
uint8_t hf_version_ = cryptonote::network_version_7;
@ -1374,28 +1374,31 @@ struct loki_chain_generator
std::shared_ptr<const service_nodes::testing_quorum> get_testing_quorum(service_nodes::quorum_type type, uint64_t height) const;
cryptonote::account_base add_account();
loki_blockchain_entry &add_block(const std::vector<cryptonote::transaction>& txs = {}, cryptonote::checkpoint_t const *checkpoint = nullptr, bool can_be_added_to_blockchain = true, std::string const &fail_msg = {});
loki_blockchain_entry &add_block(loki_blockchain_entry const &entry, bool can_be_added_to_blockchain = true, std::string const &fail_msg = {});
void add_blocks_until_version(uint8_t hf_version);
void add_n_blocks(int n);
void add_blocks_until_next_checkpointable_height();
void add_service_node_checkpoint(uint64_t block_height, size_t num_votes);
void add_mined_money_unlock_blocks(); // NOTE: Unlock all Loki generated from mining prior to this call i.e. CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW
void add_tx(cryptonote::transaction const &tx, bool can_be_added_to_blockchain, std::string const &fail_msg = {}, bool kept_by_block = false);
void add_tx(cryptonote::transaction const &tx, bool can_be_added_to_blockchain = true, std::string const &fail_msg = {}, bool kept_by_block = false);
// NOTE: Add constructed TX to events_ and assume that it is valid to add to the blockchain. If the TX is meant to be unaddable to the blockchain use the individual create + add functions to
// be able to mark the add TX event as something that should trigger a failure.
cryptonote::transaction create_and_add_tx (const cryptonote::account_base& src, const cryptonote::account_base& dest, uint64_t amount, uint64_t fee = TESTS_DEFAULT_FEE, bool kept_by_block = false);
cryptonote::transaction create_and_add_state_change_tx(service_nodes::new_state state, const crypto::public_key& pub_key, uint64_t height = -1, const std::vector<uint64_t>& voters = {}, uint64_t fee = 0, bool kept_by_block = false);
cryptonote::transaction create_and_add_registration_tx(const cryptonote::account_base& src, const cryptonote::keypair& sn_keys = cryptonote::keypair::generate(hw::get_device("default")), bool kept_by_block = false);
loki_blockchain_entry &create_and_add_next_block(const std::vector<cryptonote::transaction>& txs = {}, cryptonote::checkpoint_t const *checkpoint = nullptr, bool can_be_added_to_blockchain = true, std::string const &fail_msg = {});
// NOTE: Create transactions but don't add to events_
cryptonote::transaction create_tx (const cryptonote::account_base &src, const cryptonote::account_base &dest, uint64_t amount, uint64_t fee, bool kept_by_block, bool can_be_added_to_blockchain = true, std::string const &fail_msg = {}) const;
cryptonote::transaction create_registration_tx(const cryptonote::account_base& src, const cryptonote::keypair& sn_keys = cryptonote::keypair::generate(hw::get_device("default"))) const;
cryptonote::transaction create_state_change_tx(service_nodes::new_state state, const crypto::public_key& pub_key, uint64_t height = -1, const std::vector<uint64_t>& voters = {}, uint64_t fee = 0) const;
cryptonote::checkpoint_t create_service_node_checkpoint(uint64_t block_height, size_t num_votes) const;
loki_blockchain_entry create_genesis_block(const cryptonote::account_base &miner, uint64_t timestamp);
bool create_loki_blockchain_entry(loki_blockchain_entry &entry, uint8_t hf_version, loki_blockchain_entry &prev, const cryptonote::account_base &miner_acc, uint64_t timestamp, std::vector<uint64_t> &block_weights, const std::vector<cryptonote::transaction> &tx_list, const service_nodes::block_winner &block_winner);
loki_blockchain_entry create_next_block(const std::vector<cryptonote::transaction>& txs = {}, cryptonote::checkpoint_t const *checkpoint = nullptr);
bool create_block(loki_blockchain_entry &entry, uint8_t hf_version, loki_blockchain_entry const &prev, const cryptonote::account_base &miner_acc, uint64_t timestamp, std::vector<uint64_t> &block_weights, const std::vector<cryptonote::transaction> &tx_list, const service_nodes::block_winner &block_winner) const;
uint8_t get_hf_version_at(uint64_t height) const;
std::vector<uint64_t> last_n_block_weights(uint64_t height, uint64_t num) const;

View File

@ -158,6 +158,8 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_block_has_invalid_tx);
GENERATE_AND_PLAY(gen_block_is_too_big);
GENERATE_AND_PLAY(gen_uint_overflow_1);
// TODO(loki): We also want to run these tx tests on deregistration tx's
// as well because they special case and run under very different code
// paths from the regular tx path
@ -228,10 +230,8 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_different_blocks<false>);
GENERATE_AND_PLAY(gen_double_spend_in_alt_chain_in_different_blocks<true>);
GENERATE_AND_PLAY(gen_uint_overflow_1);
GENERATE_AND_PLAY(gen_uint_overflow_2);
GENERATE_AND_PLAY(gen_block_reward);
GENERATE_AND_PLAY(gen_uint_overflow_2);
GENERATE_AND_PLAY(gen_v2_tx_mixable_0_mixin);
GENERATE_AND_PLAY(gen_v2_tx_mixable_low_mixin);

View File

@ -29,6 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "chaingen.h"
#include "loki_tests.h"
#include "integer_overflow.h"
using namespace epee;
@ -98,43 +99,48 @@ bool gen_uint_overflow_base::mark_last_valid_block(cryptonote::core& c, size_t e
bool gen_uint_overflow_1::generate(std::vector<test_event_entry>& events) const
{
uint64_t ts_start = 1338224400;
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
GENERATE_ACCOUNT(miner_account);
MAKE_GENESIS_BLOCK(events, blk_0, miner_account, ts_start);
DO_CALLBACK(events, "mark_last_valid_block");
MAKE_ACCOUNT(events, bob_account);
MAKE_ACCOUNT(events, alice_account);
gen.add_blocks_until_version(hard_forks.back().first);
gen.add_n_blocks(40);
gen.add_mined_money_unlock_blocks();
// Problem 1. Miner tx output overflow
MAKE_MINER_TX_MANUALLY(miner_tx_0, blk_0);
split_miner_tx_outs(miner_tx_0, MONEY_SUPPLY);
block blk_1;
if (!generator.construct_block_manually(blk_1, blk_0, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx_0))
return false;
events.push_back(blk_1);
cryptonote::account_base bob = gen.add_account();
cryptonote::account_base alice = gen.add_account();
// Problem 1. Miner tx outputs overflow
MAKE_MINER_TX_MANUALLY(miner_tx_1, blk_1);
split_miner_tx_outs(miner_tx_1, MONEY_SUPPLY);
block blk_2;
if (!generator.construct_block_manually(blk_2, blk_1, miner_account, test_generator::bf_miner_tx, 0, 0, 0, crypto::hash(), 0, miner_tx_1))
return false;
events.push_back(blk_2);
{
loki_blockchain_entry entry = gen.create_next_block();
cryptonote::transaction &miner_tx = entry.block.miner_tx;
split_miner_tx_outs(miner_tx, MONEY_SUPPLY);
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "We purposely overflow miner tx by MONEY_SUPPLY in the miner tx");
}
REWIND_BLOCKS(events, blk_2r, blk_2, miner_account);
MAKE_TX_LIST_START(events, txs_0, miner_account, bob_account, MONEY_SUPPLY, blk_2);
MAKE_TX_LIST(events, txs_0, miner_account, bob_account, MONEY_SUPPLY, blk_2);
MAKE_NEXT_BLOCK_TX_LIST(events, blk_3, blk_2r, miner_account, txs_0);
REWIND_BLOCKS(events, blk_3r, blk_3, miner_account);
// Problem 2. block_reward overflow
{
{
// Create txs with fee greater than the block reward
std::vector<cryptonote::transaction> txs;
txs.push_back(gen.create_and_add_tx(gen.first_miner_, alice, MK_COINS(1), MK_COINS(100) /*fee*/, false /*kept_by_block*/));
// Problem 2. total_fee overflow, block_reward overflow
std::list<cryptonote::transaction> txs_1;
// Create txs with huge fee
txs_1.push_back(construct_tx_with_fee(events, blk_3, bob_account, alice_account, MK_COINS(1), MONEY_SUPPLY - MK_COINS(1)));
txs_1.push_back(construct_tx_with_fee(events, blk_3, bob_account, alice_account, MK_COINS(1), MONEY_SUPPLY - MK_COINS(1)));
MAKE_NEXT_BLOCK_TX_LIST(events, blk_4, blk_3r, miner_account, txs_1);
loki_blockchain_entry entry = gen.create_next_block(txs);
cryptonote::transaction &miner_tx = entry.block.miner_tx;
miner_tx.vout[0].amount = 0; // Take partial block reward, fee > block_reward so ordinarly it would overflow. This should be disallowed
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "We should not be able to add TX because the fee is greater than the base miner reward");
}
{
// Set kept_by_block = true
std::vector<cryptonote::transaction> txs;
txs.push_back(gen.create_and_add_tx(gen.first_miner_, alice, MK_COINS(1), MK_COINS(100) /*fee*/, true /*kept_by_block*/));
loki_blockchain_entry entry = gen.create_next_block(txs);
cryptonote::transaction &miner_tx = entry.block.miner_tx;
miner_tx.vout[0].amount = 0; // Take partial block reward, fee > block_reward so ordinarly it would overflow. This should be disallowed
gen.add_block(entry, false /*can_be_added_to_blockchain*/, "We should not be able to add TX because the fee is greater than the base miner reward even if kept_by_block is true");
}
}
return true;
}

View File

@ -44,10 +44,7 @@ private:
size_t m_last_valid_block_event_idx;
};
struct gen_uint_overflow_1 : public gen_uint_overflow_base
{
bool generate(std::vector<test_event_entry>& events) const;
};
struct gen_uint_overflow_1 : public gen_uint_overflow_base { bool generate(std::vector<test_event_entry>& events) const; };
struct gen_uint_overflow_2 : public gen_uint_overflow_base
{

View File

@ -59,15 +59,15 @@
// the shared stack frame where before it didn't can be optimised to utilise the
// frame instead of re-deriving where data should be in the
// test_events_entry array
static void loki_register_callback(std::vector<test_event_entry> &events,
std::string const &callback_name,
loki_callback callback)
void loki_register_callback(std::vector<test_event_entry> &events,
std::string const &callback_name,
loki_callback callback)
{
events.push_back(loki_callback_entry{callback_name, callback});
}
static std::vector<std::pair<uint8_t, uint64_t>>
generate_sequential_hard_fork_table(uint8_t max_hf_version = cryptonote::network_version_count - 1)
std::vector<std::pair<uint8_t, uint64_t>>
loki_generate_sequential_hard_fork_table(uint8_t max_hf_version)
{
assert(max_hf_version < cryptonote::network_version_count);
std::vector<std::pair<uint8_t, uint64_t>> result = {};
@ -80,7 +80,7 @@ generate_sequential_hard_fork_table(uint8_t max_hf_version = cryptonote::network
// NOTE: - Checks that a chain with a checkpoint but less PoW is preferred over a chain that is longer with more PoW but no checkpoints
bool loki_checkpointing_alt_chain_more_service_node_checkpoints_less_pow_overtakes::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -91,7 +91,7 @@ bool loki_checkpointing_alt_chain_more_service_node_checkpoints_less_pow_overtak
std::vector<cryptonote::transaction> registration_txs(NUM_SERVICE_NODES);
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
// NOTE: Add blocks until we get to the first height that has a checkpointing quorum AND there are service nodes in the quorum.
int const MAX_TRIES = 16;
@ -108,7 +108,7 @@ bool loki_checkpointing_alt_chain_more_service_node_checkpoints_less_pow_overtak
gen.add_n_blocks(60); // Add blocks so that this chain has more PoW
cryptonote::checkpoint_t checkpoint = fork_with_more_checkpoints.create_service_node_checkpoint(fork_with_more_checkpoints.height(), service_nodes::CHECKPOINT_MIN_VOTES);
fork_with_more_checkpoints.add_block({}, &checkpoint);
fork_with_more_checkpoints.create_and_add_next_block({}, &checkpoint);
uint64_t const fork_top_height = cryptonote::get_block_height(fork_with_more_checkpoints.top().block);
crypto::hash const fork_top_hash = cryptonote::get_block_hash(fork_with_more_checkpoints.top().block);
@ -128,7 +128,7 @@ bool loki_checkpointing_alt_chain_more_service_node_checkpoints_less_pow_overtak
// NOTE: - A chain that receives checkpointing votes sufficient to form a checkpoint should reorg back accordingly
bool loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -139,7 +139,7 @@ bool loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back::ge
std::vector<cryptonote::transaction> registration_txs(NUM_SERVICE_NODES);
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
// NOTE: Add blocks until we get to the first height that has a checkpointing quorum AND there are service nodes in the quorum.
int const MAX_TRIES = 16;
@ -156,8 +156,8 @@ bool loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back::ge
loki_chain_generator fork = gen;
for (size_t i = 0; i < service_nodes::CHECKPOINT_INTERVAL; i++)
{
gen.add_block();
fork.add_block();
gen.create_and_add_next_block();
fork.create_and_add_next_block();
}
// NOTE: Fork generate two checkpoints worth of blocks.
@ -168,8 +168,8 @@ bool loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back::ge
for (size_t i = 0; i < service_nodes::CHECKPOINT_INTERVAL; i++)
{
gen.add_block();
fork.add_block();
gen.create_and_add_next_block();
fork.create_and_add_next_block();
}
uint64_t second_checkpointed_height = fork.height();
@ -204,7 +204,7 @@ bool loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back::ge
}
// Upon adding the last block, we should now switch to our forked chain
fork.add_block({});
fork.create_and_add_next_block({});
crypto::hash const fork_top_hash = cryptonote::get_block_hash(fork.top().block);
loki_register_callback(events, "check_switched_to_alt_chain", [&events, fork_top_hash](cryptonote::core &c, size_t ev_index)
{
@ -223,7 +223,7 @@ bool loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back::ge
// available checkpoint heights whilst maintaining equal heights with the main chain
bool loki_checkpointing_alt_chain_with_increasing_service_node_checkpoints::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -234,7 +234,7 @@ bool loki_checkpointing_alt_chain_with_increasing_service_node_checkpoints::gene
std::vector<cryptonote::transaction> registration_txs(NUM_SERVICE_NODES);
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
// NOTE: Add blocks until we get to the first height that has a checkpointing quorum AND there are service nodes in the quorum.
int const MAX_TRIES = 16;
@ -254,15 +254,15 @@ bool loki_checkpointing_alt_chain_with_increasing_service_node_checkpoints::gene
// Fork chain - B B B B C
loki_chain_generator fork = gen;
cryptonote::checkpoint_t gen_checkpoint = gen.create_service_node_checkpoint(gen.height(), service_nodes::CHECKPOINT_MIN_VOTES);
gen.add_block({}, &gen_checkpoint);
fork.add_block();
gen.create_and_add_next_block({}, &gen_checkpoint);
fork.create_and_add_next_block();
gen.add_blocks_until_next_checkpointable_height();
gen.add_block();
gen.create_and_add_next_block();
fork.add_blocks_until_next_checkpointable_height();
cryptonote::checkpoint_t fork_first_checkpoint = fork.create_service_node_checkpoint(fork.height(), service_nodes::CHECKPOINT_MIN_VOTES);
fork.add_block({}, &fork_first_checkpoint);
fork.create_and_add_next_block({}, &fork_first_checkpoint);
crypto::hash const gen_top_hash = cryptonote::get_block_hash(gen.top().block);
loki_register_callback(events, "check_still_on_main_chain", [&events, gen_top_hash](cryptonote::core &c, size_t ev_index)
@ -279,11 +279,11 @@ bool loki_checkpointing_alt_chain_with_increasing_service_node_checkpoints::gene
// Main chain - C B B B B | B B B B
// Fork chain - B B B B C | B B B C
gen.add_blocks_until_next_checkpointable_height();
gen.add_block();
gen.create_and_add_next_block();
fork.add_blocks_until_next_checkpointable_height();
cryptonote::checkpoint_t fork_second_checkpoint = fork.create_service_node_checkpoint(fork.height(), service_nodes::CHECKPOINT_MIN_VOTES);
fork.add_block({}, &fork_second_checkpoint);
fork.create_and_add_next_block({}, &fork_second_checkpoint);
crypto::hash const fork_top_hash = cryptonote::get_block_hash(fork.top().block);
loki_register_callback(events, "check_switched_to_alt_chain", [&events, fork_top_hash](cryptonote::core &c, size_t ev_index)
@ -302,7 +302,7 @@ bool loki_checkpointing_alt_chain_with_increasing_service_node_checkpoints::gene
// - Checks invalid vote (signature or key) is not accepted due to not being part of the quorum
bool loki_checkpointing_service_node_checkpoint_from_votes::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -313,7 +313,7 @@ bool loki_checkpointing_service_node_checkpoint_from_votes::generate(std::vector
std::vector<cryptonote::transaction> registration_txs(NUM_SERVICE_NODES);
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
// NOTE: Regarding the 2nd condition in this loop, although the height could
// be a checkpoint interval, since for checkpoints we offset the height,
@ -383,7 +383,7 @@ bool loki_checkpointing_service_node_checkpoint_from_votes::generate(std::vector
// - Checks you can add a block after the 1st checkpoint out of 2 checkpoints.
bool loki_checkpointing_service_node_checkpoints_check_reorg_windows::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -394,7 +394,7 @@ bool loki_checkpointing_service_node_checkpoints_check_reorg_windows::generate(s
std::vector<cryptonote::transaction> registration_txs(NUM_SERVICE_NODES);
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
// NOTE: Add blocks until we get to the first height that has a checkpointing quorum AND there are service nodes in the quorum.
int const MAX_TRIES = 16;
@ -412,7 +412,7 @@ bool loki_checkpointing_service_node_checkpoints_check_reorg_windows::generate(s
loki_chain_generator fork_1_block_before_checkpoint = gen;
// Mine one block and fork the chain before we add the checkpoint.
gen.add_block();
gen.create_and_add_next_block();
loki_chain_generator fork_1_block_after_checkpoint = gen;
gen.add_service_node_checkpoint(gen.height(), service_nodes::CHECKPOINT_MIN_VOTES);
@ -420,25 +420,25 @@ bool loki_checkpointing_service_node_checkpoints_check_reorg_windows::generate(s
gen.add_n_blocks(service_nodes::CHECKPOINT_INTERVAL - 1);
loki_chain_generator fork_1_block_before_second_checkpoint = gen;
gen.add_block();
gen.create_and_add_next_block();
gen.add_service_node_checkpoint(gen.height(), service_nodes::CHECKPOINT_MIN_VOTES);
// Try add a block before first checkpoint, should fail because we are already 2 checkpoints deep.
fork_1_block_before_checkpoint.add_block({}, nullptr /*checkpoint*/, false /*can_be_added_to_blockchain*/, "Can NOT add a block if the height would equal the immutable height");
fork_1_block_before_checkpoint.create_and_add_next_block({}, nullptr /*checkpoint*/, false /*can_be_added_to_blockchain*/, "Can NOT add a block if the height would equal the immutable height");
// Try add a block after the first checkpoint. This should succeed because we can reorg the chain within the 2 checkpoint window
fork_1_block_after_checkpoint.add_block({});
fork_1_block_after_checkpoint.create_and_add_next_block({});
// Try add a block on the second checkpoint. This should also succeed because we can reorg the chain within the 2
// checkpoint window, and although the height is checkpointed and should fail checkpoints::check, it should still be
// allowed as an alt block
fork_1_block_before_second_checkpoint.add_block({});
fork_1_block_before_second_checkpoint.create_and_add_next_block({});
return true;
}
bool loki_core_block_reward_unpenalized::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -454,7 +454,7 @@ bool loki_core_block_reward_unpenalized::generate(std::vector<test_event_entry>&
for (int i = 0; i < NUM_TXS; i++)
txs[i] = gen.create_and_add_tx(gen.first_miner_, dummy, MK_COINS(5));
gen.add_block(txs);
gen.create_and_add_next_block(txs);
uint64_t unpenalized_block_reward = cryptonote::block_reward_unpenalized_formula_v8(gen.height());
uint64_t expected_service_node_reward = cryptonote::service_node_reward_formula(unpenalized_block_reward, newest_hf);
@ -478,7 +478,7 @@ bool loki_core_block_reward_unpenalized::generate(std::vector<test_event_entry>&
bool loki_core_governance_batched_reward::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
const cryptonote::config_t &network = cryptonote::get_config(cryptonote::FAKECHAIN, cryptonote::network_version_count - 1);
uint64_t hf10_height = 0;
@ -514,7 +514,7 @@ bool loki_core_governance_batched_reward::generate(std::vector<test_event_entry>
no_batched_governance_generator.add_blocks_until_version(other_hard_forks.back().first);
while(no_batched_governance_generator.height() < batched_governance_generator.height())
no_batched_governance_generator.add_block();
no_batched_governance_generator.create_and_add_next_block();
// NOTE(loki): Skip the last block as that is the batched payout height, we
// don't include the governance reward of that height, that gets picked up
@ -553,7 +553,7 @@ bool loki_core_governance_batched_reward::generate(std::vector<test_event_entry>
bool loki_core_test_deregister_preferred::generate(std::vector<test_event_entry> &events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
loki_chain_generator gen(events, hard_forks);
const auto miner = gen.first_miner();
const auto alice = gen.add_account();
@ -569,7 +569,7 @@ bool loki_core_test_deregister_preferred::generate(std::vector<test_event_entry>
reg_txs.push_back(tx);
}
gen.add_block(reg_txs);
gen.create_and_add_next_block(reg_txs);
/// generate transactions to fill up txpool entirely
for (auto i = 0u; i < 45; ++i) {
@ -618,7 +618,7 @@ bool loki_core_test_deregister_preferred::generate(std::vector<test_event_entry>
// to test), they don't get deregistered.
bool loki_core_test_deregister_safety_buffer::generate(std::vector<test_event_entry> &events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
loki_chain_generator gen(events, hard_forks);
const auto miner = gen.first_miner();
@ -635,7 +635,7 @@ bool loki_core_test_deregister_safety_buffer::generate(std::vector<test_event_en
const auto tx = gen.create_and_add_registration_tx(miner);
reg_txs.push_back(tx);
}
gen.add_block({reg_txs});
gen.create_and_add_next_block({reg_txs});
const auto height_a = gen.height();
std::vector<crypto::public_key> quorum_a = gen.quorum(height_a).obligations->workers;
@ -655,7 +655,7 @@ bool loki_core_test_deregister_safety_buffer::generate(std::vector<test_event_en
const auto deregister_pub_key = quorum_intersection[0];
{
const auto dereg_tx = gen.create_and_add_state_change_tx(service_nodes::new_state::deregister, deregister_pub_key, height_a);
gen.add_block({dereg_tx});
gen.create_and_add_next_block({dereg_tx});
}
/// Register the node again
@ -663,7 +663,7 @@ bool loki_core_test_deregister_safety_buffer::generate(std::vector<test_event_en
assert(gen.service_node_keys_.count(deregister_pub_key) == 1);
cryptonote::keypair pair = {deregister_pub_key, gen.service_node_keys_[deregister_pub_key]};
const auto tx = gen.create_and_add_registration_tx(miner, pair);
gen.add_block({tx});
gen.create_and_add_next_block({tx});
}
/// Try to deregister the node again for heightB (should fail)
@ -677,7 +677,7 @@ bool loki_core_test_deregister_safety_buffer::generate(std::vector<test_event_en
// Daemon A accepts the block without X. Now X is too old and should not be added in future blocks.
bool loki_core_test_deregister_too_old::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -691,7 +691,7 @@ bool loki_core_test_deregister_too_old::generate(std::vector<test_event_entry>&
const auto tx = gen.create_and_add_registration_tx(gen.first_miner());
reg_txs.push_back(tx);
}
gen.add_block(reg_txs);
gen.create_and_add_next_block(reg_txs);
const auto pk = gen.top_quorum().obligations->workers[0];
const auto dereg_tx = gen.create_and_add_state_change_tx(service_nodes::new_state::deregister, pk);
@ -700,7 +700,7 @@ bool loki_core_test_deregister_too_old::generate(std::vector<test_event_entry>&
/// In the real world, this transaction should not make it into a block, but in this case we do try to add it (as in
/// tests we must add specify transactions manually), which should exercise the same validation code and reject the
/// block
gen.add_block({dereg_tx},
gen.create_and_add_next_block({dereg_tx},
nullptr /*checkpoint*/,
false /*can_be_added_to_blockchain*/,
"Trying to add a block with an old deregister sitting in the pool that was invalidated due to old age");
@ -709,7 +709,7 @@ bool loki_core_test_deregister_too_old::generate(std::vector<test_event_entry>&
bool loki_core_test_deregister_zero_fee::generate(std::vector<test_event_entry> &events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -721,7 +721,7 @@ bool loki_core_test_deregister_zero_fee::generate(std::vector<test_event_entry>
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
reg_txs[i] = gen.create_and_add_registration_tx(gen.first_miner_);
gen.add_block(reg_txs);
gen.create_and_add_next_block(reg_txs);
const auto deregister_pub_key = gen.top_quorum().obligations->workers[0];
cryptonote::transaction const invalid_deregister =
gen.create_state_change_tx(service_nodes::new_state::deregister, deregister_pub_key, -1 /*height*/, {} /*voters*/, MK_COINS(1) /*fee*/);
@ -735,7 +735,7 @@ bool loki_core_test_deregister_zero_fee::generate(std::vector<test_event_entry>
// those sitting on Chain 1 should not have problems switching over.
bool loki_core_test_deregister_on_split::generate(std::vector<test_event_entry> &events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -749,8 +749,8 @@ bool loki_core_test_deregister_on_split::generate(std::vector<test_event_entry>
reg_txs.push_back(tx);
}
gen.add_block(reg_txs);
gen.add_block(); // Can't change service node state on the same height it was registered in
gen.create_and_add_next_block(reg_txs);
gen.create_and_add_next_block(); // Can't change service node state on the same height it was registered in
auto fork = gen;
/// public key of the node to deregister (valid at the height of the pivot block)
@ -767,9 +767,9 @@ bool loki_core_test_deregister_on_split::generate(std::vector<test_event_entry>
crypto::hash expected_tx_hash = cryptonote::get_transaction_hash(dereg_b);
size_t dereg_index = gen.event_index();
gen.add_block({dereg_a}); /// continue main chain with deregister A
fork.add_block({dereg_b}); /// continue alt chain with deregister B
fork.add_block(); /// one more block on alt chain to switch
gen.create_and_add_next_block({dereg_a}); /// continue main chain with deregister A
fork.create_and_add_next_block({dereg_b}); /// continue alt chain with deregister B
fork.create_and_add_next_block(); /// one more block on alt chain to switch
loki_register_callback(events, "test_on_split", [&events, expected_tx_hash](cryptonote::core &c, size_t ev_index)
{
@ -802,7 +802,7 @@ bool loki_core_test_deregister_on_split::generate(std::vector<test_event_entry>
bool loki_core_test_state_change_ip_penalty_disallow_dupes::generate(std::vector<test_event_entry> &events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -816,8 +816,8 @@ bool loki_core_test_state_change_ip_penalty_disallow_dupes::generate(std::vector
reg_txs.push_back(tx);
}
gen.add_block(reg_txs);
gen.add_block(); // Can't change service node state on the same height it was registered in
gen.create_and_add_next_block(reg_txs);
gen.create_and_add_next_block(); // Can't change service node state on the same height it was registered in
const auto pub_key = gen.top_quorum().obligations->workers[0];
std::vector<uint64_t> const quorum_indexes = {1, 2, 3, 4, 5, 6, 7};
@ -831,7 +831,7 @@ bool loki_core_test_state_change_ip_penalty_disallow_dupes::generate(std::vector
// NOTE: Try same duplicate state change on a new height
{
gen.add_block({state_change_1});
gen.create_and_add_next_block({state_change_1});
gen.add_tx(state_change_2, false /*can_be_added_to_blockchain*/, "Can't add a state change with different permutation of votes than previously submitted, even if the blockchain height has changed");
}
@ -845,7 +845,7 @@ bool loki_core_test_state_change_ip_penalty_disallow_dupes::generate(std::vector
// NOTE: Generate forked block, check that alternative quorums are generated and accessible
bool loki_service_nodes_alt_quorums::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -856,11 +856,11 @@ bool loki_service_nodes_alt_quorums::generate(std::vector<test_event_entry>& eve
std::vector<cryptonote::transaction> registration_txs(NUM_SERVICE_NODES);
for (auto i = 0u; i < NUM_SERVICE_NODES; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
loki_chain_generator fork = gen;
gen.add_block();
fork.add_block();
gen.create_and_add_next_block();
fork.create_and_add_next_block();
uint64_t height_with_fork = gen.height();
service_nodes::quorum_manager fork_quorums = fork.top_quorum();
@ -899,7 +899,7 @@ bool loki_service_nodes_alt_quorums::generate(std::vector<test_event_entry>& eve
bool loki_service_nodes_checkpoint_quorum_size::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table();
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table();
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -909,7 +909,7 @@ bool loki_service_nodes_checkpoint_quorum_size::generate(std::vector<test_event_
std::vector<cryptonote::transaction> registration_txs(service_nodes::CHECKPOINT_QUORUM_SIZE - 1);
for (auto i = 0u; i < service_nodes::CHECKPOINT_QUORUM_SIZE - 1; ++i)
registration_txs[i] = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block(registration_txs);
gen.create_and_add_next_block(registration_txs);
int const MAX_TRIES = 16;
int tries = 0;
@ -927,7 +927,7 @@ bool loki_service_nodes_checkpoint_quorum_size::generate(std::vector<test_event_
});
cryptonote::transaction new_registration_tx = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block({new_registration_tx});
gen.create_and_add_next_block({new_registration_tx});
for (tries = 0; tries < MAX_TRIES; tries++)
{
@ -952,7 +952,7 @@ bool loki_service_nodes_checkpoint_quorum_size::generate(std::vector<test_event_
bool loki_service_nodes_gen_nodes::generate(std::vector<test_event_entry> &events)
{
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
const std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
loki_chain_generator gen(events, hard_forks);
const auto miner = gen.first_miner();
const auto alice = gen.add_account();
@ -963,11 +963,11 @@ bool loki_service_nodes_gen_nodes::generate(std::vector<test_event_entry> &event
gen.add_mined_money_unlock_blocks();
const auto tx0 = gen.create_and_add_tx(miner, alice, MK_COINS(101));
gen.add_block({tx0});
gen.create_and_add_next_block({tx0});
gen.add_mined_money_unlock_blocks();
const auto reg_tx = gen.create_and_add_registration_tx(alice);
gen.add_block({reg_tx});
gen.create_and_add_next_block({reg_tx});
loki_register_callback(events, "check_registered", [&events, alice](cryptonote::core &c, size_t ev_index)
{
@ -995,7 +995,7 @@ bool loki_service_nodes_gen_nodes::generate(std::vector<test_event_entry> &event
});
for (auto i = 0u; i < service_nodes::staking_num_lock_blocks(cryptonote::FAKECHAIN); ++i)
gen.add_block();
gen.create_and_add_next_block();
loki_register_callback(events, "check_expired", [&events, alice](cryptonote::core &c, size_t ev_index)
{
@ -1032,7 +1032,7 @@ static bool contains(const std::vector<sn_info_t>& infos, const crypto::public_k
bool loki_service_nodes_test_rollback::generate(std::vector<test_event_entry>& events)
{
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
std::vector<std::pair<uint8_t, uint64_t>> hard_forks = loki_generate_sequential_hard_fork_table(cryptonote::network_version_9_service_nodes);
loki_chain_generator gen(events, hard_forks);
gen.add_blocks_until_version(hard_forks.back().first);
@ -1045,7 +1045,7 @@ bool loki_service_nodes_test_rollback::generate(std::vector<test_event_entry>& e
const auto tx = gen.create_and_add_registration_tx(gen.first_miner());
reg_txs.push_back(tx);
}
gen.add_block(reg_txs);
gen.create_and_add_next_block(reg_txs);
gen.add_n_blocks(5); /// create a few blocks with active service nodes
auto fork = gen; /// chain split here
@ -1054,12 +1054,12 @@ bool loki_service_nodes_test_rollback::generate(std::vector<test_event_entry>& e
const auto pk = gen.top_quorum().obligations->workers[0];
const auto dereg_tx = gen.create_and_add_state_change_tx(service_nodes::new_state::deregister, pk);
size_t deregister_index = gen.event_index();
gen.add_block({dereg_tx});
gen.create_and_add_next_block({dereg_tx});
/// create a new service node (B) in the next block
{
const auto tx = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block({tx});
gen.create_and_add_next_block({tx});
}
fork.add_n_blocks(3); /// create blocks on the alt chain and trigger chain switch
@ -1135,7 +1135,7 @@ bool loki_service_nodes_test_swarms_basic::generate(std::vector<test_event_entry
reg_txs.push_back(tx);
}
gen.add_block(reg_txs);
gen.create_and_add_next_block(reg_txs);
/// create a few blocks with active service nodes
gen.add_n_blocks(5);
@ -1161,7 +1161,7 @@ bool loki_service_nodes_test_swarms_basic::generate(std::vector<test_event_entry
/// rewind some blocks and register 1 more service node
{
const auto tx = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block({tx});
gen.create_and_add_next_block({tx});
}
loki_register_callback(events, "test_with_one_more_sn", [&events](cryptonote::core &c, size_t ev_index) /// test that another swarm has been created
@ -1181,7 +1181,7 @@ bool loki_service_nodes_test_swarms_basic::generate(std::vector<test_event_entry
for (auto i = INIT_SN_COUNT + 1; i < TOTAL_SN_COUNT; ++i)
{
const auto tx = gen.create_and_add_registration_tx(gen.first_miner());
gen.add_block({tx});
gen.create_and_add_next_block({tx});
}
loki_register_callback(events, "test_with_more_sn", [&events](cryptonote::core &c, size_t ev_index) /// test that another swarm has been created
@ -1208,7 +1208,7 @@ bool loki_service_nodes_test_swarms_basic::generate(std::vector<test_event_entry
dereg_txs.push_back(tx);
}
gen.add_block(dereg_txs);
gen.create_and_add_next_block(dereg_txs);
loki_register_callback(events, "test_after_first_deregisters", [&events](cryptonote::core &c, size_t ev_index)
{
DEFINE_TESTS_ERROR_CONTEXT("test_after_first_deregisters");
@ -1230,7 +1230,7 @@ bool loki_service_nodes_test_swarms_basic::generate(std::vector<test_event_entry
const auto tx = gen.create_and_add_state_change_tx(service_nodes::new_state::deregister, pk);
dereg_txs.push_back(tx);
}
gen.add_block(dereg_txs);
gen.create_and_add_next_block(dereg_txs);
loki_register_callback(events, "test_after_final_deregisters", [&events](cryptonote::core &c, size_t ev_index)
{

View File

@ -35,6 +35,9 @@
/* */
/************************************************************************/
void loki_register_callback (std::vector<test_event_entry> &events, std::string const &callback_name, loki_callback callback);
std::vector<std::pair<uint8_t, uint64_t>> loki_generate_sequential_hard_fork_table(uint8_t max_hf_version = cryptonote::network_version_count - 1);
struct loki_checkpointing_alt_chain_more_service_node_checkpoints_less_pow_overtakes : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_checkpointing_alt_chain_receive_checkpoint_votes_should_reorg_back : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };
struct loki_checkpointing_alt_chain_with_increasing_service_node_checkpoints : public test_chain_unit_base { bool generate(std::vector<test_event_entry>& events); };

View File

@ -83,14 +83,14 @@ bool gen_ring_signature_1::generate(std::vector<test_event_entry>& events) const
txs.push_back( gen.create_and_add_tx(miner, some_account_1, MK_COINS(20) + rnd_20) );
txs.push_back( gen.create_and_add_tx(miner, some_account_2, MK_COINS(20) + rnd_20) );
gen.add_block(txs);
gen.create_and_add_next_block(txs);
gen.add_mined_money_unlock_blocks();
DO_CALLBACK(events, "check_balances_1");
auto tx = gen.create_and_add_tx(bob, alice, MK_COINS(129) + 2 * rnd_11 + rnd_20 + 3 * rnd_29 - TESTS_DEFAULT_FEE);
gen.add_block({tx});
gen.create_and_add_next_block({tx});
DO_CALLBACK(events, "check_balances_2");