Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] full-chain membership proof++ integration #9436

Draft
wants to merge 127 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
127 commits
Select commit Hold shift + click to select a range
e1c03f4
rough fcmp++ tree impl (lots of work remaining to clean it up and fix)
j-berman May 17, 2024
1ba876b
remove whitespaces
j-berman May 17, 2024
9e6b93b
test validates lowest layer in tree
j-berman May 17, 2024
33ad50b
fix c1 c2 layer indexing issue in test helper get_last_chunk
j-berman May 18, 2024
c05bd80
actual indexing fix, tests now passing
j-berman May 18, 2024
ad8872a
Cleaner file organization
j-berman May 20, 2024
5103a94
template all curve_trees types & funcs, rename tower_cycle_types to t…
j-berman May 21, 2024
d9390c7
Implement CurveTrees & CurveTreesUnitTest classes to simplify callers
j-berman May 21, 2024
29e0fe7
Add Curve class, and Helios & Selene classes that derive from Curve
j-berman May 22, 2024
9e68475
Use widths from fcmp++ repo test & align tests with width
j-berman May 22, 2024
26009ba
slight simplification to CurveTrees::hash_layer
j-berman May 22, 2024
4ade675
Consolidate hash_leaf_layer into hash_layer
j-berman May 23, 2024
9ba00be
Move curve_trees.h implementations into curve_trees.cpp file
j-berman May 23, 2024
5ad0269
Cleaner template usage, moved static functions out of CurveTrees class
j-berman May 23, 2024
e68ea2e
small cleanup
j-berman May 23, 2024
af9b74f
start LMDB grow_tree
j-berman May 24, 2024
af47a13
Remove cxx and expose scalars/points directly
kayabaNerve May 24, 2024
42f6ef2
fmt, clippy
kayabaNerve May 24, 2024
c792b21
Use statics on the Rust side for generators
kayabaNerve May 24, 2024
effa9ee
Only pass a single prior child
kayabaNerve May 24, 2024
517f5a3
don't want to expose generator lengths in ffi
j-berman May 24, 2024
a1ee603
explicit type response to hash_grow 's
j-berman May 24, 2024
988c4ea
Remove reference from m_hash_init_point
kayabaNerve May 24, 2024
ab7c741
Simplify edge case handling in hash_layer
j-berman May 25, 2024
1ffde09
Implement get_tree_last_chunks in db, can now extend tree in db
j-berman May 25, 2024
6045357
implement db->audit_tree, and flesh out db test to init/extend tree
j-berman May 27, 2024
17b1f42
cleaner lmdb test structure for curve trees
j-berman May 27, 2024
c7c6c6a
CurveTreesUnitTest -> CurveTreesGlobalTree class
j-berman May 27, 2024
ae89fdd
Set up trim_tree_in_memory test
j-berman Jun 4, 2024
e8af709
expose and test hash_trim from rust lib
j-berman Jun 6, 2024
ed040ca
implement trim_tree_in_memory
j-berman Jun 7, 2024
8287ba6
faster trim_tree tests
j-berman Jun 7, 2024
36f1e19
Fix grow_tree, restructure it, and clean the approach
j-berman Jun 28, 2024
5ddca0c
Implement and test trim_tree algo in memory
j-berman Jul 9, 2024
4be2d7c
whitespace fixes
j-berman Jul 9, 2024
55caee9
Better tests for hash_trim
j-berman Jul 9, 2024
42fd22c
Better organization
j-berman Jul 9, 2024
f50ad5b
trim_tree db impl + db test + some housekeeping
j-berman Jul 10, 2024
8a89c20
lmdb migration to init curve trees tree from existing outputs
j-berman Jul 18, 2024
306488b
Implemented growing the tree on sync + lots of cleaning
j-berman Jul 24, 2024
634e12e
Guarantee insertion order into the tree using global output ID
j-berman Jul 25, 2024
93795b4
Match output unlock time (fix off by 1)
j-berman Jul 25, 2024
db12610
Remove leaves from locked leaves table upon insertion to tree
j-berman Jul 25, 2024
b585a7f
Remove copy in get_tree_extension and better named funcs
j-berman Jul 25, 2024
af4de99
Use a pointer for the value in CResult
kayabaNerve May 25, 2024
d6ca636
use void * to try to fix CResult
j-berman May 25, 2024
8b76958
Rust cross compilation
kayabaNerve May 25, 2024
389274a
Correct path to the staticlib
kayabaNerve May 25, 2024
75faba1
Increase misc discrepancies in ARM ARCH spec which we support
kayabaNerve May 25, 2024
8b279a0
i386 -> i686, riscv64 -> riscv64gc
kayabaNerve May 25, 2024
8c47c0d
Further match off RUST_ARCH, not ARCH_ID
kayabaNerve May 26, 2024
03679d1
Install Rust when doing the Windows build
kayabaNerve May 26, 2024
e5ed232
Use the armv7 HF Rust toolchain
kayabaNerve May 26, 2024
d69e6bd
Install Rust via the msys2 package on Windows (not the unavailable ru…
kayabaNerve May 26, 2024
0620be1
Cross-compile from Ubuntu 22.04
kayabaNerve May 26, 2024
38f1935
Ubuntu 20.04, Rust 1.72
kayabaNerve May 26, 2024
5d6a7fd
_x86_64 -> -x86_64
kayabaNerve May 26, 2024
8664736
Normalize x86-64 to x86_64
kayabaNerve May 26, 2024
170324a
Rust 1.69
kayabaNerve May 26, 2024
98569b0
LTO off
kayabaNerve May 26, 2024
6d6a2e4
Correct typo in MATCHES statement
kayabaNerve May 26, 2024
c6327cc
Correct in-tree code to Rust 1.69
kayabaNerve May 26, 2024
8eb3f29
Link additional libs on Windows
kayabaNerve May 26, 2024
da9f101
Abort on panic, fix 32-bit Windows undefined reference
kayabaNerve May 26, 2024
16536f3
Only provide dummy _Unwind_Resume on x86 Windows
kayabaNerve May 26, 2024
1a44ceb
Link additional libs on Windows (yet actually adding the relevant cha…
kayabaNerve May 26, 2024
23be5f6
Use a single target_link_libraries call
kayabaNerve May 26, 2024
aadea07
Touch up merge for cross-compilation fixes
j-berman Jul 26, 2024
420b4b6
Resolve cross-compile errors
j-berman Jul 26, 2024
d36b6fe
resolve rebase to master issues
j-berman Jul 26, 2024
c383087
Instantiate m_curve_trees on BlockchainLMDB class in c'tor
j-berman Jul 26, 2024
729e31d
include fcmp/curve_trees.h in db_lmdb.h
j-berman Jul 26, 2024
16a8ce3
Add * point from bytes
kayabaNerve Jul 27, 2024
54d5d0d
fcmp++: add support for new fcmp types in cryptonote::transaction
j-berman Aug 1, 2024
e40c5bb
fix json tagging in fcmp_pp serialization
j-berman Aug 1, 2024
95114f9
Use explicit code instead of macro in custom fcmp_pp serialization
j-berman Aug 1, 2024
34eafa8
Store points in the tree in compressed encoding (32 bytes)
j-berman Aug 1, 2024
b90cee8
Store {O,C} for each leaf tuple instead of {O.x,I.x,C.x}
j-berman Aug 2, 2024
cbf6a5d
Optimize conversion from output to leaf tuple
j-berman Aug 3, 2024
30fc80b
Don't copy when flattening leaves
j-berman Aug 3, 2024
5e76191
cleaner crypto for converting output to leaf tuple
j-berman Aug 3, 2024
edded7e
fcmp++: Restart migration from where it leaves off
j-berman Aug 8, 2024
10c6c12
fcmp++: compilation fixes + misc. cleanup
j-berman Aug 8, 2024
3a5cf70
32-bit platform compatibility in Rust FFI (untested)
j-berman Aug 8, 2024
d72f405
Revert DELETE_DB macro to original spot
j-berman Aug 8, 2024
d4847f6
Rename everything from fcmp* to fcmp_pp
j-berman Aug 8, 2024
9f0dd85
fix clang compile errors
j-berman Aug 8, 2024
8b12a33
fcmp++: implement iterative audit_tree function
j-berman Aug 9, 2024
f17db01
fcmp++: store {output pubkey, commitment} in db, pre-torsion clear
j-berman Aug 9, 2024
9ad4918
link correct cncrypto and ringct_basic libs
j-berman Aug 9, 2024
b6bcca9
Remove ringct dep in fcmp_pp, impl in fcmp_pp_crypto
j-berman Aug 9, 2024
7389cb6
add missing files
j-berman Aug 9, 2024
6525df1
Don't store output_id in locked_outpust table, table stays ordered
j-berman Aug 10, 2024
83d5659
Clean lmbd impl
j-berman Aug 10, 2024
67f5546
lmdb touchup && OutputsByUnlockBlock map -> unordered_map
j-berman Aug 13, 2024
918befb
new_leaf_tuples -> new_outputs
j-berman Aug 13, 2024
ee19361
Remove extra gcc install fixes windows build
j-berman Aug 14, 2024
47d47bd
fcmp++: proof len from inputs *AND merkle tree depth
j-berman Aug 14, 2024
41b1985
Fix compile on arm-linux-androideabi (32-bit) using a newer NDK
j-berman Sep 3, 2024
16ff6a9
fcmp++: trim tree when removing a block
j-berman Sep 4, 2024
0a604a9
fcmp++: Enable trimming to empty tree
j-berman Sep 5, 2024
acc7d05
fcmp++ LMDB: use dummy key optimization on leaves table
j-berman Sep 5, 2024
2890e8c
fcmp++: LMDB touchups
j-berman Sep 6, 2024
072a82d
fcmp++: tests now test trimming to empty tree
j-berman Sep 6, 2024
0688538
fcmp++: add test to trim the tree then grow again after trimming
j-berman Sep 6, 2024
b71f244
fcmp++: better test names
j-berman Sep 6, 2024
0ff1eaf
Use macro to de-dupe curve trees test logic
j-berman Sep 6, 2024
9784ced
fcmp++ tests: init tree once in memory and grow copy
j-berman Sep 8, 2024
f47c60e
fcmp++ tests: init tree in db once, then copy db for tests
j-berman Sep 9, 2024
e636c38
fix ubuntu 20 compile
j-berman Sep 9, 2024
90164e3
fcmp++: multithreaded hashing children chunks into tree
j-berman Sep 10, 2024
8fc87d7
fcmp++: multithreaded convert valid outputs into leaf tuples
j-berman Sep 10, 2024
b055eb3
fcmp++: output may not be present in locked outputs table on remove
j-berman Sep 11, 2024
0435974
fcmp++ lmdb: migration touchups
j-berman Sep 12, 2024
7fa01d2
fcmp++: key image migration
j-berman Sep 12, 2024
5f4b20b
fcmp++: fix build errs for ki_context_t hash specialization
j-berman Sep 12, 2024
358a66f
crypto: fe_batch_invert using Montgomery's trick
j-berman Sep 16, 2024
b2ea862
fcmp++: use batch inversion when converting outputs to leaf tupels
j-berman Sep 16, 2024
330b82f
Fix build errs + warnings
j-berman Sep 17, 2024
21664f9
fcmp++: use fe * instead of vector<fe> + clean up
j-berman Sep 17, 2024
513dae8
small touchups
j-berman Sep 17, 2024
da710fc
crypto: test more batch inversions
j-berman Sep 17, 2024
a74f7ae
fcmp++: rename "PreWeiX" -> "EdYDerivatives" + small touchups
j-berman Sep 17, 2024
901cc87
missing ref
j-berman Sep 17, 2024
036fc2a
fcmp++ tests: set up test for prove
j-berman Sep 18, 2024
1241172
fcmp++: fix trim_tree get_trim_layer_instructions logic err
j-berman Oct 7, 2024
3ac3e53
fcmp++: fix migration batching to resize db as needed
j-berman Oct 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fcmp++: implement iterative audit_tree function
- Recursion goes too deep
j-berman committed Aug 9, 2024
commit 8b12a335c6d1d358e43261cb929754f75848d906
230 changes: 131 additions & 99 deletions src/blockchain_db/lmdb/db_lmdb.cpp
Original file line number Diff line number Diff line change
@@ -1972,12 +1972,16 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const
uint64_t layer_idx = 0;
uint64_t child_chunk_idx = 0;
MDB_cursor_op leaf_op = MDB_FIRST;
MDB_cursor_op parent_op = MDB_FIRST;
while (1)
{
// Get next leaf chunk
std::vector<fcmp_pp::curve_trees::CurveTreesV1::LeafTuple> leaf_tuples_chunk;
leaf_tuples_chunk.reserve(m_curve_trees->m_c2_width);

if (child_chunk_idx && child_chunk_idx % 1000 == 0)
MINFO("Auditing layer " << layer_idx << ", child_chunk_idx " << child_chunk_idx);

// Iterate until chunk is full or we get to the end of all leaves
while (1)
{
@@ -2003,7 +2007,8 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const
MDB_val_set(v_parent, child_chunk_idx);

MDEBUG("Getting leaf chunk hash starting at child_chunk_idx " << child_chunk_idx);
int result = mdb_cursor_get(m_cur_layers, &k_parent, &v_parent, MDB_GET_BOTH);
int result = mdb_cursor_get(m_cur_layers, &k_parent, &v_parent, parent_op);
parent_op = MDB_NEXT_DUP;

// Check end condition: no more leaf tuples in the leaf layer
if (leaf_tuples_chunk.empty())
@@ -2019,6 +2024,8 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const

if (result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to get parent in first layer: ", result).c_str()));
if (layer_idx != *(uint64_t*)k_parent.mv_data)
throw0(DB_ERROR("unexpected parent encountered"));

// Get the expected leaf chunk hash
const auto leaves = m_curve_trees->flatten_leaves(std::move(leaf_tuples_chunk));
@@ -2039,40 +2046,36 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const
const auto expected_bytes = m_curve_trees->m_c2->to_bytes(chunk_hash);
const auto actual_bytes = lv->child_chunk_hash;
CHECK_AND_ASSERT_MES(expected_bytes == actual_bytes, false, "unexpected leaf chunk hash");
CHECK_AND_ASSERT_MES(lv->child_chunk_idx == child_chunk_idx, false, "unexpected child chunk idx");

++child_chunk_idx;
}

MDEBUG("Successfully audited leaf layer");

// Traverse up the tree auditing each layer until we've audited every layer in the tree
while (1)
bool audit_complete = false;
while (!audit_complete)
{
MDEBUG("Auditing layer " << layer_idx);

// Alternate starting with c1 as parent (we already audited c2 leaf parents), then c2 as parent, then c1, etc.
const bool parent_is_c1 = layer_idx % 2 == 0;
if (parent_is_c1)
{
if (this->audit_layer(
audit_complete = this->audit_layer(
/*c_child*/ m_curve_trees->m_c2,
/*c_parent*/ m_curve_trees->m_c1,
layer_idx,
/*child_start_idx*/ 0,
/*child_chunk_idx*/ 0,
/*chunk_width*/ m_curve_trees->m_c1_width))
{
break;
}
/*chunk_width*/ m_curve_trees->m_c1_width);
}
else
{
if (this->audit_layer(
audit_complete = this->audit_layer(
/*c_child*/ m_curve_trees->m_c1,
/*c_parent*/ m_curve_trees->m_c2,
layer_idx,
/*child_start_idx*/ 0,
/*child_chunk_idx*/ 0,
/*chunk_width*/ m_curve_trees->m_c2_width))
{
break;
}
/*chunk_width*/ m_curve_trees->m_c2_width);
}

++layer_idx;
@@ -2086,112 +2089,141 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const
template<typename C_CHILD, typename C_PARENT>
bool BlockchainLMDB::audit_layer(const std::unique_ptr<C_CHILD> &c_child,
const std::unique_ptr<C_PARENT> &c_parent,
const uint64_t layer_idx,
const uint64_t child_start_idx,
const uint64_t child_chunk_idx,
const uint64_t child_layer_idx,
const uint64_t chunk_width) const
{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();

TXN_PREFIX_RDONLY();
RCURSOR(layers)

MDEBUG("Auditing layer " << layer_idx << " at child_start_idx " << child_start_idx
<< " and child_chunk_idx " << child_chunk_idx);
// Open separate cursors for child and parent layer
MDB_cursor *child_layer_cursor, *parent_layer_cursor;

int c_result = mdb_cursor_open(m_txn, m_layers, &child_layer_cursor);
if (c_result)
throw0(DB_ERROR(lmdb_error("Failed to open child cursor: ", c_result).c_str()));
int p_result = mdb_cursor_open(m_txn, m_layers, &parent_layer_cursor);
if (p_result)
throw0(DB_ERROR(lmdb_error("Failed to open parent cursor: ", p_result).c_str()));

// Set the cursors to the start of each layer
const uint64_t parent_layer_idx = child_layer_idx + 1;

MDB_val_set(k_child, child_layer_idx);
MDB_val_set(k_parent, parent_layer_idx);

// Get next child chunk
std::vector<typename C_CHILD::Point> child_chunk;
child_chunk.reserve(chunk_width);
MDB_val v_child, v_parent;

MDB_val_copy<uint64_t> k_child(layer_idx);
MDB_val_set(v_child, child_start_idx);
MDB_cursor_op op_child = MDB_GET_BOTH;
c_result = mdb_cursor_get(child_layer_cursor, &k_child, &v_child, MDB_SET);
p_result = mdb_cursor_get(parent_layer_cursor, &k_parent, &v_parent, MDB_SET);

if (c_result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to get child: ", c_result).c_str()));
if (p_result != MDB_SUCCESS && p_result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("Failed to get parent: ", p_result).c_str()));

// Begin to audit the layer
MDB_cursor_op op_child = MDB_FIRST_DUP;
MDB_cursor_op op_parent = MDB_FIRST_DUP;
bool audit_complete = false;
uint64_t child_chunk_idx = 0;
while (1)
{
int result = mdb_cursor_get(m_cur_layers, &k_child, &v_child, op_child);
op_child = MDB_NEXT_DUP;
if (result == MDB_NOTFOUND)
break;
if (result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to get child: ", result).c_str()));
if (child_chunk_idx && child_chunk_idx % 1000 == 0)
MINFO("Auditing layer " << parent_layer_idx << ", child_chunk_idx " << child_chunk_idx);

// Get next child chunk
std::vector<typename C_CHILD::Point> child_chunk;
child_chunk.reserve(chunk_width);
while (1)
{
int result = mdb_cursor_get(child_layer_cursor, &k_child, &v_child, op_child);
op_child = MDB_NEXT_DUP;
if (result == MDB_NOTFOUND)
break;
if (result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to get child: ", result).c_str()));

const auto *lv = (layer_val *)v_child.mv_data;
auto child_point = c_child->from_bytes(lv->child_chunk_hash);
const auto *lv = (layer_val *)v_child.mv_data;
auto child_point = c_child->from_bytes(lv->child_chunk_hash);

child_chunk.emplace_back(std::move(child_point));
child_chunk.emplace_back(std::move(child_point));

if (child_chunk.size() == chunk_width)
if (child_chunk.size() == chunk_width)
break;
}

// Get the actual chunk hash from the db
int result = mdb_cursor_get(parent_layer_cursor, &k_parent, &v_parent, op_parent);
op_parent = MDB_NEXT_DUP;

// Check for end conditions
// End condition A (audit_complete=false): finished auditing layer and ready to move up a layer
// End condition B (audit_complete=true ): finished auditing the tree, no more layers remaining

// End condition A: check if finished auditing this layer
if (child_chunk.empty())
{
// No more children, expect to be done auditing layer and ready to move up a layer
if (result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("unexpected parent result at parent_layer_idx " + std::to_string(parent_layer_idx)
+ " , child_chunk_idx " + std::to_string(child_chunk_idx) + " : ", result).c_str()));

MDEBUG("Finished auditing layer " << child_layer_idx);
audit_complete = false;
break;
}
}

// Get the actual chunk hash from the db
const uint64_t parent_layer_idx = layer_idx + 1;
MDB_val_copy<uint64_t> k_parent(parent_layer_idx);
MDB_val_set(v_parent, child_chunk_idx);
// End condition B: check if finished auditing the tree
if (child_chunk_idx == 0 && child_chunk.size() == 1)
{
if (p_result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("unexpected parent of root at parent_layer_idx " + std::to_string(parent_layer_idx)
+ " , child_chunk_idx " + std::to_string(child_chunk_idx) + " : ", result).c_str()));

// Check for end conditions
// End condition A (return false): finished auditing layer and ready to move up a layer
// End condition B (return true): finished auditing the tree, no more layers remaining
int result = mdb_cursor_get(m_cur_layers, &k_parent, &v_parent, MDB_GET_BOTH);
MDEBUG("Encountered root at layer_idx " << child_layer_idx);
audit_complete = true;
break;
}

// End condition A: check if finished auditing this layer
if (child_chunk.empty())
{
// No more children, expect to be done auditing layer and ready to move up a layer
if (result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("unexpected parent result at parent_layer_idx " + std::to_string(parent_layer_idx)
+ " , child_chunk_idx " + std::to_string(child_chunk_idx) + " : ", result).c_str()));
if (result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to get parent: ", result).c_str()));

MDEBUG("Finished auditing layer " << layer_idx);
TXN_POSTFIX_RDONLY();
return false;
}
if (child_layer_idx != *(uint64_t*)k_child.mv_data)
throw0(DB_ERROR("unexpected child encountered"));
if (parent_layer_idx != *(uint64_t*)k_parent.mv_data)
throw0(DB_ERROR("unexpected parent encountered"));

// End condition B: check if finished auditing the tree
if (child_chunk_idx == 0 && child_chunk.size() == 1)
{
if (result != MDB_NOTFOUND)
throw0(DB_ERROR(lmdb_error("unexpected parent of root at parent_layer_idx " + std::to_string(parent_layer_idx)
+ " , child_chunk_idx " + std::to_string(child_chunk_idx) + " : ", result).c_str()));
// Get the expected chunk hash
std::vector<typename C_PARENT::Scalar> child_scalars;
child_scalars.reserve(child_chunk.size());
for (const auto &child : child_chunk)
child_scalars.emplace_back(c_child->point_to_cycle_scalar(child));
const typename C_PARENT::Chunk chunk{child_scalars.data(), child_scalars.size()};

MDEBUG("Encountered root at layer_idx " << layer_idx);
TXN_POSTFIX_RDONLY();
return true;
for (uint64_t i = 0; i < child_scalars.size(); ++i)
MDEBUG("Hashing " << c_parent->to_string(child_scalars[i]));

const auto chunk_hash = fcmp_pp::curve_trees::get_new_parent(c_parent, chunk);
MDEBUG("Expected chunk_hash " << c_parent->to_string(chunk_hash) << " (" << child_scalars.size() << " children)");

const auto *lv = (layer_val *)v_parent.mv_data;
MDEBUG("Actual chunk hash " << epee::string_tools::pod_to_hex(lv->child_chunk_hash));

const auto actual_bytes = lv->child_chunk_hash;
const auto expected_bytes = c_parent->to_bytes(chunk_hash);
if (actual_bytes != expected_bytes)
throw0(DB_ERROR(("unexpected hash at child_chunk_idx " + std::to_string(child_chunk_idx)).c_str()));
if (lv->child_chunk_idx != child_chunk_idx)
throw0(DB_ERROR(("unexpected child_chunk_idx, epxected " + std::to_string(child_chunk_idx)).c_str()));

++child_chunk_idx;
}

if (result != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to get parent: ", result).c_str()));

// Get the expected chunk hash
std::vector<typename C_PARENT::Scalar> child_scalars;
child_scalars.reserve(child_chunk.size());
for (const auto &child : child_chunk)
child_scalars.emplace_back(c_child->point_to_cycle_scalar(child));
const typename C_PARENT::Chunk chunk{child_scalars.data(), child_scalars.size()};

for (uint64_t i = 0; i < child_scalars.size(); ++i)
MDEBUG("Hashing " << c_parent->to_string(child_scalars[i]));

const auto chunk_hash = fcmp_pp::curve_trees::get_new_parent(c_parent, chunk);
MDEBUG("chunk_hash " << c_parent->to_string(chunk_hash) << " , hash init point: "
<< c_parent->to_string(c_parent->hash_init_point()) << " (" << child_scalars.size() << " children)");

const auto *lv = (layer_val *)v_parent.mv_data;
MDEBUG("Actual chunk hash " << epee::string_tools::pod_to_hex(lv->child_chunk_hash));

const auto actual_bytes = lv->child_chunk_hash;
const auto expected_bytes = c_parent->to_bytes(chunk_hash);
if (actual_bytes != expected_bytes)
throw0(DB_ERROR(("unexpected hash at child_chunk_idx " + std::to_string(child_chunk_idx)).c_str()));

// TODO: use while (1) for iterative pattern, don't use recursion
return this->audit_layer(c_child,
c_parent,
layer_idx,
child_start_idx + child_chunk.size(),
child_chunk_idx + 1,
chunk_width);
TXN_POSTFIX_RDONLY();

return audit_complete;
}

std::vector<fcmp_pp::curve_trees::LeafTupleContext> BlockchainLMDB::get_leaf_tuples_at_unlock_block_id(
2 changes: 0 additions & 2 deletions src/blockchain_db/lmdb/db_lmdb.h
Original file line number Diff line number Diff line change
@@ -445,8 +445,6 @@ class BlockchainLMDB : public BlockchainDB
bool audit_layer(const std::unique_ptr<C_CHILD> &c_child,
const std::unique_ptr<C_PARENT> &c_parent,
const uint64_t layer_idx,
const uint64_t child_start_idx,
const uint64_t child_chunk_idx,
const uint64_t chunk_width) const;

std::vector<fcmp_pp::curve_trees::LeafTupleContext> get_leaf_tuples_at_unlock_block_id(uint64_t block_id);
2 changes: 1 addition & 1 deletion tests/unit_tests/serialization.cpp
Original file line number Diff line number Diff line change
@@ -1397,12 +1397,12 @@ TEST(Serialization, tx_fcmp_pp)
// 2. fcmp++ proof is longer than expected when serializing
{
transaction tx = make_dummy_fcmp_pp_tx();
string blob;

// Extend fcmp++ proof
ASSERT_TRUE(tx.rct_signatures.p.fcmp_pp.size() == fcmp_pp::proof_len(n_inputs));
tx.rct_signatures.p.fcmp_pp.push_back(0x01);

string blob;
ASSERT_FALSE(serialization::dump_binary(tx, blob));
}