Skip to content

Commit c30e0d9

Browse files
committed
WIP utreexo port.
1 parent 420ede4 commit c30e0d9

2 files changed

Lines changed: 663 additions & 0 deletions

File tree

test/utreexo/utreexo.cpp

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
/**
2+
* Copyright (c) 2011-2024 libbitcoin developers (see AUTHORS)
3+
*
4+
* This file is part of libbitcoin.
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18+
*/
19+
#include "../test.hpp"
20+
#include "utreexo.hpp"
21+
22+
using namespace utreexo;
23+
24+
BOOST_AUTO_TEST_SUITE(utreexo_tests)
25+
26+
// inferred from rustreexo implementation (no test provided)
27+
28+
BOOST_AUTO_TEST_CASE(utreexo__is_root_populated__various__expected)
29+
{
30+
static_assert(!is_root_populated(0b00000000, 0));
31+
static_assert( is_root_populated(0b00000001, 0));
32+
static_assert(!is_root_populated(0b00000000, 1));
33+
static_assert( is_root_populated(0b00000010, 1));
34+
static_assert(!is_root_populated(0b00000000, 2));
35+
static_assert( is_root_populated(0b00000100, 2));
36+
BOOST_REQUIRE(!is_root_populated(0, 0));
37+
BOOST_REQUIRE( is_root_populated(1, 0));
38+
BOOST_REQUIRE(!is_root_populated(0, 1));
39+
BOOST_REQUIRE( is_root_populated(2, 1));
40+
BOOST_REQUIRE(!is_root_populated(0, 2));
41+
BOOST_REQUIRE( is_root_populated(4, 2));
42+
}
43+
44+
BOOST_AUTO_TEST_CASE(utreexo__is_left_niece__various__expected)
45+
{
46+
static_assert( is_left_niece(0b00000000));
47+
static_assert(!is_left_niece(0b00000001));
48+
static_assert( is_left_niece(0b00000010));
49+
BOOST_REQUIRE( is_left_niece(0));
50+
BOOST_REQUIRE(!is_left_niece(1));
51+
BOOST_REQUIRE( is_left_niece(2));
52+
}
53+
54+
BOOST_AUTO_TEST_CASE(utreexo__left_sibling__various__expected)
55+
{
56+
static_assert(left_sibling(0b00000000) == 0b00000000);
57+
static_assert(left_sibling(0b00000001) == 0b00000000);
58+
static_assert(left_sibling(0b10101010) == 0b10101010);
59+
static_assert(left_sibling(0b10101011) == 0b10101010);
60+
BOOST_REQUIRE_EQUAL(left_sibling(0b00000000), 0b00000000);
61+
BOOST_REQUIRE_EQUAL(left_sibling(0b00000001), 0b00000000);
62+
BOOST_REQUIRE_EQUAL(left_sibling(0b10101010), 0b10101010);
63+
BOOST_REQUIRE_EQUAL(left_sibling(0b10101011), 0b10101010);
64+
}
65+
66+
BOOST_AUTO_TEST_CASE(utreexo__start_position_at_row__various__expected)
67+
{
68+
// forest_rows must be >= row.
69+
static_assert(start_position_at_row(0, 0) == 0_u64);
70+
static_assert(start_position_at_row(0, 1) == 0_u64);
71+
static_assert(start_position_at_row(1, 1) == 2_u64);
72+
static_assert(start_position_at_row(1, 2) == 4_u64);
73+
static_assert(start_position_at_row(1, 3) == 8_u64);
74+
static_assert(start_position_at_row(2, 2) == 6_u64);
75+
static_assert(start_position_at_row(2, 3) == 12_u64);
76+
static_assert(start_position_at_row(3, 3) == 14_u64);
77+
BOOST_REQUIRE_EQUAL(start_position_at_row(0, 0), 0_u64);
78+
BOOST_REQUIRE_EQUAL(start_position_at_row(0, 1), 0_u64);
79+
BOOST_REQUIRE_EQUAL(start_position_at_row(1, 1), 2_u64);
80+
BOOST_REQUIRE_EQUAL(start_position_at_row(1, 2), 4_u64);
81+
BOOST_REQUIRE_EQUAL(start_position_at_row(1, 3), 8_u64);
82+
BOOST_REQUIRE_EQUAL(start_position_at_row(2, 2), 6_u64);
83+
BOOST_REQUIRE_EQUAL(start_position_at_row(2, 3), 12_u64);
84+
BOOST_REQUIRE_EQUAL(start_position_at_row(3, 3), 14_u64);
85+
}
86+
87+
BOOST_AUTO_TEST_CASE(utreexo__number_of_roots__various__expected)
88+
{
89+
static_assert(number_of_roots(0) == 0_size);
90+
static_assert(number_of_roots(1) == 1_size);
91+
static_assert(number_of_roots(2) == 1_size);
92+
static_assert(number_of_roots(3) == 2_size);
93+
static_assert(number_of_roots(0xfefefefefefefefe) == (64_size - 8_size));
94+
BOOST_REQUIRE_EQUAL(number_of_roots(0), 0_size);
95+
BOOST_REQUIRE_EQUAL(number_of_roots(1), 1_size);
96+
BOOST_REQUIRE_EQUAL(number_of_roots(2), 1_size);
97+
BOOST_REQUIRE_EQUAL(number_of_roots(3), 2_size);
98+
BOOST_REQUIRE_EQUAL(number_of_roots(0xfefefefefefefefe), 56_size);
99+
}
100+
101+
// based on rustreexo tests
102+
103+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/node_hash.rs#L327
104+
BOOST_AUTO_TEST_CASE(utreexo__parent_hash__zero_one__expected)
105+
{
106+
constexpr auto expected = base16_array("02242b37d8e851f1e86f46790298c7097df06893d6226b7c1453c213e91717de");
107+
static_assert(parent_hash(hash_from_u8(0), hash_from_u8(1)) == expected);
108+
BOOST_REQUIRE_EQUAL(parent_hash(hash_from_u8(0), hash_from_u8(1)), expected);
109+
}
110+
111+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L368
112+
BOOST_AUTO_TEST_CASE(utreexo__is_right_sibling__zero_one__true)
113+
{
114+
static_assert(is_right_sibling(0, 1));
115+
BOOST_REQUIRE(is_right_sibling(0, 1));
116+
}
117+
118+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L351
119+
BOOST_AUTO_TEST_CASE(utreexo__is_sibling__various__expected)
120+
{
121+
static_assert( is_sibling(0, 1));
122+
static_assert( is_sibling(1, 0));
123+
static_assert(!is_sibling(1, 2));
124+
static_assert(!is_sibling(2, 1));
125+
BOOST_REQUIRE( is_sibling(0, 1));
126+
BOOST_REQUIRE( is_sibling(1, 0));
127+
BOOST_REQUIRE(!is_sibling(1, 2));
128+
BOOST_REQUIRE(!is_sibling(2, 1));
129+
}
130+
131+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L474
132+
BOOST_AUTO_TEST_CASE(utreexo__children__various__expected)
133+
{
134+
static_assert(children(4, 2) == 0_u64);
135+
static_assert(children(49, 5) == 34_u64);
136+
static_assert(children(50, 5) == 36_u64);
137+
static_assert(children(44, 5) == 24_u64);
138+
BOOST_REQUIRE_EQUAL(children(4, 2), 0_u64);
139+
BOOST_REQUIRE_EQUAL(children(49, 5), 34_u64);
140+
BOOST_REQUIRE_EQUAL(children(50, 5), 36_u64);
141+
BOOST_REQUIRE_EQUAL(children(44, 5), 24_u64);
142+
}
143+
144+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L468
145+
BOOST_AUTO_TEST_CASE(utreexo__is_root_position__various__expected)
146+
{
147+
static_assert(is_root_position(14, 8, 3));
148+
BOOST_REQUIRE(is_root_position(14, 8, 3));
149+
}
150+
151+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L424
152+
BOOST_AUTO_TEST_CASE(utreexo__tree_rows__various__expected)
153+
{
154+
static_assert(tree_rows(8) == 3_u8);
155+
static_assert(tree_rows(9) == 4_u8);
156+
static_assert(tree_rows(12) == 4_u8);
157+
static_assert(tree_rows(255) == 8_u8);
158+
BOOST_REQUIRE_EQUAL(tree_rows(8), 3_u8);
159+
BOOST_REQUIRE_EQUAL(tree_rows(9), 4_u8);
160+
BOOST_REQUIRE_EQUAL(tree_rows(12), 4_u8);
161+
BOOST_REQUIRE_EQUAL(tree_rows(255), 8_u8);
162+
}
163+
164+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L439
165+
BOOST_AUTO_TEST_CASE(utreexo__detect_row__scenario__expected)
166+
{
167+
constexpr auto test_detect_row_ = []() NOEXCEPT
168+
{
169+
auto success{ true };
170+
171+
// This is start_position_at_row.
172+
constexpr auto row_offset = [](auto row, auto forest_rows) NOEXCEPT
173+
{
174+
return subtract(
175+
bit_right<uint64_t>(add1<size_t>(forest_rows)),
176+
bit_right<uint64_t>(add1<size_t>(subtract(forest_rows, row))));
177+
};
178+
179+
// NONSTANDARD TEST (non-declarative).
180+
for (uint8_t forest_rows = 1; forest_rows < 64; ++forest_rows)
181+
{
182+
const auto top = sub1(sub1(shift_left<uint64_t>(2, forest_rows)));
183+
success &= (detect_row(top, forest_rows) == forest_rows);
184+
185+
for (uint8_t row = 0; row < forest_rows; ++row)
186+
{
187+
const auto offset = row_offset(row, forest_rows);
188+
success &= (detect_row(offset, forest_rows) == row);
189+
}
190+
}
191+
192+
return success;
193+
};
194+
195+
static_assert(test_detect_row_());
196+
BOOST_REQUIRE(test_detect_row_());
197+
}
198+
199+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L359
200+
BOOST_AUTO_TEST_CASE(utreexo__root_position__various__expected)
201+
{
202+
static_assert(root_position(5, 2, 3) == 12_u64);
203+
static_assert(root_position(5, 0, 3) == 4_u64);
204+
BOOST_REQUIRE_EQUAL(root_position(5, 2, 3), 12_u64);
205+
BOOST_REQUIRE_EQUAL(root_position(5, 0, 3), 4_u64);
206+
}
207+
208+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L391
209+
BOOST_AUTO_TEST_CASE(utreexo__remove_bit__various__expected)
210+
{
211+
static_assert(remove_bit(15, 2) == 7);
212+
static_assert(remove_bit(14, 1) == 6);
213+
static_assert(remove_bit(10, 0) == 5);
214+
BOOST_REQUIRE_EQUAL(remove_bit(15, 2), 7_u64);
215+
BOOST_REQUIRE_EQUAL(remove_bit(14, 1), 6_u64);
216+
BOOST_REQUIRE_EQUAL(remove_bit(10, 0), 5_u64);
217+
}
218+
219+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L482
220+
BOOST_AUTO_TEST_CASE(utreexo__calculate_next__various__expected)
221+
{
222+
constexpr auto calculate_next_ =
223+
[](uint64_t a, uint64_t b, uint8_t c, uint64_t expected) NOEXCEPT
224+
{
225+
uint64_t next{};
226+
return calculate_next(next, a, b, c) && (next == expected);
227+
};
228+
229+
static_assert(calculate_next_(0, 1, 3, 8));
230+
static_assert(calculate_next_(1, 9, 3, 9));
231+
232+
uint64_t next{};
233+
BOOST_REQUIRE(calculate_next(next, 0, 1, 3) && next == 8);
234+
BOOST_REQUIRE(calculate_next(next, 1, 9, 3) && next == 9);
235+
}
236+
237+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/util.rs#L406
238+
BOOST_AUTO_TEST_CASE(utreexo__detwin__various__expected)
239+
{
240+
// 14
241+
// |---------------\
242+
// 12 13
243+
// |-------\ |-------\
244+
// 8 9 10 11
245+
// |---\ |---\ |---\ |---\
246+
// 0 1 2 3 4 5 6 7
247+
248+
const positions expected1{ 7, 8, 10 };
249+
positions targets1{ 0, 1, 4, 5, 7 };
250+
detwin(targets1, 3);
251+
BOOST_REQUIRE_EQUAL(targets1, expected1);
252+
253+
const positions expected2{ 4, 6, 12 };
254+
positions targets2{ 4, 6, 8, 9 };
255+
detwin(targets2, 3);
256+
BOOST_REQUIRE_EQUAL(targets2, expected2);
257+
}
258+
259+
// rustreexo examples
260+
// -------------------------------------------------------------------------------------------
261+
262+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/node_hash.rs#L260
263+
BOOST_AUTO_TEST_CASE(utreexo__node_hash__rustreexo_example__expected)
264+
{
265+
constexpr auto left = base16_array("0000000000000000000000000000000000000000000000000000000000000000");
266+
constexpr auto right = base16_array("0101010101010101010101010101010101010101010101010101010101010101");
267+
constexpr auto expected = base16_array("34e33ca0c40b7bd33d28932ca9e35170def7309a3bf91ecda5e1ceb067548a12");
268+
static_assert(parent_hash(left, right) == expected);
269+
BOOST_REQUIRE_EQUAL(parent_hash(left, right), expected);
270+
}
271+
272+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/node_hash.rs#L346
273+
BOOST_AUTO_TEST_CASE(utreexo__empty_hash__rustreexo_example__expected)
274+
{
275+
constexpr auto expected = base16_array("0000000000000000000000000000000000000000000000000000000000000000");
276+
static_assert(empty_hash == expected);
277+
BOOST_REQUIRE_EQUAL(empty_hash, expected);
278+
}
279+
280+
// github.com/mit-dci/rustreexo/blob/main/src/accumulator/node_hash.rs#L338
281+
BOOST_AUTO_TEST_CASE(utreexo__hash_from_u8__rustreexo_example__expected)
282+
{
283+
constexpr auto expected = base16_array("6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d");
284+
static_assert(hash_from_u8(0) == expected);
285+
BOOST_REQUIRE_EQUAL(hash_from_u8(0), expected);
286+
}
287+
288+
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)