1
+ use std:: collections:: HashMap ;
2
+
1
3
use triton_vm:: prelude:: * ;
2
4
3
5
use super :: leaf_index_to_mt_index_and_peak_index:: MmrLeafIndexToMtIndexAndPeakIndex ;
4
- use crate :: arithmetic :: u64 :: div2 :: Div2 ;
6
+ use crate :: hashing :: merkle_step_mem_u64_index :: MerkleStepMemU64Index ;
5
7
use crate :: list:: get:: Get ;
6
8
use crate :: prelude:: * ;
7
-
9
+ use crate :: traits:: basic_snippet:: Reviewer ;
10
+ use crate :: traits:: basic_snippet:: SignOffFingerprint ;
11
+
12
+ /// Check whether a given leaf is a member of a pointed-to [MMR], with the
13
+ /// inclusion proof (the authentication path) residing in RAM.
14
+ ///
15
+ /// ### Behavior
16
+ ///
17
+ /// ```text
18
+ /// BEFORE: _ *peaks [leaf_count: u64] [leaf_index: u64] [leaf: Digest] *auth_path
19
+ /// AFTER: _ [validation_result: bool]
20
+ /// ```
21
+ ///
22
+ /// ### Preconditions
23
+ ///
24
+ /// - all input arguments are properly [`BFieldCodec`] encoded
25
+ /// - input arguments `*peaks` points to a properly [`BFieldCodec`] encoded list
26
+ /// of [`Digest`]s
27
+ /// - input arguments `*auth_path` points to a properly [`BFieldCodec`] encoded
28
+ /// list of [`Digest`]s
29
+ /// - the `leaf_count` is consistent with the pointed-to MMR
30
+ /// - the `leaf_index` is smaller than the `leaf_count`
31
+ ///
32
+ /// ### Postconditions
33
+ ///
34
+ /// - all output is properly [`BFieldCodec`] encoded
35
+ ///
36
+ /// [MMR]: twenty_first::util_types::mmr::mmr_accumulator::MmrAccumulator
8
37
#[ derive( Debug , Default , Copy , Clone , Eq , PartialEq , Hash ) ]
9
38
pub struct MmrVerifyFromMemory ;
10
39
11
- impl MmrVerifyFromMemory { }
12
-
13
40
impl BasicSnippet for MmrVerifyFromMemory {
14
41
fn inputs ( & self ) -> Vec < ( DataType , String ) > {
15
42
let list_type = DataType :: List ( Box :: new ( DataType :: Digest ) ) ;
@@ -34,16 +61,14 @@ impl BasicSnippet for MmrVerifyFromMemory {
34
61
fn code ( & self , library : & mut Library ) -> Vec < LabelledInstruction > {
35
62
let leaf_index_to_mt_index = library. import ( Box :: new ( MmrLeafIndexToMtIndexAndPeakIndex ) ) ;
36
63
let get_list_element = library. import ( Box :: new ( Get :: new ( DataType :: Digest ) ) ) ;
37
- let div_2 = library. import ( Box :: new ( Div2 ) ) ;
64
+ let merkle_step_mem = library. import ( Box :: new ( MerkleStepMemU64Index ) ) ;
38
65
39
66
let entrypoint = self . entrypoint ( ) ;
40
67
let loop_label = format ! ( "{entrypoint}_loop" ) ;
41
- let swap_digests = format ! ( "{entrypoint}_swap_digests" ) ;
42
68
43
69
triton_asm ! (
44
70
// BEFORE: _ *peaks [leaf_count: u64] [leaf_index: u64] [leaf: Digest] *auth_path
45
71
// AFTER: _ validation_result
46
- // Will crash if `leaf_index >= leaf_count`
47
72
{ entrypoint} :
48
73
pick 9 pick 9
49
74
pick 9 pick 9
@@ -53,30 +78,28 @@ impl BasicSnippet for MmrVerifyFromMemory {
53
78
place 8
54
79
// _ *peaks peak_index [leaf: Digest] *auth_path [mt_index: u64]
55
80
56
- pick 7 pick 7 pick 7 pick 7 pick 7
57
- // _ *peaks peak_index *auth_path [mt_index: u64] [leaf: Digest]
81
+ place 7 place 7
82
+ // _ *peaks peak_index [mt_index: u64] [leaf: Digest] *auth_path
58
83
59
- pick 7
60
- addi { Digest :: LEN }
84
+ addi 1
61
85
place 7
86
+ // _ *peaks peak_index *auth_path[0] [mt_index: u64] [leaf: Digest]
62
87
63
88
call { loop_label}
64
- // _ *peaks peak_index *auth_path [1: u64] [peak: Digest]
89
+ // _ *peaks peak_index *auth_path[n] [1: u64] [peak: Digest]
65
90
66
- /* Compare computed `peak` to the `expected_peak `,
67
- * where `expected_peak = peaks[peak_index]`
91
+ /* Compare computed `peak` to `peaks[peak_index] `,
92
+ * which is the expected peak.
68
93
*/
69
94
pick 9 pick 9
70
- // _ *auth_path [1: u64] [acc: Digest] *peaks peak_index
95
+ // _ *auth_path[n] [1: u64] [acc: Digest] *peaks peak_index
71
96
72
97
call { get_list_element}
73
- // _ *auth_path [1: u64] [acc: Digest] [expected_peak: Digest]
98
+ // _ *auth_path[n] [1: u64] [acc: Digest] [expected_peak: Digest]
74
99
75
100
{ & DataType :: Digest . compare( ) }
76
- // _ *auth_path [1: u64] (expected_peak == acc_hash)
77
-
78
- // Rename: expected_peak == acc_hash -> validation_result
79
- // _ *auth_path [1: u64] validation_result
101
+ // _ *auth_path[n] [1: u64] (expected_peak == acc_hash)
102
+ // _ *auth_path[n] [1: u64] validation_result
80
103
81
104
place 3
82
105
pop 3
@@ -85,7 +108,6 @@ impl BasicSnippet for MmrVerifyFromMemory {
85
108
return
86
109
87
110
// INVARIANT: _ *auth_path[n] [mt_index: u64] [acc: Digest]
88
- // todo: use `MerkleStepMemU64Index` to speed up this loop
89
111
{ loop_label} :
90
112
dup 6 push 0 eq
91
113
dup 6 push 1 eq
@@ -95,41 +117,16 @@ impl BasicSnippet for MmrVerifyFromMemory {
95
117
skiz return
96
118
// _ *auth_path[n] [mt_index: u64] [acc: Digest]
97
119
98
- // declare `ap_element = auth_path[i]`
99
- pick 7
100
- read_mem { Digest :: LEN }
101
- addi { Digest :: LEN * 2 }
102
- place 12
103
- // _ *auth_path[n+1] [mt_index: u64] [acc: Digest] [sibling: Digest]
104
-
105
- dup 10
106
- push 1
107
- and
108
- // _ *auth_path[n+1] [mt_index: u64] [acc: Digest] [sibling: Digest] (index%2 == 1)
109
-
110
- push 0
111
- eq
112
- // _ *auth_path[n+1] [mt_index: u64] [acc: Digest] [sibling: Digest] (index%2 == 0)
113
-
114
- skiz call { swap_digests}
115
- // _ *auth_path[n+1] [mt_index: u64] [right_node: Digest] [left_node: Digest]
116
-
117
- hash
118
- // _ *auth_path[n+1] [mt_index: u64] [acc: Digest]
119
-
120
- // mt_index -> mt_index / 2
121
- pick 6 pick 6
122
- call { div_2}
123
- place 6 place 6
124
- // _ *auth_path[n+1] [mt_index / 2: u64] [acc: Digest]
125
-
120
+ call { merkle_step_mem}
126
121
recurse
127
-
128
- { swap_digests} :
129
- pick 9 pick 9 pick 9 pick 9 pick 9
130
- return
131
122
)
132
123
}
124
+
125
+ fn sign_offs ( & self ) -> HashMap < Reviewer , SignOffFingerprint > {
126
+ let mut sign_offs = HashMap :: new ( ) ;
127
+ sign_offs. insert ( Reviewer ( "ferdinand" ) , 0xc35bd96dd2348c49 . into ( ) ) ;
128
+ sign_offs
129
+ }
133
130
}
134
131
135
132
#[ cfg( test) ]
0 commit comments