Rename 'unlock block' to 'last locked block'

This commit is contained in:
j-berman 2025-01-21 11:46:12 -08:00
parent 61c3b9c762
commit 23b1b35ba7
23 changed files with 252 additions and 251 deletions

View File

@ -232,11 +232,11 @@ 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,
// and we store them as rct outputs with an identity mask
// note: get_outs_by_unlock_block mirrors this logic
// note: get_outs_by_last_locked_block mirrors this logic
if (miner_tx && tx.version == 2)
{
cryptonote::tx_out vout = tx.vout[i];
// TODO: avoid duplicate zeroCommitVartime call in get_outs_by_unlock_block
// TODO: avoid duplicate zeroCommitVartime call in get_outs_by_last_locked_block
rct::key commitment = rct::zeroCommitVartime(vout.amount);
vout.amount = 0;
amount_output_indices[i] = add_output(tx_hash, vout, i, tx.unlock_time,
@ -304,13 +304,13 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
// When adding a block, we also need to keep track of when outputs unlock, so
// we can use them to grow the merkle tree used in fcmp's at that point.
const auto outs_by_unlock_block_meta = cryptonote::get_outs_by_unlock_block(blk.miner_tx, _txs, total_n_outputs, prev_height);
const auto &outs_by_unlock_block = outs_by_unlock_block_meta.outs_by_unlock_block;
const auto &timelocked_outputs = outs_by_unlock_block_meta.timelocked_outputs;
const auto outs_by_last_locked_block_meta = cryptonote::get_outs_by_last_locked_block(blk.miner_tx, _txs, total_n_outputs, prev_height);
const auto &outs_by_last_locked_block = outs_by_last_locked_block_meta.outs_by_last_locked_block;
const auto &timelocked_outputs = outs_by_last_locked_block_meta.timelocked_outputs;
// call out to subclass implementation to add the block & metadata
time1 = epee::misc_utils::get_tick_count();
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, blk_hash, outs_by_unlock_block, timelocked_outputs);
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, blk_hash, outs_by_last_locked_block, timelocked_outputs);
TIME_MEASURE_FINISH(time1);
time_add_block1 += time1;

View File

@ -422,7 +422,7 @@ private:
* @param cumulative_difficulty the accumulated difficulty after this block
* @param coins_generated the number of coins generated total after this block
* @param blk_hash the hash of the block
* @param outs_by_unlock_block the outputs from this block to add to the merkle tree
* @param outs_by_last_locked_block the outputs from this block to add to the merkle tree
* @param timelocked_outputs the outputs from this block that are custom timelocked
*/
virtual void add_block( const block& blk
@ -432,8 +432,8 @@ private:
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& blk_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
) = 0;
/**
@ -1823,18 +1823,21 @@ public:
*
* @param start_block_idx
*
* @return custom timelocked outputs grouped by unlock block
* @return custom timelocked outputs grouped by last locked block
*/
virtual fcmp_pp::curve_trees::OutputsByUnlockBlock get_custom_timelocked_outputs(uint64_t start_block_idx) const = 0;
virtual fcmp_pp::curve_trees::OutputsByLastLockedBlock get_custom_timelocked_outputs(uint64_t start_block_idx) const = 0;
/**
* @brief return recent timelocked outputs after the provided end_block_idx
*
* @param end_block_idx
*
* @return the recent locked outputs grouped by unlock block, that unlock
* @return
* - coinbase outputs created between [end_block_idx - CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW]
* - normal outputs created between [end_block_idx - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE]
* - the outputs are grouped by last locked block idx
*/
virtual fcmp_pp::curve_trees::OutputsByUnlockBlock get_recent_locked_outputs(uint64_t end_block_idx) const = 0;
virtual fcmp_pp::curve_trees::OutputsByLastLockedBlock get_recent_locked_outputs(uint64_t end_block_idx) const = 0;
//
// Hard fork related storage

View File

@ -35,16 +35,16 @@
#include "profile_tools.h"
//----------------------------------------------------------------------------------------------------------------------
// Helper function to group outputs by unlock block
static uint64_t set_tx_outs_by_unlock_block(const cryptonote::transaction &tx,
// Helper function to group outputs by last locked block idx
static uint64_t set_tx_outs_by_last_locked_block(const cryptonote::transaction &tx,
const uint64_t &first_output_id,
const uint64_t block_idx,
const bool miner_tx,
fcmp_pp::curve_trees::OutputsByUnlockBlock &outs_by_unlock_block_inout,
std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/> &timelocked_outputs_inout)
fcmp_pp::curve_trees::OutputsByLastLockedBlock &outs_by_last_locked_block_inout,
std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/> &timelocked_outputs_inout)
{
const uint64_t unlock_block = cryptonote::get_unlock_block_index(tx.unlock_time, block_idx);
const bool has_custom_timelock = cryptonote::is_custom_timelocked(miner_tx, unlock_block, block_idx);
const uint64_t last_locked_block = cryptonote::get_last_locked_block_index(tx.unlock_time, block_idx);
const bool has_custom_timelock = cryptonote::is_custom_timelocked(miner_tx, last_locked_block, block_idx);
uint64_t getting_commitment_ns = 0;
@ -84,17 +84,17 @@ static uint64_t set_tx_outs_by_unlock_block(const cryptonote::transaction &tx,
if (has_custom_timelock)
{
timelocked_outputs_inout[output_id] = unlock_block;
timelocked_outputs_inout[output_id] = last_locked_block;
}
if (outs_by_unlock_block_inout.find(unlock_block) == outs_by_unlock_block_inout.end())
if (outs_by_last_locked_block_inout.find(last_locked_block) == outs_by_last_locked_block_inout.end())
{
auto new_vec = std::vector<fcmp_pp::curve_trees::OutputContext>{std::move(output_context)};
outs_by_unlock_block_inout[unlock_block] = std::move(new_vec);
outs_by_last_locked_block_inout[last_locked_block] = std::move(new_vec);
}
else
{
outs_by_unlock_block_inout[unlock_block].emplace_back(std::move(output_context));
outs_by_last_locked_block_inout[last_locked_block].emplace_back(std::move(output_context));
}
getting_commitment_ns += getting_commitment;
@ -108,37 +108,37 @@ static uint64_t set_tx_outs_by_unlock_block(const cryptonote::transaction &tx,
//----------------------------------------------------------------------------------------------------------------------
namespace cryptonote
{
OutsByUnlockBlockMeta get_outs_by_unlock_block(
OutsByLastLockedBlockMeta get_outs_by_last_locked_block(
const cryptonote::transaction &miner_tx,
const std::vector<std::reference_wrapper<const cryptonote::transaction>> &txs,
const uint64_t first_output_id,
const uint64_t block_idx)
{
OutsByUnlockBlockMeta outs_by_unlock_meta_out;
outs_by_unlock_meta_out.next_output_id = first_output_id;
OutsByLastLockedBlockMeta outs_by_last_locked_block_meta_out;
outs_by_last_locked_block_meta_out.next_output_id = first_output_id;
// Get miner tx's leaf tuples
outs_by_unlock_meta_out.next_output_id += set_tx_outs_by_unlock_block(
outs_by_last_locked_block_meta_out.next_output_id += set_tx_outs_by_last_locked_block(
miner_tx,
outs_by_unlock_meta_out.next_output_id,
outs_by_last_locked_block_meta_out.next_output_id,
block_idx,
true/*miner_tx*/,
outs_by_unlock_meta_out.outs_by_unlock_block,
outs_by_unlock_meta_out.timelocked_outputs);
outs_by_last_locked_block_meta_out.outs_by_last_locked_block,
outs_by_last_locked_block_meta_out.timelocked_outputs);
// Get all other txs' leaf tuples
for (const auto &tx : txs)
{
outs_by_unlock_meta_out.next_output_id += set_tx_outs_by_unlock_block(
outs_by_last_locked_block_meta_out.next_output_id += set_tx_outs_by_last_locked_block(
tx.get(),
outs_by_unlock_meta_out.next_output_id,
outs_by_last_locked_block_meta_out.next_output_id,
block_idx,
false/*miner_tx*/,
outs_by_unlock_meta_out.outs_by_unlock_block,
outs_by_unlock_meta_out.timelocked_outputs);
outs_by_last_locked_block_meta_out.outs_by_last_locked_block,
outs_by_last_locked_block_meta_out.timelocked_outputs);
}
return outs_by_unlock_meta_out;
return outs_by_last_locked_block_meta_out;
}
//----------------------------------------------------------------------------------------------------------------------
}//namespace cryptonote

View File

@ -38,10 +38,10 @@
namespace cryptonote
{
struct OutsByUnlockBlockMeta
struct OutsByLastLockedBlockMeta
{
fcmp_pp::curve_trees::OutputsByUnlockBlock outs_by_unlock_block;
std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/> timelocked_outputs;
fcmp_pp::curve_trees::OutputsByLastLockedBlock outs_by_last_locked_block;
std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/> timelocked_outputs;
uint64_t next_output_id;
};
@ -49,7 +49,7 @@ struct OutsByUnlockBlockMeta
// instead of cryptonote_basic (where it would seem the better place to put it) to avoid a circular dependency between
// ringct <> cryptonote_basic.
// Note that zeroCommitVartime is expensive.
OutsByUnlockBlockMeta get_outs_by_unlock_block(
OutsByLastLockedBlockMeta get_outs_by_last_locked_block(
const cryptonote::transaction &miner_tx,
const std::vector<std::reference_wrapper<const cryptonote::transaction>> &txs,
const uint64_t first_output_id,

View File

@ -790,7 +790,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,
uint64_t num_rct_outs, const crypto::hash& blk_hash, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs)
uint64_t num_rct_outs, const crypto::hash& blk_hash, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@ -818,8 +818,8 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
throw0(BLOCK_PARENT_DNE("Top block is not new block's parent"));
}
// Grow the tree with outputs that unlock at this block height
auto unlocked_outputs = this->get_outs_at_unlock_block_id(m_height);
// Grow the tree with outputs that are no longer locked once this block is in the chain
auto unlocked_outputs = this->get_outs_at_last_locked_block_id(m_height);
this->grow_tree(std::move(unlocked_outputs));
// Now that we've used the unlocked leaves to grow the tree, we can delete them from the locked outputs table
@ -874,10 +874,10 @@ void BlockchainLMDB::add_block(const block& blk, size_t block_weight, uint64_t l
CURSOR(timelocked_outputs)
// Add the locked outputs from this block to the locked outputs and custom timelocked tables
for (const auto &unlock_block : outs_by_unlock_block)
for (const auto &last_locked_block : outs_by_last_locked_block)
{
const uint64_t last_locked_block_idx = unlock_block.first;
for (const auto &locked_output : unlock_block.second)
const uint64_t last_locked_block_idx = last_locked_block.first;
for (const auto &locked_output : last_locked_block.second)
{
MDB_val_set(k_block_id, last_locked_block_idx);
MDB_val_set(v_output, locked_output);
@ -1259,9 +1259,9 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in
// from the chain, then progress the chain again.
CURSOR(locked_outputs);
const uint64_t unlock_block = cryptonote::get_unlock_block_index(ok->data.unlock_time, ok->data.height);
const uint64_t last_locked_block = cryptonote::get_last_locked_block_index(ok->data.unlock_time, ok->data.height);
MDB_val_set(k_block_id, unlock_block);
MDB_val_set(k_block_id, last_locked_block);
MDB_val_set(v_output, ok->output_id);
result = mdb_cursor_get(m_cur_locked_outputs, &k_block_id, &v_output, MDB_GET_BOTH);
@ -1283,7 +1283,7 @@ void BlockchainLMDB::remove_output(const uint64_t amount, const uint64_t& out_in
// Remove output from custom timelocked outputs table if present
CURSOR(timelocked_outputs);
MDB_val_set(k_timelocked_block_id, unlock_block);
MDB_val_set(k_timelocked_block_id, last_locked_block);
MDB_val_set(v_timelocked_output, ok->output_id);
result = mdb_cursor_get(m_cur_timelocked_outputs, &k_timelocked_block_id, &v_timelocked_output, MDB_GET_BOTH);
@ -1766,7 +1766,7 @@ void BlockchainLMDB::trim_tree(const uint64_t new_n_leaf_tuples, const uint64_t
// be in the outputs tables.
const auto *o = (mdb_leaf *)v.mv_data;
MDB_val_set(v_output, o->output_context);
MDEBUG("Re-adding locked output_id: " << o->output_context.output_id << " , unlock block: " << trim_block_id);
MDEBUG("Re-adding locked output_id: " << o->output_context.output_id << " , last locked block: " << trim_block_id);
result = mdb_cursor_put(m_cur_locked_outputs, &k_block_id, &v_output, MDB_APPENDDUP);
if (result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to re-add locked output: ", result).c_str()));
@ -2482,7 +2482,7 @@ bool BlockchainLMDB::audit_layer(const std::unique_ptr<C_CHILD> &c_child,
return audit_complete;
}
std::vector<fcmp_pp::curve_trees::OutputContext> BlockchainLMDB::get_outs_at_unlock_block_id(
std::vector<fcmp_pp::curve_trees::OutputContext> BlockchainLMDB::get_outs_at_last_locked_block_id(
uint64_t block_id)
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
@ -2553,7 +2553,7 @@ void BlockchainLMDB::del_locked_outs_at_block_id(uint64_t block_id)
throw1(DB_ERROR(lmdb_error("Error removing locked outputs: ", result).c_str()));
}
fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_custom_timelocked_outputs(uint64_t start_block_idx) const
fcmp_pp::curve_trees::OutputsByLastLockedBlock BlockchainLMDB::get_custom_timelocked_outputs(uint64_t start_block_idx) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
@ -2561,7 +2561,7 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_custom_timelocked
TXN_PREFIX_RDONLY();
RCURSOR(timelocked_outputs)
fcmp_pp::curve_trees::OutputsByUnlockBlock outs;
fcmp_pp::curve_trees::OutputsByLastLockedBlock outs;
/*
We expect the timelocked outputs table to be sorted primarily by key, i.e.
@ -2605,12 +2605,12 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_custom_timelocked
// 2. Only return outputs that were created BEFORE start_block_idx
// 2a. Place all output id's in a flat vector
using output_id_pair_t = std::pair<uint64_t/*output_id*/, uint64_t/*unlock_block*/>;
using output_id_pair_t = std::pair<uint64_t/*output_id*/, uint64_t/*last_locked_block*/>;
std::vector<output_id_pair_t> output_ids;
for (const auto &outs_by_unlock_block : outs)
for (const auto &outs_by_last_locked_block : outs)
{
for (const auto &o : outs_by_unlock_block.second)
output_ids.push_back({ o.output_id, outs_by_unlock_block.first });
for (const auto &o : outs_by_last_locked_block.second)
output_ids.push_back({ o.output_id, outs_by_last_locked_block.first });
}
// 2b. Sort the vector in descending order by output ID, so outputs are ordered most recently created first
@ -2628,15 +2628,15 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_custom_timelocked
break;
// Find the output in the outs container
auto blk_it = outs.find(output_id.second/*unlock_block*/);
auto blk_it = outs.find(output_id.second/*last_locked_block*/);
// The first one in the vec should be the output id since outputs were added from the table in descending order
if (blk_it == outs.end())
throw0(DB_ERROR("Missing output's unlock block"));
throw0(DB_ERROR("Missing output's last locked block"));
if (blk_it->second.empty())
throw0(DB_ERROR("Unlock block missing outputs"));
throw0(DB_ERROR("last locked block missing outputs"));
if (blk_it->second.front().output_id != output_id.first)
throw0(DB_ERROR("Output id is not first in outs by unlock block"));
throw0(DB_ERROR("Output id is not first in outs by last locked block"));
// Remove the output from outs container
blk_it->second.erase(blk_it->second.begin());
@ -2645,9 +2645,9 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_custom_timelocked
}
// 3. Sort outputs of each last locked block by output id
for (auto &outs_by_unlock_block : outs)
for (auto &outs_by_last_locked_block : outs)
{
auto &unsorted = outs_by_unlock_block.second;
auto &unsorted = outs_by_last_locked_block.second;
std::sort(unsorted.begin(), unsorted.end(),
[](const fcmp_pp::curve_trees::OutputContext &a, const fcmp_pp::curve_trees::OutputContext &b)
{return a.output_id < b.output_id; });
@ -2658,14 +2658,14 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_custom_timelocked
return outs;
}
fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_recent_locked_outputs(uint64_t end_block_idx) const
fcmp_pp::curve_trees::OutputsByLastLockedBlock BlockchainLMDB::get_recent_locked_outputs(uint64_t end_block_idx) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
TXN_PREFIX_RDONLY();
fcmp_pp::curve_trees::OutputsByUnlockBlock outs;
fcmp_pp::curve_trees::OutputsByLastLockedBlock outs;
const uint64_t height = this->height();
if (height == 0)
@ -2681,26 +2681,26 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_recent_locked_out
const uint64_t end_blk_idx = std::min(height - 1, end_block_idx);
const auto get_out_unlock_blocks = [this, &outs, normal_start_idx](uint64_t b_idx, const crypto::hash, const block &b) -> bool
const auto get_last_locked_blocks = [this, &outs, normal_start_idx](uint64_t b_idx, const crypto::hash, const block &b) -> bool
{
// Add output data grouped by unlock block
auto add_outs_by_unlock_block = [this, &outs, b_idx](const crypto::hash &tx_hash, const bool is_coinbase)
// Add output data grouped by last locked block idx
auto add_by_last_locked_block = [this, &outs, b_idx](const crypto::hash &tx_hash, const bool is_coinbase)
{
auto out_data = this->get_tx_output_data(tx_hash);
if (out_data.empty())
return;
const uint64_t unlock_block = cryptonote::get_unlock_block_index(out_data.front().data.unlock_time, b_idx);
const uint64_t last_locked_block = cryptonote::get_last_locked_block_index(out_data.front().data.unlock_time, b_idx);
// Ignore custom timelocked outputs
if (cryptonote::is_custom_timelocked(is_coinbase, unlock_block, b_idx))
if (cryptonote::is_custom_timelocked(is_coinbase, last_locked_block, b_idx))
return;
auto outs_it = outs.find(unlock_block);
auto outs_it = outs.find(last_locked_block);
if (outs_it == outs.end())
{
outs[unlock_block] = {};
outs_it = outs.find(unlock_block);
outs[last_locked_block] = {};
outs_it = outs.find(last_locked_block);
}
for (auto &out : out_data)
@ -2708,19 +2708,19 @@ fcmp_pp::curve_trees::OutputsByUnlockBlock BlockchainLMDB::get_recent_locked_out
};
// Add coinbase outputs
add_outs_by_unlock_block(cryptonote::get_transaction_hash(b.miner_tx), true);
add_by_last_locked_block(cryptonote::get_transaction_hash(b.miner_tx), true);
if (normal_start_idx > b_idx)
return true;
// Add normal outputs
for (const auto &tx_hash : b.tx_hashes)
add_outs_by_unlock_block(tx_hash, false);
add_by_last_locked_block(tx_hash, false);
return true;
};
for_blocks_range(coinbase_start_idx, end_blk_idx, get_out_unlock_blocks);
for_blocks_range(coinbase_start_idx, end_blk_idx, get_last_locked_blocks);
TXN_POSTFIX_RDONLY();
@ -7556,11 +7556,11 @@ void BlockchainLMDB::migrate_5_6()
.output_pair = std::move(output_pair)
};
// Get the block in which the output will unlock
const uint64_t unlock_block = cryptonote::get_unlock_block_index(output_data.unlock_time, output_data.height);
// Get the output's last locked block
const uint64_t last_locked_block = cryptonote::get_last_locked_block_index(output_data.unlock_time, output_data.height);
// Add the output to the locked outputs table
MDB_val_set(k_block_id, unlock_block);
MDB_val_set(k_block_id, last_locked_block);
MDB_val_set(v_output, output_context);
// MDB_NODUPDATA because all output id's should be unique
@ -7571,20 +7571,20 @@ void BlockchainLMDB::migrate_5_6()
// Check if the output is a coinbase output
bool is_coinbase = false;
const bool has_coinbase_unlock_block = unlock_block == (output_data.height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW - 1);
if (has_coinbase_unlock_block)
const bool has_coinbase_last_locked_block = last_locked_block == (output_data.height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW - 1);
if (has_coinbase_last_locked_block)
{
// Only coinbase outputs could potentially have the coinbase unlock block (see prevalidate_miner_transaction)
// Only coinbase outputs could potentially have the coinbase last locked block (see prevalidate_miner_transaction)
auto toi = this->get_output_tx_and_index_from_global(output_id);
auto tx = this->get_pruned_tx(toi.first);
is_coinbase = cryptonote::is_coinbase(tx);
}
// Add custom timelocked outputs to the timelocked outputs table
if (!cryptonote::is_custom_timelocked(is_coinbase, unlock_block, output_data.height))
if (!cryptonote::is_custom_timelocked(is_coinbase, last_locked_block, output_data.height))
continue;
MDB_val_set(k_timelocked_block_id, unlock_block);
MDB_val_set(k_timelocked_block_id, last_locked_block);
MDB_val_set(v_timelocked_output, output_context);
// MDB_NODUPDATA because all output id's should be unique
@ -7596,7 +7596,7 @@ void BlockchainLMDB::migrate_5_6()
}
// 3. Set up the curve trees merkle tree by growing the tree block by block,
// with leaves that unlock in each respective block
// with leaves that are spendable in each respective block
{
MINFO("Setting up a merkle tree using existing cryptonote outputs (step 3/3 of full-chain membership proof migration)");
@ -7660,8 +7660,8 @@ void BlockchainLMDB::migrate_5_6()
}
}
// Get the leaf tuples that unlock at the given block
auto unlocked_outputs = this->get_outs_at_unlock_block_id(i);
// Get leaf tuples of outputs that unlock once i is in the chain, since i is their last locked block
auto unlocked_outputs = this->get_outs_at_last_locked_block_id(i);
this->grow_tree(std::move(unlocked_outputs));
// Now that we've used the unlocked leaves to grow the tree, we delete them from the locked outputs table

View File

@ -399,8 +399,8 @@ private:
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& block_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
);
virtual void remove_block();
@ -466,17 +466,17 @@ private:
const uint64_t child_layer_idx,
const uint64_t chunk_width) const;
std::vector<fcmp_pp::curve_trees::OutputContext> get_outs_at_unlock_block_id(uint64_t block_id);
std::vector<fcmp_pp::curve_trees::OutputContext> get_outs_at_last_locked_block_id(uint64_t block_id);
void del_locked_outs_at_block_id(uint64_t block_id);
virtual fcmp_pp::curve_trees::OutputsByUnlockBlock get_custom_timelocked_outputs(uint64_t start_block_idx) const;
virtual fcmp_pp::curve_trees::OutputsByLastLockedBlock get_custom_timelocked_outputs(uint64_t start_block_idx) const;
// Returns:
// - coinbase outputs created between [end_block_idx - CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW]
// - normal outputs created between [end_block_idx - CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE]
// - the outputs are grouped by unlock block idx
virtual fcmp_pp::curve_trees::OutputsByUnlockBlock get_recent_locked_outputs(uint64_t end_block_idx) const;
// - the outputs are grouped by last locked block idx
virtual fcmp_pp::curve_trees::OutputsByLastLockedBlock get_recent_locked_outputs(uint64_t end_block_idx) const;
// Hard fork
virtual void set_hard_fork_version(uint64_t height, uint8_t version);

View File

@ -124,8 +124,8 @@ public:
virtual crypto::ec_point get_tree_root() const override { return {}; };
virtual uint64_t get_n_leaf_tuples() const override { return 0; };
virtual uint64_t get_block_n_leaf_tuples(const uint64_t block_idx) const override { return 0; };
virtual fcmp_pp::curve_trees::OutputsByUnlockBlock get_custom_timelocked_outputs(uint64_t start_block_idx) const override { return {{}}; };
virtual fcmp_pp::curve_trees::OutputsByUnlockBlock get_recent_locked_outputs(uint64_t end_block_idx) const override { return {{}}; };
virtual fcmp_pp::curve_trees::OutputsByLastLockedBlock get_custom_timelocked_outputs(uint64_t start_block_idx) const override { return {{}}; };
virtual fcmp_pp::curve_trees::OutputsByLastLockedBlock get_recent_locked_outputs(uint64_t end_block_idx) const override { return {{}}; };
virtual bool for_all_key_images(std::function<bool(const crypto::key_image_y&)>) const override { return true; }
virtual bool for_blocks_range(const uint64_t&, const uint64_t&, std::function<bool(uint64_t, const crypto::hash&, const cryptonote::block&)>) const override { return true; }
@ -154,8 +154,8 @@ public:
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& blk_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
) override { }
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 {}

View File

@ -1636,21 +1636,21 @@ namespace cryptonote
}
//---------------------------------------------------------------
// TODO: write tests for this func that match with current daemon logic
uint64_t get_unlock_block_index(uint64_t unlock_time, uint64_t block_included_in_chain)
uint64_t get_last_locked_block_index(uint64_t unlock_time, uint64_t block_included_in_chain)
{
uint64_t unlock_block_index = 0;
uint64_t last_locked_block_index = 0;
const uint64_t default_block_index = get_default_last_locked_block_index(block_included_in_chain);
if (unlock_time == 0)
{
unlock_block_index = default_block_index;
last_locked_block_index = default_block_index;
}
else if (unlock_time < CRYPTONOTE_MAX_BLOCK_NUMBER)
{
// The unlock_time in this case is supposed to be the chain height at which the output unlocks
// The chain height is 1 higher than the highest block index, so we subtract 1 for this delta
unlock_block_index = unlock_time > 0 ? (unlock_time - 1) : 0;
last_locked_block_index = unlock_time > 0 ? (unlock_time - 1) : 0;
}
else
{
@ -1659,14 +1659,14 @@ namespace cryptonote
const auto hf_v15_time = 1656629118;
const auto hf_v15_height = 2689608;
// Use the last hard fork's time and block combo to convert the time-based timelock into an unlock block
// Use the last hard fork's time and block combo to convert the time-based timelock into an last locked block
// TODO: consider taking into account 60s block times when that was consensus
if (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;
unlock_block_index = hf_v15_height > blocks_since_unlock
last_locked_block_index = hf_v15_height > blocks_since_unlock
? (hf_v15_height - blocks_since_unlock)
: default_block_index;
}
@ -1674,29 +1674,29 @@ namespace cryptonote
{
const auto seconds_until_unlock = unlock_time - hf_v15_time;
const auto blocks_until_unlock = seconds_until_unlock / DIFFICULTY_TARGET_V2;
unlock_block_index = hf_v15_height + blocks_until_unlock;
last_locked_block_index = hf_v15_height + blocks_until_unlock;
}
/* Note: since this function was introduced for the hf that included fcmp's, it's possible for an output to be
spent before it reaches the unlock_block_index going by the old rules; this is ok. It can't be spent again b/c
spent before it reaches the last_locked_block_index going by the old rules; this is ok. It can't be spent again b/c
it'll have a duplicate key image. It's also possible for an output to unlock by old rules, and then re-lock
again at the fork. This is also ok, we just need to be sure that the new hf rules use this unlock_block_index
again at the fork. This is also ok, we just need to be sure that the new hf rules use this last_locked_block_index
starting at the fork for fcmp's.
*/
// TODO: double check the accuracy of this calculation
MDEBUG("unlock time: " << unlock_time << " , unlock_block_index: " << unlock_block_index);
MDEBUG("unlock time: " << unlock_time << " , last_locked_block_index: " << last_locked_block_index);
}
// Can't unlock earlier than the default unlock block
return std::max(unlock_block_index, default_block_index);
// Can't unlock earlier than the default last locked block
return std::max(last_locked_block_index, default_block_index);
}
//---------------------------------------------------------------
bool is_custom_timelocked(bool is_coinbase, uint64_t unlock_block_idx, uint64_t block_included_in_chain)
bool is_custom_timelocked(bool is_coinbase, uint64_t last_locked_block_idx, uint64_t block_included_in_chain)
{
if (is_coinbase)
return false;
return unlock_block_idx > cryptonote::get_default_last_locked_block_index(block_included_in_chain);
return last_locked_block_idx > cryptonote::get_default_last_locked_block_index(block_included_in_chain);
}
}

View File

@ -267,9 +267,9 @@ namespace cryptonote
crypto::secret_key encrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase);
crypto::secret_key decrypt_key(crypto::secret_key key, const epee::wipeable_string &passphrase);
// Returns the block index in which the provided unlock_time unlocks
uint64_t get_unlock_block_index(uint64_t unlock_time, uint64_t block_included_in_chain);
bool is_custom_timelocked(bool is_coinbase, uint64_t unlock_block_idx, uint64_t block_included_in_chain);
// Returns the last locked block index for the provided unlock_time
uint64_t get_last_locked_block_index(uint64_t unlock_time, uint64_t block_included_in_chain);
bool is_custom_timelocked(bool is_coinbase, uint64_t last_locked_block_idx, uint64_t block_included_in_chain);
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \

View File

@ -915,7 +915,7 @@ typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extensio
TIME_MEASURE_START(sorting_outputs);
// Sort the outputs by order they appear in the chain
// Note: the outputs are expected to be grouped by unlock block
// Note: the outputs are expected to be grouped by last locked block
std::vector<OutputContext> flat_sorted_outputs;
for (auto &unsorted_outputs : new_outputs)
{

View File

@ -190,7 +190,7 @@ struct OutputContext final
static_assert(sizeof(OutputPair) == (32+32), "db expects 64 bytes for output pairs");
static_assert(sizeof(OutputContext) == (8+32+32), "db expects 72 bytes for output context");
using OutputsByUnlockBlock = std::unordered_map<uint64_t, std::vector<OutputContext>>;
using OutputsByLastLockedBlock = std::unordered_map<uint64_t, std::vector<OutputContext>>;
// Ed25519 points (can go from OutputTuple -> LeafTuple)
struct OutputTuple final

View File

@ -76,32 +76,32 @@ static void assign_new_output(const OutputPair &output_pair,
return;
}
//----------------------------------------------------------------------------------------------------------------------
static uint64_t add_to_locked_outputs_cache(const fcmp_pp::curve_trees::OutputsByUnlockBlock &outs_by_unlock_block,
static uint64_t add_to_locked_outputs_cache(const fcmp_pp::curve_trees::OutputsByLastLockedBlock &outs_by_last_locked_block,
const CreatedBlockIdx created_block_idx,
LockedOutputsByUnlock &locked_outputs_inout,
LockedOutputsByLastLockedBlock &locked_outputs_inout,
LockedOutputsByCreated &locked_outputs_refs_inout)
{
uint64_t n_outputs_added = 0;
LockedOutputRefs locked_output_refs;
for (const auto &unlock_block : outs_by_unlock_block)
for (const auto &last_locked_block : outs_by_last_locked_block)
{
const UnlockBlockIdx unlock_block_idx = unlock_block.first;
CHECK_AND_ASSERT_THROW_MES(unlock_block_idx > created_block_idx, "unlock block idx should be > created block");
const auto &new_locked_outputs = unlock_block.second;
const LastLockedBlockIdx last_locked_block_idx = last_locked_block.first;
CHECK_AND_ASSERT_THROW_MES(last_locked_block_idx > created_block_idx, "last locked block idx should be > created block");
const auto &new_locked_outputs = last_locked_block.second;
// We keep track of the number outputs we're adding to the cache at a specific unlock block, so that we can
// We keep track of the number outputs we're adding to the cache at a specific last locked block, so that we can
// quickly remove those outputs from the cache upon popping a block.
const auto n_new_outputs = new_locked_outputs.size();
locked_output_refs[unlock_block_idx] = n_new_outputs;
locked_output_refs[last_locked_block_idx] = n_new_outputs;
n_outputs_added += n_new_outputs;
// Add to locked outputs cache by unlock block, so we can use them to grow the tree upon unlock.
auto locked_outputs_it = locked_outputs_inout.find(unlock_block_idx);
// Add to locked outputs cache by last locked block, so we can use them to grow the tree upon unlock.
auto locked_outputs_it = locked_outputs_inout.find(last_locked_block_idx);
if (locked_outputs_it == locked_outputs_inout.end())
{
locked_outputs_inout[unlock_block_idx] = new_locked_outputs;
locked_outputs_inout[last_locked_block_idx] = new_locked_outputs;
continue;
}
@ -112,7 +112,7 @@ static uint64_t add_to_locked_outputs_cache(const fcmp_pp::curve_trees::OutputsB
bool r = tools::merge_sorted_vectors(locked_outputs, new_locked_outputs, is_less, all_locked_outputs);
CHECK_AND_ASSERT_THROW_MES(r, "failed to merge sorted locked outputs");
locked_outputs_inout[unlock_block_idx] = std::move(all_locked_outputs);
locked_outputs_inout[last_locked_block_idx] = std::move(all_locked_outputs);
}
// This is keeping track of locked output refs in the locked outputs cache by their created block. We use this to
@ -125,7 +125,7 @@ static uint64_t add_to_locked_outputs_cache(const fcmp_pp::curve_trees::OutputsB
}
//----------------------------------------------------------------------------------------------------------------------
static uint64_t remove_outputs_created_at_block(const CreatedBlockIdx &created_block_idx,
LockedOutputsByUnlock &locked_outputs_inout,
LockedOutputsByLastLockedBlock &locked_outputs_inout,
LockedOutputsByCreated &locked_outputs_refs_inout)
{
uint64_t n_outputs_removed = 0;
@ -136,12 +136,12 @@ static uint64_t remove_outputs_created_at_block(const CreatedBlockIdx &created_b
for (const auto &locked_output_refs : locked_output_refs_it->second)
{
// The outputs are grouped by unlock block
const UnlockBlockIdx unlock_block_idx = locked_output_refs.first;
// The outputs are grouped by last locked block
const LastLockedBlockIdx last_locked_block_idx = locked_output_refs.first;
const NumOutputs n_outputs_to_remove = locked_output_refs.second;
// Find the locked outputs using the unlock block
const auto locked_outputs_it = locked_outputs_inout.find(unlock_block_idx);
// Find the locked outputs using the last locked block
const auto locked_outputs_it = locked_outputs_inout.find(last_locked_block_idx);
CHECK_AND_ASSERT_THROW_MES(locked_outputs_it != locked_outputs_inout.end(), "missing locked outputs");
const NumOutputs n_cur_outputs = locked_outputs_it->second.size();
@ -791,15 +791,15 @@ static std::vector<typename C_PARENT::Scalar> get_layer_last_chunk_children_to_r
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
template<typename C1, typename C2>
bool TreeCache<C1, C2>::register_output(const OutputPair &output, const uint64_t unlock_block_idx)
bool TreeCache<C1, C2>::register_output(const OutputPair &output, const uint64_t last_locked_block_idx)
{
if (!m_cached_blocks.empty())
{
const auto &top_synced_block = m_cached_blocks.back();
// If the output is already unlocked, we won't be able to tell the output's position in the tree
CHECK_AND_ASSERT_MES(unlock_block_idx > top_synced_block.blk_idx, false,
"already synced block in which output unlocked");
CHECK_AND_ASSERT_MES(last_locked_block_idx > top_synced_block.blk_idx, false,
"already synced output's last locked block");
}
auto output_ref = get_output_ref(output);
@ -815,16 +815,16 @@ bool TreeCache<C1, C2>::register_output(const OutputPair &output, const uint64_t
}
// Explicit instantiation
template bool TreeCache<Selene, Helios>::register_output(const OutputPair &output, const uint64_t unlock_block_idx);
template bool TreeCache<Selene, Helios>::register_output(const OutputPair &output, const uint64_t last_locked_block_idx);
//----------------------------------------------------------------------------------------------------------------------
template<typename C1, typename C2>
void TreeCache<C1, C2>::sync_block(const uint64_t block_idx,
const crypto::hash &block_hash,
const crypto::hash &prev_block_hash,
const fcmp_pp::curve_trees::OutputsByUnlockBlock &outs_by_unlock_block)
const fcmp_pp::curve_trees::OutputsByLastLockedBlock &outs_by_last_locked_block)
{
const std::vector<crypto::hash> new_block_hashes{block_hash};
const std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock> outs{outs_by_unlock_block};
const std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock> outs{outs_by_last_locked_block};
typename fcmp_pp::curve_trees::CurveTrees<C1, C2>::TreeExtension tree_extension;
std::vector<uint64_t> n_new_leaf_tuples_per_block;
@ -843,17 +843,17 @@ void TreeCache<C1, C2>::sync_block(const uint64_t block_idx,
template void TreeCache<Selene, Helios>::sync_block(const uint64_t block_idx,
const crypto::hash &block_hash,
const crypto::hash &prev_block_hash,
const fcmp_pp::curve_trees::OutputsByUnlockBlock &outs_by_unlock_block);
const fcmp_pp::curve_trees::OutputsByLastLockedBlock &outs_by_last_locked_block);
//----------------------------------------------------------------------------------------------------------------------
template<typename C1, typename C2>
void TreeCache<C1, C2>::sync_blocks(const uint64_t start_block_idx,
const crypto::hash &prev_block_hash,
const std::vector<crypto::hash> &new_block_hashes,
const std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock> &outs_by_unlock_blocks,
const std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock> &outs_by_last_locked_blocks,
typename fcmp_pp::curve_trees::CurveTrees<C1, C2>::TreeExtension &tree_extension_out,
std::vector<uint64_t> &n_new_leaf_tuples_per_block_out)
{
CHECK_AND_ASSERT_THROW_MES(new_block_hashes.size() == outs_by_unlock_blocks.size(), "size mismatch sync_blocks");
CHECK_AND_ASSERT_THROW_MES(new_block_hashes.size() == outs_by_last_locked_blocks.size(), "size mismatch sync_blocks");
tree_extension_out = typename fcmp_pp::curve_trees::CurveTrees<C1, C2>::TreeExtension{};
n_new_leaf_tuples_per_block_out.clear();
@ -897,7 +897,7 @@ void TreeCache<C1, C2>::sync_blocks(const uint64_t start_block_idx,
{
const BlockIdx blk_idx = start_block_idx + i;
m_output_count += add_to_locked_outputs_cache(outs_by_unlock_blocks[i],
m_output_count += add_to_locked_outputs_cache(outs_by_last_locked_blocks[i],
blk_idx,
m_locked_outputs,
m_locked_output_refs
@ -967,7 +967,7 @@ void TreeCache<C1, C2>::sync_blocks(const uint64_t start_block_idx,
template void TreeCache<Selene, Helios>::sync_blocks(const uint64_t start_block_idx,
const crypto::hash &prev_block_hash,
const std::vector<crypto::hash> &new_block_hashes,
const std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock> &outs_by_unlock_blocks,
const std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock> &outs_by_last_locked_blocks,
typename fcmp_pp::curve_trees::CurveTrees<Selene, Helios>::TreeExtension &tree_extension_out,
std::vector<uint64_t> &n_new_leaf_tuples_per_block_out);
//----------------------------------------------------------------------------------------------------------------------
@ -1084,7 +1084,7 @@ void TreeCache<C1, C2>::process_synced_blocks(const uint64_t start_block_idx,
// All locked outputs that unlocked in the oldest block idx should already be in the tree. We keep them cached
// to handle reorgs (in case an output trimmed from the tree is supposed to re-enter the cache). We don't need
// to keep them past the reorg depth.
m_locked_outputs.erase(/*UnlockBlockIdx*/oldest_block.blk_idx);
m_locked_outputs.erase(/*LastLockedBlockIdx*/oldest_block.blk_idx);
// We keep locked output refs around for outputs *created* in the oldest block, so we can quickly remove them
// from the locked outputs cache upon popping the block. Once the reorg depth is exceeded, we can't remove those
@ -1305,7 +1305,7 @@ void TreeCache<C1, C2>::init(const uint64_t start_block_idx,
const crypto::hash &start_block_hash,
const uint64_t n_leaf_tuples,
const fcmp_pp::curve_trees::PathBytes &last_path,
const OutputsByUnlockBlock &timelocked_outputs)
const OutputsByLastLockedBlock &timelocked_outputs)
{
CHECK_AND_ASSERT_THROW_MES(m_cached_blocks.empty(), "expected empty tree cache");
CHECK_AND_ASSERT_THROW_MES(n_leaf_tuples >= last_path.leaves.size(), "n_leaf_tuples too small");
@ -1403,7 +1403,7 @@ template void TreeCache<Selene, Helios>::init(const uint64_t start_block_idx,
const crypto::hash &start_block_hash,
const uint64_t n_leaf_tuples,
const fcmp_pp::curve_trees::PathBytes &last_hashes,
const OutputsByUnlockBlock &timelocked_outputs);
const OutputsByLastLockedBlock &timelocked_outputs);
//----------------------------------------------------------------------------------------------------------------------
template<typename C1, typename C2>
crypto::ec_point TreeCache<C1, C2>::get_tree_root() const

View File

@ -59,7 +59,7 @@ using LeafIdx = uint64_t;
using LayerIdx = std::size_t;
using ChildChunkIdx = uint64_t;
using UnlockBlockIdx = BlockIdx;
using LastLockedBlockIdx = BlockIdx;
using CreatedBlockIdx = BlockIdx;
using NumOutputs = std::size_t;
@ -147,8 +147,8 @@ struct AssignedLeafIdx final
END_SERIALIZE()
};
using LockedOutputsByUnlock = std::unordered_map<UnlockBlockIdx, std::vector<OutputContext>>;
using LockedOutputRefs = std::unordered_map<UnlockBlockIdx, NumOutputs>;
using LockedOutputsByLastLockedBlock = std::unordered_map<LastLockedBlockIdx, std::vector<OutputContext>>;
using LockedOutputRefs = std::unordered_map<LastLockedBlockIdx, NumOutputs>;
using LockedOutputsByCreated = std::unordered_map<CreatedBlockIdx, LockedOutputRefs>;
using RegisteredOutputs = std::unordered_map<OutputRef, AssignedLeafIdx>;
@ -179,14 +179,14 @@ public:
TreeSync<C1, C2>(curve_trees, max_reorg_depth)
{};
bool register_output(const OutputPair &output, const uint64_t unlock_block_idx) override;
bool register_output(const OutputPair &output, const uint64_t last_locked_block_idx) override;
// TODO: bool cancel_output_registration
void sync_block(const uint64_t block_idx,
const crypto::hash &block_hash,
const crypto::hash &prev_block_hash,
const OutputsByUnlockBlock &outs_by_unlock_block) override;
const OutputsByLastLockedBlock &outs_by_last_locked_block) override;
bool pop_block() override;
@ -198,7 +198,7 @@ public:
const crypto::hash &start_block_hash,
const uint64_t n_leaf_tuples,
const fcmp_pp::curve_trees::PathBytes &last_path,
const OutputsByUnlockBlock &timelocked_outputs);
const OutputsByLastLockedBlock &timelocked_outputs);
// TODO: make this part of the TreeSync interface
crypto::ec_point get_tree_root() const;
@ -217,7 +217,7 @@ public:
void sync_blocks(const uint64_t start_block_idx,
const crypto::hash &prev_block_hash,
const std::vector<crypto::hash> &new_block_hashes,
const std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock> &outs_by_unlock_blocks,
const std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock> &outs_by_last_locked_blocks,
typename fcmp_pp::curve_trees::CurveTrees<C1, C2>::TreeExtension &tree_extension_out,
std::vector<uint64_t> &n_new_leaf_tuples_per_block_out);
@ -244,7 +244,7 @@ private:
// State held in memory
private:
// Locked outputs in the chain that we use to grow the tree with internally upon unlock
LockedOutputsByUnlock m_locked_outputs;
LockedOutputsByLastLockedBlock m_locked_outputs;
LockedOutputsByCreated m_locked_output_refs;
// Keep a global output counter so the caller knows how output id's should be set

View File

@ -64,11 +64,11 @@ public:
// - if the output is already registered.
// - if the TreeSync object has already synced the block in which the output unlocks. The scanner would not
// be able to determine the output's position in the tree in this case.
virtual bool register_output(const OutputPair &output, const uint64_t unlock_block_idx) = 0;
virtual bool register_output(const OutputPair &output, const uint64_t last_locked_block_idx) = 0;
// TODO: bool cancel_output_registration
// Sync the outputs created in the provided block and grow the tree with outputs that unlock in this block
// Sync the outputs created in the provided block and grow the tree with outputs with last locked block block_idx
// - The block must be contiguous to the most recently synced block
// - If any registered outputs are present in the new leaf tuples, keeps track of their paths in the tree
// - Uses the new leaf tuples to update any existing known output paths in the tree
@ -84,7 +84,7 @@ public:
virtual void sync_block(const uint64_t block_idx,
const crypto::hash &block_hash,
const crypto::hash &prev_block_hash,
const fcmp_pp::curve_trees::OutputsByUnlockBlock &outs_by_unlock_block) = 0;
const fcmp_pp::curve_trees::OutputsByLastLockedBlock &outs_by_last_locked_block) = 0;
// Trim from the locally synced tree and update any paths as necesary
// - Returns false if we cannot pop any more blocks (if the max reorg depth is reached, or no more blocks to pop)

View File

@ -618,25 +618,25 @@ namespace cryptonote
// 1. Custom timelocked outputs created before sync_start_idx with last locked block >= sync_start_idx
const uint64_t sync_start_idx = init_block_idx + 1;
auto custom_outs_by_unlock_block = m_core.get_blockchain_storage().get_db().get_custom_timelocked_outputs(sync_start_idx);
auto custom_outs_by_last_locked_block = m_core.get_blockchain_storage().get_db().get_custom_timelocked_outputs(sync_start_idx);
// 2a. Coinbase output contexts created between blocks [init_block_idx - 60, init_block_idx] inclusive
// 2b. Normal output contexts created between blocks [init_block_idx - 10, init_block_idx] inclusive
auto outs_by_unlock_block = m_core.get_blockchain_storage().get_db().get_recent_locked_outputs(init_block_idx);
auto outs_by_last_locked_block = m_core.get_blockchain_storage().get_db().get_recent_locked_outputs(init_block_idx);
// 3. Combine all locked outputs into vec
auto &locked_outputs = init_tree_sync_data.locked_outputs;
locked_outputs.reserve(custom_outs_by_unlock_block.size() + outs_by_unlock_block.size());
locked_outputs.reserve(custom_outs_by_last_locked_block.size() + outs_by_last_locked_block.size());
// 3a. Iterate over all custom locked outs and check if unlock block is present in other outs. If so, combine.
for (auto &o : custom_outs_by_unlock_block)
// 3a. Iterate over all custom locked outs and check if last locked block is present in other outs. If so, combine.
for (auto &o : custom_outs_by_last_locked_block)
{
const uint64_t unlock_block = o.first;
const uint64_t last_locked_block = o.first;
auto outs_it = outs_by_unlock_block.find(unlock_block);
if (outs_it == outs_by_unlock_block.end())
auto outs_it = outs_by_last_locked_block.find(last_locked_block);
if (outs_it == outs_by_last_locked_block.end())
{
locked_outputs.push_back({ unlock_block, std::move(o.second) });
locked_outputs.push_back({ last_locked_block, std::move(o.second) });
continue;
}
@ -650,28 +650,28 @@ namespace cryptonote
return false;
}
locked_outputs.push_back({ unlock_block, std::move(sorted_outs) });
locked_outputs.push_back({ last_locked_block, std::move(sorted_outs) });
}
// 3b. Get the remaining locked outs
for (auto &o : outs_by_unlock_block)
for (auto &o : outs_by_last_locked_block)
{
const uint64_t unlock_block = o.first;
const uint64_t last_locked_block = o.first;
auto custom_outs_it = custom_outs_by_unlock_block.find(unlock_block);
if (custom_outs_it != custom_outs_by_unlock_block.end())
auto custom_outs_it = custom_outs_by_last_locked_block.find(last_locked_block);
if (custom_outs_it != custom_outs_by_last_locked_block.end())
{
// We've already added it in 3a above
continue;
}
locked_outputs.push_back({ unlock_block, std::move(o.second) });
locked_outputs.push_back({ last_locked_block, std::move(o.second) });
}
// 3c. Sort locked outputs by last locked block
std::sort(locked_outputs.begin(), locked_outputs.end(),
[](const COMMAND_RPC_GET_BLOCKS_FAST::locked_outputs_t &a, const COMMAND_RPC_GET_BLOCKS_FAST::locked_outputs_t &b)
{ return a.unlock_block < b.unlock_block; });
{ return a.last_locked_block < b.last_locked_block; });
// 4. N leaf tuples and last chunk at each layer of the tree when init_block_idx was the last block in the chain
auto last_path = m_core.get_blockchain_storage().get_db().get_last_path(init_block_idx);

View File

@ -249,11 +249,11 @@ inline const std::string get_rpc_status(const bool trusted_daemon, const std::st
struct locked_outputs_t
{
uint64_t unlock_block;
uint64_t last_locked_block;
std::vector<fcmp_pp::curve_trees::OutputContext> outputs;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(unlock_block)
KV_SERIALIZE(last_locked_block)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(outputs)
END_KV_SERIALIZE_MAP()
};

View File

@ -2556,7 +2556,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (!ignore_callbacks && 0 != m_callback)
m_callback->on_money_received(height, txid, tx, td.m_amount, 0, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time);
m_tree_cache.register_output(output_pair, cryptonote::get_unlock_block_index(tx.unlock_time, height));
m_tree_cache.register_output(output_pair, cryptonote::get_last_locked_block_index(tx.unlock_time, height));
}
total_received_1 += amount;
notify = true;
@ -2635,7 +2635,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L0("Received money: " << print_money(td.amount()) << ", with tx: " << txid);
if (!ignore_callbacks && 0 != m_callback)
m_callback->on_money_received(height, txid, tx, td.m_amount, burnt, td.m_subaddr_index, spends_one_of_ours(tx), td.m_tx.unlock_time);
m_tree_cache.register_output(output_pair, cryptonote::get_unlock_block_index(tx.unlock_time, height));
m_tree_cache.register_output(output_pair, cryptonote::get_last_locked_block_index(tx.unlock_time, height));
}
total_received_1 += extra_amount;
notify = true;
@ -3336,7 +3336,7 @@ static TreeSyncStartParams tree_sync_reorg_check(const uint64_t parsed_blocks_st
return TreeSyncStartParams { sync_start_block_idx, start_parsed_block_i, prev_block_hash };
}
static void tree_sync_blocks_async(const TreeSyncStartParams &tree_sync_start_params, const std::vector<tools::wallet2::parsed_block> &parsed_blocks, tools::wallet2::TreeCacheV1 &tree_cache_inout, uint64_t &outs_by_unlock_time_ms_inout, uint64_t &sync_blocks_time_ms_inout, std::vector<crypto::hash> &new_block_hashes_out, fcmp_pp::curve_trees::CurveTreesV1::TreeExtension &tree_extension_out, std::vector<uint64_t> &new_leaf_tuples_per_block_out)
static void tree_sync_blocks_async(const TreeSyncStartParams &tree_sync_start_params, const std::vector<tools::wallet2::parsed_block> &parsed_blocks, tools::wallet2::TreeCacheV1 &tree_cache_inout, uint64_t &outs_by_last_locked_time_ms_inout, uint64_t &sync_blocks_time_ms_inout, std::vector<crypto::hash> &new_block_hashes_out, fcmp_pp::curve_trees::CurveTreesV1::TreeExtension &tree_extension_out, std::vector<uint64_t> &new_leaf_tuples_per_block_out)
{
TIME_MEASURE_START(sync_blocks_time);
@ -3354,12 +3354,12 @@ static void tree_sync_blocks_async(const TreeSyncStartParams &tree_sync_start_pa
THROW_WALLET_EXCEPTION_IF(sync_start_block_idx == 0, error::wallet_internal_error, "sync_start_block_idx must be > 0");
// Collect all outs from all blocks by unlock block
TIME_MEASURE_START(collecting_outs_by_unlock_block);
std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock> outs_by_unlock_blocks;
// Collect all outs from all blocks by last locked block
TIME_MEASURE_START(collecting_outs_by_last_locked_block);
std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock> outs_by_last_locked_blocks;
new_block_hashes_out.reserve(n_new_blocks);
outs_by_unlock_blocks.reserve(n_new_blocks);
outs_by_last_locked_blocks.reserve(n_new_blocks);
uint64_t first_output_id = tree_cache_inout.get_output_count();
for (size_t i = start_parsed_block_i; i < parsed_blocks.size(); ++i)
@ -3374,29 +3374,29 @@ static void tree_sync_blocks_async(const TreeSyncStartParams &tree_sync_start_pa
txs.push_back(std::ref(parsed_blocks[i].txes[j]));
// Note: this function is slow because of zeroCommitVartime
auto res = cryptonote::get_outs_by_unlock_block(miner_tx, txs, first_output_id, created_block_idx);
auto res = cryptonote::get_outs_by_last_locked_block(miner_tx, txs, first_output_id, created_block_idx);
outs_by_unlock_blocks.emplace_back(std::move(res.outs_by_unlock_block));
outs_by_last_locked_blocks.emplace_back(std::move(res.outs_by_last_locked_block));
first_output_id = res.next_output_id;
}
TIME_MEASURE_FINISH(collecting_outs_by_unlock_block);
TIME_MEASURE_FINISH(collecting_outs_by_last_locked_block);
// Get a tree extension with the outputs that will unlock in this chunk of blocks
tree_cache_inout.sync_blocks(sync_start_block_idx,
prev_block_hash,
new_block_hashes_out,
outs_by_unlock_blocks,
outs_by_last_locked_blocks,
tree_extension_out,
new_leaf_tuples_per_block_out);
TIME_MEASURE_FINISH(sync_blocks_time);
outs_by_unlock_time_ms_inout += collecting_outs_by_unlock_block;
outs_by_last_locked_time_ms_inout += collecting_outs_by_last_locked_block;
sync_blocks_time_ms_inout += sync_blocks_time;
LOG_PRINT_L1("Total time spent building tree: " << sync_blocks_time_ms_inout / 1000
<< " , time spent collecting outs by unlock time while building tree: " << outs_by_unlock_time_ms_inout / 1000);
<< " , time spent collecting outs by unlock time while building tree: " << outs_by_last_locked_time_ms_inout / 1000);
}
//----------------------------------------------------------------------------------------------------
void wallet2::process_parsed_blocks(const uint64_t start_height, const std::vector<cryptonote::block_complete_entry> &blocks, const std::vector<parsed_block> &parsed_blocks, uint64_t& blocks_added, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
@ -3439,7 +3439,7 @@ void wallet2::process_parsed_blocks(const uint64_t start_height, const std::vect
// the tree extension, saving any path elements we need for received outputs,
// and throwing away excess tree elems we won't need to continue syncing.
tpool.submit(&tree_sync_blocks_waiter, [this, &parsed_blocks, &new_block_hashes, &tree_extension, &new_leaf_tuples_per_block, tree_sync_start_params]() {
tree_sync_blocks_async(tree_sync_start_params, parsed_blocks, m_tree_cache, m_outs_by_unlock_time_ms, m_sync_blocks_time_ms, new_block_hashes, tree_extension, new_leaf_tuples_per_block);
tree_sync_blocks_async(tree_sync_start_params, parsed_blocks, m_tree_cache, m_outs_by_last_locked_time_ms, m_sync_blocks_time_ms, new_block_hashes, tree_extension, new_leaf_tuples_per_block);
});
for (size_t i = 0; i < blocks.size(); ++i)
@ -3756,9 +3756,9 @@ void wallet2::pull_and_parse_next_blocks(bool first, bool try_incremental, uint6
const crypto::hash &init_block_hash = init_tree_sync_data->init_block_hash;
MINFO("Initializing wallet tree at block " << init_block_idx << " with block hash " << init_block_hash);
fcmp_pp::curve_trees::OutputsByUnlockBlock locked_outputs;
fcmp_pp::curve_trees::OutputsByLastLockedBlock locked_outputs;
for (auto &lo : init_tree_sync_data->locked_outputs)
locked_outputs[lo.unlock_block] = std::move(lo.outputs);
locked_outputs[lo.last_locked_block] = std::move(lo.outputs);
m_tree_cache.init(init_block_idx, init_block_hash, init_tree_sync_data->n_leaf_tuples, init_tree_sync_data->last_path, locked_outputs);
}

View File

@ -1950,7 +1950,7 @@ private:
std::unordered_map<crypto::public_key, crypto::key_image> m_cold_key_images;
uint64_t m_sync_blocks_time_ms;
uint64_t m_outs_by_unlock_time_ms;
uint64_t m_outs_by_last_locked_time_ms;
std::atomic<bool> m_run;

View File

@ -65,8 +65,8 @@ public:
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& blk_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
) override {
blocks.push_back({block_weight, long_term_block_weight});
}

View File

@ -88,8 +88,8 @@ namespace
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& blk_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
) override
{
blocks.push_back({blk, blk_hash});

View File

@ -55,8 +55,8 @@ public:
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& blk_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
) override {
blocks.push_back(blk);
}

View File

@ -58,8 +58,8 @@ public:
, const uint64_t& coins_generated
, uint64_t num_rct_outs
, const crypto::hash& blk_hash
, const fcmp_pp::curve_trees::OutputsByUnlockBlock& outs_by_unlock_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*unlock block_id*/>& timelocked_outputs
, const fcmp_pp::curve_trees::OutputsByLastLockedBlock& outs_by_last_locked_block
, const std::unordered_map<uint64_t/*output_id*/, uint64_t/*last locked block_id*/>& timelocked_outputs
) override {
blocks.push_back({block_weight, long_term_block_weight});
}

View File

@ -63,14 +63,14 @@ TEST(tree_cache, register_output)
CHECK_AND_ASSERT_THROW_MES(outputs.size() == INIT_LEAVES, "unexpected size of outputs");
// Mock values
const uint64_t unlock_block_idx = 1;
const uint64_t last_locked_block_idx = 1;
const auto output = outputs[0].output_pair;
// 2. Register output - valid
ASSERT_TRUE(tree_cache->register_output(output, unlock_block_idx));
ASSERT_TRUE(tree_cache->register_output(output, last_locked_block_idx));
// 3. Register same output again - already registered
ASSERT_FALSE(tree_cache->register_output(output, unlock_block_idx));
ASSERT_FALSE(tree_cache->register_output(output, last_locked_block_idx));
// 4. Register another output with the same output pubkey as existing, different commitment - valid
auto output_new_commitment = output;
@ -79,21 +79,21 @@ TEST(tree_cache, register_output)
ASSERT_EQ(output_new_commitment.output_pubkey, output.output_pubkey);
ASSERT_NE(output_new_commitment.commitment, output.commitment);
ASSERT_TRUE(tree_cache->register_output(output_new_commitment, unlock_block_idx));
ASSERT_TRUE(tree_cache->register_output(output_new_commitment, last_locked_block_idx));
// 5. Sync the block of outputs
crypto::hash block_hash{0x01};
crypto::hash prev_block_hash{};
tree_cache->sync_block(0, block_hash, prev_block_hash, {{ unlock_block_idx, outputs }});
tree_cache->sync_block(0, block_hash, prev_block_hash, {{ last_locked_block_idx, outputs }});
// 6. Sync 1 more block so the outputs unlock and enter the tree
prev_block_hash = block_hash;
block_hash = crypto::hash{0x02};
tree_cache->sync_block(unlock_block_idx, block_hash, prev_block_hash, {});
tree_cache->sync_block(last_locked_block_idx, block_hash, prev_block_hash, {});
// 7. Register a new output where we already synced the block output unlocks in - invalid
const auto &new_output = test::generate_random_outputs(*curve_trees, INIT_LEAVES, 1).front().output_pair;
ASSERT_FALSE(tree_cache->register_output(new_output, unlock_block_idx));
ASSERT_FALSE(tree_cache->register_output(new_output, last_locked_block_idx));
}
//----------------------------------------------------------------------------------------------------------------------
TEST(tree_cache, sync_block_simple)
@ -108,21 +108,21 @@ TEST(tree_cache, sync_block_simple)
CHECK_AND_ASSERT_THROW_MES(outputs.size() == INIT_LEAVES, "unexpected size of outputs");
// Mock values
const uint64_t unlock_block_idx = 1;
const uint64_t last_locked_block_idx = 1;
const auto output = outputs[0].output_pair;
// 2. Register output
ASSERT_TRUE(tree_cache->register_output(output, unlock_block_idx));
ASSERT_TRUE(tree_cache->register_output(output, last_locked_block_idx));
// 3. Sync the block of outputs
crypto::hash block_hash{0x01};
crypto::hash prev_block_hash{};
tree_cache->sync_block(0, block_hash, prev_block_hash, {{ unlock_block_idx, outputs }});
tree_cache->sync_block(0, block_hash, prev_block_hash, {{ last_locked_block_idx, outputs }});
// 4. Sync 1 more block so the outputs unlock and enter the tree
prev_block_hash = block_hash;
block_hash = crypto::hash{0x02};
tree_cache->sync_block(unlock_block_idx, block_hash, prev_block_hash, {});
tree_cache->sync_block(last_locked_block_idx, block_hash, prev_block_hash, {});
// 5. Get the output's path in the tree
CurveTreesV1::Path output_path;
@ -152,36 +152,36 @@ TEST(tree_cache, sync_n_chunks_of_blocks)
// 2. Make chunks of blocks
std::vector<std::vector<crypto::hash>> chunks_of_block_hashes;
std::vector<std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock>> chunks_of_outputs;
std::vector<std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock>> chunks_of_outputs;
std::size_t leaf_count = 0;
uint64_t unlock_block_idx = 0;
uint64_t last_locked_block_idx = 0;
fcmp_pp::curve_trees::OutputPair output;
for (std::size_t i = 0; i < N_CHUNKS; ++i)
{
std::vector<crypto::hash> block_hashes;
std::vector<fcmp_pp::curve_trees::OutputsByUnlockBlock> outs;
std::vector<fcmp_pp::curve_trees::OutputsByLastLockedBlock> outs;
for (std::size_t j = 0; j < N_BLOCKS_PER_CHUNK; ++j)
{
auto outputs = test::generate_random_outputs(*curve_trees, leaf_count, INIT_LEAVES);
leaf_count += INIT_LEAVES;
const auto unlock_block = 1 + i * N_BLOCKS_PER_CHUNK + j;
const auto last_locked_block = 1 + i * N_BLOCKS_PER_CHUNK + j;
if (i == rand_chunk && j == rand_block)
{
unlock_block_idx = unlock_block;
last_locked_block_idx = last_locked_block;
output = outputs[rand_leaf].output_pair;
}
outs.push_back({{ unlock_block, std::move(outputs) }});
outs.push_back({{ last_locked_block, std::move(outputs) }});
block_hashes.push_back(mock_block_hash);
}
chunks_of_block_hashes.push_back(std::move(block_hashes));
chunks_of_outputs.push_back(std::move(outs));
}
ASSERT_TRUE(unlock_block_idx > 0);
ASSERT_TRUE(last_locked_block_idx > 0);
// 3. Register output
ASSERT_TRUE(tree_cache->register_output(output, unlock_block_idx));
ASSERT_TRUE(tree_cache->register_output(output, last_locked_block_idx));
// 4. Sync the chunks of blocks
for (std::size_t i = 0; i < N_CHUNKS; ++i)
@ -250,13 +250,13 @@ TEST(tree_cache, sync_n_blocks_register_n_outputs)
MDEBUG("Registering output " << n_outputs + output_to_register);
// Register the output
const uint64_t unlock_block_idx = block_idx + 1;
ASSERT_TRUE(tree_cache->register_output(output, unlock_block_idx));
const uint64_t last_locked_block_idx = block_idx + 1;
ASSERT_TRUE(tree_cache->register_output(output, last_locked_block_idx));
// Sync the outputs generated above
crypto::hash block_hash;
crypto::cn_fast_hash(&block_idx, sizeof(std::size_t), block_hash);
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ unlock_block_idx, outputs }});
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ last_locked_block_idx, outputs }});
n_unlocked_outputs = n_outputs;
n_outputs += sync_n_outputs;
@ -320,7 +320,7 @@ TEST(tree_cache, sync_n_blocks_register_one_output)
CHECK_AND_ASSERT_THROW_MES(outputs.size() == sync_n_outputs, "unexpected size of outputs");
// Check if this chunk includes the output we're supposed to register
const uint64_t unlock_block_idx = block_idx + 1;
const uint64_t last_locked_block_idx = block_idx + 1;
bool just_registered = n_outputs <= i && i < (n_outputs + sync_n_outputs);
if (just_registered)
{
@ -330,7 +330,7 @@ TEST(tree_cache, sync_n_blocks_register_one_output)
auto output_to_register = i - n_outputs;
const auto output = outputs[output_to_register].output_pair;
ASSERT_TRUE(tree_cache->register_output(output, unlock_block_idx));
ASSERT_TRUE(tree_cache->register_output(output, last_locked_block_idx));
registered = true;
registered_output = output;
@ -339,7 +339,7 @@ TEST(tree_cache, sync_n_blocks_register_one_output)
// Sync the outputs generated above
crypto::hash block_hash;
crypto::cn_fast_hash(&block_idx, sizeof(uint64_t), block_hash);
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ unlock_block_idx, outputs }});
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ last_locked_block_idx, outputs }});
n_unlocked_outputs = n_outputs;
n_outputs += sync_n_outputs;
@ -408,7 +408,7 @@ TEST(tree_cache, sync_past_max_reorg_depth)
CHECK_AND_ASSERT_THROW_MES(outputs.size() == sync_n_outputs, "unexpected size of outputs");
// Check if this chunk includes the output we're supposed to register
const uint64_t unlock_block_idx = block_idx + 1;
const uint64_t last_locked_block_idx = block_idx + 1;
const bool just_registered = n_outputs <= i && i < (n_outputs + sync_n_outputs);
if (just_registered)
{
@ -426,7 +426,7 @@ TEST(tree_cache, sync_past_max_reorg_depth)
// Sync the outputs generated above
crypto::hash block_hash;
crypto::cn_fast_hash(&block_idx, sizeof(uint64_t), block_hash);
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ unlock_block_idx, outputs }});
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ last_locked_block_idx, outputs }});
n_unlocked_outputs = n_outputs;
n_outputs += sync_n_outputs;
@ -472,8 +472,8 @@ TEST(tree_cache, reorg_after_register)
fcmp_pp::curve_trees::OutputPair registered_output;
bool registered = false;
uint64_t unlocked_block_idx = 0;
crypto::hash unlocked_block_hash;
uint64_t last_locked_block_idx = 0;
crypto::hash last_locked_block_hash;
crypto::hash prev_block_hash = crypto::hash{};
@ -484,18 +484,18 @@ TEST(tree_cache, reorg_after_register)
std::vector<uint64_t> n_outputs_synced_by_block;
while (n_unlocked_outputs < n_leaves_needed)
{
if (registered && block_idx > (unlocked_block_idx + 1))
if (registered && block_idx > (last_locked_block_idx + 1))
{
uint64_t cur_block_idx = block_idx;
ASSERT_EQ(n_outputs_synced_by_block.size(), block_idx);
LOG_PRINT_L1("Popping blocks back to block " << unlocked_block_idx + 1 << " , then re-syncing");
LOG_PRINT_L1("Popping blocks back to block " << last_locked_block_idx + 1 << " , then re-syncing");
auto n_outputs_unlocked = [&n_outputs_synced_by_block](uint64_t blk_idx) -> uint64_t
{ return blk_idx < 2 ? 0 : n_outputs_synced_by_block[blk_idx - 2]; };
// Pop blocks until the included block is the top block
while (cur_block_idx > (unlocked_block_idx + 1))
while (cur_block_idx > (last_locked_block_idx + 1))
{
ASSERT_TRUE(tree_cache->pop_block());
--cur_block_idx;
@ -509,7 +509,7 @@ TEST(tree_cache, reorg_after_register)
}
// Sync back up again until cur_block_idx == block_idx
prev_block_hash = unlocked_block_hash;
prev_block_hash = last_locked_block_hash;
while (cur_block_idx < block_idx)
{
const auto sync_n_outputs = (cur_block_idx % max_outputs_per_block) + 1;
@ -522,11 +522,10 @@ TEST(tree_cache, reorg_after_register)
// Sync the outputs generated above
crypto::hash block_hash;
crypto::cn_fast_hash(&cur_block_idx, sizeof(uint64_t), block_hash);
const uint64_t unlock_block_idx = cur_block_idx + 1;
tree_cache->sync_block(cur_block_idx,
block_hash,
prev_block_hash,
{{ unlock_block_idx, outputs }});
{{ cur_block_idx + 1, outputs }});
++cur_block_idx;
CurveTreesV1::Path output_path;
@ -550,7 +549,6 @@ TEST(tree_cache, reorg_after_register)
// Check if this chunk includes the output we're supposed to register
const bool just_registered = n_outputs <= i && i < (n_outputs + sync_n_outputs);
const uint64_t unlock_block_idx = block_idx + 1;
if (just_registered)
{
ASSERT_FALSE(registered);
@ -562,17 +560,17 @@ TEST(tree_cache, reorg_after_register)
registered = true;
registered_output = output;
unlocked_block_idx = unlock_block_idx;
last_locked_block_idx = block_idx + 1;
}
if (registered && block_idx == unlocked_block_idx)
unlocked_block_hash = block_hash;
if (registered && block_idx == last_locked_block_idx)
last_locked_block_hash = block_hash;
// Sync the outputs generated above
tree_cache->sync_block(block_idx,
block_hash,
prev_block_hash,
{{ unlock_block_idx, outputs }});
{{ block_idx + 1, outputs }});
n_unlocked_outputs = n_outputs;
n_outputs += sync_n_outputs;
@ -622,11 +620,11 @@ TEST(tree_cache, register_after_reorg)
crypto::cn_fast_hash(&block_idx, sizeof(uint64_t), block_hash);
// Sync the outputs generated above
const uint64_t unlock_block_idx = block_idx + 1;
const uint64_t last_locked_block_idx = block_idx + 1;
tree_cache->sync_block(block_idx,
block_hash,
block_hashes.empty() ? crypto::hash{} : block_hashes.back(),
{{ unlock_block_idx, outputs }});
{{ last_locked_block_idx, outputs }});
n_unlocked_outputs = n_outputs;
n_outputs += sync_n_outputs;
@ -660,11 +658,11 @@ TEST(tree_cache, register_after_reorg)
crypto::cn_fast_hash(&block_idx, sizeof(uint64_t), block_hash);
// Sync the output generated above
const uint64_t unlock_block_idx = block_idx + 1;
const uint64_t last_locked_block_idx = block_idx + 1;
tree_cache->sync_block(block_idx,
block_hash,
block_hashes.empty() ? crypto::hash{} : block_hashes.back(),
{{ unlock_block_idx, outputs }});
{{ last_locked_block_idx, outputs }});
block_hashes.push_back(block_hash);
n_unlocked_outputs = n_outputs;
@ -674,8 +672,8 @@ TEST(tree_cache, register_after_reorg)
ASSERT_TRUE(output_path.leaves.empty() && output_path.c1_layers.empty() && output_path.c2_layers.empty());
// Sync 1 more block so the output unlocks and enters the tree
crypto::cn_fast_hash(&unlock_block_idx, sizeof(uint64_t), block_hash);
tree_cache->sync_block(unlock_block_idx, block_hash, block_hashes.back(), {});
crypto::cn_fast_hash(&last_locked_block_idx, sizeof(uint64_t), block_hash);
tree_cache->sync_block(last_locked_block_idx, block_hash, block_hashes.back(), {});
n_unlocked_outputs += outputs.size();
ASSERT_TRUE(tree_cache->get_output_path(output, output_path));
@ -692,13 +690,13 @@ TEST(tree_cache, serialization)
CHECK_AND_ASSERT_THROW_MES(outputs.size() == INIT_LEAVES, "unexpected size of outputs");
const uint64_t block_idx = 0;
const uint64_t unlock_block_idx = 1;
const uint64_t last_locked_block_idx = 1;
const auto output = outputs[0].output_pair;
ASSERT_TRUE(tree_cache->register_output(output, unlock_block_idx));
ASSERT_TRUE(tree_cache->register_output(output, last_locked_block_idx));
crypto::hash block_hash{0x01};
crypto::hash prev_block_hash{};
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ unlock_block_idx, outputs }});
tree_cache->sync_block(block_idx, block_hash, prev_block_hash, {{ last_locked_block_idx, outputs }});
// 2. Serialize the tree_cache object
std::string blob;
@ -716,8 +714,8 @@ TEST(tree_cache, serialization)
// 5. Sync 1 more block in tree_cache and tree_cache2 so the init outputs unlock and enter the trees
prev_block_hash = block_hash;
block_hash = crypto::hash{0x02};
tree_cache->sync_block(unlock_block_idx, block_hash, prev_block_hash, {});
tree_cache2.sync_block(unlock_block_idx, block_hash, prev_block_hash, {});
tree_cache->sync_block(last_locked_block_idx, block_hash, prev_block_hash, {});
tree_cache2.sync_block(last_locked_block_idx, block_hash, prev_block_hash, {});
// 6. Make sure output's path is the same across both tree_cache and tree_cache2
CurveTreesV1::Path output_path;