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

Add MerkleSet struct to Rust #454

Merged
merged 70 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
81216a9
rebase merkle_vec
matt-o-how Apr 3, 2024
c145830
fmt
matt-o-how Apr 3, 2024
b517fd6
clippy
matt-o-how Apr 3, 2024
050f532
manual stub update
matt-o-how Apr 3, 2024
f9ac666
test CI fix
matt-o-how Apr 4, 2024
2b2de50
fix syntax
matt-o-how Apr 4, 2024
810d94d
add merkle_set to pyi and generate_stubs
matt-o-how Apr 5, 2024
ae88f58
add stub for deserialize_proof
matt-o-how Apr 5, 2024
ca271d4
fixes for Arvid's comments
matt-o-how Apr 5, 2024
607dedd
black test
matt-o-how Apr 5, 2024
13449dc
move test code to test mod
matt-o-how Apr 5, 2024
31a325a
fmt
matt-o-how Apr 5, 2024
c1cb05b
add comments / syntax fixes
matt-o-how Apr 8, 2024
2955484
apply changes to correct file
matt-o-how Apr 8, 2024
3056623
fix bad proof catching
matt-o-how Apr 8, 2024
366fda4
another fmt
matt-o-how Apr 8, 2024
812fec8
delete automated stubs
matt-o-how Apr 9, 2024
2ac8e59
move tests back into merkle_set
matt-o-how Apr 9, 2024
309a24f
delete wheel cargo.lock
matt-o-how Apr 9, 2024
c71cb5b
add `new` constructor for MerkleSet
matt-o-how Apr 10, 2024
57246b7
make BLANK pub(crate)
matt-o-how Apr 10, 2024
a99d7ee
store nodes as u32 rather than usize
matt-o-how Apr 10, 2024
2ce911c
make merkleset attributes private and split tests
matt-o-how Apr 10, 2024
db2b5df
cargo fmt
matt-o-how Apr 10, 2024
c80a78b
restore unnecessary changes to merkle_set.rs. simplify and fix issues…
arvidn Apr 13, 2024
ba9a2d9
fix parsing malicious proof
arvidn Apr 13, 2024
06f1cf6
more efficient proof parser
arvidn Apr 13, 2024
1c2c78b
use tuple instead of struct for ArrayTypes
arvidn Apr 13, 2024
fb77b28
report conversion errors in python binding
arvidn Apr 13, 2024
5aa2e38
optimize away leaf_vec from MerkleSet
arvidn Apr 13, 2024
3ae8e28
turn generate_merkle_tree into a constructor (from_leaf())
arvidn Apr 13, 2024
8c6c3a1
turn deserialize_proof() into a MerkleSet constructor, from_leaf()
arvidn Apr 13, 2024
a7aac63
combine nodes_vec and hash_cache into a single vector
arvidn Apr 13, 2024
c6b0aeb
convert array_type_to_node_type() to implement the From trait. and so…
arvidn Apr 14, 2024
a1d6dc9
add negative test cases to generate_proof(). minor simplifications
arvidn Apr 14, 2024
d1ad40b
fix typo in merkle proof protocol constants
arvidn Apr 14, 2024
434a7fa
add python fidelity test for MerkleSet
arvidn Apr 14, 2024
999d336
simplify proof generation to truncate the sub tree we're not traversing
arvidn Apr 14, 2024
b900bf9
add fuzzer for deserialize proof
arvidn Apr 15, 2024
b692a78
black test
matt-o-how Apr 15, 2024
76c3ba5
simplify merkle_set test
arvidn Apr 15, 2024
0fe3089
add merkle-set benchmark
arvidn Apr 15, 2024
b87c205
add fuzzer for merkle-set
arvidn Apr 15, 2024
e06b954
make get_root() return a bytes32
arvidn Apr 16, 2024
e403fff
allow BLANK to be accessed bny merkle_tree
matt-o-how Apr 16, 2024
f475af6
readd test that got lost from rebase
matt-o-how Apr 16, 2024
f20a4d8
generate proofs that include redundant empty nodes, even though the t…
matt-o-how Apr 16, 2024
47fdc29
port merkle test cases from rust to python tests
arvidn Apr 18, 2024
24db419
comment proof parsing and generation, about how hashes are computed o…
arvidn Apr 18, 2024
c45e864
Merge pull request #470 from Chia-Network/correct-proof-generation
matt-o-how Apr 18, 2024
b62ced6
improve and fix merkle_set tests
arvidn Apr 18, 2024
5a730da
Merge pull request #472 from Chia-Network/merkle-tests2
matt-o-how Apr 18, 2024
1e39f8c
use hex instead of array of ints
arvidn Apr 18, 2024
fc605da
add test for padding/expanding collapsed tree levels when generating …
arvidn Apr 18, 2024
f3505d8
add proof audit
matt-o-how Apr 18, 2024
31bb684
cargo fmt
matt-o-how Apr 18, 2024
1bc9279
save indentation layer
matt-o-how Apr 18, 2024
c8692c7
fmt
matt-o-how Apr 18, 2024
9c0794b
add test that asserts proof deserialization fails the audit when pass…
matt-o-how Apr 18, 2024
f5e733d
rebase
matt-o-how Apr 18, 2024
152d763
flag test
matt-o-how Apr 18, 2024
603e459
fmt test
matt-o-how Apr 18, 2024
478322f
use 0x80 for test
matt-o-how Apr 18, 2024
2614e97
Merge pull request #473 from Chia-Network/proof_audit
matt-o-how Apr 18, 2024
944088c
Merge pull request #474 from Chia-Network/test-proofs
arvidn Apr 18, 2024
f54e6e1
rename get_merkle_root() -> get_root(). Merkle is implied and this ma…
arvidn Apr 19, 2024
6807871
Merge pull request #475 from Chia-Network/merkle-root
arvidn Apr 19, 2024
c3773e4
use the merkle_set.py from chia-blockchain to test against
arvidn Apr 19, 2024
899668e
reformat merkle_set.py, since we appear to have different black setti…
arvidn Apr 19, 2024
b3c93de
Merge pull request #476 from Chia-Network/merkle-set-from-blockchain
matt-o-how Apr 19, 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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions crates/chia-consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ num-traits = "0.2.15"
rstest = "0.16.0"
text-diff = "0.4.0"
criterion = "0.5.1"
rand = { version = "0.8.5", features = [ "small_rng" ] }

[lib]
bench = false
Expand All @@ -43,3 +44,7 @@ harness = false
[[bench]]
name = "tree-hash"
harness = false

[[bench]]
name = "merkle-set"
harness = false
60 changes: 60 additions & 0 deletions crates/chia-consensus/benches/merkle-set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use chia_consensus::merkle_tree::MerkleSet;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use rand::rngs::SmallRng;
use rand::{Rng, SeedableRng};
use std::time::Instant;

fn run(c: &mut Criterion) {
let mut group = c.benchmark_group("merkle-set");

let mut rng = SmallRng::seed_from_u64(1337);

let mut leafs = Vec::<[u8; 32]>::with_capacity(1000);
for _ in 0..1000 {
let mut item = [0_u8; 32];
rng.fill(&mut item);
leafs.push(item);
}

group.bench_function("from_leafs", |b| {
b.iter(|| {
let start = Instant::now();
let _ = black_box(MerkleSet::from_leafs(&mut leafs));
start.elapsed()
})
});

let tree = MerkleSet::from_leafs(&mut leafs);

group.bench_function("generate_proof", |b| {
b.iter(|| {
let start = Instant::now();
for item in &leafs {
let _ = black_box(tree.generate_proof(&item));
}
start.elapsed()
})
});

let mut proofs = Vec::<Vec<u8>>::with_capacity(leafs.len());
for item in &leafs {
proofs.push(
tree.generate_proof(&item)
.expect("failed to generate proof")
.expect("item not found"),
);
}

group.bench_function("deserialize_proof", |b| {
b.iter(|| {
let start = Instant::now();
for p in &proofs {
let _ = black_box(MerkleSet::from_proof(&p));
}
start.elapsed()
})
});
}

criterion_group!(merkle_set, run);
criterion_main!(merkle_set);
14 changes: 14 additions & 0 deletions crates/chia-consensus/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,17 @@ path = "fuzz_targets/parse-spend-id.rs"
test = false
doc = false
bench = false

[[bin]]
name = "deserialize-proof"
path = "fuzz_targets/deserialize-proof.rs"
test = false
doc = false
bench = false

[[bin]]
name = "merkle-set"
path = "fuzz_targets/merkle-set.rs"
test = false
doc = false
bench = false
8 changes: 8 additions & 0 deletions crates/chia-consensus/fuzz/fuzz_targets/deserialize-proof.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![no_main]
use libfuzzer_sys::fuzz_target;

use chia_consensus::merkle_tree::MerkleSet;

fuzz_target!(|data: &[u8]| {
let _r = MerkleSet::from_proof(data);
});
28 changes: 28 additions & 0 deletions crates/chia-consensus/fuzz/fuzz_targets/merkle-set.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#![no_main]
use chia_consensus::merkle_tree::MerkleSet;
use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
let mut input = data;
let num_leafs = input.len() / 32;
let mut leafs = Vec::<[u8; 32]>::with_capacity(num_leafs);
for _ in 0..num_leafs {
leafs.push(input[..32].try_into().unwrap());
input = &input[32..];
}

let tree = MerkleSet::from_leafs(&mut leafs);

for item in &leafs {
let proof = tree
.generate_proof(item)
.expect("failed to generate proof")
.expect("item not found");
let rebuilt = MerkleSet::from_proof(&proof).expect("failed to parse proof");
assert!(rebuilt
.generate_proof(item)
.expect("failed to validate proof")
.is_some());
assert_eq!(rebuilt.get_root(), tree.get_root());
}
});
1 change: 1 addition & 0 deletions crates/chia-consensus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub mod fast_forward;
pub mod gen;
pub mod generator_rom;
pub mod merkle_set;
pub mod merkle_tree;
16 changes: 11 additions & 5 deletions crates/chia-consensus/src/merkle_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn get_bit(val: &[u8; 32], bit: u8) -> u8 {

#[repr(u8)]
#[derive(PartialEq, Eq, Copy, Clone)]
enum NodeType {
pub(crate) enum NodeType {
Empty,
Term,
Mid,
Expand All @@ -27,7 +27,12 @@ fn encode_type(t: NodeType) -> u8 {
}
}

fn hash(ltype: NodeType, rtype: NodeType, left: &[u8; 32], right: &[u8; 32]) -> [u8; 32] {
pub(crate) fn hash(
ltype: NodeType,
rtype: NodeType,
left: &[u8; 32],
right: &[u8; 32],
) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(hex!(
"000000000000000000000000000000000000000000000000000000000000"
Expand All @@ -38,7 +43,8 @@ fn hash(ltype: NodeType, rtype: NodeType, left: &[u8; 32], right: &[u8; 32]) ->
hasher.finalize().into()
}

const BLANK: [u8; 32] = hex!("0000000000000000000000000000000000000000000000000000000000000000");
pub(crate) const BLANK: [u8; 32] =
hex!("0000000000000000000000000000000000000000000000000000000000000000");

// this function performs an in-place, recursive radix sort of the range.
// as each level returns, values are hashed pair-wise and as a hash tree.
Expand Down Expand Up @@ -171,7 +177,7 @@ pub fn compute_merkle_set_root(leafs: &mut [[u8; 32]]) -> [u8; 32] {
}

#[cfg(test)]
mod test {
pub mod test {
use super::*;

fn h2(buf1: &[u8], buf2: &[u8]) -> [u8; 32] {
Expand Down Expand Up @@ -399,7 +405,7 @@ mod test {
// c b
}

fn merkle_set_test_cases() -> Vec<([u8; 32], Vec<[u8; 32]>)> {
pub fn merkle_set_test_cases() -> Vec<([u8; 32], Vec<[u8; 32]>)> {
let a = hex!("7000000000000000000000000000000000000000000000000000000000000000");
let b = hex!("7100000000000000000000000000000000000000000000000000000000000000");
let c = hex!("8000000000000000000000000000000000000000000000000000000000000000");
Expand Down
Loading
Loading