Skip to content

Commit ad0afc0

Browse files
committed
Balances merkle tree example added.
1 parent 1fc7f93 commit ad0afc0

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

examples/cpp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,4 @@ add_example(pallas_curve_multiplication_cpp_example
7878
#add_example(ed25519_curve_add_cpp SOURCES ed25519_curve_add.cpp INPUT ed25519_curve_add.inp)
7979
add_example(ed25519_field_add_cpp SOURCES ed25519_field_add.cpp INPUT ed25519_field_add.inp)
8080
add_example(strlen_cpp_example SOURCES strlen.cpp INPUT strlen.inp)
81+
add_example(balances_tree_cpp_example SOURCES balances_tree.cpp INPUT balances_tree.inp)

examples/cpp/balances_tree.cpp

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#include <nil/crypto3/hash/algorithm/hash.hpp>
2+
#include <nil/crypto3/hash/sha2.hpp>
3+
4+
using namespace nil::crypto3;
5+
6+
constexpr std::size_t validators_amount_log2 = 20;
7+
constexpr std::size_t validators_per_leaf_log2 = 2;
8+
9+
const std::array<typename hashes::sha2<256>::block_type, 39> precomputed_zero_hashes = {{
10+
{0xf5a5fd42d16a20302798ef6ed309979b_cppui255, 0x43003d2320d9f0e8ea9831a92759fb4b_cppui255},
11+
{0xdb56114e00fdd4c1f85c892bf35ac9a8_cppui255, 0x9289aaecb1ebd0a96cde606a748b5d71_cppui255},
12+
{0xc78009fdf07fc56a11f122370658a353_cppui255, 0xaaa542ed63e44c4bc15ff4cd105ab33c_cppui255},
13+
{0x536d98837f2dd165a55d5eeae9148595_cppui255, 0x4472d56f246df256bf3cae19352a123c_cppui255},
14+
{0x9efde052aa15429fae05bad4d0b1d7c6_cppui255, 0x4da64d03d7a1854a588c2cb8430c0d30_cppui255},
15+
{0xd88ddfeed400a8755596b21942c1497e_cppui255, 0x114c302e6118290f91e6772976041fa1_cppui255},
16+
{0x87eb0ddba57e35f6d286673802a4af59_cppui255, 0x75e22506c7cf4c64bb6be5ee11527f2c_cppui255},
17+
{0x26846476fd5fc54a5d43385167c95144_cppui255, 0xf2643f533cc85bb9d16b782f8d7db193_cppui255},
18+
{0x506d86582d252405b840018792cad2bf_cppui255, 0x1259f1ef5aa5f887e13cb2f0094f51e1_cppui255},
19+
{0xffff0ad7e659772f9534c195c815efc4_cppui255, 0x14ef1e1daed4404c06385d11192e92b_cppui255},
20+
{0x6cf04127db05441cd833107a52be8528_cppui255, 0x68890e4317e6a02ab47683aa75964220_cppui255},
21+
{0xb7d05f875f140027ef5118a2247bbb84_cppui255, 0xce8f2f0f1123623085daf7960c329f5f_cppui255},
22+
{0xdf6af5f5bbdb6be9ef8aa618e4bf8073_cppui255, 0x960867171e29676f8b284dea6a08a85e_cppui255},
23+
{0xb58d900f5e182e3c50ef74969ea16c77_cppui255, 0x26c549757cc23523c369587da7293784_cppui255},
24+
{0xd49a7502ffcfb0340b1d7885688500ca_cppui255, 0x308161a7f96b62df9d083b71fcc8f2bb_cppui255},
25+
{0x8fe6b1689256c0d385f42f5bbe2027a2_cppui255, 0x2c1996e110ba97c171d3e5948de92beb_cppui255},
26+
{0x8d0d63c39ebade8509e0ae3c9c3876fb_cppui255, 0x5fa112be18f905ecacfecb92057603ab_cppui255},
27+
{0x95eec8b2e541cad4e91de38385f2e046_cppui255, 0x619f54496c2382cb6cacd5b98c26f5a4_cppui255},
28+
{0xf893e908917775b62bff23294dbbe3a1_cppui255, 0xcd8e6cc1c35b4801887b646a6f81f17f_cppui255},
29+
{0xcddba7b592e3133393c16194fac7431a_cppui255, 0xbf2f5485ed711db282183c819e08ebaa_cppui255},
30+
{0x8a8d7fe3af8caa085a7639a832001457_cppui255, 0xdfb9128a8061142ad0335629ff23ff9c_cppui255},
31+
{0xfeb3c337d7a51a6fbf00b9e34c52e1c9_cppui255, 0x195c969bd4e7a0bfd51d5c5bed9c1167_cppui255},
32+
{0xe71f0aa83cc32edfbefa9f4d3e0174ca_cppui255, 0x85182eec9f3a09f6a6c0df6377a510d7_cppui255},
33+
{0x31206fa80a50bb6abe29085058f16212_cppui255, 0x212a60eec8f049fecb92d8c8e0a84bc0_cppui255},
34+
{0x21352bfecbeddde993839f614c3dac0a_cppui255, 0x3ee37543f9b412b16199dc158e23b544_cppui255},
35+
{0x619e312724bb6d7c3153ed9de791d764_cppui255, 0xa366b389af13c58bf8a8d90481a46765_cppui255},
36+
{0x7cdd2986268250628d0c10e385c58c61_cppui255, 0x91e6fbe05191bcc04f133f2cea72c1c4_cppui255},
37+
{0x848930bd7ba8cac54661072113fb2788_cppui255, 0x69e07bb8587f91392933374d017bcbe1_cppui255},
38+
{0x8869ff2c22b28cc10510d98532928033_cppui255, 0x28be4fb0e80495e8bb8d271f5b889636_cppui255},
39+
{0xb5fe28e79f1b850f8658246ce9b6a1e7_cppui255, 0xb49fc06db7143e8fe0b4f2b0c5523a5c_cppui255},
40+
{0x985e929f70af28d0bdd1a90a808f977f_cppui255, 0x597c7c778c489e98d3bd8910d31ac0f7_cppui255},
41+
{0xc6f67e02e6e4e1bdefb994c6098953f3_cppui255, 0x4636ba2b6ca20a4721d2b26a886722ff_cppui255},
42+
{0x1c9a7e5ff1cf48b4ad1582d3f4e4a100_cppui255, 0x4f3b20d8c5a2b71387a4254ad933ebc5_cppui255},
43+
{0x2f075ae229646b6f6aed19a5e372cf29_cppui255, 0x5081401eb893ff599b3f9acc0c0d3e7d_cppui255},
44+
{0x328921deb59612076801e8cd61592107_cppui255, 0xb5c67c79b846595cc6320c395b46362c_cppui255},
45+
{0xbfb909fdb236ad2411b4e4883810a074_cppui255, 0xb840464689986c3f8a8091827e17c327_cppui255},
46+
{0x55d8fb3687ba3ba49f342c77f5a1f89b_cppui255, 0xec83d811446e1a467139213d640b6a74_cppui255},
47+
{0xf7210d4f8e7e1039790e7bf4efa20755_cppui255, 0x5a10a6db1dd4b95da313aaa88b88fe76_cppui255},
48+
{0xad21b516cbc645ffe34ab5de1c8aef8c_cppui255, 0xd4e7f8d2b51e8e1456adc7563cda206f_cppui255}
49+
}};
50+
51+
constexpr std::array<unsigned long long, 39> precomputed_powers_of_two = {{
52+
1,
53+
2,
54+
4,
55+
8,
56+
16,
57+
32,
58+
64,
59+
128,
60+
256,
61+
512,
62+
1024,
63+
2048,
64+
4096,
65+
8192,
66+
16384,
67+
32768,
68+
65536,
69+
131072,
70+
262144,
71+
524288,
72+
1048576,
73+
2097152,
74+
4194304,
75+
8388608,
76+
16777216,
77+
33554432,
78+
67108864,
79+
134217728,
80+
268435456,
81+
536870912,
82+
1073741824,
83+
2147483648,
84+
4294967296,
85+
8589934592,
86+
17179869184,
87+
34359738368,
88+
68719476736,
89+
137438953472,
90+
274877906944
91+
}};
92+
93+
bool is_same(typename hashes::sha2<256>::block_type block0,
94+
typename hashes::sha2<256>::block_type block1){
95+
96+
return block0[0] == block1[0] && block0[1] == block1[1];
97+
}
98+
99+
template <std::size_t LayerSize>
100+
typename hashes::sha2<256>::block_type hash_layer(std::array<typename hashes::sha2<256>::block_type, LayerSize> input){
101+
std::array<typename hashes::sha2<256>::block_type, LayerSize / 2> next_layer;
102+
103+
for (std::size_t leaf_index = 0; leaf_index < LayerSize / 2; leaf_index++) {
104+
next_layer[leaf_index] =
105+
hash<hashes::sha2<256>>(input[2 * leaf_index], input[2 * leaf_index + 1]);
106+
}
107+
if (LayerSize == 2)
108+
return next_layer[0];
109+
else
110+
return hash_layer<LayerSize / 2>(next_layer);
111+
}
112+
113+
[[circuit]] bool balance_tree(
114+
[[private]] std::array<unsigned long long, precomputed_powers_of_two[validators_amount_log2]> validator_balances,
115+
typename hashes::sha2<256>::block_type expected_root,
116+
unsigned long long expected_total_balance) {
117+
118+
constexpr std::size_t validators_amount = precomputed_powers_of_two[validators_amount_log2];
119+
constexpr std::size_t potentially_non_zero_leaves_amount_log2 = validators_amount_log2 - validators_per_leaf_log2;
120+
constexpr std::size_t potentially_non_zero_leaves_amount = precomputed_powers_of_two[potentially_non_zero_leaves_amount_log2];
121+
122+
std::array<typename hashes::sha2<256>::block_type, potentially_non_zero_leaves_amount> potentially_non_zero_leaves;
123+
for (std::size_t i = 0; i < potentially_non_zero_leaves_amount; i++) {
124+
// MSB first
125+
typedef __zkllvm_field_pallas_base __attribute__((ext_vector_type(64))) decomposed_int64_type;
126+
127+
decomposed_int64_type first_balance_in_block_bits =
128+
__builtin_assigner_bit_decomposition64(validator_balances[4*i]);
129+
decomposed_int64_type second_balance_in_block_bits =
130+
__builtin_assigner_bit_decomposition64(validator_balances[4*i+1]);
131+
decomposed_int64_type third_balance_in_block_bits =
132+
__builtin_assigner_bit_decomposition64(validator_balances[4*i+2]);
133+
decomposed_int64_type fourth_balance_in_block_bits =
134+
__builtin_assigner_bit_decomposition64(validator_balances[4*i+3]);
135+
136+
typename algebra::curves::pallas::base_field_type::value_type first_block = __builtin_assigner_bit_composition128(
137+
first_balance_in_block_bits, second_balance_in_block_bits);
138+
typename algebra::curves::pallas::base_field_type::value_type second_block = __builtin_assigner_bit_composition128(
139+
third_balance_in_block_bits, fourth_balance_in_block_bits);
140+
141+
potentially_non_zero_leaves[i] = {first_block, second_block};
142+
}
143+
144+
unsigned long long total_balance = 0;
145+
for (std::size_t i = 0; i < validators_amount; i++) {
146+
total_balance += validator_balances[i];
147+
}
148+
149+
typename hashes::sha2<256>::block_type non_zero_balances_subtree_root = hash_layer<potentially_non_zero_leaves_amount>(potentially_non_zero_leaves);
150+
151+
constexpr std::size_t leaves_total_amount_log2 = precomputed_powers_of_two.size();
152+
constexpr std::size_t layer_with_zero_balance_subtrees_roots_size_log2 = leaves_total_amount_log2 - potentially_non_zero_leaves_amount_log2;
153+
constexpr std::size_t layer_with_zero_balance_subtrees_roots_size = precomputed_powers_of_two[layer_with_zero_balance_subtrees_roots_size_log2];
154+
155+
std::array<typename hashes::sha2<256>::block_type, layer_with_zero_balance_subtrees_roots_size> layer_with_zero_balance_subtrees_roots;
156+
layer_with_zero_balance_subtrees_roots[0] = non_zero_balances_subtree_root;
157+
for (std::size_t i = 1; i < layer_with_zero_balance_subtrees_roots_size; i++) {
158+
layer_with_zero_balance_subtrees_roots[i] = {
159+
precomputed_zero_hashes[potentially_non_zero_leaves_amount_log2][0],
160+
precomputed_zero_hashes[potentially_non_zero_leaves_amount_log2][1]
161+
};
162+
}
163+
164+
typename hashes::sha2<256>::block_type root = hash_layer<layer_with_zero_balance_subtrees_roots_size>(layer_with_zero_balance_subtrees_roots);
165+
166+
return (is_same(expected_root, root) && (expected_total_balance == total_balance));
167+
}

examples/inputs/balances_tree.inp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[ { "array": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32] },
2+
{ "vector": ["326522724692461750427768532537390503835","89059515727727869117346995944635890507"] },
3+
{ "int": 180 }]

0 commit comments

Comments
 (0)