Guarantee insertion order into the tree using global output ID

- Leaves enter the tree in the block they unlock, in the order
they appear in the chain
This commit is contained in:
j-berman 2024-07-25 12:37:41 -07:00
parent 306488b690
commit 634e12e9ad
13 changed files with 152 additions and 109 deletions

View File

@ -179,7 +179,7 @@ void BlockchainDB::pop_block()
pop_block(blk, txs); pop_block(blk, txs);
} }
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr) std::vector<uint64_t> BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& txp, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr)
{ {
const transaction &tx = txp.first; const transaction &tx = txp.first;
@ -223,7 +223,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
uint64_t tx_id = add_transaction_data(blk_hash, txp, tx_hash, tx_prunable_hash); uint64_t tx_id = add_transaction_data(blk_hash, txp, tx_hash, tx_prunable_hash);
std::vector<uint64_t> amount_output_indices(tx.vout.size()); std::vector<output_indexes_t> output_indices(tx.vout.size());
// iterate tx.vout using indices instead of C++11 foreach syntax because // iterate tx.vout using indices instead of C++11 foreach syntax because
// we need the index // we need the index
@ -231,21 +231,35 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
{ {
// miner v2 txes have their coinbase output in one single out to save space, // miner v2 txes have their coinbase output in one single out to save space,
// and we store them as rct outputs with an identity mask // and we store them as rct outputs with an identity mask
// note: tx_outs_to_leaf_tuples in curve_trees.cpp mirrors this logic
if (miner_tx && tx.version == 2) if (miner_tx && tx.version == 2)
{ {
cryptonote::tx_out vout = tx.vout[i]; cryptonote::tx_out vout = tx.vout[i];
rct::key commitment = rct::zeroCommit(vout.amount); rct::key commitment = rct::zeroCommit(vout.amount);
vout.amount = 0; vout.amount = 0;
amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time, output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time,
&commitment); &commitment);
} }
else else
{ {
amount_output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time, output_indices[i] = add_output(tx_hash, tx.vout[i], i, tx.unlock_time,
tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL); tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL);
} }
} }
std::vector<uint64_t> amount_output_indices;
std::vector<uint64_t> output_ids;
amount_output_indices.reserve(output_indices.size());
output_ids.reserve(output_indices.size());
for (const auto &o_idx : output_indices)
{
amount_output_indices.push_back(o_idx.amount_index);
output_ids.push_back(o_idx.output_id);
}
add_tx_amount_output_indices(tx_id, amount_output_indices); add_tx_amount_output_indices(tx_id, amount_output_indices);
return output_ids;
} }
uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
@ -273,9 +287,12 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
time1 = epee::misc_utils::get_tick_count(); time1 = epee::misc_utils::get_tick_count();
std::vector<std::vector<uint64_t>> output_ids;
output_ids.reserve(1 + txs.size());
uint64_t num_rct_outs = 0; uint64_t num_rct_outs = 0;
blobdata miner_bd = tx_to_blob(blk.miner_tx); blobdata miner_bd = tx_to_blob(blk.miner_tx);
add_transaction(blk_hash, std::make_pair(blk.miner_tx, blobdata_ref(miner_bd))); output_ids.push_back(add_transaction(blk_hash, std::make_pair(blk.miner_tx, blobdata_ref(miner_bd))));
if (blk.miner_tx.version == 2) if (blk.miner_tx.version == 2)
num_rct_outs += blk.miner_tx.vout.size(); num_rct_outs += blk.miner_tx.vout.size();
int tx_i = 0; int tx_i = 0;
@ -283,7 +300,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
for (const std::pair<transaction, blobdata>& tx : txs) for (const std::pair<transaction, blobdata>& tx : txs)
{ {
tx_hash = blk.tx_hashes[tx_i]; tx_hash = blk.tx_hashes[tx_i];
add_transaction(blk_hash, tx, &tx_hash); output_ids.push_back(add_transaction(blk_hash, tx, &tx_hash));
for (const auto &vout: tx.first.vout) for (const auto &vout: tx.first.vout)
{ {
if (vout.amount == 0) if (vout.amount == 0)
@ -297,20 +314,22 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
// When adding a block, we also need to add all the leaf tuples included in // When adding a block, we also need to add all the leaf tuples included in
// the block to a table keeping track of locked leaf tuples. Once those leaf // the block to a table keeping track of locked leaf tuples. Once those leaf
// tuples unlock, we use them to grow the tree. // tuples unlock, we use them to grow the tree.
std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple> leaf_tuples_by_unlock_height; std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext> leaf_tuples_by_unlock_height;
// Get miner tx's leaf tuples // Get miner tx's leaf tuples
fcmp::curve_trees::curve_trees_v1.tx_outs_to_leaf_tuples( fcmp::curve_trees::curve_trees_v1.tx_outs_to_leaf_tuples(
blk.miner_tx, blk.miner_tx,
output_ids[0],
prev_height, prev_height,
true/*miner_tx*/, true/*miner_tx*/,
leaf_tuples_by_unlock_height); leaf_tuples_by_unlock_height);
// Get all other txs' leaf tuples // Get all other txs' leaf tuples
for (const auto &txp : txs) for (std::size_t i = 0; i < txs.size(); ++i)
{ {
fcmp::curve_trees::curve_trees_v1.tx_outs_to_leaf_tuples( fcmp::curve_trees::curve_trees_v1.tx_outs_to_leaf_tuples(
txp.first, txs[i].first,
output_ids[i+1],
prev_height, prev_height,
false/*miner_tx*/, false/*miner_tx*/,
leaf_tuples_by_unlock_height); leaf_tuples_by_unlock_height);

View File

@ -188,6 +188,14 @@ struct txpool_tx_meta_t
} }
}; };
/**
* @brief a struct containing output indexes for convenience
*/
struct output_indexes_t
{
uint64_t amount_index;
uint64_t output_id;
};
#define DBF_SAFE 1 #define DBF_SAFE 1
#define DBF_FAST 2 #define DBF_FAST 2
@ -408,7 +416,7 @@ private:
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& blk_hash , const crypto::hash& blk_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
) = 0; ) = 0;
/** /**
@ -473,8 +481,9 @@ private:
* future, this tracking (of the number, at least) should be moved to * future, this tracking (of the number, at least) should be moved to
* this class, as it is necessary and the same among all BlockchainDB. * this class, as it is necessary and the same among all BlockchainDB.
* *
* It returns an amount output index, which is the index of the output * It returns the output indexes, which contains an amount output index (the
* for its specified amount. * index of the output for its specified amount) and output id (the global
* index of the output among all outputs of any amount).
* *
* This data should be stored in such a manner that the only thing needed to * This data should be stored in such a manner that the only thing needed to
* reverse the process is the tx_out. * reverse the process is the tx_out.
@ -487,9 +496,9 @@ private:
* @param local_index index of the output in its transaction * @param local_index index of the output in its transaction
* @param unlock_time unlock time/height of the output * @param unlock_time unlock time/height of the output
* @param commitment the rct commitment to the output amount * @param commitment the rct commitment to the output amount
* @return amount output index * @return output indexes
*/ */
virtual uint64_t add_output(const crypto::hash& tx_hash, const tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) = 0; virtual output_indexes_t add_output(const crypto::hash& tx_hash, const tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) = 0;
/** /**
* @brief store amount output indices for a tx's outputs * @brief store amount output indices for a tx's outputs
@ -570,8 +579,10 @@ protected:
* @param tx the transaction to add * @param tx the transaction to add
* @param tx_hash_ptr the hash of the transaction, if already calculated * @param tx_hash_ptr the hash of the transaction, if already calculated
* @param tx_prunable_hash_ptr the hash of the prunable part of the transaction, if already calculated * @param tx_prunable_hash_ptr the hash of the prunable part of the transaction, if already calculated
*
* @return the global output ids of all outputs inserted
*/ */
void add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL); std::vector<uint64_t> add_transaction(const crypto::hash& blk_hash, const std::pair<transaction, blobdata_ref>& tx, const crypto::hash* tx_hash_ptr = NULL, const crypto::hash* tx_prunable_hash_ptr = NULL);
mutable uint64_t time_tx_exists = 0; //!< a performance metric mutable uint64_t time_tx_exists = 0; //!< a performance metric
uint64_t time_commit1 = 0; //!< a performance metric uint64_t time_commit1 = 0; //!< a performance metric
@ -1396,17 +1407,6 @@ public:
*/ */
virtual uint64_t get_num_outputs(const uint64_t& amount) const = 0; virtual uint64_t get_num_outputs(const uint64_t& amount) const = 0;
// returns the total number of global outputs
/**
* @brief fetches the total number of global outputs
*
* The subclass should return a count of all outputs,
* or zero if there are none.
* *
* @return the number of global outputs
*/
virtual uint64_t get_num_global_outputs() const = 0;
/** /**
* @brief return index of the first element (should be hidden, but isn't) * @brief return index of the first element (should be hidden, but isn't)
* *
@ -1780,7 +1780,7 @@ public:
// TODO: description and make private // TODO: description and make private
virtual void grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, virtual void grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees,
const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> &new_leaves) = 0; const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &new_leaves) = 0;
virtual void trim_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t trim_n_leaf_tuples) = 0; virtual void trim_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t trim_n_leaf_tuples) = 0;

View File

@ -216,7 +216,7 @@ namespace
* *
* spent_keys input hash - * spent_keys input hash -
* *
* locked_leaves block ID [{leaf tuple}...] * locked_leaves block ID [{output ID, leaf tuple}...]
* leaves leaf_idx {leaf tuple} * leaves leaf_idx {leaf tuple}
* layers layer_idx [{child_chunk_idx, child_chunk_hash}...] * layers layer_idx [{child_chunk_idx, child_chunk_hash}...]
* *
@ -817,7 +817,7 @@ estim:
} }
void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated, void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t long_term_block_weight, const difficulty_type& cumulative_difficulty, const uint64_t& coins_generated,
uint64_t num_rct_outs, const crypto::hash& blk_hash, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple> &leaf_tuples_by_unlock_height) uint64_t num_rct_outs, const crypto::hash& blk_hash, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &leaf_tuples_by_unlock_height)
{ {
LOG_PRINT_L3("BlockchainLMDB::" << __func__); LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open(); check_open();
@ -848,10 +848,9 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
// Grow the tree with outputs that unlock at this block height // Grow the tree with outputs that unlock at this block height
const auto unlocked_leaf_tuples = this->get_locked_leaf_tuples_at_height(m_height); const auto unlocked_leaf_tuples = this->get_locked_leaf_tuples_at_height(m_height);
// TODO: double check consistent order for inserting outputs into the tree
this->grow_tree(fcmp::curve_trees::curve_trees_v1, unlocked_leaf_tuples); this->grow_tree(fcmp::curve_trees::curve_trees_v1, unlocked_leaf_tuples);
// TODO: remove unlocked_leaf_tuples from the locked outputs table // TODO: remove locked from the locked outputs table
int result = 0; int result = 0;
@ -1119,7 +1118,7 @@ void BlockchainLMDB::remove_transaction_data(const crypto::hash& tx_hash, const
throw1(DB_ERROR("Failed to add removal of tx index to db transaction")); throw1(DB_ERROR("Failed to add removal of tx index to db transaction"));
} }
uint64_t BlockchainLMDB::add_output(const crypto::hash& tx_hash, output_indexes_t BlockchainLMDB::add_output(const crypto::hash& tx_hash,
const tx_out& tx_output, const tx_out& tx_output,
const uint64_t& local_index, const uint64_t& local_index,
const uint64_t unlock_time, const uint64_t unlock_time,
@ -1183,7 +1182,10 @@ uint64_t BlockchainLMDB::add_output(const crypto::hash& tx_hash,
if ((result = mdb_cursor_put(m_cur_output_amounts, &val_amount, &data, MDB_APPENDDUP))) if ((result = mdb_cursor_put(m_cur_output_amounts, &val_amount, &data, MDB_APPENDDUP)))
throw0(DB_ERROR(lmdb_error("Failed to add output pubkey to db transaction: ", result).c_str())); throw0(DB_ERROR(lmdb_error("Failed to add output pubkey to db transaction: ", result).c_str()));
return ok.amount_index; return output_indexes_t{
.amount_index = ok.amount_index,
.output_id = ok.output_id
};
} }
void BlockchainLMDB::add_tx_amount_output_indices(const uint64_t tx_id, void BlockchainLMDB::add_tx_amount_output_indices(const uint64_t tx_id,
@ -1362,12 +1364,11 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image& k_image)
} }
void BlockchainLMDB::grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, void BlockchainLMDB::grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees,
const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> &new_leaves) const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &new_leaves)
{ {
if (new_leaves.empty()) if (new_leaves.empty())
return; return;
// TODO: block_wtxn_start like pop_block, then call BlockchainDB::grow_tree
LOG_PRINT_L3("BlockchainLMDB::" << __func__); LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open(); check_open();
mdb_txn_cursors *m_cursors = &m_wcursors; mdb_txn_cursors *m_cursors = &m_wcursors;
@ -1970,6 +1971,8 @@ bool BlockchainLMDB::audit_tree(const fcmp::curve_trees::CurveTreesV1 &curve_tre
const uint64_t actual_n_leaf_tuples = this->get_num_leaf_tuples(); const uint64_t actual_n_leaf_tuples = this->get_num_leaf_tuples();
CHECK_AND_ASSERT_MES(actual_n_leaf_tuples == expected_n_leaf_tuples, false, "unexpected num leaf tuples"); CHECK_AND_ASSERT_MES(actual_n_leaf_tuples == expected_n_leaf_tuples, false, "unexpected num leaf tuples");
MDEBUG("Auditing tree with " << actual_n_leaf_tuples << " leaf tuples");
if (actual_n_leaf_tuples == 0) if (actual_n_leaf_tuples == 0)
{ {
// Make sure layers table is also empty // Make sure layers table is also empty
@ -2203,7 +2206,7 @@ bool BlockchainLMDB::audit_layer(const C_CHILD &c_child,
chunk_width); chunk_width);
} }
std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> BlockchainLMDB::get_locked_leaf_tuples_at_height( std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> BlockchainLMDB::get_locked_leaf_tuples_at_height(
const uint64_t height) const uint64_t height)
{ {
LOG_PRINT_L3("BlockchainLMDB::" << __func__); LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@ -2216,7 +2219,7 @@ std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> BlockchainLMDB::get_lock
MDB_val v_tuple; MDB_val v_tuple;
// Get all the locked outputs at that height // Get all the locked outputs at that height
std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> leaf_tuples; std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> leaf_tuples;
// TODO: double check this gets all leaf tuples when it does multiple iters // TODO: double check this gets all leaf tuples when it does multiple iters
MDB_cursor_op op = MDB_SET; MDB_cursor_op op = MDB_SET;
@ -2233,8 +2236,8 @@ std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> BlockchainLMDB::get_lock
if (h != height) if (h != height)
throw0(DB_ERROR(("Height " + std::to_string(h) + " not the expected" + std::to_string(height)).c_str())); throw0(DB_ERROR(("Height " + std::to_string(h) + " not the expected" + std::to_string(height)).c_str()));
const auto range_begin = ((const fcmp::curve_trees::CurveTreesV1::LeafTuple*)v_tuple.mv_data); const auto range_begin = ((const fcmp::curve_trees::CurveTreesV1::LeafTupleContext*)v_tuple.mv_data);
const auto range_end = range_begin + v_tuple.mv_size / sizeof(fcmp::curve_trees::CurveTreesV1::LeafTuple); const auto range_end = range_begin + v_tuple.mv_size / sizeof(fcmp::curve_trees::CurveTreesV1::LeafTupleContext);
auto it = range_begin; auto it = range_begin;
@ -4399,27 +4402,6 @@ uint64_t BlockchainLMDB::get_num_outputs(const uint64_t& amount) const
return num_elems; return num_elems;
} }
uint64_t BlockchainLMDB::get_num_global_outputs() const
{
LOG_PRINT_L3("BlockchainLMDB:: " << __func__);
check_open();
TXN_PREFIX_RDONLY();
RCURSOR(output_amounts);
MDB_stat db_stats;
int result = mdb_stat(m_txn, m_output_amounts, &db_stats);
uint64_t count = 0;
if (result != MDB_NOTFOUND)
{
if (result)
throw0(DB_ERROR(lmdb_error("Failed to query m_output_amounts: ", result).c_str()));
count = db_stats.ms_entries;
}
TXN_POSTFIX_RDONLY();
return count;
}
output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const output_data_t BlockchainLMDB::get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const
{ {
LOG_PRINT_L3("BlockchainLMDB::" << __func__); LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@ -6688,6 +6670,9 @@ void BlockchainLMDB::migrate_5_6()
// ... Could also require outputs be inserted all-or-nothing first, and then can pick up where left off for the tree // ... Could also require outputs be inserted all-or-nothing first, and then can pick up where left off for the tree
// if any of leaves, layers, or block_infn tables exist, then locked_leaves migration should be complete // if any of leaves, layers, or block_infn tables exist, then locked_leaves migration should be complete
// TODO: I can keep track of the contiguous output_id inserted in a separate table used strictly for this migration
// On next run, read all outputs until we reach the highest contiguous output_id, then continue from there
do do
{ {
// 1. Set up locked outputs table // 1. Set up locked outputs table
@ -6711,7 +6696,7 @@ void BlockchainLMDB::migrate_5_6()
MDB_cursor_op op = MDB_FIRST; MDB_cursor_op op = MDB_FIRST;
const uint64_t n_outputs = this->get_num_global_outputs(); const uint64_t n_outputs = this->num_outputs();
i = 0; i = 0;
while (1) while (1)
@ -6763,23 +6748,25 @@ void BlockchainLMDB::migrate_5_6()
uint64_t amount = *(const uint64_t*)k.mv_data; uint64_t amount = *(const uint64_t*)k.mv_data;
output_data_t output_data; output_data_t output_data;
fcmp::curve_trees::CurveTreesV1::LeafTupleContext tuple_context;
if (amount == 0) if (amount == 0)
{ {
const outkey *okp = (const outkey *)v.mv_data; const outkey *okp = (const outkey *)v.mv_data;
output_data = okp->data; output_data = okp->data;
tuple_context.output_id = okp->output_id;
} }
else else
{ {
const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data; const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
memcpy(&output_data, &okp->data, sizeof(pre_rct_output_data_t)); memcpy(&output_data, &okp->data, sizeof(pre_rct_output_data_t));
output_data.commitment = rct::zeroCommit(amount); output_data.commitment = rct::zeroCommit(amount);
tuple_context.output_id = okp->output_id;
} }
// Convert the output into a leaf tuple // Convert the output into a leaf tuple
fcmp::curve_trees::CurveTreesV1::LeafTuple leaf_tuple;
try try
{ {
leaf_tuple = fcmp::curve_trees::curve_trees_v1.output_to_leaf_tuple( tuple_context.leaf_tuple = fcmp::curve_trees::curve_trees_v1.output_to_leaf_tuple(
output_data.pubkey, output_data.pubkey,
rct::rct2pk(output_data.commitment)); rct::rct2pk(output_data.commitment));
} }
@ -6792,9 +6779,9 @@ void BlockchainLMDB::migrate_5_6()
// Get the block in which the output will unlock // Get the block in which the output will unlock
const uint64_t unlock_height = cryptonote::get_unlock_height(output_data.unlock_time, output_data.height); const uint64_t unlock_height = cryptonote::get_unlock_height(output_data.unlock_time, output_data.height);
// Now add the leaf tuple to the locked outputs table // Now add the leaf tuple to the locked leaves table
MDB_val_set(k_height, unlock_height); MDB_val_set(k_height, unlock_height);
MDB_val_set(v_tuple, leaf_tuple); MDB_val_set(v_tuple, tuple_context);
// MDB_NODUPDATA because no benefit to having duplicate outputs in the tree, only 1 can be spent // MDB_NODUPDATA because no benefit to having duplicate outputs in the tree, only 1 can be spent
// Can't use MDB_APPENDDUP because outputs aren't inserted in order sorted by unlock height // Can't use MDB_APPENDDUP because outputs aren't inserted in order sorted by unlock height

View File

@ -278,7 +278,6 @@ public:
virtual uint64_t get_tx_block_height(const crypto::hash& h) const; virtual uint64_t get_tx_block_height(const crypto::hash& h) const;
virtual uint64_t get_num_outputs(const uint64_t& amount) const; virtual uint64_t get_num_outputs(const uint64_t& amount) const;
virtual uint64_t get_num_global_outputs() const;
virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const; virtual output_data_t get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const;
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial = false) const; virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial = false) const;
@ -370,7 +369,7 @@ public:
// make private // make private
virtual void grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, virtual void grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees,
const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> &new_leaves); const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &new_leaves);
virtual void trim_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t trim_n_leaf_tuples); virtual void trim_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t trim_n_leaf_tuples);
@ -391,7 +390,7 @@ private:
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& block_hash , const crypto::hash& block_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
); );
virtual void remove_block(); virtual void remove_block();
@ -400,7 +399,7 @@ private:
virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx); virtual void remove_transaction_data(const crypto::hash& tx_hash, const transaction& tx);
virtual uint64_t add_output(const crypto::hash& tx_hash, virtual output_indexes_t add_output(const crypto::hash& tx_hash,
const tx_out& tx_output, const tx_out& tx_output,
const uint64_t& local_index, const uint64_t& local_index,
const uint64_t unlock_time, const uint64_t unlock_time,
@ -451,7 +450,7 @@ private:
const uint64_t child_chunk_idx, const uint64_t child_chunk_idx,
const uint64_t chunk_width) const; const uint64_t chunk_width) const;
std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> get_locked_leaf_tuples_at_height(const uint64_t height); std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> get_locked_leaf_tuples_at_height(const uint64_t height);
uint64_t num_outputs() const; uint64_t num_outputs() const;
@ -547,6 +546,8 @@ private:
mdb_txn_cursors m_wcursors; mdb_txn_cursors m_wcursors;
mutable boost::thread_specific_ptr<mdb_threadinfo> m_tinfo; mutable boost::thread_specific_ptr<mdb_threadinfo> m_tinfo;
// TODO: m_curve_trees
#if defined(__arm__) #if defined(__arm__)
// force a value so it can compile with 32-bit ARM // force a value so it can compile with 32-bit ARM
constexpr static uint64_t DEFAULT_MAPSIZE = 1LL << 31; constexpr static uint64_t DEFAULT_MAPSIZE = 1LL << 31;

View File

@ -100,7 +100,6 @@ public:
virtual std::vector<cryptonote::transaction> get_tx_list(const std::vector<crypto::hash>& hlist) const override { return std::vector<cryptonote::transaction>(); } virtual std::vector<cryptonote::transaction> get_tx_list(const std::vector<crypto::hash>& hlist) const override { return std::vector<cryptonote::transaction>(); }
virtual uint64_t get_tx_block_height(const crypto::hash& h) const override { return 0; } virtual uint64_t get_tx_block_height(const crypto::hash& h) const override { return 0; }
virtual uint64_t get_num_outputs(const uint64_t& amount) const override { return 1; } virtual uint64_t get_num_outputs(const uint64_t& amount) const override { return 1; }
virtual uint64_t get_num_global_outputs() const override { return 1; }
virtual uint64_t get_indexing_base() const override { return 0; } virtual uint64_t get_indexing_base() const override { return 0; }
virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const override { return cryptonote::output_data_t(); } virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const override { return cryptonote::output_data_t(); }
virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const override { return cryptonote::tx_out_index(); } virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const override { return cryptonote::tx_out_index(); }
@ -113,12 +112,12 @@ public:
virtual void remove_block() override { } virtual void remove_block() override { }
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;} virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {} virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {}
virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return 0;} virtual output_indexes_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return {0, 0};}
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {} virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {}
virtual void add_spent_key(const crypto::key_image& k_image) override {} virtual void add_spent_key(const crypto::key_image& k_image) override {}
virtual void remove_spent_key(const crypto::key_image& k_image) override {} virtual void remove_spent_key(const crypto::key_image& k_image) override {}
virtual void grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, virtual void grow_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees,
const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTuple> &new_leaves) override {}; const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &new_leaves) override {};
virtual void trim_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t trim_n_leaf_tuples) override {}; virtual void trim_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t trim_n_leaf_tuples) override {};
virtual bool audit_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t expected_n_leaf_tuples) const override { return false; }; virtual bool audit_tree(const fcmp::curve_trees::CurveTreesV1 &curve_trees, const uint64_t expected_n_leaf_tuples) const override { return false; };
@ -149,7 +148,7 @@ public:
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& blk_hash , const crypto::hash& blk_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
) override { } ) override { }
virtual cryptonote::block get_block_from_height(const uint64_t& height) const override { return cryptonote::block(); } virtual cryptonote::block get_block_from_height(const uint64_t& height) const override { return cryptonote::block(); }
virtual void set_hard_fork_version(uint64_t height, uint8_t version) override {} virtual void set_hard_fork_version(uint64_t height, uint8_t version) override {}

View File

@ -1673,8 +1673,10 @@ namespace cryptonote
{ {
const auto seconds_since_unlock = hf_v15_time - unlock_time; const auto seconds_since_unlock = hf_v15_time - unlock_time;
const auto blocks_since_unlock = seconds_since_unlock / DIFFICULTY_TARGET_V2; const auto blocks_since_unlock = seconds_since_unlock / DIFFICULTY_TARGET_V2;
CHECK_AND_ASSERT_THROW_MES(hf_v15_height > blocks_since_unlock, "unexpected blocks since unlock");
unlock_height = hf_v15_height - blocks_since_unlock; unlock_height = hf_v15_height >= blocks_since_unlock
? (hf_v15_height - blocks_since_unlock)
: default_unlock_height;
} }
else else
{ {

View File

@ -630,25 +630,27 @@ CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::output_to_leaf
const crypto::public_key &output_pubkey, const crypto::public_key &output_pubkey,
const crypto::public_key &commitment) const const crypto::public_key &commitment) const
{ {
CHECK_AND_ASSERT_THROW_MES(crypto::check_key(output_pubkey), "invalid output pub key"); if (!crypto::check_key(output_pubkey))
throw std::runtime_error("invalid output pub key");
const auto clear_torsion = [](const crypto::public_key &key) const auto clear_torsion = [](const crypto::public_key &key, const std::string &s)
{ {
// TODO: don't need to decompress and recompress points, can be optimized // TODO: don't need to decompress and recompress points, can be optimized
rct::key torsion_cleared_key = rct::scalarmultKey(rct::pk2rct(key), rct::INV_EIGHT); rct::key torsion_cleared_key = rct::scalarmultKey(rct::pk2rct(key), rct::INV_EIGHT);
torsion_cleared_key = rct::scalarmult8(torsion_cleared_key); torsion_cleared_key = rct::scalarmult8(torsion_cleared_key);
CHECK_AND_ASSERT_THROW_MES(torsion_cleared_key != rct::I, "cannot equal identity"); if (torsion_cleared_key == rct::I)
throw std::runtime_error(s + " cannot equal identity");
return torsion_cleared_key; return torsion_cleared_key;
}; };
// Torsion clear the output pub key and commitment // Torsion clear the output pub key and commitment
const rct::key rct_O = clear_torsion(output_pubkey); const rct::key rct_O = clear_torsion(output_pubkey, "output pub key");
const rct::key rct_C = clear_torsion(commitment); const rct::key rct_C = clear_torsion(commitment, "commitment");
const crypto::public_key O = rct::rct2pk(rct_O); const crypto::public_key &O = rct::rct2pk(rct_O);
const crypto::public_key C = rct::rct2pk(rct_C); const crypto::public_key &C = rct::rct2pk(rct_C);
crypto::ec_point I; crypto::ec_point I;
crypto::derive_key_image_generator(O, I); crypto::derive_key_image_generator(O, I);
@ -679,12 +681,15 @@ std::vector<typename C2::Scalar> CurveTrees<C1, C2>::flatten_leaves(const std::v
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
template <> template <>
void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transaction &tx, void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transaction &tx,
const std::vector<uint64_t> &output_ids,
const uint64_t tx_height, const uint64_t tx_height,
const bool miner_tx, const bool miner_tx,
std::multimap<uint64_t, CurveTrees<Helios, Selene>::LeafTuple> &leaf_tuples_by_unlock_height_inout) const std::multimap<uint64_t, CurveTrees<Helios, Selene>::LeafTupleContext> &leaf_tuples_by_unlock_height_inout) const
{ {
const uint64_t unlock_height = cryptonote::get_unlock_height(tx.unlock_time, tx_height); const uint64_t unlock_height = cryptonote::get_unlock_height(tx.unlock_time, tx_height);
CHECK_AND_ASSERT_THROW_MES(tx.vout.size() == output_ids.size(), "unexpected size of output ids");
for (std::size_t i = 0; i < tx.vout.size(); ++i) for (std::size_t i = 0; i < tx.vout.size(); ++i)
{ {
const auto &out = tx.vout[i]; const auto &out = tx.vout[i];
@ -693,7 +698,13 @@ void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transa
if (!cryptonote::get_output_public_key(out, output_public_key)) if (!cryptonote::get_output_public_key(out, output_public_key))
throw std::runtime_error("Could not get an output public key from a tx output."); throw std::runtime_error("Could not get an output public key from a tx output.");
const rct::key commitment = (miner_tx || tx.version < 2) static_assert(CURRENT_TRANSACTION_VERSION == 2, "This section of code was written with 2 tx versions in mind. "
"Revisit this section and update for the new tx version.");
if (!miner_tx && tx.version == 2)
CHECK_AND_ASSERT_THROW_MES(tx.rct_signatures.outPk.size() > i, "unexpected size of outPk");
const rct::key commitment = (miner_tx || tx.version != 2)
? rct::zeroCommit(out.amount) ? rct::zeroCommit(out.amount)
: tx.rct_signatures.outPk[i].mask; : tx.rct_signatures.outPk[i].mask;
@ -704,7 +715,12 @@ void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transa
output_public_key, output_public_key,
rct::rct2pk(commitment)); rct::rct2pk(commitment));
leaf_tuples_by_unlock_height_inout.emplace(unlock_height, std::move(leaf_tuple)); auto tuple_context = CurveTrees<Helios, Selene>::LeafTupleContext{
.output_id = output_ids[i],
.leaf_tuple = std::move(leaf_tuple),
};
leaf_tuples_by_unlock_height_inout.emplace(unlock_height, std::move(tuple_context));
} }
catch (...) catch (...)
{ /*continue*/ }; { /*continue*/ };
@ -715,7 +731,7 @@ template<typename C1, typename C2>
typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extension( typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extension(
const uint64_t old_n_leaf_tuples, const uint64_t old_n_leaf_tuples,
const LastHashes &existing_last_hashes, const LastHashes &existing_last_hashes,
const std::vector<LeafTuple> &new_leaf_tuples) const const std::vector<LeafTupleContext> &new_leaf_tuples) const
{ {
TreeExtension tree_extension; TreeExtension tree_extension;
@ -730,15 +746,21 @@ typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extensio
tree_extension.leaves.start_leaf_tuple_idx = grow_layer_instructions.old_total_children / LEAF_TUPLE_SIZE; tree_extension.leaves.start_leaf_tuple_idx = grow_layer_instructions.old_total_children / LEAF_TUPLE_SIZE;
// Copy the leaves // Sort the leaves by order they appear in the chain
// TODO: don't copy here
std::vector<LeafTupleContext> sorted_leaf_tuples = new_leaf_tuples;
const auto sort_fn = [](const LeafTupleContext &a, const LeafTupleContext &b) { return a.output_id < b.output_id; };
std::sort(sorted_leaf_tuples.begin(), sorted_leaf_tuples.end(), sort_fn);
// Copy the sorted leaves into the tree extension struct
// TODO: don't copy here // TODO: don't copy here
tree_extension.leaves.tuples.reserve(new_leaf_tuples.size()); tree_extension.leaves.tuples.reserve(new_leaf_tuples.size());
for (const auto &leaf : new_leaf_tuples) for (const auto &leaf : sorted_leaf_tuples)
{ {
tree_extension.leaves.tuples.emplace_back(LeafTuple{ tree_extension.leaves.tuples.emplace_back(LeafTuple{
.O_x = leaf.O_x, .O_x = leaf.leaf_tuple.O_x,
.I_x = leaf.I_x, .I_x = leaf.leaf_tuple.I_x,
.C_x = leaf.C_x .C_x = leaf.leaf_tuple.C_x
}); });
} }
@ -751,7 +773,7 @@ typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extensio
grow_layer_instructions.need_old_last_parent ? &existing_last_hashes.c2_last_hashes[0] : nullptr, grow_layer_instructions.need_old_last_parent ? &existing_last_hashes.c2_last_hashes[0] : nullptr,
grow_layer_instructions.start_offset, grow_layer_instructions.start_offset,
grow_layer_instructions.next_parent_start_index, grow_layer_instructions.next_parent_start_index,
this->flatten_leaves(new_leaf_tuples), this->flatten_leaves(tree_extension.leaves.tuples),
m_leaf_layer_chunk_width m_leaf_layer_chunk_width
); );

View File

@ -164,6 +164,14 @@ public:
static const uint64_t LEAF_TUPLE_SIZE = 3; static const uint64_t LEAF_TUPLE_SIZE = 3;
static_assert(sizeof(LeafTuple) == (sizeof(typename C2::Scalar) * LEAF_TUPLE_SIZE), "unexpected LeafTuple size"); static_assert(sizeof(LeafTuple) == (sizeof(typename C2::Scalar) * LEAF_TUPLE_SIZE), "unexpected LeafTuple size");
// Contextual wrapper for leaf tuple
struct LeafTupleContext final
{
// Global output ID useful to order the leaf tuple for insertion into the tree
uint64_t output_id;
LeafTuple leaf_tuple;
};
// Contiguous leaves in the tree, starting a specified start_idx in the leaf layer // Contiguous leaves in the tree, starting a specified start_idx in the leaf layer
struct Leaves final struct Leaves final
{ {
@ -221,15 +229,16 @@ public:
// Convert cryptonote tx outs to leaf tuples, grouped by the leaf tuple unlock height // Convert cryptonote tx outs to leaf tuples, grouped by the leaf tuple unlock height
void tx_outs_to_leaf_tuples(const cryptonote::transaction &tx, void tx_outs_to_leaf_tuples(const cryptonote::transaction &tx,
const std::vector<uint64_t> &output_ids,
const uint64_t tx_height, const uint64_t tx_height,
const bool miner_tx, const bool miner_tx,
std::multimap<uint64_t, LeafTuple> &leaf_tuples_by_unlock_height_inout) const; std::multimap<uint64_t, LeafTupleContext> &leaf_tuples_by_unlock_height_inout) const;
// Take in the existing number of leaf tuples and the existing last hashes of each layer in the tree, as well as new // Take in the existing number of leaf tuples and the existing last hashes of each layer in the tree, as well as new
// leaves to add to the tree, and return a tree extension struct that can be used to extend a tree // leaves to add to the tree, and return a tree extension struct that can be used to extend a tree
TreeExtension get_tree_extension(const uint64_t old_n_leaf_tuples, TreeExtension get_tree_extension(const uint64_t old_n_leaf_tuples,
const LastHashes &existing_last_hashes, const LastHashes &existing_last_hashes,
const std::vector<LeafTuple> &new_leaf_tuples) const; const std::vector<LeafTupleContext> &new_leaf_tuples) const;
// Get instructions useful for trimming all existing layers in the tree // Get instructions useful for trimming all existing layers in the tree
std::vector<TrimLayerInstructions> get_trim_instructions( std::vector<TrimLayerInstructions> get_trim_instructions(

View File

@ -65,7 +65,7 @@ public:
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& blk_hash , const crypto::hash& blk_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
) override { ) override {
blocks.push_back({block_weight, long_term_block_weight}); blocks.push_back({block_weight, long_term_block_weight});
} }

View File

@ -88,7 +88,7 @@ namespace
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& blk_hash , const crypto::hash& blk_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
) override ) override
{ {
blocks.push_back({blk, blk_hash}); blocks.push_back({blk, blk_hash});

View File

@ -730,13 +730,14 @@ void CurveTreesGlobalTree::log_tree()
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// Test helpers // Test helpers
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
static const std::vector<CurveTreesV1::LeafTuple> generate_random_leaves(const CurveTreesV1 &curve_trees, static const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> generate_random_leaves(const CurveTreesV1 &curve_trees,
const std::size_t num_leaves) const std::size_t old_n_leaf_tuples,
const std::size_t new_n_leaf_tuples)
{ {
std::vector<CurveTreesV1::LeafTuple> tuples; std::vector<CurveTreesV1::LeafTupleContext> tuples;
tuples.reserve(num_leaves); tuples.reserve(new_n_leaf_tuples);
for (std::size_t i = 0; i < num_leaves; ++i) for (std::size_t i = 0; i < new_n_leaf_tuples; ++i)
{ {
// Generate random output tuple // Generate random output tuple
crypto::secret_key o,c; crypto::secret_key o,c;
@ -746,7 +747,10 @@ static const std::vector<CurveTreesV1::LeafTuple> generate_random_leaves(const C
auto leaf_tuple = curve_trees.output_to_leaf_tuple(O, C); auto leaf_tuple = curve_trees.output_to_leaf_tuple(O, C);
tuples.emplace_back(std::move(leaf_tuple)); tuples.emplace_back(fcmp::curve_trees::CurveTreesV1::LeafTupleContext{
.output_id = old_n_leaf_tuples + i,
.leaf_tuple = std::move(leaf_tuple),
});
} }
return tuples; return tuples;
@ -775,7 +779,7 @@ static bool grow_tree(CurveTreesV1 &curve_trees,
// - The tree extension includes all elements we'll need to add to the existing tree when adding the new leaves // - The tree extension includes all elements we'll need to add to the existing tree when adding the new leaves
const auto tree_extension = curve_trees.get_tree_extension(old_n_leaf_tuples, const auto tree_extension = curve_trees.get_tree_extension(old_n_leaf_tuples,
last_hashes, last_hashes,
generate_random_leaves(curve_trees, new_n_leaf_tuples)); generate_random_leaves(curve_trees, old_n_leaf_tuples, new_n_leaf_tuples));
global_tree.log_tree_extension(tree_extension); global_tree.log_tree_extension(tree_extension);
@ -852,14 +856,14 @@ static bool grow_tree_db(const std::size_t init_leaves,
LOG_PRINT_L1("Adding " << init_leaves << " leaves to db, then extending by " << ext_leaves << " leaves"); LOG_PRINT_L1("Adding " << init_leaves << " leaves to db, then extending by " << ext_leaves << " leaves");
test_db.m_db->grow_tree(curve_trees, generate_random_leaves(curve_trees, init_leaves)); test_db.m_db->grow_tree(curve_trees, generate_random_leaves(curve_trees, 0, init_leaves));
CHECK_AND_ASSERT_MES(test_db.m_db->audit_tree(curve_trees, init_leaves), false, CHECK_AND_ASSERT_MES(test_db.m_db->audit_tree(curve_trees, init_leaves), false,
"failed to add initial leaves to db"); "failed to add initial leaves to db");
MDEBUG("Successfully added initial " << init_leaves << " leaves to db, extending by " MDEBUG("Successfully added initial " << init_leaves << " leaves to db, extending by "
<< ext_leaves << " leaves"); << ext_leaves << " leaves");
test_db.m_db->grow_tree(curve_trees, generate_random_leaves(curve_trees, ext_leaves)); test_db.m_db->grow_tree(curve_trees, generate_random_leaves(curve_trees, init_leaves, ext_leaves));
CHECK_AND_ASSERT_MES(test_db.m_db->audit_tree(curve_trees, init_leaves + ext_leaves), false, CHECK_AND_ASSERT_MES(test_db.m_db->audit_tree(curve_trees, init_leaves + ext_leaves), false,
"failed to extend tree in db"); "failed to extend tree in db");
@ -881,7 +885,7 @@ static bool trim_tree_db(const std::size_t init_leaves,
LOG_PRINT_L1("Adding " << init_leaves << " leaves to db, then trimming by " << trim_leaves << " leaves"); LOG_PRINT_L1("Adding " << init_leaves << " leaves to db, then trimming by " << trim_leaves << " leaves");
test_db.m_db->grow_tree(curve_trees, generate_random_leaves(curve_trees, init_leaves)); test_db.m_db->grow_tree(curve_trees, generate_random_leaves(curve_trees, 0, init_leaves));
CHECK_AND_ASSERT_MES(test_db.m_db->audit_tree(curve_trees, init_leaves), false, CHECK_AND_ASSERT_MES(test_db.m_db->audit_tree(curve_trees, init_leaves), false,
"failed to add initial leaves to db"); "failed to add initial leaves to db");

View File

@ -54,7 +54,7 @@ public:
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& blk_hash , const crypto::hash& blk_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
) override { ) override {
blocks.push_back(blk); blocks.push_back(blk);
} }

View File

@ -58,7 +58,7 @@ public:
, const uint64_t& coins_generated , const uint64_t& coins_generated
, uint64_t num_rct_outs , uint64_t num_rct_outs
, const crypto::hash& blk_hash , const crypto::hash& blk_hash
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTuple>& leaf_tuples_by_unlock_height , const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_height
) override { ) override {
blocks.push_back({block_weight, long_term_block_weight}); blocks.push_back({block_weight, long_term_block_weight});
} }