mirror of
https://github.com/monero-project/monero.git
synced 2025-01-07 10:27:55 -05:00
Store {O,C} for each leaf tuple instead of {O.x,I.x,C.x}
- Can derive {O.x,I.x,C.x} from {O,C} - Note: this slows down tests since they do the derivation both on insertion into the tree, and when auditing the tree - At the hard fork, we don't need to store {O,C} in the output_amounts table anymore since that table will no longer be useful
This commit is contained in:
parent
34eafa85f3
commit
b90cee8bab
@ -231,7 +231,7 @@ std::vector<uint64_t> BlockchainDB::add_transaction(const crypto::hash& blk_hash
|
||||
{
|
||||
// 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: tx_outs_to_leaf_tuples in curve_trees.cpp mirrors this logic
|
||||
// note: tx_outs_to_leaf_tuple_contexts in curve_trees.cpp mirrors this logic
|
||||
if (miner_tx && tx.version == 2)
|
||||
{
|
||||
cryptonote::tx_out vout = tx.vout[i];
|
||||
@ -314,11 +314,11 @@ 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
|
||||
// the block to a table keeping track of locked leaf tuples. Once those leaf
|
||||
// tuples unlock, we use them to grow the tree.
|
||||
std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext> leaf_tuples_by_unlock_block;
|
||||
std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext> leaf_tuples_by_unlock_block;
|
||||
|
||||
// Get miner tx's leaf tuples
|
||||
CHECK_AND_ASSERT_THROW_MES(m_curve_trees != nullptr, "curve trees must be set");
|
||||
m_curve_trees->tx_outs_to_leaf_tuples(
|
||||
m_curve_trees->tx_outs_to_leaf_tuple_contexts(
|
||||
blk.miner_tx,
|
||||
miner_output_ids,
|
||||
prev_height,
|
||||
@ -328,7 +328,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
// Get all other txs' leaf tuples
|
||||
for (std::size_t i = 0; i < txs.size(); ++i)
|
||||
{
|
||||
m_curve_trees->tx_outs_to_leaf_tuples(
|
||||
m_curve_trees->tx_outs_to_leaf_tuple_contexts(
|
||||
txs[i].first,
|
||||
output_ids[i],
|
||||
prev_height,
|
||||
|
@ -417,7 +417,7 @@ private:
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
@ -1782,7 +1782,7 @@ public:
|
||||
virtual bool for_all_alt_blocks(std::function<bool(const crypto::hash &blkid, const alt_block_data_t &data, const cryptonote::blobdata_ref *blob)> f, bool include_blob = false) const = 0;
|
||||
|
||||
// TODO: description and make private
|
||||
virtual void grow_tree(std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &&new_leaves) = 0;
|
||||
virtual void grow_tree(std::vector<fcmp::curve_trees::LeafTupleContext> &&new_leaves) = 0;
|
||||
|
||||
virtual void trim_tree(const uint64_t trim_n_leaf_tuples) = 0;
|
||||
|
||||
|
@ -216,7 +216,6 @@ namespace
|
||||
*
|
||||
* spent_keys input hash -
|
||||
*
|
||||
* TODO: don't store leaf tuples, store reference to outputs
|
||||
* locked_leaves block ID [{output ID, leaf tuple}...]
|
||||
* leaves leaf_idx {leaf tuple}
|
||||
* layers layer_idx [{child_chunk_idx, child_chunk_hash}...]
|
||||
@ -816,7 +815,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 std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &leaf_tuples_by_unlock_block)
|
||||
uint64_t num_rct_outs, const crypto::hash& blk_hash, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext> &leaf_tuples_by_unlock_block)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
check_open();
|
||||
@ -845,8 +844,8 @@ 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
|
||||
auto unlocked_leaf_tuples = this->get_leaf_tuples_at_unlock_block_id(m_height);
|
||||
this->grow_tree(std::move(unlocked_leaf_tuples));
|
||||
auto unlocked_leaves = this->get_leaf_tuples_at_unlock_block_id(m_height);
|
||||
this->grow_tree(std::move(unlocked_leaves));
|
||||
|
||||
// Now that we've used the unlocked leaves to grow the tree, we can delete them from the locked leaves table
|
||||
this->del_locked_leaf_tuples_at_block_id(m_height);
|
||||
@ -1362,7 +1361,7 @@ void BlockchainLMDB::remove_spent_key(const crypto::key_image& k_image)
|
||||
}
|
||||
}
|
||||
|
||||
void BlockchainLMDB::grow_tree(std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &&new_leaves)
|
||||
void BlockchainLMDB::grow_tree(std::vector<fcmp::curve_trees::LeafTupleContext> &&new_leaves)
|
||||
{
|
||||
if (new_leaves.empty())
|
||||
return;
|
||||
@ -1815,6 +1814,8 @@ fcmp::curve_trees::CurveTreesV1::LastChunkChildrenToTrim BlockchainLMDB::get_las
|
||||
|
||||
if (trim_leaf_layer_instructions.end_trim_idx > trim_leaf_layer_instructions.start_trim_idx)
|
||||
{
|
||||
leaves_to_trim.reserve(trim_leaf_layer_instructions.end_trim_idx - trim_leaf_layer_instructions.start_trim_idx);
|
||||
|
||||
uint64_t idx = trim_leaf_layer_instructions.start_trim_idx;
|
||||
CHECK_AND_ASSERT_THROW_MES(idx % fcmp::curve_trees::CurveTreesV1::LEAF_TUPLE_SIZE == 0,
|
||||
"expected divisble by leaf tuple size");
|
||||
@ -1833,11 +1834,14 @@ fcmp::curve_trees::CurveTreesV1::LastChunkChildrenToTrim BlockchainLMDB::get_las
|
||||
if (result != MDB_SUCCESS)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to get leaf: ", result).c_str()));
|
||||
|
||||
const auto leaf = *(fcmp::curve_trees::CurveTreesV1::LeafTuple *)v.mv_data;
|
||||
const auto preprocessed_leaf_tuple = *(fcmp::curve_trees::PreprocessedLeafTuple *)v.mv_data;
|
||||
|
||||
leaves_to_trim.push_back(leaf.O_x);
|
||||
leaves_to_trim.push_back(leaf.I_x);
|
||||
leaves_to_trim.push_back(leaf.C_x);
|
||||
// TODO: parallelize calls to this function
|
||||
auto leaf = m_curve_trees->leaf_tuple(preprocessed_leaf_tuple);
|
||||
|
||||
leaves_to_trim.emplace_back(std::move(leaf.O_x));
|
||||
leaves_to_trim.emplace_back(std::move(leaf.I_x));
|
||||
leaves_to_trim.emplace_back(std::move(leaf.C_x));
|
||||
|
||||
idx += fcmp::curve_trees::CurveTreesV1::LEAF_TUPLE_SIZE;
|
||||
}
|
||||
@ -2002,8 +2006,10 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const
|
||||
if (result != MDB_SUCCESS)
|
||||
throw0(DB_ERROR(lmdb_error("Failed to add leaf: ", result).c_str()));
|
||||
|
||||
const auto leaf = *(fcmp::curve_trees::CurveTreesV1::LeafTuple *)v.mv_data;
|
||||
leaf_tuples_chunk.push_back(leaf);
|
||||
const auto preprocessed_leaf_tuple = *(fcmp::curve_trees::PreprocessedLeafTuple *)v.mv_data;
|
||||
auto leaf = m_curve_trees->leaf_tuple(preprocessed_leaf_tuple);
|
||||
|
||||
leaf_tuples_chunk.emplace_back(std::move(leaf));
|
||||
|
||||
if (leaf_tuples_chunk.size() == m_curve_trees->m_c2_width)
|
||||
break;
|
||||
@ -2205,7 +2211,7 @@ bool BlockchainLMDB::audit_layer(const C_CHILD &c_child,
|
||||
chunk_width);
|
||||
}
|
||||
|
||||
std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> BlockchainLMDB::get_leaf_tuples_at_unlock_block_id(
|
||||
std::vector<fcmp::curve_trees::LeafTupleContext> BlockchainLMDB::get_leaf_tuples_at_unlock_block_id(
|
||||
uint64_t block_id)
|
||||
{
|
||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||
@ -2218,7 +2224,7 @@ std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> BlockchainLMDB::g
|
||||
MDB_val v_tuple;
|
||||
|
||||
// Get all the locked outputs at the provided block id
|
||||
std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> leaf_tuples;
|
||||
std::vector<fcmp::curve_trees::LeafTupleContext> leaf_tuples;
|
||||
|
||||
MDB_cursor_op op = MDB_SET;
|
||||
while (1)
|
||||
@ -2234,8 +2240,8 @@ std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> BlockchainLMDB::g
|
||||
if (blk_id != block_id)
|
||||
throw0(DB_ERROR(("Blk id " + std::to_string(blk_id) + " not the expected" + std::to_string(block_id)).c_str()));
|
||||
|
||||
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::LeafTupleContext);
|
||||
const auto range_begin = ((const fcmp::curve_trees::LeafTupleContext*)v_tuple.mv_data);
|
||||
const auto range_end = range_begin + v_tuple.mv_size / sizeof(fcmp::curve_trees::LeafTupleContext);
|
||||
|
||||
auto it = range_begin;
|
||||
|
||||
@ -6772,25 +6778,27 @@ void BlockchainLMDB::migrate_5_6()
|
||||
// Read the output data
|
||||
uint64_t amount = *(const uint64_t*)k.mv_data;
|
||||
output_data_t output_data;
|
||||
fcmp::curve_trees::CurveTreesV1::LeafTupleContext tuple_context;
|
||||
uint64_t output_id;
|
||||
if (amount == 0)
|
||||
{
|
||||
const outkey *okp = (const outkey *)v.mv_data;
|
||||
output_data = okp->data;
|
||||
tuple_context.output_id = okp->output_id;
|
||||
output_id = okp->output_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
const pre_rct_outkey *okp = (const pre_rct_outkey *)v.mv_data;
|
||||
memcpy(&output_data, &okp->data, sizeof(pre_rct_output_data_t));
|
||||
output_data.commitment = rct::zeroCommit(amount);
|
||||
tuple_context.output_id = okp->output_id;
|
||||
output_id = okp->output_id;
|
||||
}
|
||||
|
||||
// Convert the output into a leaf tuple
|
||||
// Convert the output into a leaf tuple context
|
||||
fcmp::curve_trees::LeafTupleContext tuple_context;
|
||||
try
|
||||
{
|
||||
tuple_context.leaf_tuple = m_curve_trees->output_to_leaf_tuple(
|
||||
tuple_context = m_curve_trees->output_to_leaf_context(
|
||||
output_id,
|
||||
output_data.pubkey,
|
||||
rct::rct2pk(output_data.commitment));
|
||||
}
|
||||
@ -6890,8 +6898,8 @@ void BlockchainLMDB::migrate_5_6()
|
||||
}
|
||||
|
||||
// Get the leaf tuples that unlock at the given block
|
||||
auto unlocked_leaf_tuples = this->get_leaf_tuples_at_unlock_block_id(i);
|
||||
this->grow_tree(std::move(unlocked_leaf_tuples));
|
||||
auto unlocked_leaves = this->get_leaf_tuples_at_unlock_block_id(i);
|
||||
this->grow_tree(std::move(unlocked_leaves));
|
||||
|
||||
// Now that we've used the unlocked leaves to grow the tree, we can delete them from the locked leaves table
|
||||
this->del_locked_leaf_tuples_at_block_id(i);
|
||||
|
@ -368,7 +368,7 @@ public:
|
||||
static int compare_string(const MDB_val *a, const MDB_val *b);
|
||||
|
||||
// make private
|
||||
virtual void grow_tree(std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &&new_leaves);
|
||||
virtual void grow_tree(std::vector<fcmp::curve_trees::LeafTupleContext> &&new_leaves);
|
||||
|
||||
virtual void trim_tree(const uint64_t trim_n_leaf_tuples);
|
||||
|
||||
@ -388,7 +388,7 @@ private:
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& block_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
);
|
||||
|
||||
virtual void remove_block();
|
||||
@ -449,7 +449,7 @@ private:
|
||||
const uint64_t child_chunk_idx,
|
||||
const uint64_t chunk_width) const;
|
||||
|
||||
std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> get_leaf_tuples_at_unlock_block_id(uint64_t block_id);
|
||||
std::vector<fcmp::curve_trees::LeafTupleContext> get_leaf_tuples_at_unlock_block_id(uint64_t block_id);
|
||||
|
||||
void del_locked_leaf_tuples_at_block_id(uint64_t block_id);
|
||||
|
||||
|
@ -116,7 +116,7 @@ public:
|
||||
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 remove_spent_key(const crypto::key_image& k_image) override {}
|
||||
virtual void grow_tree(std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> &&new_leaves) override {};
|
||||
virtual void grow_tree(std::vector<fcmp::curve_trees::LeafTupleContext> &&new_leaves) override {};
|
||||
virtual void trim_tree(const uint64_t trim_n_leaf_tuples) override {};
|
||||
virtual bool audit_tree(const uint64_t expected_n_leaf_tuples) const override { return false; };
|
||||
|
||||
@ -147,7 +147,7 @@ public:
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
) 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 {}
|
||||
|
@ -153,6 +153,7 @@ static LayerExtension<C> hash_children_chunks(const C &curve,
|
||||
std::size_t chunk_start_idx = chunk_size;
|
||||
while (chunk_start_idx < new_child_scalars.size())
|
||||
{
|
||||
// TODO: this loop can be parallelized
|
||||
chunk_size = std::min(chunk_width, new_child_scalars.size() - chunk_start_idx);
|
||||
|
||||
const auto chunk_start = new_child_scalars.data() + chunk_start_idx;
|
||||
@ -626,7 +627,8 @@ static typename fcmp::curve_trees::LayerReduction<C_PARENT> get_next_layer_reduc
|
||||
// CurveTrees public member functions
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
template<>
|
||||
CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::output_to_leaf_tuple(
|
||||
LeafTupleContext CurveTrees<Helios, Selene>::output_to_leaf_context(
|
||||
const std::uint64_t output_id,
|
||||
const crypto::public_key &output_pubkey,
|
||||
const crypto::public_key &commitment) const
|
||||
{
|
||||
@ -646,11 +648,26 @@ CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::output_to_leaf
|
||||
};
|
||||
|
||||
// Torsion clear the output pub key and commitment
|
||||
const rct::key rct_O = clear_torsion(output_pubkey, "output pub key");
|
||||
const rct::key rct_C = clear_torsion(commitment, "commitment");
|
||||
rct::key O = clear_torsion(output_pubkey, "output pub key");
|
||||
rct::key C = clear_torsion(commitment, "commitment");
|
||||
|
||||
const crypto::public_key &O = rct::rct2pk(rct_O);
|
||||
const crypto::public_key &C = rct::rct2pk(rct_C);
|
||||
PreprocessedLeafTuple o_c{
|
||||
.O = std::move(O),
|
||||
.C = std::move(C)
|
||||
};
|
||||
|
||||
return LeafTupleContext{
|
||||
.output_id = output_id,
|
||||
.preprocessed_leaf_tuple = std::move(o_c)
|
||||
};
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
template<>
|
||||
CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::leaf_tuple(
|
||||
const PreprocessedLeafTuple &preprocessed_leaf_tuple) const
|
||||
{
|
||||
const crypto::public_key &O = rct::rct2pk(preprocessed_leaf_tuple.O);
|
||||
const crypto::public_key &C = rct::rct2pk(preprocessed_leaf_tuple.C);
|
||||
|
||||
crypto::ec_point I;
|
||||
crypto::derive_key_image_generator(O, I);
|
||||
@ -680,11 +697,11 @@ std::vector<typename C2::Scalar> CurveTrees<C1, C2>::flatten_leaves(const std::v
|
||||
};
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
template <>
|
||||
void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transaction &tx,
|
||||
void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuple_contexts(const cryptonote::transaction &tx,
|
||||
const std::vector<uint64_t> &output_ids,
|
||||
const uint64_t tx_height,
|
||||
const bool miner_tx,
|
||||
std::multimap<uint64_t, CurveTrees<Helios, Selene>::LeafTupleContext> &leaf_tuples_by_unlock_block_inout) const
|
||||
std::multimap<uint64_t, LeafTupleContext> &leaf_tuples_by_unlock_block_inout) const
|
||||
{
|
||||
const uint64_t unlock_block = cryptonote::get_unlock_block_index(tx.unlock_time, tx_height);
|
||||
|
||||
@ -692,6 +709,7 @@ void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transa
|
||||
|
||||
for (std::size_t i = 0; i < tx.vout.size(); ++i)
|
||||
{
|
||||
// TODO: this loop can be parallelized
|
||||
const auto &out = tx.vout[i];
|
||||
|
||||
crypto::public_key output_public_key;
|
||||
@ -708,13 +726,11 @@ void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transa
|
||||
? rct::zeroCommit(out.amount)
|
||||
: tx.rct_signatures.outPk[i].mask;
|
||||
|
||||
CurveTrees<Helios, Selene>::LeafTupleContext tuple_context;
|
||||
tuple_context.output_id = output_ids[i];
|
||||
|
||||
LeafTupleContext leaf_tuple_context;
|
||||
try
|
||||
{
|
||||
// Convert output to leaf tuple; throws if output is invalid
|
||||
tuple_context.leaf_tuple = output_to_leaf_tuple(
|
||||
// Convert output to leaf tuple context; throws if output is invalid
|
||||
leaf_tuple_context = output_to_leaf_context(output_ids[i],
|
||||
output_public_key,
|
||||
rct::rct2pk(commitment));
|
||||
}
|
||||
@ -724,7 +740,7 @@ void CurveTrees<Helios, Selene>::tx_outs_to_leaf_tuples(const cryptonote::transa
|
||||
continue;
|
||||
};
|
||||
|
||||
leaf_tuples_by_unlock_block_inout.emplace(unlock_block, std::move(tuple_context));
|
||||
leaf_tuples_by_unlock_block_inout.emplace(unlock_block, std::move(leaf_tuple_context));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
@ -751,16 +767,25 @@ typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extensio
|
||||
const auto sort_fn = [](const LeafTupleContext &a, const LeafTupleContext &b) { return a.output_id < b.output_id; };
|
||||
std::sort(new_leaf_tuples.begin(), new_leaf_tuples.end(), sort_fn);
|
||||
|
||||
// Copy the sorted leaves into the tree extension struct
|
||||
// TODO: don't copy here
|
||||
// Convert sorted pre-processed tuples into leaf tuples, place each element of each leaf tuple in a flat vector to
|
||||
// be hashed, and place the pre-processed tuples in tree extension struct for insertion into the db
|
||||
std::vector<typename C2::Scalar> flattened_leaves;
|
||||
flattened_leaves.reserve(new_leaf_tuples.size() * LEAF_TUPLE_SIZE);
|
||||
tree_extension.leaves.tuples.reserve(new_leaf_tuples.size());
|
||||
for (const auto &leaf : new_leaf_tuples)
|
||||
for (auto &l : new_leaf_tuples)
|
||||
{
|
||||
tree_extension.leaves.tuples.emplace_back(LeafTuple{
|
||||
.O_x = leaf.leaf_tuple.O_x,
|
||||
.I_x = leaf.leaf_tuple.I_x,
|
||||
.C_x = leaf.leaf_tuple.C_x
|
||||
});
|
||||
// TODO: this loop can be parallelized
|
||||
auto leaf = leaf_tuple(l.preprocessed_leaf_tuple);
|
||||
|
||||
flattened_leaves.emplace_back(std::move(leaf.O_x));
|
||||
flattened_leaves.emplace_back(std::move(leaf.I_x));
|
||||
flattened_leaves.emplace_back(std::move(leaf.C_x));
|
||||
|
||||
// We only need to store O and C in the db, the leaf tuple can be derived from O and C
|
||||
tree_extension.leaves.tuples.emplace_back(PreprocessedLeafTuple{
|
||||
.O = std::move(l.preprocessed_leaf_tuple.O),
|
||||
.C = std::move(l.preprocessed_leaf_tuple.C)
|
||||
});
|
||||
}
|
||||
|
||||
if (grow_layer_instructions.need_old_last_parent)
|
||||
@ -772,7 +797,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.start_offset,
|
||||
grow_layer_instructions.next_parent_start_index,
|
||||
this->flatten_leaves(tree_extension.leaves.tuples),
|
||||
flattened_leaves,
|
||||
m_leaf_layer_chunk_width
|
||||
);
|
||||
|
||||
@ -865,6 +890,7 @@ typename CurveTrees<C1, C2>::TreeReduction CurveTrees<C1, C2>::get_tree_reductio
|
||||
{
|
||||
TreeReduction tree_reduction_out;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(!trim_instructions.empty(), "missing trim instructions");
|
||||
CHECK_AND_ASSERT_THROW_MES((trim_instructions[0].new_total_children % LEAF_TUPLE_SIZE) == 0,
|
||||
"unexpected new total leaves");
|
||||
const uint64_t new_total_leaf_tuples = trim_instructions[0].new_total_children / LEAF_TUPLE_SIZE;
|
||||
|
@ -128,9 +128,27 @@ struct TrimLayerInstructions final
|
||||
uint64_t end_trim_idx;
|
||||
};
|
||||
|
||||
// Output pub key and commitment, ready to be converted into a leaf tuple (from {O,C} -> {O.x, I.x, C.x})
|
||||
struct PreprocessedLeafTuple final
|
||||
{
|
||||
// Output pubkey that has been checked valid and torsion cleared
|
||||
rct::key O;
|
||||
// Commitment that has been torsion cleared
|
||||
rct::key C;
|
||||
};
|
||||
static_assert(sizeof(PreprocessedLeafTuple) == (32+32), "db expects 64 bytes for pre-processed leaf tuples");
|
||||
|
||||
// Contextual wrapper for a pre-processed leaf tuple
|
||||
struct LeafTupleContext final
|
||||
{
|
||||
// Global output ID useful to order the leaf tuple for insertion into the tree
|
||||
uint64_t output_id;
|
||||
PreprocessedLeafTuple preprocessed_leaf_tuple;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// This class is useful help update the curve trees tree without needing to keep the entire tree in memory
|
||||
// This class is useful to help update the curve trees merkle tree without needing to keep the entire tree in memory
|
||||
// - It requires instantiation with the C1 and C2 curve classes and widths, hardening the tree structure
|
||||
// - It ties the C2 curve in the tree to the leaf layer
|
||||
template<typename C1, typename C2>
|
||||
@ -163,21 +181,13 @@ public:
|
||||
static const std::size_t LEAF_TUPLE_SIZE = 3;
|
||||
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
|
||||
struct Leaves final
|
||||
{
|
||||
// Starting leaf tuple index in the leaf layer
|
||||
uint64_t start_leaf_tuple_idx{0};
|
||||
uint64_t start_leaf_tuple_idx{0};
|
||||
// Contiguous leaves in a tree that start at the start_idx
|
||||
std::vector<LeafTuple> tuples;
|
||||
std::vector<PreprocessedLeafTuple> tuples;
|
||||
};
|
||||
|
||||
// A struct useful to extend an existing tree
|
||||
@ -221,13 +231,17 @@ public:
|
||||
//member functions
|
||||
public:
|
||||
// Convert cryptonote output pub key and commitment to a leaf tuple for the curve trees tree
|
||||
LeafTuple output_to_leaf_tuple(const crypto::public_key &output_pubkey, const crypto::public_key &C) const;
|
||||
LeafTupleContext output_to_leaf_context(const std::uint64_t output_id,
|
||||
const crypto::public_key &output_pubkey,
|
||||
const crypto::public_key &C) const;
|
||||
|
||||
LeafTuple leaf_tuple(const PreprocessedLeafTuple &preprocessed_leaf_tuple) const;
|
||||
|
||||
// Flatten leaves [(O.x, I.x, C.x),(O.x, I.x, C.x),...] -> [scalar,scalar,scalar,scalar,scalar,scalar,...]
|
||||
std::vector<typename C2::Scalar> flatten_leaves(const std::vector<LeafTuple> &leaves) const;
|
||||
|
||||
// Convert cryptonote tx outs to leaf tuples, grouped by the leaf tuple unlock height
|
||||
void tx_outs_to_leaf_tuples(const cryptonote::transaction &tx,
|
||||
// Convert cryptonote tx outs to contexts ready to be converted to leaf tuples, grouped by unlock height
|
||||
void tx_outs_to_leaf_tuple_contexts(const cryptonote::transaction &tx,
|
||||
const std::vector<uint64_t> &output_ids,
|
||||
const uint64_t tx_height,
|
||||
const bool miner_tx,
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
) override {
|
||||
blocks.push_back({block_weight, long_term_block_weight});
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ namespace
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
) override
|
||||
{
|
||||
blocks.push_back({blk, blk_hash});
|
||||
|
@ -167,12 +167,14 @@ void CurveTreesGlobalTree::extend_tree(const CurveTreesV1::TreeExtension &tree_e
|
||||
"unexpected leaf start idx");
|
||||
|
||||
m_tree.leaves.reserve(m_tree.leaves.size() + tree_extension.leaves.tuples.size());
|
||||
for (const auto &leaf : tree_extension.leaves.tuples)
|
||||
for (const auto &preprocessed_leaf_tuple : tree_extension.leaves.tuples)
|
||||
{
|
||||
auto leaf = m_curve_trees.leaf_tuple(preprocessed_leaf_tuple);
|
||||
|
||||
m_tree.leaves.emplace_back(CurveTreesV1::LeafTuple{
|
||||
.O_x = leaf.O_x,
|
||||
.I_x = leaf.I_x,
|
||||
.C_x = leaf.C_x
|
||||
.O_x = std::move(leaf.O_x),
|
||||
.I_x = std::move(leaf.I_x),
|
||||
.C_x = std::move(leaf.C_x)
|
||||
});
|
||||
}
|
||||
|
||||
@ -587,6 +589,9 @@ bool CurveTreesGlobalTree::audit_tree(const std::size_t expected_n_leaf_tuples)
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void CurveTreesGlobalTree::log_last_hashes(const CurveTreesV1::LastHashes &last_hashes)
|
||||
{
|
||||
if (!el::Loggers::allowed(el::Level::Debug, "serialization"))
|
||||
return;
|
||||
|
||||
const auto &c1_last_hashes = last_hashes.c1_last_hashes;
|
||||
const auto &c2_last_hashes = last_hashes.c2_last_hashes;
|
||||
|
||||
@ -622,6 +627,9 @@ void CurveTreesGlobalTree::log_last_hashes(const CurveTreesV1::LastHashes &last_
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void CurveTreesGlobalTree::log_tree_extension(const CurveTreesV1::TreeExtension &tree_extension)
|
||||
{
|
||||
if (!el::Loggers::allowed(el::Level::Debug, "serialization"))
|
||||
return;
|
||||
|
||||
const auto &c1_extensions = tree_extension.c1_layer_extensions;
|
||||
const auto &c2_extensions = tree_extension.c2_layer_extensions;
|
||||
|
||||
@ -631,7 +639,8 @@ void CurveTreesGlobalTree::log_tree_extension(const CurveTreesV1::TreeExtension
|
||||
MDEBUG("Leaf start idx: " << tree_extension.leaves.start_leaf_tuple_idx);
|
||||
for (std::size_t i = 0; i < tree_extension.leaves.tuples.size(); ++i)
|
||||
{
|
||||
const auto &leaf = tree_extension.leaves.tuples[i];
|
||||
const auto &preprocessed_leaf_tuple = tree_extension.leaves.tuples[i];
|
||||
const auto leaf = m_curve_trees.leaf_tuple(preprocessed_leaf_tuple);
|
||||
|
||||
const auto O_x = m_curve_trees.m_c2.to_string(leaf.O_x);
|
||||
const auto I_x = m_curve_trees.m_c2.to_string(leaf.I_x);
|
||||
@ -679,6 +688,9 @@ void CurveTreesGlobalTree::log_tree_extension(const CurveTreesV1::TreeExtension
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void CurveTreesGlobalTree::log_tree()
|
||||
{
|
||||
if (!el::Loggers::allowed(el::Level::Debug, "serialization"))
|
||||
return;
|
||||
|
||||
MDEBUG("Tree has " << m_tree.leaves.size() << " leaves, "
|
||||
<< m_tree.c1_layers.size() << " helios layers, " << m_tree.c2_layers.size() << " selene layers");
|
||||
|
||||
@ -730,27 +742,26 @@ void CurveTreesGlobalTree::log_tree()
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
// Test helpers
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static const std::vector<fcmp::curve_trees::CurveTreesV1::LeafTupleContext> generate_random_leaves(const CurveTreesV1 &curve_trees,
|
||||
static const std::vector<fcmp::curve_trees::LeafTupleContext> generate_random_leaves(const CurveTreesV1 &curve_trees,
|
||||
const std::size_t old_n_leaf_tuples,
|
||||
const std::size_t new_n_leaf_tuples)
|
||||
{
|
||||
std::vector<CurveTreesV1::LeafTupleContext> tuples;
|
||||
std::vector<fcmp::curve_trees::LeafTupleContext> tuples;
|
||||
tuples.reserve(new_n_leaf_tuples);
|
||||
|
||||
for (std::size_t i = 0; i < new_n_leaf_tuples; ++i)
|
||||
{
|
||||
const std::uint64_t output_id = old_n_leaf_tuples + i;
|
||||
|
||||
// Generate random output tuple
|
||||
crypto::secret_key o,c;
|
||||
crypto::public_key O,C;
|
||||
crypto::generate_keys(O, o, o, false);
|
||||
crypto::generate_keys(C, c, c, false);
|
||||
|
||||
auto leaf_tuple = curve_trees.output_to_leaf_tuple(O, C);
|
||||
auto tuple_context = curve_trees.output_to_leaf_context(output_id, O, C);
|
||||
|
||||
tuples.emplace_back(fcmp::curve_trees::CurveTreesV1::LeafTupleContext{
|
||||
.output_id = old_n_leaf_tuples + i,
|
||||
.leaf_tuple = std::move(leaf_tuple),
|
||||
});
|
||||
tuples.emplace_back(std::move(tuple_context));
|
||||
}
|
||||
|
||||
return tuples;
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
) override {
|
||||
blocks.push_back(blk);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::CurveTreesV1::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
, const std::multimap<uint64_t, fcmp::curve_trees::LeafTupleContext>& leaf_tuples_by_unlock_block
|
||||
) override {
|
||||
blocks.push_back({block_weight, long_term_block_weight});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user