1
1
use crate :: error:: MerkleTreeError ;
2
- use crate :: merkle_tree:: leaf :: MTLeaf ;
3
- use crate :: merkle_tree:: tree :: { parent , sibling } ;
2
+ use crate :: merkle_tree:: { parent , sibling } ;
3
+ use crate :: merkle_tree:: { BatchPath , MTLeaf , Path } ;
4
4
use blake2:: digest:: { Digest , FixedOutput } ;
5
5
use serde:: { Deserialize , Serialize } ;
6
6
use std:: marker:: PhantomData ;
7
7
8
- /// Path of hashes for a batch of indices .
9
- /// Contains the hashes and the corresponding merkle tree indices of given batch .
10
- /// Used to verify the signatures are issued by the registered signers .
11
- #[ derive( Default , Clone , Debug , PartialEq , Eq , Serialize , Deserialize ) ]
12
- pub struct BatchPath < D : Digest + FixedOutput > {
13
- pub ( crate ) values : Vec < Vec < u8 > > ,
14
- pub ( crate ) indices : Vec < usize > ,
15
- pub ( crate ) hasher : PhantomData < D > ,
8
+ /// `MerkleTree` commitment .
9
+ /// This structure differs from `MerkleTree` in that it does not contain all elements, which are not always necessary .
10
+ /// Instead, it only contains the root of the tree .
11
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
12
+ pub struct MerkleTreeCommitment < D : Digest > {
13
+ /// Root of the merkle commitment.
14
+ pub root : Vec < u8 > ,
15
+ hasher : PhantomData < D > ,
16
16
}
17
17
18
- impl < D : Digest + FixedOutput > BatchPath < D > {
19
- pub ( crate ) fn new ( values : Vec < Vec < u8 > > , indices : Vec < usize > ) -> BatchPath < D > {
20
- Self {
21
- values,
22
- indices,
23
- hasher : Default :: default ( ) ,
18
+ impl < D : Digest + FixedOutput > MerkleTreeCommitment < D > {
19
+ pub ( crate ) fn new ( root : Vec < u8 > ) -> Self {
20
+ MerkleTreeCommitment {
21
+ root,
22
+ hasher : PhantomData ,
24
23
}
25
24
}
26
25
27
- /// Convert the `BatchPath` into byte representation.
28
- ///
29
- /// # Layout
30
- /// The layout of a `BatchPath` is
31
- /// * Length of values
32
- /// * Length of indices
33
- /// * Values
34
- /// * Indices
35
- pub fn to_bytes ( & self ) -> Vec < u8 > {
36
- let mut output = Vec :: new ( ) ;
37
- let len_v = self . values . len ( ) ;
38
- let len_i = self . indices . len ( ) ;
39
-
40
- output. extend_from_slice ( & u64:: try_from ( len_v) . unwrap ( ) . to_be_bytes ( ) ) ;
41
- output. extend_from_slice ( & u64:: try_from ( len_i) . unwrap ( ) . to_be_bytes ( ) ) ;
42
-
43
- for value in & self . values {
44
- output. extend_from_slice ( value. as_slice ( ) )
26
+ /// Check an inclusion proof that `val` is part of the tree by traveling the whole path until the root.
27
+ /// # Error
28
+ /// If the merkle tree path is invalid, then the function fails.
29
+ pub fn check ( & self , val : & MTLeaf , proof : & Path < D > ) -> Result < ( ) , MerkleTreeError < D > >
30
+ where
31
+ D : FixedOutput + Clone ,
32
+ {
33
+ let mut idx = proof. index ;
34
+
35
+ let mut h = D :: digest ( val. to_bytes ( ) ) . to_vec ( ) ;
36
+ for p in & proof. values {
37
+ if ( idx & 0b1 ) == 0 {
38
+ h = D :: new ( ) . chain_update ( h) . chain_update ( p) . finalize ( ) . to_vec ( ) ;
39
+ } else {
40
+ h = D :: new ( ) . chain_update ( p) . chain_update ( h) . finalize ( ) . to_vec ( ) ;
41
+ }
42
+ idx >>= 1 ;
45
43
}
46
44
47
- for & index in & self . indices {
48
- output . extend_from_slice ( & u64 :: try_from ( index ) . unwrap ( ) . to_be_bytes ( ) ) ;
45
+ if h == self . root {
46
+ return Ok ( ( ) ) ;
49
47
}
50
- output
48
+ Err ( MerkleTreeError :: PathInvalid ( proof . clone ( ) ) )
51
49
}
52
50
53
- /// Try to convert a byte string into a `BatchPath`.
54
- // todo: We should not panic if the size of the slice is invalid (I believe `bytes[offset + i * 8..offset + (i + 1) * 8]` will panic if bytes is not large enough.
55
- pub fn from_bytes ( bytes : & [ u8 ] ) -> Result < Self , MerkleTreeError < D > > {
56
- let mut u64_bytes = [ 0u8 ; 8 ] ;
57
- u64_bytes. copy_from_slice ( & bytes[ ..8 ] ) ;
58
- let len_v = usize:: try_from ( u64:: from_be_bytes ( u64_bytes) )
59
- . map_err ( |_| MerkleTreeError :: SerializationError ) ?;
60
-
61
- u64_bytes. copy_from_slice ( & bytes[ 8 ..16 ] ) ;
62
- let len_i = usize:: try_from ( u64:: from_be_bytes ( u64_bytes) )
63
- . map_err ( |_| MerkleTreeError :: SerializationError ) ?;
64
-
65
- let mut values = Vec :: with_capacity ( len_v) ;
66
- for i in 0 ..len_v {
67
- values. push (
68
- bytes[ 16 + i * <D as Digest >:: output_size ( )
69
- ..16 + ( i + 1 ) * <D as Digest >:: output_size ( ) ]
70
- . to_vec ( ) ,
71
- ) ;
72
- }
73
- let offset = 16 + len_v * <D as Digest >:: output_size ( ) ;
74
-
75
- let mut indices = Vec :: with_capacity ( len_v) ;
76
- for i in 0 ..len_i {
77
- u64_bytes. copy_from_slice ( & bytes[ offset + i * 8 ..offset + ( i + 1 ) * 8 ] ) ;
78
- indices. push (
79
- usize:: try_from ( u64:: from_be_bytes ( u64_bytes) )
80
- . map_err ( |_| MerkleTreeError :: SerializationError ) ?,
81
- ) ;
82
- }
51
+ /// Serializes the Merkle Tree commitment together with a message in a single vector of bytes.
52
+ /// Outputs `msg || self` as a vector of bytes.
53
+ pub fn concat_with_msg ( & self , msg : & [ u8 ] ) -> Vec < u8 >
54
+ where
55
+ D : Digest ,
56
+ {
57
+ let mut msgp = msg. to_vec ( ) ;
58
+ let mut bytes = self . root . clone ( ) ;
59
+ msgp. append ( & mut bytes) ;
83
60
84
- Ok ( BatchPath {
85
- values,
86
- indices,
87
- hasher : PhantomData ,
88
- } )
61
+ msgp
89
62
}
90
63
}
91
64
@@ -110,7 +83,7 @@ impl<D: Digest> MerkleTreeCommitmentBatchCompat<D> {
110
83
}
111
84
}
112
85
113
- #[ allow ( dead_code ) ]
86
+ #[ cfg ( test ) ]
114
87
/// Used in property test of `tree`: `test_bytes_tree_commitment_batch_compat`
115
88
pub ( crate ) fn get_nr_leaves ( & self ) -> usize {
116
89
self . nr_leaves
@@ -119,8 +92,7 @@ impl<D: Digest> MerkleTreeCommitmentBatchCompat<D> {
119
92
/// Serializes the Merkle Tree commitment together with a message in a single vector of bytes.
120
93
/// Outputs `msg || self` as a vector of bytes.
121
94
// todo: Do we need to concat msg to whole commitment (nr_leaves and root) or just the root?
122
- pub fn concat_with_msg ( & self , msg : & [ u8 ] ) -> Vec < u8 >
123
- {
95
+ pub fn concat_with_msg ( & self , msg : & [ u8 ] ) -> Vec < u8 > {
124
96
let mut msgp = msg. to_vec ( ) ;
125
97
let mut bytes = self . root . clone ( ) ;
126
98
msgp. append ( & mut bytes) ;
0 commit comments