Skip to content

Commit a89d4c5

Browse files
committed
build node from leafs and final root
1 parent 990edbe commit a89d4c5

File tree

9 files changed

+140
-79
lines changed

9 files changed

+140
-79
lines changed

circuits/app/proof_of_reserve/coins/src/main.nr

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// First proof
2+
// Checks if user own coresponding utxos and acumulate amount
3+
14
mod constants;
25

36
use constants::MAX_COINS_DATABASE_AMOUNT;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "nodes_tree"
3+
type = "bin"
4+
authors = [""]
5+
6+
[dependencies]
7+
utils = { path = "../../../crates/utils" }
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pub global MAX_MERKLE_TREE_LEVELS: u32 = 3;
2+
pub global MAX_NODES_AMOUNT: u32 = 3;
3+
4+
pub global HONK_VK_SIZE: u32 = 128;
5+
pub global HONK_PROOF_SIZE: u32 = 456;
6+
pub global HONK_IDENTIFIER: u32 = 1;
7+
pub global PUBLIC_INPUTS: u32 = 33;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Third proof
2+
// Build root from many nodes
3+
4+
mod constants;
5+
6+
use constants::{
7+
HONK_IDENTIFIER, HONK_PROOF_SIZE, HONK_VK_SIZE,
8+
MAX_MERKLE_TREE_LEVELS, PUBLIC_INPUTS, MAX_NODES_AMOUNT
9+
};
10+
use utils::merkle_root::merkle_root;
11+
12+
struct NodeProof {
13+
proof: [Field; HONK_PROOF_SIZE],
14+
public_inputs: [Field; PUBLIC_INPUTS],
15+
}
16+
17+
fn main(
18+
verification_key: [Field; HONK_VK_SIZE],
19+
node_proofs: [NodeProof; MAX_NODES_AMOUNT]
20+
) -> pub ([u8; 32], u64) {
21+
let mut nodes = [[0; 32]; MAX_NODES_AMOUNT];
22+
let mut owned_amount = 0;
23+
24+
for i in 0..MAX_NODES_AMOUNT {
25+
std::verify_proof_with_type(verification_key, node_proofs[i].proof, node_proofs[i].public_inputs, 0x0, HONK_IDENTIFIER);
26+
for j in 0..32 {
27+
nodes[i][j] = node_proofs[i].public_inputs[j] as u8;
28+
}
29+
30+
owned_amount += node_proofs[i].public_inputs[32] as u64;
31+
}
32+
33+
(merkle_root::<MAX_NODES_AMOUNT, MAX_MERKLE_TREE_LEVELS>(nodes), owned_amount)
34+
}

circuits/app/proof_of_reserve/utxos_tree/Nargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ name = "utxos_tree"
33
type = "bin"
44

55
[dependencies]
6-
sha256 = { tag = "v0.1.0", git = "https://github.com/noir-lang/sha256" }
6+
utils = { path = "../../../crates/utils" }
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
pub global MAX_MERKLE_TREE_LEVELS: u32 = 6;
1+
pub global MAX_COINS_DATABASE_AMOUNT: u32 = 3;
2+
pub global MAX_MERKLE_TREE_LEVELS: u32 = 3;
3+
4+
pub global HONK_VK_SIZE: u32 = 128;
5+
pub global HONK_PROOF_SIZE: u32 = 456;
6+
pub global HONK_IDENTIFIER: u32 = 1;
7+
pub global PUBLIC_INPUTS: u32 = 32 + 32 * MAX_COINS_DATABASE_AMOUNT + 1;
Lines changed: 24 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,30 @@
1-
mod constants;
2-
3-
use constants::MAX_MERKLE_TREE_LEVELS;
4-
use std::cmp::max;
5-
6-
fn main() {
7-
// let mut utxos = [[0; 32]; MAX_COINS_DATABASE_AMOUNT];
8-
9-
// for i in 0..MAX_COINS_DATABASE_AMOUNT {
10-
// // There is a bug with append, so we fill the array manually
11-
// let mut utx_bytes = [0; 33];
12-
13-
// let amount_bytes = u64_to_be_bytes(coins_database[i].amount);
14-
// for j in 0..8 {
15-
// utx_bytes[j] = amount_bytes[j];
16-
// }
17-
18-
// for j in 0..25 {
19-
// utx_bytes[j + 8] = coins_database[i].script_pub_key[j];
20-
// }
21-
22-
// utxos[i] = if coins_database[i].amount != 0 {
23-
// sha256::digest(utx_bytes)
24-
// } else {
25-
// [0; 32]
26-
// };
27-
// }
28-
29-
// (merkle_root(utxos), 0)
30-
}
1+
// Second proof
2+
// Build node from one chunk leafs
313

32-
fn hash(leaf1: [u8; 32], leaf2: [u8; 32]) -> [u8; 32] {
33-
sha256::digest(leaf1.as_slice().append(leaf2).as_array::<64>())
34-
}
35-
36-
fn merkle_root<let N: u32>(mut leafs: [[u8; 32]; N]) -> [u8; 32] {
37-
assert((N as Field).lt(2.pow_32(MAX_MERKLE_TREE_LEVELS as Field)));
38-
let mut mtree = [[0; 32]; MAX_MERKLE_TREE_LEVELS];
39-
let mut last_level = 0;
40-
41-
for i in 0..N {
42-
let mut leaf = leafs[i];
43-
for j in 0..MAX_MERKLE_TREE_LEVELS {
44-
if !leaf.all(|e| e == 0) {
45-
if mtree[j].all(|e| e == 0) {
46-
mtree[j] = leaf;
47-
leaf = [0; 32];
48-
} else {
49-
leaf = hash(mtree[j], leaf);
50-
mtree[j] = [0; 32];
51-
}
52-
last_level = max(j, last_level);
53-
}
54-
}
55-
}
56-
57-
let mut tmp_node = [0; 32];
58-
for i in 0..MAX_MERKLE_TREE_LEVELS {
59-
if (
60-
(i < last_level & tmp_node.all(|e| e == 0))
61-
| (i <= last_level & !tmp_node.all(|e| e == 0))
62-
) {
63-
if !mtree[i].all(|e| e == 0) {
64-
let right = if tmp_node.all(|e| e == 0) {
65-
mtree[i]
66-
} else {
67-
tmp_node
68-
};
4+
mod constants;
695

70-
tmp_node = hash(mtree[i], right);
71-
mtree[i] = [0; 32];
72-
} else if !tmp_node.all(|e| e == 0) {
73-
tmp_node = hash(tmp_node, tmp_node);
74-
}
6+
use constants::{
7+
HONK_IDENTIFIER, HONK_PROOF_SIZE, HONK_VK_SIZE, MAX_COINS_DATABASE_AMOUNT,
8+
MAX_MERKLE_TREE_LEVELS, PUBLIC_INPUTS,
9+
};
10+
use utils::merkle_root::merkle_root;
11+
12+
fn main(
13+
verification_key: [Field; HONK_VK_SIZE],
14+
proof: [Field; HONK_PROOF_SIZE],
15+
public_inputs: [Field; PUBLIC_INPUTS],
16+
) -> pub ([u8; 32], u64) {
17+
std::verify_proof_with_type(verification_key, proof, public_inputs, 0x0, HONK_IDENTIFIER);
18+
let mut leafs = [[0; 32]; MAX_COINS_DATABASE_AMOUNT];
19+
20+
for i in 0..MAX_COINS_DATABASE_AMOUNT {
21+
for j in 0..32 {
22+
leafs[i][j] = public_inputs[i * 32 + 32 + j] as u8;
7523
}
7624
}
7725

78-
if tmp_node.all(|e| e == 0) {
79-
mtree[last_level]
80-
} else {
81-
tmp_node
82-
}
26+
(
27+
merkle_root::<MAX_COINS_DATABASE_AMOUNT, MAX_MERKLE_TREE_LEVELS>(leafs),
28+
public_inputs[MAX_COINS_DATABASE_AMOUNT * 32 + 32] as u64,
29+
)
8330
}

circuits/crates/utils/src/lib.nr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod convert;
22
pub mod encode;
33
pub mod decode;
4+
pub mod merkle_root;
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use std::cmp::max;
2+
3+
fn hash(leaf1: [u8; 32], leaf2: [u8; 32]) -> [u8; 32] {
4+
sha256::digest(leaf1.as_slice().append(leaf2).as_array::<64>())
5+
}
6+
7+
pub fn merkle_root<let N: u32, let MAX_MERKLE_TREE_LEVELS: u32>(
8+
mut leafs: [[u8; 32]; N],
9+
) -> [u8; 32] {
10+
assert((N as Field).lt(2.pow_32(MAX_MERKLE_TREE_LEVELS as Field)));
11+
let mut mtree = [[0; 32]; MAX_MERKLE_TREE_LEVELS];
12+
let mut last_level = 0;
13+
14+
for i in 0..N {
15+
let mut leaf = leafs[i];
16+
for j in 0..MAX_MERKLE_TREE_LEVELS {
17+
if !leaf.all(|e| e == 0) {
18+
if mtree[j].all(|e| e == 0) {
19+
mtree[j] = leaf;
20+
leaf = [0; 32];
21+
} else {
22+
leaf = hash(mtree[j], leaf);
23+
mtree[j] = [0; 32];
24+
}
25+
last_level = max(j, last_level);
26+
}
27+
}
28+
}
29+
30+
let mut tmp_node = [0; 32];
31+
for i in 0..MAX_MERKLE_TREE_LEVELS {
32+
if (
33+
(i < last_level & tmp_node.all(|e| e == 0))
34+
| (i <= last_level & !tmp_node.all(|e| e == 0))
35+
) {
36+
if !mtree[i].all(|e| e == 0) {
37+
let right = if tmp_node.all(|e| e == 0) {
38+
mtree[i]
39+
} else {
40+
tmp_node
41+
};
42+
43+
tmp_node = hash(mtree[i], right);
44+
mtree[i] = [0; 32];
45+
} else if !tmp_node.all(|e| e == 0) {
46+
tmp_node = hash(tmp_node, tmp_node);
47+
}
48+
}
49+
}
50+
51+
if tmp_node.all(|e| e == 0) {
52+
mtree[last_level]
53+
} else {
54+
tmp_node
55+
}
56+
}

0 commit comments

Comments
 (0)