1
0
Fork 0
forked from lthn/blockchain

tx hardfork id: wip (basic structures, miner tx creation adapted, tests adapted almost all + hard_fork_5_tx_version)

This commit is contained in:
sowle 2024-12-06 05:39:18 +01:00
parent 8a8e5c3011
commit 13f524defb
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
15 changed files with 105 additions and 20 deletions

View file

@ -414,7 +414,7 @@ bool generate_genesis(const std::string& path_config, uint64_t premine_split_amo
std::cout << ENDL << "PROOF PHRASE: " << gcp.proof_string << ENDL;
uint64_t block_reward_without_fee = 0;
uint64_t block_reward = 0;
construct_miner_tx(0, 0, 0, 0, 0, dummy_address, dummy_address, bl.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS, false, pos_entry(), nullptr, nullptr, destinations);
construct_miner_tx(0, 0, 0, 0, 0, dummy_address, dummy_address, bl.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0, gcp.proof_string, CURRENCY_MINER_TX_MAX_OUTS, false, pos_entry(), nullptr, nullptr, destinations);
currency::blobdata txb = tx_to_blob(bl.miner_tx);
//self validate block

View file

@ -1589,6 +1589,9 @@ bool blockchain_storage::create_block_template(const create_block_template_param
resp.txs_fee = fee;
size_t tx_hardfork_id = 0;
size_t tx_version = get_tx_version_and_hardfork_id(height, m_core_runtime_config.hard_forks, tx_hardfork_id);
/*
instead of complicated two-phase template construction and adjustment of cumulative size with block reward we
use CURRENCY_COINBASE_BLOB_RESERVED_SIZE as penalty-free coinbase transaction reservation.
@ -1601,7 +1604,8 @@ bool blockchain_storage::create_block_template(const create_block_template_param
b.miner_tx,
resp.block_reward_without_fee,
resp.block_reward,
get_tx_version(height, m_core_runtime_config.hard_forks),
tx_version,
tx_hardfork_id,
ex_nonce,
CURRENCY_MINER_TX_MAX_OUTS,
pos,
@ -6080,6 +6084,7 @@ struct visitor_proxy : public boost::static_visitor<const x_type*>
bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const
{
size_t most_recent_hardfork_id_for_height = m_core_runtime_config.hard_forks.get_the_most_recent_hardfork_id_for_height(block_height);
bool var_is_after_hardfork_1_zone = m_core_runtime_config.is_hardfork_active_for_height(1, block_height);
bool var_is_after_hardfork_2_zone = m_core_runtime_config.is_hardfork_active_for_height(2, block_height);
bool var_is_after_hardfork_3_zone = m_core_runtime_config.is_hardfork_active_for_height(3, block_height);
@ -6218,7 +6223,9 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
if (var_is_after_hardfork_5_zone)
{
// additional checks here
CHECK_AND_ASSERT_MES(tx.version >= TRANSACTION_VERSION_POST_HF5, false, "HF5: tx with version " << tx.version << " is not allowed");
// starting from HF5 each tx must have hardfork_id corresponding to the current active hardfork
CHECK_AND_ASSERT_MES(tx.hardfork_id == most_recent_hardfork_id_for_height, false, "tx's hardfork_id is " << (int)tx.hardfork_id << ", but the current hardfork is " << most_recent_hardfork_id_for_height << ", rejected");
}
else
{

View file

@ -1032,6 +1032,7 @@ namespace currency
{
public:
uint64_t version = 0;
uint8_t hardfork_id = 0;
std::vector<txin_v> vin;
std::vector<extra_v> extra;
std::vector<tx_out_v> vout;
@ -1044,6 +1045,8 @@ namespace currency
FIELD(vin)
FIELD(extra)
FIELD(vout)
if(version < TRANSACTION_VERSION_POST_HF5) return true;
FIELD(hardfork_id)
END_SERIALIZE()
};

View file

@ -28,10 +28,11 @@
#define CURRENCY_PUBLIC_AUDITABLE_ADDRESS_BASE58_PREFIX 0x98c8 // auditable addresses start with 'aZx'
#define CURRENCY_PUBLIC_AUDITABLE_INTEG_ADDRESS_BASE58_PREFIX 0x8a49 // auditable integrated addresses start with 'aiZX'
#define CURRENCY_MINED_MONEY_UNLOCK_WINDOW 10
#define CURRENT_TRANSACTION_VERSION 2
#define CURRENT_TRANSACTION_VERSION 3
#define TRANSACTION_VERSION_INITAL 0
#define TRANSACTION_VERSION_PRE_HF4 1
#define TRANSACTION_VERSION_POST_HF4 2
#define TRANSACTION_VERSION_POST_HF4 2
#define TRANSACTION_VERSION_POST_HF5 3
#define HF1_BLOCK_MAJOR_VERSION 1
#define HF3_BLOCK_MAJOR_VERSION 2
#define HF3_BLOCK_MINOR_VERSION 0

View file

@ -393,6 +393,7 @@ namespace currency
uint64_t& block_reward_without_fee,
uint64_t& block_reward,
uint64_t tx_version,
size_t tx_hadrfork_id,
const blobdata& extra_nonce /* = blobdata() */,
size_t max_outs /* = CURRENCY_MINER_TX_MAX_OUTS */,
bool pos /* = false */,
@ -476,6 +477,8 @@ namespace currency
CHECK_AND_ASSERT_MES(destinations.size() <= CURRENCY_TX_MAX_ALLOWED_OUTS || height == 0, false, "Too many outs (" << destinations.size() << ")! Miner tx can't be constructed.");
// tx is not cleared intentionally to allow passing additional args in the extra/attachments
tx.version = tx_version;
if (tx.version >= TRANSACTION_VERSION_POST_HF5)
tx.hardfork_id = tx_hadrfork_id;
tx_generation_context tx_gen_context{};
tx_gen_context.set_tx_key(tx_one_time_key_to_use ? *tx_one_time_key_to_use : keypair::generate());
@ -2819,15 +2822,26 @@ namespace currency
//---------------------------------------------------------------
uint64_t get_tx_version(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd)
uint64_t get_tx_version_and_hardfork_id(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd, size_t& tx_hardfork_id)
{
tx_hardfork_id = hfd.get_the_most_recent_hardfork_id_for_height(tx_expected_block_height);
if (!hfd.is_hardfork_active_for_height(ZANO_HARDFORK_04_ZARCANUM, tx_expected_block_height))
{
return TRANSACTION_VERSION_PRE_HF4;
}
if (!hfd.is_hardfork_active_for_height(ZANO_HARDFORK_05, tx_expected_block_height))
{
return TRANSACTION_VERSION_POST_HF4;
}
return CURRENT_TRANSACTION_VERSION;
}
//---------------------------------------------------------------
uint64_t get_tx_version(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd)
{
[[maybe_unused]] size_t tx_hardfork_id{};
return get_tx_version_and_hardfork_id(tx_expected_block_height, hfd, tx_hardfork_id);
}
//---------------------------------------------------------------
// TODO @#@# this function is obsolete and needs to be re-written
uint64_t get_reward_from_miner_tx(const transaction& tx)
{

View file

@ -295,6 +295,7 @@ namespace currency
uint64_t& block_reward_without_fee,
uint64_t& block_reward,
uint64_t tx_version,
size_t tx_hadrfork_id,
const blobdata& extra_nonce = blobdata(),
size_t max_outs = CURRENCY_MINER_TX_MAX_OUTS,
bool pos = false,
@ -348,6 +349,7 @@ namespace currency
bool shuffle = true,
uint64_t flags = 0);
uint64_t get_tx_version_and_hardfork_id(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd, size_t& tx_hardfork_id); // returns tx version and tx hardfork id based on the height of the block where the transaction is expected to be
uint64_t get_tx_version(uint64_t tx_expected_block_height, const hard_forks_descriptor& hfd); // returns tx version based on the height of the block where the transaction is expected to be
bool construct_tx(const account_keys& sender_account_keys, const finalize_tx_param& param, finalized_tx& result);
bool get_or_calculate_asset_id(const asset_descriptor_operation& ado, crypto::point_t* p_result_point, crypto::public_key* p_result_pub_key);

View file

@ -299,6 +299,8 @@ bool test_generator::construct_block(currency::block& blk,
tx_generation_context miner_tx_tgc{};
uint64_t block_reward_without_fee = 0;
uint64_t block_reward = 0;
size_t tx_hardfork_id = 0;
uint64_t tx_version = get_tx_version_and_hardfork_id(height, m_hardforks, tx_hardfork_id);
while (true)
{
r = construct_miner_tx(height, misc_utils::median(block_sizes),
@ -310,7 +312,8 @@ bool test_generator::construct_block(currency::block& blk,
blk.miner_tx,
block_reward_without_fee,
block_reward,
get_tx_version(height, m_hardforks),
tx_version,
tx_hardfork_id,
blobdata(),
test_generator::get_test_gentime_settings().miner_tx_max_outs,
static_cast<bool>(coin_stake_sources.size()),
@ -956,10 +959,12 @@ bool test_generator::construct_block(int64_t manual_timestamp_adjustment,
{
uint64_t base_block_reward = 0;
uint64_t block_reward = 0;
size_t tx_hardfork_id = 0;
uint64_t tx_version = get_tx_version_and_hardfork_id(height, m_hardforks, tx_hardfork_id);
size_t current_block_size = txs_sizes + get_object_blobsize(blk.miner_tx);
// TODO: This will work, until size of constructed block is less then CURRENCY_BLOCK_GRANTED_FULL_REWARD_ZONE
if (!construct_miner_tx(height, misc_utils::median(block_sizes), already_generated_coins, current_block_size, 0,
miner_acc.get_public_address(), miner_acc.get_public_address(), blk.miner_tx, base_block_reward, block_reward, get_tx_version(height, m_hardforks), blobdata(), 1))
miner_acc.get_public_address(), miner_acc.get_public_address(), blk.miner_tx, base_block_reward, block_reward, tx_version, tx_hardfork_id, blobdata(), 1))
return false;
}

View file

@ -994,10 +994,12 @@ bool test_generator::construct_block_gentime_with_coinbase_cb(const currency::bl
uint64_t block_reward_without_fee = 0;
uint64_t block_reward = 0;
size_t tx_hardfork_id = 0;
uint64_t tx_version = get_tx_version_and_hardfork_id(height, m_hardforks, tx_hardfork_id);
currency::keypair tx_sec_key = currency::keypair::generate();
r = construct_miner_tx(height, epee::misc_utils::median(block_sizes), already_generated_coins, 0 /* current_block_size !HACK! */, 0,
acc.get_public_address(), acc.get_public_address(), miner_tx, block_reward_without_fee, block_reward, get_tx_version(height, m_hardforks), currency::blobdata(), /* max outs: */ 1,
acc.get_public_address(), acc.get_public_address(), miner_tx, block_reward_without_fee, block_reward, tx_version, tx_hardfork_id, currency::blobdata(), /* max outs: */ 1,
/* pos: */ false, currency::pos_entry(), /* ogc_ptr: */ nullptr, &tx_sec_key);
CHECK_AND_ASSERT_MES(r, false, "construct_miner_tx failed");

View file

@ -1271,6 +1271,9 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(hardfork_4_wallet_sweep_bare_outs);
GENERATE_AND_PLAY_HF(hardfork_4_pop_tx_from_global_index, "4-*");
// HF5
GENERATE_AND_PLAY_HF(hard_fork_5_tx_version, "5-*");
// atomics
GENERATE_AND_PLAY(atomic_simple_test);
GENERATE_AND_PLAY(atomic_test_wrong_redeem_wrong_refund);

View file

@ -39,6 +39,7 @@
#include "hard_fork_1.h"
#include "hard_fork_2.h"
#include "hard_fork_4.h"
#include "hard_fork_5.h"
#include "atomic_tests.h"
#include "isolate_auditable_and_proof.h"
#include "zarcanum_test.h"

View file

@ -0,0 +1,32 @@
// Copyright (c) 2024 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "chaingen.h"
#include "hard_fork_5.h"
#include "random_helper.h"
using namespace currency;
bool hard_fork_5_tx_version::generate(std::vector<test_event_entry>& events) const
{
//
// Test idea:
//
uint64_t ts = test_core_time::get_time();
GENERATE_ACCOUNT(miner_acc);
GENERATE_ACCOUNT(alice_acc);
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, ts);
//// rebuild genesis miner tx
//std::vector<tx_destination_entry> destinations;
//destinations.emplace_back(MK_TEST_COINS(1), alice_acc.get_public_address());
//destinations.emplace_back(MK_TEST_COINS(1), alice_acc.get_public_address());
//CHECK_AND_ASSERT_MES(replace_coinbase_in_genesis_block(destinations, generator, events, blk_0), false, ""); // leftover amount will be also send to miner
DO_CALLBACK(events, "configure_core"); // default configure_core callback will initialize core runtime config with m_hardforks
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
MAKE_TX(events, tx_1, miner_acc, alice_acc, MK_TEST_COINS(1), blk_0r);
return true;
}

View file

@ -0,0 +1,12 @@
// Copyright (c) 2024 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include "chaingen.h"
#include "wallet_tests_basic.h"
struct hard_fork_5_tx_version : public test_chain_unit_enchanced
{
bool generate(std::vector<test_event_entry>& events) const;
};

View file

@ -161,6 +161,8 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
CHECK_AND_ASSERT_THROW_MES(m_step == 3, "pos_block_builder: incorrect step sequence");
uint64_t tx_version = m_context.zarcanum ? TRANSACTION_VERSION_POST_HF4 : TRANSACTION_VERSION_PRE_HF4;
// TODO @#@# tx_hardfork_id
pos_entry pe{};
pe.stake_unlock_time = 0; // TODO
pe.amount = m_context.stake_amount;
@ -171,7 +173,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
size_t estimated_block_size = m_txs_total_size;
m_block.miner_tx = transaction{};
bool r = construct_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee,
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, m_block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, m_block_reward, tx_version, 0, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
CHECK_AND_ASSERT_THROW_MES(r, "construct_miner_tx failed");
estimated_block_size = m_txs_total_size + get_object_blobsize(m_block.miner_tx);
@ -180,7 +182,7 @@ void pos_block_builder::step4_generate_coinbase_tx(size_t median_size,
{
m_block.miner_tx = transaction{};
r = construct_miner_tx(m_height, median_size, already_generated_coins, estimated_block_size, m_total_fee,
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, m_block_reward, tx_version, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
reward_receiver_address, stakeholder_address, m_block.miner_tx, block_reward_without_fee, m_block_reward, tx_version, 0, extra_nonce, max_outs, true, pe, &m_miner_tx_tgc, tx_one_time_key_to_use);
CHECK_AND_ASSERT_THROW_MES(r, "construct_homemade_pos_miner_tx failed");
cumulative_size = m_txs_total_size + get_object_blobsize(m_block.miner_tx);

View file

@ -42,17 +42,17 @@ bool test_transaction_generation_and_ring_signature()
account_base rv_acc2;
rv_acc2.generate();
transaction tx_mine_1;
construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().account_address, miner_acc1.get_keys().account_address, tx_mine_1, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().account_address, miner_acc1.get_keys().account_address, tx_mine_1, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
transaction tx_mine_2;
construct_miner_tx(0, 0, 0, 0, 0, miner_acc2.get_keys().account_address, miner_acc2.get_keys().account_address, tx_mine_2, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
construct_miner_tx(0, 0, 0, 0, 0, miner_acc2.get_keys().account_address, miner_acc2.get_keys().account_address, tx_mine_2, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
transaction tx_mine_3;
construct_miner_tx(0, 0, 0, 0, 0, miner_acc3.get_keys().account_address, miner_acc3.get_keys().account_address, tx_mine_3, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
construct_miner_tx(0, 0, 0, 0, 0, miner_acc3.get_keys().account_address, miner_acc3.get_keys().account_address, tx_mine_3, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
transaction tx_mine_4;
construct_miner_tx(0, 0, 0, 0, 0, miner_acc4.get_keys().account_address, miner_acc4.get_keys().account_address, tx_mine_4, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
construct_miner_tx(0, 0, 0, 0, 0, miner_acc4.get_keys().account_address, miner_acc4.get_keys().account_address, tx_mine_4, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
transaction tx_mine_5;
construct_miner_tx(0, 0, 0, 0, 0, miner_acc5.get_keys().account_address, miner_acc5.get_keys().account_address, tx_mine_5, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
construct_miner_tx(0, 0, 0, 0, 0, miner_acc5.get_keys().account_address, miner_acc5.get_keys().account_address, tx_mine_5, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
transaction tx_mine_6;
construct_miner_tx(0, 0, 0, 0, 0, miner_acc6.get_keys().account_address, miner_acc6.get_keys().account_address, tx_mine_6, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
construct_miner_tx(0, 0, 0, 0, 0, miner_acc6.get_keys().account_address, miner_acc6.get_keys().account_address, tx_mine_6, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
//fill inputs entry
typedef tx_source_entry::output_entry tx_output_entry;
@ -139,7 +139,7 @@ bool test_block_creation()
uint64_t block_reward_without_fee = 0;
uint64_t block_reward = 0;
block b;
r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, adr, b.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4);
r = construct_miner_tx(90, epee::misc_utils::median(szs), 3553616528562147, 33094, 10000000, adr, adr, b.miner_tx, block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0);
return r;
}

View file

@ -1,3 +1,4 @@
// Copyright (c) 2014-2024 Zano Project
// Copyright (c) 2012-2013 The Cryptonote developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
@ -16,7 +17,7 @@ TEST(parse_and_validate_tx_extra, is_correct_parse_and_validate_tx_extra)
currency::blobdata b = "dsdsdfsdfsf";
uint64_t block_reward_without_fee = 0, block_reward = 0;
bool r = currency::construct_miner_tx(0, 0, 10000000000000, 1000, TESTS_DEFAULT_FEE, acc.get_keys().account_address, acc.get_keys().account_address, tx,
block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, b, 1);
block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0, b, 1);
ASSERT_TRUE(r);
crypto::public_key tx_pub_key;
r = currency::parse_and_validate_tx_extra(tx, tx_pub_key);
@ -30,7 +31,7 @@ TEST(parse_and_validate_tx_extra, is_correct_extranonce_too_big)
currency::blobdata b(260, 0);
uint64_t block_reward_without_fee = 0, block_reward = 0;
bool r = currency::construct_miner_tx(0, 0, 10000000000000, 1000, TESTS_DEFAULT_FEE, acc.get_keys().account_address, acc.get_keys().account_address, tx,
block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, b, 1);
block_reward_without_fee, block_reward, TRANSACTION_VERSION_PRE_HF4, 0, b, 1);
ASSERT_FALSE(r);
}