Skip to content

Commit 655ca1f

Browse files
committed
signoff: mmr::verify_from_memory
Also, improve its performance. 🙂
1 parent 2af7c95 commit 655ca1f

File tree

2 files changed

+58
-61
lines changed

2 files changed

+58
-61
lines changed

tasm-lib/benchmarks/tasmlib_mmr_verify_from_memory.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,21 @@
22
{
33
"name": "tasmlib_mmr_verify_from_memory",
44
"benchmark_result": {
5-
"clock_cycle_count": 1317,
6-
"hash_table_height": 396,
7-
"u32_table_height": 1409,
8-
"op_stack_table_height": 1026,
5+
"clock_cycle_count": 817,
6+
"hash_table_height": 366,
7+
"u32_table_height": 848,
8+
"op_stack_table_height": 468,
99
"ram_table_height": 161
1010
},
1111
"case": "CommonCase"
1212
},
1313
{
1414
"name": "tasmlib_mmr_verify_from_memory",
1515
"benchmark_result": {
16-
"clock_cycle_count": 2477,
17-
"hash_table_height": 582,
18-
"u32_table_height": 1568,
19-
"op_stack_table_height": 1966,
16+
"clock_cycle_count": 1481,
17+
"hash_table_height": 552,
18+
"u32_table_height": 1010,
19+
"op_stack_table_height": 850,
2020
"ram_table_height": 316
2121
},
2222
"case": "WorstCase"

tasm-lib/src/mmr/verify_from_memory.rs

Lines changed: 50 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,42 @@
1+
use std::collections::HashMap;
2+
13
use triton_vm::prelude::*;
24

35
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;
57
use crate::list::get::Get;
68
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
837
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
938
pub struct MmrVerifyFromMemory;
1039

11-
impl MmrVerifyFromMemory {}
12-
1340
impl BasicSnippet for MmrVerifyFromMemory {
1441
fn inputs(&self) -> Vec<(DataType, String)> {
1542
let list_type = DataType::List(Box::new(DataType::Digest));
@@ -34,16 +61,14 @@ impl BasicSnippet for MmrVerifyFromMemory {
3461
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
3562
let leaf_index_to_mt_index = library.import(Box::new(MmrLeafIndexToMtIndexAndPeakIndex));
3663
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));
3865

3966
let entrypoint = self.entrypoint();
4067
let loop_label = format!("{entrypoint}_loop");
41-
let swap_digests = format!("{entrypoint}_swap_digests");
4268

4369
triton_asm!(
4470
// BEFORE: _ *peaks [leaf_count: u64] [leaf_index: u64] [leaf: Digest] *auth_path
4571
// AFTER: _ validation_result
46-
// Will crash if `leaf_index >= leaf_count`
4772
{entrypoint}:
4873
pick 9 pick 9
4974
pick 9 pick 9
@@ -53,30 +78,28 @@ impl BasicSnippet for MmrVerifyFromMemory {
5378
place 8
5479
// _ *peaks peak_index [leaf: Digest] *auth_path [mt_index: u64]
5580

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
5883

59-
pick 7
60-
addi {Digest::LEN}
84+
addi 1
6185
place 7
86+
// _ *peaks peak_index *auth_path[0] [mt_index: u64] [leaf: Digest]
6287

6388
call {loop_label}
64-
// _ *peaks peak_index *auth_path [1: u64] [peak: Digest]
89+
// _ *peaks peak_index *auth_path[n] [1: u64] [peak: Digest]
6590

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.
6893
*/
6994
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
7196

7297
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]
7499

75100
{&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
80103

81104
place 3
82105
pop 3
@@ -85,7 +108,6 @@ impl BasicSnippet for MmrVerifyFromMemory {
85108
return
86109

87110
// INVARIANT: _ *auth_path[n] [mt_index: u64] [acc: Digest]
88-
// todo: use `MerkleStepMemU64Index` to speed up this loop
89111
{loop_label}:
90112
dup 6 push 0 eq
91113
dup 6 push 1 eq
@@ -95,41 +117,16 @@ impl BasicSnippet for MmrVerifyFromMemory {
95117
skiz return
96118
// _ *auth_path[n] [mt_index: u64] [acc: Digest]
97119

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}
126121
recurse
127-
128-
{swap_digests}:
129-
pick 9 pick 9 pick 9 pick 9 pick 9
130-
return
131122
)
132123
}
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+
}
133130
}
134131

135132
#[cfg(test)]

0 commit comments

Comments
 (0)