From 489f889ae29a34e470275f601cdea95d80b50698 Mon Sep 17 00:00:00 2001
From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com>
Date: Tue, 28 May 2024 12:06:09 +0200
Subject: [PATCH 01/14] feat: migrate to new padding rule
---
assembly/src/assembler/instruction/crypto_ops.rs | 11 ++++++-----
core/Cargo.toml | 2 +-
processor/src/host/mod.rs | 2 --
stdlib/asm/crypto/hashes/native.masm | 10 +++++-----
stdlib/asm/mem.masm | 15 ++++++++-------
5 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/assembly/src/assembler/instruction/crypto_ops.rs b/assembly/src/assembler/instruction/crypto_ops.rs
index d59867fe5b..47ce8c29dd 100644
--- a/assembly/src/assembler/instruction/crypto_ops.rs
+++ b/assembly/src/assembler/instruction/crypto_ops.rs
@@ -1,5 +1,5 @@
use super::SpanBuilder;
-use vm_core::{AdviceInjector, Operation::*};
+use vm_core::{AdviceInjector, Felt, Operation::*};
// HASHING
// ================================================================================================
@@ -26,14 +26,15 @@ use vm_core::{AdviceInjector, Operation::*};
pub(super) fn hash(span: &mut SpanBuilder) {
#[rustfmt::skip]
let ops = [
- // add 4 elements to the stack to be used as the capacity elements for the RPO permutation
- Pad, Incr, Pad, Pad, Pad,
+ // add 4 elements to the stack to be used as the capacity elements for the RPO permutation.
+ // Since we are hashing 4 field elements, the first capacity element is set to 4.
+ Push(Felt::from(4_u32)), Pad, Pad, Pad,
// swap capacity elements such that they are below the elements to be hashed
SwapW,
- // Duplicate capacity elements in the rate portion of the stack
- Dup7, Dup7, Dup7, Dup7,
+ // add 4 ZERO elements for the second half of the rate portion
+ Pad, Dup7, Dup7, Dup7,
// Apply a hashing permutation on the top 12 elements in the stack
HPerm,
diff --git a/core/Cargo.toml b/core/Cargo.toml
index 261c9066f5..78460f9772 100644
--- a/core/Cargo.toml
+++ b/core/Cargo.toml
@@ -29,7 +29,7 @@ std = [
[dependencies]
math = { package = "winter-math", version = "0.9", default-features = false }
#miden-crypto = { version = "0.9", default-features = false }
-miden-crypto = { git = "https://github.com/0xPolygonMiden/crypto", branch = "next", default-features = false }
+miden-crypto = { git = "https://github.com/0xPolygonMiden/crypto", branch = "al-rpo-new-padding-rule", default-features = false }
miden-formatting = { version = "0.1", default-features = false }
thiserror = { version = "1.0", git = "https://github.com/bitwalker/thiserror", branch = "no-std", default-features = false }
winter-utils = { package = "winter-utils", version = "0.9", default-features = false }
diff --git a/processor/src/host/mod.rs b/processor/src/host/mod.rs
index 13574f11e4..b54553dc55 100644
--- a/processor/src/host/mod.rs
+++ b/processor/src/host/mod.rs
@@ -1,5 +1,3 @@
-use std::println;
-
use super::{ExecutionError, Felt, ProcessState};
use crate::MemAdviceProvider;
use vm_core::{crypto::merkle::MerklePath, AdviceInjector, DebugOptions, Word};
diff --git a/stdlib/asm/crypto/hashes/native.masm b/stdlib/asm/crypto/hashes/native.masm
index 1cd8ac3355..4e8d572aaf 100644
--- a/stdlib/asm/crypto/hashes/native.masm
+++ b/stdlib/asm/crypto/hashes/native.masm
@@ -54,8 +54,8 @@ end
#! Input: [start_addr, end_addr, ...]
#! Output: [H, ...]
#! Cycles:
-#! even words: 48 cycles + 3 * words
-#! odd words: 60 cycles + 3 * words
+#! even words: 50 cycles + 3 * words
+#! odd words: 62 cycles + 3 * words
export.hash_memory
# enforce `start_addr < end_addr`
dup.1 dup.1 u32assert2 u32gt assert
@@ -72,8 +72,8 @@ export.hash_memory
movup.2
# stack: [start_addr, end_addr, is_odd, ...]
- # prepare hasher state (12 cycles)
- dup.2 push.0.0.0 padw padw
+ # prepare hasher state (14 cycles)
+ dup.2 mul.4 push.0.0.0 padw padw
# stack: [C, B, A, start_addr, end_addr, is_odd, ...]
# (4 + 3 * words cycles)
@@ -89,7 +89,7 @@ export.hash_memory
dup.13 mem_loadw
# set the padding (9 cycles)
- swapw dropw push.1.0.0.0
+ swapw dropw push.0.0.0.0
# (1 cycles)
hperm
diff --git a/stdlib/asm/mem.masm b/stdlib/asm/mem.masm
index f81508faf4..e4117a609f 100644
--- a/stdlib/asm/mem.masm
+++ b/stdlib/asm/mem.masm
@@ -84,8 +84,8 @@ end
#! Input: [num_words, write_ptr, ...]
#! Output: [HASH, write_ptr', ...]
#! Cycles:
-#! even num_words: 48 + 9 * num_words / 2
-#! odd num_words: 65 + 9 * round_down(num_words / 2)
+#! even num_words: 50 + 9 * num_words / 2
+#! odd num_words: 67 + 9 * round_down(num_words / 2)
export.pipe_words_to_memory.0
# check if there is an odd number of words (6 cycles)
dup is_odd
@@ -99,10 +99,11 @@ export.pipe_words_to_memory.0
sub dup.1 add swap
# => [write_ptr, end_ptr, needs_padding, ...]
- # Prepare the capacity word. For rescue prime optimized the first element is
- # set to `1` when padding is used and `0` otherwse, this is determined by the
- # `needs_padding` flag. (4 cycles)
- dup.2 push.0.0.0
+ # Prepare the capacity word. We use the padding rule which sets the first capacity
+ # element to `len % 8` where `len` is the length of the hashed sequence. Since `len % 8`
+ # is either equal to 0 or 4, this is determined by the `needs_padding` flag multiplied
+ # by 4. (6 cycles)
+ dup.2 mul.4 push.0.0.0
# => [A, write_ptr, end_ptr, needs_padding, ...]
# set initial hasher state (8 cycles)
@@ -141,7 +142,7 @@ export.pipe_words_to_memory.0
# => [B', A, write_ptr+1, ...]
# Push padding word (4 cycles)
- push.1.0.0.0
+ push.0.0.0.0
# => [C, B', A, write_ptr+1, ...]
# Run RPO permutation (1 cycles)
From 1ce5c00676f978ba49cfa07dcc476e6be6b9cb31 Mon Sep 17 00:00:00 2001
From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com>
Date: Tue, 28 May 2024 12:55:07 +0200
Subject: [PATCH 02/14] fix: clippy
---
core/src/operations/mod.rs | 2 +-
stdlib/docs/crypto/hashes/native.md | 2 +-
stdlib/docs/mem.md | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/core/src/operations/mod.rs b/core/src/operations/mod.rs
index 0bef6cbc01..4f22c5ab4c 100644
--- a/core/src/operations/mod.rs
+++ b/core/src/operations/mod.rs
@@ -129,7 +129,7 @@ pub enum Operation {
///
/// The top 4 elements of the stack are expected to be arranged as follows (form the top):
/// - least significant bit of the exponent in the previous trace if there's an expacc call,
- /// otherwise ZERO
+ /// otherwise ZERO
/// - exponent of base number `a` for this turn
/// - accumulated power of base number `a` so far
/// - number which needs to be shifted to the right
diff --git a/stdlib/docs/crypto/hashes/native.md b/stdlib/docs/crypto/hashes/native.md
index db8dc41628..5fbdec4796 100644
--- a/stdlib/docs/crypto/hashes/native.md
+++ b/stdlib/docs/crypto/hashes/native.md
@@ -4,4 +4,4 @@ Prepares the top of the stack with the hasher initial state.
This pro
| ----------- | ------------- |
| state_to_digest | Given the hasher state, returns the hash output
Input: [C, B, A, ...]
Ouptut: [HASH, ...]
Where: For the native RPO hasher HASH is B.
Cycles: 9
|
| hash_memory_even | Hashes the memory `start_addr` to `end_addr`.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
-| hash_memory | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 48 cycles + 3 * words
odd words: 60 cycles + 3 * words
|
+| hash_memory | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 50 cycles + 3 * words
odd words: 62 cycles + 3 * words
|
diff --git a/stdlib/docs/mem.md b/stdlib/docs/mem.md
index 4aa67c46b7..2013c68546 100644
--- a/stdlib/docs/mem.md
+++ b/stdlib/docs/mem.md
@@ -4,5 +4,5 @@
| ----------- | ------------- |
| memcopy | Copies `n` words from `read_ptr` to `write_ptr`.
Stack transition looks as follows:
[n, read_ptr, write_ptr, ...] -> [...]
cycles: 15 + 16n
|
| pipe_double_words_to_memory | Copies an even number of words from the advice_stack to memory.
Input: [C, B, A, write_ptr, end_ptr, ...]
Output: [C, B, A, write_ptr, ...]
Where:
- The words C, B, and A are the RPO hasher state
- A is the capacity
- C,B are the rate portion of the state
- The value `words = end_ptr - write_ptr` must be positive and even
Cycles: 10 + 9 * word_pairs
|
-| pipe_words_to_memory | Copies an arbitrary number of words from the advice stack to memory
Input: [num_words, write_ptr, ...]
Output: [HASH, write_ptr', ...]
Cycles:
even num_words: 48 + 9 * num_words / 2
odd num_words: 65 + 9 * round_down(num_words / 2)
|
+| pipe_words_to_memory | Copies an arbitrary number of words from the advice stack to memory
Input: [num_words, write_ptr, ...]
Output: [HASH, write_ptr', ...]
Cycles:
even num_words: 50 + 9 * num_words / 2
odd num_words: 67 + 9 * round_down(num_words / 2)
|
| pipe_preimage_to_memory | Moves an arbitrary number of words from the advice stack to memory and asserts it matches the commitment.
Input: [num_words, write_ptr, COM, ...]
Output: [write_ptr', ...]
Cycles:
even num_words: 58 + 9 * num_words / 2
odd num_words: 75 + 9 * round_down(num_words / 2)
|
From 47ed024f2a3e894b4d0f5215eea420f428903921 Mon Sep 17 00:00:00 2001
From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com>
Date: Wed, 29 May 2024 14:28:30 +0200
Subject: [PATCH 03/14] fix: update namings and optimize masm code
---
.../src/assembler/instruction/crypto_ops.rs | 8 ++--
stdlib/asm/collections/mmr.masm | 6 +--
.../crypto/hashes/{native.masm => rpo.masm} | 26 ++++++------
stdlib/asm/mem.masm | 24 ++++++-----
stdlib/docs/crypto/hashes/native.md | 7 ----
stdlib/docs/crypto/hashes/rpo.md | 7 ++++
stdlib/docs/mem.md | 4 +-
stdlib/tests/crypto/native.rs | 42 +++++++++----------
stdlib/tests/mem/mod.rs | 2 +
9 files changed, 65 insertions(+), 61 deletions(-)
rename stdlib/asm/crypto/hashes/{native.masm => rpo.masm} (80%)
delete mode 100644 stdlib/docs/crypto/hashes/native.md
create mode 100644 stdlib/docs/crypto/hashes/rpo.md
diff --git a/assembly/src/assembler/instruction/crypto_ops.rs b/assembly/src/assembler/instruction/crypto_ops.rs
index 47ce8c29dd..7852a432ac 100644
--- a/assembly/src/assembler/instruction/crypto_ops.rs
+++ b/assembly/src/assembler/instruction/crypto_ops.rs
@@ -14,10 +14,10 @@ use vm_core::{AdviceInjector, Felt, Operation::*};
/// To perform the operation we do the following:
/// 1. Prepare the stack with 12 elements for HPERM by pushing 4 more elements for the capacity,
/// then reordering the stack and pushing an additional 4 elements so that the stack looks like:
-/// [0, 0, 0, 1, a3, a2, a1, a0, 0, 0, 0, 1, ...]. The first capacity element is set to ONE as
-/// we are hashing a number of elements which is not a multiple of the rate width. We also set
-/// the next element in the rate after `A` to ONE. All other capacity and rate elements are set
-/// to ZERO, in accordance with the RPO rules.
+/// [0, 0, 0, 0, a3, a2, a1, a0, 0, 0, 0, 4, ...]. The first capacity element is set to Felt(4)
+/// as we are hashing a number of elements which is equal to 4 modulo the rate width, while the
+/// other capacity elements are set to ZERO. A sequence of 4 ZERO elements is used as padding.
+/// The padding rule used follows the one described in this [work](https://eprint.iacr.org/2023/1045).
/// 2. Append the HPERM operation, which performs a permutation of RPO on the top 12 elements and
/// leaves the an output of [D, C, B, ...] on the stack. C is our 1-to-1 has result.
/// 3. Drop D and B to achieve our result [C, ...]
diff --git a/stdlib/asm/collections/mmr.masm b/stdlib/asm/collections/mmr.masm
index 3f50adfb09..04f6c627a3 100644
--- a/stdlib/asm/collections/mmr.masm
+++ b/stdlib/asm/collections/mmr.masm
@@ -1,5 +1,5 @@
use.std::mem
-use.std::crypto::hashes::native
+use.std::crypto::hashes::rpo
use.std::math::u64
#! Loads the leaf at the absolute `pos` in the MMR.
@@ -196,8 +196,8 @@ export.pack
# hash the memory contents (25 + 3 * num_peaks)
padw padw padw
- exec.native::hash_memory_even
- exec.native::state_to_digest
+ exec.rpo::absorb_double_words_from_memory
+ exec.rpo::squeeze_digest
# => [HASH, peaks_end, peaks_end, mmr_ptr, ...]
# prepare stack for adv.insert_mem (4 cycles)
diff --git a/stdlib/asm/crypto/hashes/native.masm b/stdlib/asm/crypto/hashes/rpo.masm
similarity index 80%
rename from stdlib/asm/crypto/hashes/native.masm
rename to stdlib/asm/crypto/hashes/rpo.masm
index 4e8d572aaf..4913020310 100644
--- a/stdlib/asm/crypto/hashes/native.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -10,13 +10,13 @@ export.init_no_padding
padw padw padw
end
-#! Given the hasher state, returns the hash output
+#! Given the hasher state, returns the hash output.
#!
#! Input: [C, B, A, ...]
#! Ouptut: [HASH, ...]
-#! Where: For the native RPO hasher HASH is B.
+#! where: For the native RPO hasher HASH is B.
#! Cycles: 9
-export.state_to_digest
+export.squeeze_digest
# drop the first rate word (4 cycles)
dropw
@@ -38,7 +38,7 @@ end
#! Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
#!
#! Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
-export.hash_memory_even
+export.absorb_double_words_from_memory
dup.13 dup.13 neq # (4 cycles )
while.true
mem_stream hperm # (2 cycles)
@@ -54,8 +54,8 @@ end
#! Input: [start_addr, end_addr, ...]
#! Output: [H, ...]
#! Cycles:
-#! even words: 50 cycles + 3 * words
-#! odd words: 62 cycles + 3 * words
+#! even words: 49 cycles + 3 * words
+#! odd words: 61 cycles + 3 * words
export.hash_memory
# enforce `start_addr < end_addr`
dup.1 dup.1 u32assert2 u32gt assert
@@ -77,25 +77,25 @@ export.hash_memory
# stack: [C, B, A, start_addr, end_addr, is_odd, ...]
# (4 + 3 * words cycles)
- exec.hash_memory_even
+ exec.absorb_double_words_from_memory
# (1 cycles)
movup.14
# handle the odd element, if any (12 cycles)
if.true
- # start_addr and end_addr are equal after calling `hash_memory_even`, and both point
- # to the last element. Load the last word (2 cycles)
- dup.13 mem_loadw
+ # start_addr and end_addr are equal after calling `absorb_double_words_from_memory`, and both point
+ # to the last element. Load the last word (6 cycles)
+ dropw dup.9 mem_loadw
- # set the padding (9 cycles)
- swapw dropw push.0.0.0.0
+ # set the padding (4 cycles)
+ padw
# (1 cycles)
hperm
end
- exec.state_to_digest
+ exec.squeeze_digest
# drop start_addr/end_addr (4 cycles)
movup.4 drop movup.4 drop
diff --git a/stdlib/asm/mem.masm b/stdlib/asm/mem.masm
index e4117a609f..d984dc4968 100644
--- a/stdlib/asm/mem.masm
+++ b/stdlib/asm/mem.masm
@@ -1,3 +1,5 @@
+use.std::crypto::hashes::rpo
+
# ===== MEMORY FUNCTIONS ==========================================================================
#! Copies `n` words from `read_ptr` to `write_ptr`.
@@ -82,10 +84,10 @@ end
#! Copies an arbitrary number of words from the advice stack to memory
#!
#! Input: [num_words, write_ptr, ...]
-#! Output: [HASH, write_ptr', ...]
+#! Output: [C, B, A, write_ptr', ...]
#! Cycles:
-#! even num_words: 50 + 9 * num_words / 2
-#! odd num_words: 67 + 9 * round_down(num_words / 2)
+#! even num_words: 41 + 9 * num_words / 2
+#! odd num_words: 58 + 9 * round_down(num_words / 2)
export.pipe_words_to_memory.0
# check if there is an odd number of words (6 cycles)
dup is_odd
@@ -142,17 +144,13 @@ export.pipe_words_to_memory.0
# => [B', A, write_ptr+1, ...]
# Push padding word (4 cycles)
- push.0.0.0.0
+ padw
# => [C, B', A, write_ptr+1, ...]
# Run RPO permutation (1 cycles)
hperm
# => [C', B', A', write_ptr+1, ...]
end
-
- # The RPO result is word B, discard the unused portion of the rate and the capacity. (9 cycles)
- dropw swapw dropw
- # => [rpo_hash, write_ptr', ...]
end
#! Moves an arbitrary number of words from the advice stack to memory and asserts it matches the commitment.
@@ -160,12 +158,16 @@ end
#! Input: [num_words, write_ptr, COM, ...]
#! Output: [write_ptr', ...]
#! Cycles:
-#! even num_words: 58 + 9 * num_words / 2
-#! odd num_words: 75 + 9 * round_down(num_words / 2)
+#! even num_words: 67 + 9 * num_words / 2
+#! odd num_words: 84 + 9 * round_down(num_words / 2)
export.pipe_preimage_to_memory.0
# Copies the advice stack data to memory
exec.pipe_words_to_memory
- # => [HASH, write_ptr', COM, ...]
+ # => [C, B, A, write_ptr', COM, ...]
+
+ # Leave only the digest on the stack
+ exec.rpo::squeeze_digest
+ # => [B, write_ptr', COM, ...]
# Save the write_ptr (2 cycles)
movup.4 movdn.8
diff --git a/stdlib/docs/crypto/hashes/native.md b/stdlib/docs/crypto/hashes/native.md
deleted file mode 100644
index 5fbdec4796..0000000000
--- a/stdlib/docs/crypto/hashes/native.md
+++ /dev/null
@@ -1,7 +0,0 @@
-Prepares the top of the stack with the hasher initial state.
This procedures does not handle padding, therefore, the user is expected to
consume an amount of data which is a multiple of the rate (2 words).
Input: []
Ouptut: [PERM, PERM, PERM, ...]
Cycles: 12
-## std::crypto::hashes::native
-| Procedure | Description |
-| ----------- | ------------- |
-| state_to_digest | Given the hasher state, returns the hash output
Input: [C, B, A, ...]
Ouptut: [HASH, ...]
Where: For the native RPO hasher HASH is B.
Cycles: 9
|
-| hash_memory_even | Hashes the memory `start_addr` to `end_addr`.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
-| hash_memory | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 50 cycles + 3 * words
odd words: 62 cycles + 3 * words
|
diff --git a/stdlib/docs/crypto/hashes/rpo.md b/stdlib/docs/crypto/hashes/rpo.md
new file mode 100644
index 0000000000..cbeb54b721
--- /dev/null
+++ b/stdlib/docs/crypto/hashes/rpo.md
@@ -0,0 +1,7 @@
+Prepares the top of the stack with the hasher initial state.
This procedures does not handle padding, therefore, the user is expected to
consume an amount of data which is a multiple of the rate (2 words).
Input: []
Ouptut: [PERM, PERM, PERM, ...]
Cycles: 12
+## std::crypto::hashes::rpo
+| Procedure | Description |
+| ----------- | ------------- |
+| squeeze_digest | Given the hasher state, returns the hash output.
Input: [C, B, A, ...]
Ouptut: [HASH, ...]
where: For the native RPO hasher HASH is B.
Cycles: 9
|
+| absorb_double_words_from_memory | Hashes the memory `start_addr` to `end_addr`.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
+| hash_memory | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 49 cycles + 3 * words
odd words: 61 cycles + 3 * words
|
diff --git a/stdlib/docs/mem.md b/stdlib/docs/mem.md
index 2013c68546..8267ca28e1 100644
--- a/stdlib/docs/mem.md
+++ b/stdlib/docs/mem.md
@@ -4,5 +4,5 @@
| ----------- | ------------- |
| memcopy | Copies `n` words from `read_ptr` to `write_ptr`.
Stack transition looks as follows:
[n, read_ptr, write_ptr, ...] -> [...]
cycles: 15 + 16n
|
| pipe_double_words_to_memory | Copies an even number of words from the advice_stack to memory.
Input: [C, B, A, write_ptr, end_ptr, ...]
Output: [C, B, A, write_ptr, ...]
Where:
- The words C, B, and A are the RPO hasher state
- A is the capacity
- C,B are the rate portion of the state
- The value `words = end_ptr - write_ptr` must be positive and even
Cycles: 10 + 9 * word_pairs
|
-| pipe_words_to_memory | Copies an arbitrary number of words from the advice stack to memory
Input: [num_words, write_ptr, ...]
Output: [HASH, write_ptr', ...]
Cycles:
even num_words: 50 + 9 * num_words / 2
odd num_words: 67 + 9 * round_down(num_words / 2)
|
-| pipe_preimage_to_memory | Moves an arbitrary number of words from the advice stack to memory and asserts it matches the commitment.
Input: [num_words, write_ptr, COM, ...]
Output: [write_ptr', ...]
Cycles:
even num_words: 58 + 9 * num_words / 2
odd num_words: 75 + 9 * round_down(num_words / 2)
|
+| pipe_words_to_memory | Copies an arbitrary number of words from the advice stack to memory
Input: [num_words, write_ptr, ...]
Output: [C, B, A, write_ptr', ...]
Cycles:
even num_words: 41 + 9 * num_words / 2
odd num_words: 58 + 9 * round_down(num_words / 2)
|
+| pipe_preimage_to_memory | Moves an arbitrary number of words from the advice stack to memory and asserts it matches the commitment.
Input: [num_words, write_ptr, COM, ...]
Output: [write_ptr', ...]
Cycles:
even num_words: 67 + 9 * num_words / 2
odd num_words: 84 + 9 * round_down(num_words / 2)
|
diff --git a/stdlib/tests/crypto/native.rs b/stdlib/tests/crypto/native.rs
index 3c96997aa3..8100264dce 100644
--- a/stdlib/tests/crypto/native.rs
+++ b/stdlib/tests/crypto/native.rs
@@ -5,13 +5,13 @@ use test_utils::{build_expected_hash, build_expected_perm, expect_exec_error};
fn test_invalid_end_addr() {
// end_addr can not be smaller than start_addr
let empty_range = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.0999 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
let test = build_test!(empty_range, &[]);
@@ -26,13 +26,13 @@ fn test_invalid_end_addr() {
// address range can not contain zero elements
let empty_range = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1000 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
let test = build_test!(empty_range, &[]);
@@ -69,13 +69,13 @@ fn test_hash_empty() {
// checks the hash compute from 8 zero elements is the same when using hash_memory
let two_zeros = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1002 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
@@ -110,7 +110,7 @@ fn test_single_iteration() {
// Note: This is testing the hashing of two words, so no padding is added
// here
let one_element = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
# insert 1 to memory
@@ -119,7 +119,7 @@ fn test_single_iteration() {
push.1002 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
@@ -139,7 +139,7 @@ fn test_hash_one_word() {
// checks the hash of 1 is the same when using hash_memory
let one_element = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1.1000 mem_store # push data to memory
@@ -147,7 +147,7 @@ fn test_hash_one_word() {
push.1001 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
@@ -158,7 +158,7 @@ fn test_hash_one_word() {
fn test_hash_even_words() {
// checks the hash of two words
let even_words = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1.0.0.0.1000 mem_storew dropw
@@ -167,7 +167,7 @@ fn test_hash_even_words() {
push.1002 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
@@ -183,7 +183,7 @@ fn test_hash_even_words() {
fn test_hash_odd_words() {
// checks the hash of three words
let odd_words = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1.0.0.0.1000 mem_storew dropw
@@ -193,7 +193,7 @@ fn test_hash_odd_words() {
push.1003 # end address
push.1000 # start address
- exec.native::hash_memory
+ exec.rpo::hash_memory
end
";
@@ -207,9 +207,9 @@ fn test_hash_odd_words() {
}
#[test]
-fn test_hash_memory_even() {
+fn test_absorb_double_words_from_memory() {
let even_words = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1.0.0.0.1000 mem_storew dropw
@@ -218,7 +218,7 @@ fn test_hash_memory_even() {
push.1002 # end address
push.1000 # start address
padw padw padw # hasher state
- exec.native::hash_memory_even
+ exec.rpo::absorb_double_words_from_memory
end
";
@@ -237,9 +237,9 @@ fn test_hash_memory_even() {
}
#[test]
-fn test_state_to_digest() {
+fn test_squeeze_digest() {
let even_words = "
- use.std::crypto::hashes::native
+ use.std::crypto::hashes::rpo
begin
push.1.0.0.0.1000 mem_storew dropw
@@ -250,9 +250,9 @@ fn test_state_to_digest() {
push.1004 # end address
push.1000 # start address
padw padw padw # hasher state
- exec.native::hash_memory_even
+ exec.rpo::absorb_double_words_from_memory
- exec.native::state_to_digest
+ exec.rpo::squeeze_digest
end
";
diff --git a/stdlib/tests/mem/mod.rs b/stdlib/tests/mem/mod.rs
index b199db7042..12dcc099ac 100644
--- a/stdlib/tests/mem/mod.rs
+++ b/stdlib/tests/mem/mod.rs
@@ -128,6 +128,7 @@ fn test_pipe_words_to_memory() {
push.1 # number of words
exec.mem::pipe_words_to_memory
+ dropw swapw dropw
end",
mem_addr
);
@@ -150,6 +151,7 @@ fn test_pipe_words_to_memory() {
push.3 # number of words
exec.mem::pipe_words_to_memory
+ dropw swapw dropw
end",
mem_addr
);
From 649b342166252086adbb3e1bcf22043242ca6ebf Mon Sep 17 00:00:00 2001
From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com>
Date: Wed, 5 Jun 2024 17:37:58 +0200
Subject: [PATCH 04/14] chore: minor nits and comment updates
---
assembly/src/ast/instruction/print.rs | 2 +-
stdlib/asm/collections/mmr.masm | 2 +-
stdlib/asm/crypto/dsa/rpo_falcon512.masm | 4 +++-
stdlib/asm/crypto/hashes/rpo.masm | 2 +-
stdlib/asm/crypto/stark/ood_frames.masm | 3 ++-
stdlib/asm/crypto/stark/random_coin.masm | 6 +++---
stdlib/asm/mem.masm | 4 ++--
stdlib/docs/crypto/hashes/rpo.md | 2 +-
stdlib/docs/mem.md | 2 +-
stdlib/tests/crypto/falcon.rs | 2 +-
stdlib/tests/crypto/native.rs | 8 ++++++--
stdlib/tests/mem/mod.rs | 6 ++++--
12 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/assembly/src/ast/instruction/print.rs b/assembly/src/ast/instruction/print.rs
index 421e28fd68..99358b4132 100644
--- a/assembly/src/ast/instruction/print.rs
+++ b/assembly/src/ast/instruction/print.rs
@@ -422,7 +422,7 @@ mod tests {
let target = InvocationTarget::MastRoot(Span::unknown(digest));
let instruction = format!("{}", Instruction::Exec(target));
assert_eq!(
- "exec.0x03b49d98981575360dd1f8c8b5a7feefcadadd56ec2a33e3e43edae3577de150",
+ "exec.0x90b3926941061b28638b6cc0bbdb3bcb335e834dc9ab8044250875055202d2fe",
instruction
);
}
diff --git a/stdlib/asm/collections/mmr.masm b/stdlib/asm/collections/mmr.masm
index 04f6c627a3..4ed948fc62 100644
--- a/stdlib/asm/collections/mmr.masm
+++ b/stdlib/asm/collections/mmr.masm
@@ -165,7 +165,7 @@ export.unpack
# => [C, B, A, mmr_ptr+17, HASH, ...]
# drop anything but the hash result, word B (11 cycles)
- dropw swapw dropw movup.4 drop
+ exec.rpo::squeeze_digest movup.4 drop
# => [B, HASH, ...]
# assert on the resulting hash (11 cycles)
diff --git a/stdlib/asm/crypto/dsa/rpo_falcon512.masm b/stdlib/asm/crypto/dsa/rpo_falcon512.masm
index 5cb418dce3..637f490bf9 100644
--- a/stdlib/asm/crypto/dsa/rpo_falcon512.masm
+++ b/stdlib/asm/crypto/dsa/rpo_falcon512.masm
@@ -1,3 +1,5 @@
+use.std::crypto::hashes::rpo
+
# CONSTANTS
# =================================================================================================
@@ -224,7 +226,7 @@ export.load_h_s2_and_product.1
end
# 6) Return the challenge point and the incremented pointer
- dropw swapw dropw
+ exec.rpo::squeeze_digest
drop drop
#=> [tau1, tau0, ptr + 512]
end
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index 4913020310..27c6b12aec 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -27,7 +27,7 @@ export.squeeze_digest
dropw
end
-#! Hashes the memory `start_addr` to `end_addr`.
+#! Hashes the memory `start_addr` to `end_addr` given an RPO state specified by 3 words.
#!
#! This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
#! loop. `end_addr` is not inclusive.
diff --git a/stdlib/asm/crypto/stark/ood_frames.masm b/stdlib/asm/crypto/stark/ood_frames.masm
index c6b9e50f26..bb3fabc1bc 100644
--- a/stdlib/asm/crypto/stark/ood_frames.masm
+++ b/stdlib/asm/crypto/stark/ood_frames.masm
@@ -1,4 +1,5 @@
use.std::crypto::stark::constants
+use.std::crypto::hashes::rpo
#! Loads OOD evaluation frame, with current and next rows interleaved, into memory. This ouputs
@@ -105,7 +106,7 @@ export.load_constraint_evaluations
hperm
- dropw swapw dropw
+ exec.rpo::squeeze_digest
end
#! Computes the H(z) evaluation of the constraint composition polynomial at the OOD element z.
diff --git a/stdlib/asm/crypto/stark/random_coin.masm b/stdlib/asm/crypto/stark/random_coin.masm
index e66b024a40..07f431cb22 100644
--- a/stdlib/asm/crypto/stark/random_coin.masm
+++ b/stdlib/asm/crypto/stark/random_coin.masm
@@ -1,6 +1,6 @@
use.std::crypto::stark::constants
use.std::crypto::stark::utils
-
+use.std::crypto::hashes::rpo
#! Helper procedure to compute addition of two words component-wise.
#! Input: [b3, b2, b1, b0, a3, a2, a1, a0]
@@ -665,7 +665,7 @@ export.generate_list_indices
exec.get_rate_2
hperm
- dropw swapw dropw
+ exec.rpo::squeeze_digest
#=> [R1, query_ptr, mask, depth, num_queries, ...]
@@ -698,7 +698,7 @@ export.generate_list_indices
exec.get_rate_2
hperm
- dropw swapw dropw
+ exec.rpo::squeeze_digest
#=> [R1, query_ptr, mask, depth, num_queries, ...]
movup.7 sub.1 dup movdn.8
push.0 neq
diff --git a/stdlib/asm/mem.masm b/stdlib/asm/mem.masm
index d984dc4968..b420ab944a 100644
--- a/stdlib/asm/mem.masm
+++ b/stdlib/asm/mem.masm
@@ -158,8 +158,8 @@ end
#! Input: [num_words, write_ptr, COM, ...]
#! Output: [write_ptr', ...]
#! Cycles:
-#! even num_words: 67 + 9 * num_words / 2
-#! odd num_words: 84 + 9 * round_down(num_words / 2)
+#! even num_words: 62 + 9 * num_words / 2
+#! odd num_words: 79 + 9 * round_down(num_words / 2)
export.pipe_preimage_to_memory.0
# Copies the advice stack data to memory
exec.pipe_words_to_memory
diff --git a/stdlib/docs/crypto/hashes/rpo.md b/stdlib/docs/crypto/hashes/rpo.md
index cbeb54b721..eb10fb3cfb 100644
--- a/stdlib/docs/crypto/hashes/rpo.md
+++ b/stdlib/docs/crypto/hashes/rpo.md
@@ -3,5 +3,5 @@ Prepares the top of the stack with the hasher initial state.
This pro
| Procedure | Description |
| ----------- | ------------- |
| squeeze_digest | Given the hasher state, returns the hash output.
Input: [C, B, A, ...]
Ouptut: [HASH, ...]
where: For the native RPO hasher HASH is B.
Cycles: 9
|
-| absorb_double_words_from_memory | Hashes the memory `start_addr` to `end_addr`.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
+| absorb_double_words_from_memory | Hashes the memory `start_addr` to `end_addr` given an RPO state specified by 3 words.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
| hash_memory | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 49 cycles + 3 * words
odd words: 61 cycles + 3 * words
|
diff --git a/stdlib/docs/mem.md b/stdlib/docs/mem.md
index 8267ca28e1..84fdb8134e 100644
--- a/stdlib/docs/mem.md
+++ b/stdlib/docs/mem.md
@@ -5,4 +5,4 @@
| memcopy | Copies `n` words from `read_ptr` to `write_ptr`.
Stack transition looks as follows:
[n, read_ptr, write_ptr, ...] -> [...]
cycles: 15 + 16n
|
| pipe_double_words_to_memory | Copies an even number of words from the advice_stack to memory.
Input: [C, B, A, write_ptr, end_ptr, ...]
Output: [C, B, A, write_ptr, ...]
Where:
- The words C, B, and A are the RPO hasher state
- A is the capacity
- C,B are the rate portion of the state
- The value `words = end_ptr - write_ptr` must be positive and even
Cycles: 10 + 9 * word_pairs
|
| pipe_words_to_memory | Copies an arbitrary number of words from the advice stack to memory
Input: [num_words, write_ptr, ...]
Output: [C, B, A, write_ptr', ...]
Cycles:
even num_words: 41 + 9 * num_words / 2
odd num_words: 58 + 9 * round_down(num_words / 2)
|
-| pipe_preimage_to_memory | Moves an arbitrary number of words from the advice stack to memory and asserts it matches the commitment.
Input: [num_words, write_ptr, COM, ...]
Output: [write_ptr', ...]
Cycles:
even num_words: 67 + 9 * num_words / 2
odd num_words: 84 + 9 * round_down(num_words / 2)
|
+| pipe_preimage_to_memory | Moves an arbitrary number of words from the advice stack to memory and asserts it matches the commitment.
Input: [num_words, write_ptr, COM, ...]
Output: [write_ptr', ...]
Cycles:
even num_words: 62 + 9 * num_words / 2
odd num_words: 79 + 9 * round_down(num_words / 2)
|
diff --git a/stdlib/tests/crypto/falcon.rs b/stdlib/tests/crypto/falcon.rs
index 4e3693a504..4e5c65d19d 100644
--- a/stdlib/tests/crypto/falcon.rs
+++ b/stdlib/tests/crypto/falcon.rs
@@ -172,7 +172,7 @@ fn test_falcon512_probabilistic_product_failure() {
expect_exec_error!(
test,
ExecutionError::FailedAssertion {
- clk: 17490,
+ clk: 17498,
err_code: 0,
err_msg: None,
}
diff --git a/stdlib/tests/crypto/native.rs b/stdlib/tests/crypto/native.rs
index 8100264dce..51617c238a 100644
--- a/stdlib/tests/crypto/native.rs
+++ b/stdlib/tests/crypto/native.rs
@@ -50,13 +50,15 @@ fn test_invalid_end_addr() {
fn test_hash_empty() {
// computes the hash for 8 consecutive zeros using mem_stream directly
let two_zeros_mem_stream = "
+ use.std::crypto::hashes::rpo
+
begin
# mem_stream state
push.1000 padw padw padw
mem_stream hperm
# drop everything except the hash
- dropw swapw dropw movup.4 drop
+ exec.rpo::squeeze_digest movup.4 drop
end
";
@@ -86,6 +88,8 @@ fn test_hash_empty() {
fn test_single_iteration() {
// computes the hash of 1 using mem_stream
let one_memstream = "
+ use.std::crypto::hashes::rpo
+
begin
# insert 1 to memory
push.1.1000 mem_store
@@ -95,7 +99,7 @@ fn test_single_iteration() {
mem_stream hperm
# drop everything except the hash
- dropw swapw dropw movup.4 drop
+ exec.rpo::squeeze_digest movup.4 drop
end
";
diff --git a/stdlib/tests/mem/mod.rs b/stdlib/tests/mem/mod.rs
index 12dcc099ac..0486258771 100644
--- a/stdlib/tests/mem/mod.rs
+++ b/stdlib/tests/mem/mod.rs
@@ -122,13 +122,14 @@ fn test_pipe_words_to_memory() {
let mem_addr = 1000;
let one_word = format!(
"use.std::mem
+ use.std::crypto::hashes::rpo
begin
push.{} # target address
push.1 # number of words
exec.mem::pipe_words_to_memory
- dropw swapw dropw
+ exec.rpo::squeeze_digest
end",
mem_addr
);
@@ -145,13 +146,14 @@ fn test_pipe_words_to_memory() {
let three_words = format!(
"use.std::mem
+ use.std::crypto::hashes::rpo
begin
push.{} # target address
push.3 # number of words
exec.mem::pipe_words_to_memory
- dropw swapw dropw
+ exec.rpo::squeeze_digest
end",
mem_addr
);
From 96f24acef7d5aba6d1eb63aeeda76b59a801eb69 Mon Sep 17 00:00:00 2001
From: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com>
Date: Wed, 5 Jun 2024 17:42:17 +0200
Subject: [PATCH 05/14] chore: change file name
---
stdlib/tests/crypto/mod.rs | 2 +-
stdlib/tests/crypto/{native.rs => rpo.rs} | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename stdlib/tests/crypto/{native.rs => rpo.rs} (100%)
diff --git a/stdlib/tests/crypto/mod.rs b/stdlib/tests/crypto/mod.rs
index 848b9e1f62..e68dbc291e 100644
--- a/stdlib/tests/crypto/mod.rs
+++ b/stdlib/tests/crypto/mod.rs
@@ -6,6 +6,6 @@ mod ecdsa_secp256k1;
mod elgamal;
mod fri;
mod keccak256;
-mod native;
+mod rpo;
mod sha256;
mod stark;
diff --git a/stdlib/tests/crypto/native.rs b/stdlib/tests/crypto/rpo.rs
similarity index 100%
rename from stdlib/tests/crypto/native.rs
rename to stdlib/tests/crypto/rpo.rs
From 9ff8f064ee5b23e3d6d2dca1d501f361395ff376 Mon Sep 17 00:00:00 2001
From: Andrey
Date: Wed, 26 Jun 2024 19:38:44 +0300
Subject: [PATCH 06/14] feat: implement hash_memory procedure
---
CHANGELOG.md | 1 +
stdlib/asm/crypto/hashes/rpo.masm | 151 +++++++++++++++++++++++++++++-
stdlib/docs/crypto/hashes/rpo.md | 3 +-
stdlib/tests/crypto/rpo.rs | 47 ++++++++--
4 files changed, 190 insertions(+), 12 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5bd1db4fb..8718d8ab51 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
#### Stdlib
- Added `init_no_padding` procedure to `std::crypto::hashes::native` (#1313).
+- Added `hash_memory` procedure to `std::crypto::hashes::rpo` (#1368).
#### VM Internals
- Removed unused `find_lone_leaf()` function from the Advice Provider (#1262).
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index 27c6b12aec..471f3c97bd 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -56,7 +56,7 @@ end
#! Cycles:
#! even words: 49 cycles + 3 * words
#! odd words: 61 cycles + 3 * words
-export.hash_memory
+export.hash_memory_words
# enforce `start_addr < end_addr`
dup.1 dup.1 u32assert2 u32gt assert
@@ -100,3 +100,152 @@ export.hash_memory
# drop start_addr/end_addr (4 cycles)
movup.4 drop movup.4 drop
end
+
+#! Computes hash of note inputs starting at the specified memory address.
+#!
+#! If the number if inputs is 0, procedure returns the empty word: [ZERO, ZERO, ZERO, ZERO].
+#!
+#! Inputs: [inputs_ptr, num_inputs]
+#! Outputs: [HASH]
+export.hash_memory
+ # move number of inputs to the top of the stack
+ swap
+ # => [num_inputs, inputs_ptr]
+
+ # get the number of double words
+ u32divmod.8 swap
+ # => [num_inputs/8, num_inputs%8, inputs_ptr]
+
+ # get the end_addr for hash_memory_even proc (end address for pairs of words)
+ mul.2 dup.2 add movup.2
+ # => [inputs_ptr, end_addr, num_inputs%8]
+
+ # get the capacity element which is equal to num_inputs%8
+ dup.2
+ # => [capacity, inputs_ptr, end_addr, num_inputs%8]
+
+ # prepare hasher state for RPO permutation
+ push.0.0.0 padw padw
+ # => [C, B, A, inputs_ptr, end_addr, num_inputs%8]
+
+ # hash every pair of words
+ exec.absorb_double_words_from_memory
+ # => [C', B', A', inputs_ptr', end_addr, num_inputs%8] where inputs_ptr' = end_addr
+
+ # hash remaining input values if there any left
+ # if num_inputs%8 is not ZERO
+ dup.14 push.0 neq
+ if.true
+ # load the remaining double word
+ mem_stream
+ # => [E, D, A', inputs_ptr'+2, end_addr, num_inputs%8]
+
+ # clean the stack
+ movup.12 drop movup.12 drop
+ # => [E, D, A', num_inputs%8]
+
+ # get the number of elements we need to drop
+ # notice that drop_counter could be any number from 1 to 7
+ push.8 movup.13 sub movdn.12
+ # => [E, D, A', drop_counter]
+
+ ### 0th value ########################################################
+
+ # we need to drop first value anyway, since number of values is not divisible by 8
+ drop
+ # => [e_1, e_2, e_3, d_0, d_1, d_2, d_3, A', drop_counter]
+
+ # push the padding 0 value
+ push.0
+ # => [0, e_1, e_2, e_3, d_0, d_1, d_2, d_3, A', drop_counter]
+
+ # move the calculated value down the stack
+ movdn.6
+ # => [e_1, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
+
+ ### 1st value ########################################################
+
+ # prepare the second element of the E Word (e_1) for cdrop instruction
+ push.0 swap
+ # => [e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
+
+ # push latch variable onto the stack; this will be the control for the cdrop instruction
+ push.0
+ # => [latch = 0, e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
+
+ # get the flag whether the drop counter is equal 1
+ dup.14 eq.1
+ # => [drop_counter == 1, latch = 0, e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
+
+ # update the latch: if drop_counter == 1, latch will become 1
+ or
+ # => [latch', e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
+
+ # save the latch value
+ dup movdn.14
+ # => [latch', e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', latch', drop_counter]
+
+ # if latch == 1, drop 0; otherwise drop e_1
+ cdrop
+ # => [e_1_or_0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', latch', drop_counter]
+
+ # move the calculated value down the stack
+ movdn.6
+ # => [e_2, e_3, d_0, d_1, d_2, 0, e_1_or_0, d_3, A', latch', drop_counter]
+
+ ### 2nd value ########################################################
+
+ # repeat the above process but now compare drop_counter to 2
+ push.0 swap
+ movup.13 dup.14 eq.2 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [e_3, d_0, d_1, d_2, 0, e_1_or_0, e_2_or_0, d_3, A', latch', drop_counter]
+
+ ### 3rd value ########################################################
+
+ # repeat the above process but now compare drop_counter to 3
+ push.0 swap
+ movup.13 dup.14 eq.3 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [d_0, d_1, d_2, 0, e_1_or_0, e_2_or_0, e_3_or_0, d_3, A', latch', drop_counter]
+
+ ### 4th value ########################################################
+
+ # repeat the above process but now compare drop_counter to 4
+ push.0 swap
+ movup.13 dup.14 eq.4 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [d_1, d_2, 0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_3, A', latch', drop_counter]
+
+ ### 5th value ########################################################
+
+ # repeat the above process but now compare drop_counter to 5
+ push.0 swap
+ movup.13 dup.14 eq.5 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [d_2, 0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_1_or_0, d_3, A', latch', drop_counter]
+
+ ### 6th value ########################################################
+
+ # repeat the above process but now compare drop_counter to 6
+ push.0 swap
+ movup.13 movup.14 eq.6 or
+ cdrop movdn.6
+ # => [0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_1_or_0, d_2_or_0, d_3, A']
+ # or in other words
+ # => [C, B, A', ... ]
+
+ hperm
+ # => [F, E, D]
+
+ exec.squeeze_digest
+ # => [E]
+ else
+ dropw movdnw.2 dropw dropw
+ # => [B']
+ end
+end
\ No newline at end of file
diff --git a/stdlib/docs/crypto/hashes/rpo.md b/stdlib/docs/crypto/hashes/rpo.md
index eb10fb3cfb..cafe2d96e5 100644
--- a/stdlib/docs/crypto/hashes/rpo.md
+++ b/stdlib/docs/crypto/hashes/rpo.md
@@ -4,4 +4,5 @@ Prepares the top of the stack with the hasher initial state.
This pro
| ----------- | ------------- |
| squeeze_digest | Given the hasher state, returns the hash output.
Input: [C, B, A, ...]
Ouptut: [HASH, ...]
where: For the native RPO hasher HASH is B.
Cycles: 9
|
| absorb_double_words_from_memory | Hashes the memory `start_addr` to `end_addr` given an RPO state specified by 3 words.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
-| hash_memory | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 49 cycles + 3 * words
odd words: 61 cycles + 3 * words
|
+| hash_memory_words | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 49 cycles + 3 * words
odd words: 61 cycles + 3 * words
|
+| hash_memory | Computes hash of note inputs starting at the specified memory address.
If the number if inputs is 0, procedure returns the empty word: [ZERO, ZERO, ZERO, ZERO].
Inputs: [inputs_ptr, num_inputs]
Outputs: [HASH]
|
diff --git a/stdlib/tests/crypto/rpo.rs b/stdlib/tests/crypto/rpo.rs
index 51617c238a..3c7bd7244b 100644
--- a/stdlib/tests/crypto/rpo.rs
+++ b/stdlib/tests/crypto/rpo.rs
@@ -11,7 +11,7 @@ fn test_invalid_end_addr() {
push.0999 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
let test = build_test!(empty_range, &[]);
@@ -32,7 +32,7 @@ fn test_invalid_end_addr() {
push.1000 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
let test = build_test!(empty_range, &[]);
@@ -69,7 +69,7 @@ fn test_hash_empty() {
]).into_iter().map(|e| e.as_int()).collect();
build_test!(two_zeros_mem_stream, &[]).expect_stack(&zero_hash);
- // checks the hash compute from 8 zero elements is the same when using hash_memory
+ // checks the hash compute from 8 zero elements is the same when using hash_memory_words
let two_zeros = "
use.std::crypto::hashes::rpo
@@ -77,7 +77,7 @@ fn test_hash_empty() {
push.1002 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
@@ -110,7 +110,7 @@ fn test_single_iteration() {
]).into_iter().map(|e| e.as_int()).collect();
build_test!(one_memstream, &[]).expect_stack(&one_hash);
- // checks the hash of 1 is the same when using hash_memory
+ // checks the hash of 1 is the same when using hash_memory_words
// Note: This is testing the hashing of two words, so no padding is added
// here
let one_element = "
@@ -123,7 +123,7 @@ fn test_single_iteration() {
push.1002 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
@@ -141,7 +141,7 @@ fn test_hash_one_word() {
1, 0, 0, 0,
]).into_iter().map(|e| e.as_int()).collect();
- // checks the hash of 1 is the same when using hash_memory
+ // checks the hash of 1 is the same when using hash_memory_words
let one_element = "
use.std::crypto::hashes::rpo
@@ -151,7 +151,7 @@ fn test_hash_one_word() {
push.1001 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
@@ -171,7 +171,7 @@ fn test_hash_even_words() {
push.1002 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
@@ -197,7 +197,7 @@ fn test_hash_odd_words() {
push.1003 # end address
push.1000 # start address
- exec.rpo::hash_memory
+ exec.rpo::hash_memory_words
end
";
@@ -274,3 +274,30 @@ fn test_squeeze_digest() {
build_test!(even_words, &[]).expect_stack(&even_hash);
}
+
+#[test]
+fn test_hash_memory() {
+ let compute_inputs_hash = "
+ use.std::crypto::hashes::rpo
+
+ begin
+ push.1.2.3.4.1000 mem_storew dropw
+ push.5.6.7.8.1001 mem_storew dropw
+ push.9.10.11.12.1002 mem_storew dropw
+ push.13.14.15.0.1003 mem_storew dropw
+
+
+ push.15.1000
+
+ #######################################################
+
+ exec.rpo::hash_memory
+ end
+ ";
+
+ #[rustfmt::skip]
+ let expected_hash: Vec = build_expected_hash(&[
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ ]).into_iter().map(|e| e.as_int()).collect();
+ build_test!(compute_inputs_hash, &[]).expect_stack(&expected_hash);
+}
From cdba4ac491b10bc649c43a8a34a6686f03739f6f Mon Sep 17 00:00:00 2001
From: Andrey
Date: Wed, 26 Jun 2024 19:57:13 +0300
Subject: [PATCH 07/14] chore: fix clippy errors
---
air/src/constraints/chiplets/hasher/mod.rs | 4 +-
air/src/constraints/stack/field_ops/mod.rs | 8 +--
air/src/constraints/stack/op_flags/mod.rs | 2 +-
air/src/constraints/stack/overflow/mod.rs | 6 +-
.../stack/stack_manipulation/mod.rs | 4 +-
air/src/constraints/stack/u32_ops/mod.rs | 8 +--
assembly/src/assembler/mod.rs | 8 +--
.../assembler/module_graph/rewrites/module.rs | 4 +-
assembly/src/ast/module.rs | 8 +--
assembly/src/ast/visit.rs | 15 ++---
processor/src/chiplets/mod.rs | 64 ++++++++++---------
processor/src/decoder/mod.rs | 2 +-
processor/src/host/advice/injectors/dsa.rs | 2 +-
processor/src/operations/comb_ops.rs | 12 ++--
processor/src/operations/field_ops.rs | 6 +-
processor/src/operations/io_ops.rs | 4 +-
processor/src/trace/utils.rs | 2 +-
test-utils/src/lib.rs | 2 +-
test-utils/src/test_builders.rs | 18 +++---
19 files changed, 90 insertions(+), 89 deletions(-)
diff --git a/air/src/constraints/chiplets/hasher/mod.rs b/air/src/constraints/chiplets/hasher/mod.rs
index e58828d80b..8df5fca0cb 100644
--- a/air/src/constraints/chiplets/hasher/mod.rs
+++ b/air/src/constraints/chiplets/hasher/mod.rs
@@ -101,9 +101,9 @@ pub fn get_transition_constraint_count() -> usize {
/// Enforces constraints for the hasher chiplet.
///
/// - The `hasher_flag` determines if the hasher chiplet is currently enabled. It should be
-/// computed by the caller and set to `Felt::ONE`
+/// computed by the caller and set to `Felt::ONE`
/// - The `transition_flag` indicates whether this is the last row this chiplet's execution trace,
-/// and therefore the constraints should not be enforced.
+/// and therefore the constraints should not be enforced.
pub fn enforce_constraints>(
frame: &EvaluationFrame,
periodic_values: &[E],
diff --git a/air/src/constraints/stack/field_ops/mod.rs b/air/src/constraints/stack/field_ops/mod.rs
index 4248eea85a..f185e255c9 100644
--- a/air/src/constraints/stack/field_ops/mod.rs
+++ b/air/src/constraints/stack/field_ops/mod.rs
@@ -188,7 +188,7 @@ pub fn enforce_incr_constraints(
/// enforced:
/// - The top element should be a binary. It is enforced as a general constraint.
/// - The first element of the next frame should be a binary not of the first element of
-/// the current frame. s0` + s0 = 1.
+/// the current frame. s0` + s0 = 1.
pub fn enforce_not_constraints(
frame: &EvaluationFrame,
result: &mut [E],
@@ -207,7 +207,7 @@ pub fn enforce_not_constraints(
/// Enforces constraints of the AND operation. The AND operation computes the bitwise and of the
/// first two elements in the current trace. Therefore, the following constraints are enforced:
/// - The top two element in the current frame of the stack should be binary. s0^2 - s0 = 0,
-/// s1^2 - s1 = 0. The top element is binary or not is enforced as a general constraint.
+/// s1^2 - s1 = 0. The top element is binary or not is enforced as a general constraint.
/// - The first element of the next frame should be a binary and of the first two elements in the
/// current frame. s0` - s0 * s1 = 0.
pub fn enforce_and_constraints(
@@ -234,7 +234,7 @@ pub fn enforce_and_constraints(
/// Enforces constraints of the OR operation. The OR operation computes the bitwise or of the
/// first two elements in the current trace. Therefore, the following constraints are enforced:
/// - The top two element in the current frame of the stack should be binary. s0^2 - s0 = 0,
-/// s1^2 - s1 = 0. The top element is binary or not is enforced as a general constraint.
+/// s1^2 - s1 = 0. The top element is binary or not is enforced as a general constraint.
/// - The first element of the next frame should be a binary or of the first two elements in the
/// current frame. s0` - ( s0 + s1 - s0 * s1 ) = 0.
pub fn enforce_or_constraints(
@@ -324,7 +324,7 @@ pub fn enforce_eqz_constraints(
/// constraint.
/// - The exp value in the next frame should be the square of exp value in the current frame.
/// - The accumulation value in the next frame is the product of the accumulation value in the
-/// current frame and the value which needs to be included in this turn.
+/// current frame and the value which needs to be included in this turn.
/// - The b value is right shifted by 1 bit.
pub fn enforce_expacc_constraints(
frame: &EvaluationFrame,
diff --git a/air/src/constraints/stack/op_flags/mod.rs b/air/src/constraints/stack/op_flags/mod.rs
index 8359917d8d..ce08893ffb 100644
--- a/air/src/constraints/stack/op_flags/mod.rs
+++ b/air/src/constraints/stack/op_flags/mod.rs
@@ -100,7 +100,7 @@ impl OpFlags {
/// - composite flag for the stack if the stack has been shifted to the right.
/// - composite flag if the current operation being executed is a control flow operation or not.
/// - composite flag if the current operation being executed has a binary element constraint on
- /// the top element in the stack.
+ /// the top element in the stack.
pub fn new(frame: &EvaluationFrame) -> Self {
// intermediary array to cache the value of intermediate flags.
let mut degree7_op_flags = [E::ZERO; NUM_DEGREE_7_OPS];
diff --git a/air/src/constraints/stack/overflow/mod.rs b/air/src/constraints/stack/overflow/mod.rs
index 346bba5906..4cc319711c 100644
--- a/air/src/constraints/stack/overflow/mod.rs
+++ b/air/src/constraints/stack/overflow/mod.rs
@@ -93,7 +93,7 @@ pub fn enforce_stack_depth_constraints(
/// Enforces constraints on the overflow flag h0. Therefore, the following constraints
/// are enforced:
/// - If overflow table has values, then, h0 should be set to ONE, otherwise it should
-/// be ZERO.
+/// be ZERO.
pub fn enforce_overflow_flag_constraints(
frame: &EvaluationFrame,
result: &mut [E],
@@ -108,9 +108,9 @@ pub fn enforce_overflow_flag_constraints(
/// Enforces constraints on the bookkeeping index `b1`. The following constraints are enforced:
/// - In the case of a right shift operation, the next b1 index should be updated with current
-/// `clk` value.
+/// `clk` value.
/// - In the case of a left shift operation, the last stack item should be set to ZERO when the
-/// depth of the stack is 16.
+/// depth of the stack is 16.
pub fn enforce_overflow_index_constraints(
frame: &EvaluationFrame,
result: &mut [E],
diff --git a/air/src/constraints/stack/stack_manipulation/mod.rs b/air/src/constraints/stack/stack_manipulation/mod.rs
index ab32a8263c..0678fe615e 100644
--- a/air/src/constraints/stack/stack_manipulation/mod.rs
+++ b/air/src/constraints/stack/stack_manipulation/mod.rs
@@ -94,7 +94,7 @@ pub fn enforce_pad_constraints(
/// at depth n in the stack and pushes the copy onto the stack, whereas MOVUPn opearation moves the
/// element at depth n to the top of the stack. Therefore, the following constraints are enforced:
/// - The top element in the next frame should be equal to the element at depth n in the
-/// current frame. s0` - sn = 0.
+/// current frame. s0` - sn = 0.
pub fn enforce_dup_movup_n_constraints(
frame: &EvaluationFrame,
result: &mut [E],
@@ -245,7 +245,7 @@ pub fn enforce_swapwx_constraints(
/// Enforces constraints of the MOVDNn operation. The MOVDNn operation moves the top element
/// to depth n in the stack. Therefore, the following constraints are enforced:
/// - The top element in the current frame should be equal to the element at depth n in the
-/// next frame. s0 - sn` = 0.
+/// next frame. s0 - sn` = 0.
pub fn enforce_movdnn_constraints(
frame: &EvaluationFrame,
result: &mut [E],
diff --git a/air/src/constraints/stack/u32_ops/mod.rs b/air/src/constraints/stack/u32_ops/mod.rs
index ffe7ee56e0..d04b4a75b1 100644
--- a/air/src/constraints/stack/u32_ops/mod.rs
+++ b/air/src/constraints/stack/u32_ops/mod.rs
@@ -120,7 +120,7 @@ pub fn enforce_u32split_constraints>(
/// elements in the current trace of the stack. Therefore, the following constraints are
/// enforced:
/// - The aggregation of limbs from the helper registers is equal to the sum of the top two
-/// element in the stack.
+/// element in the stack.
pub fn enforce_u32add_constraints>(
frame: &EvaluationFrame,
result: &mut [E],
@@ -141,7 +141,7 @@ pub fn enforce_u32add_constraints>(
/// elements in the current trace of the stack. Therefore, the following constraints are
/// enforced:
/// - The aggregation of limbs from the helper registers is equal to the sum of the top three
-/// elements in the stack.
+/// elements in the stack.
pub fn enforce_u32add3_constraints>(
frame: &EvaluationFrame,
result: &mut [E],
@@ -290,9 +290,9 @@ pub fn enforce_check_element_validity>(
/// are aggregated correctly or not. Therefore, the following constraints are enforced:
/// - The aggregation of lower two lower 16-bits limbs in the helper registers is equal to the
/// second
-/// element in the next row.
+/// element in the next row.
/// - The aggregation of lower two upper 16-bits limbs in the helper registers is equal to the first
-/// element in the next row.
+/// element in the next row.
pub fn enforce_limbs_agg>(
frame: &EvaluationFrame,
result: &mut [E],
diff --git a/assembly/src/assembler/mod.rs b/assembly/src/assembler/mod.rs
index c8c6dc8229..09d21b2f76 100644
--- a/assembly/src/assembler/mod.rs
+++ b/assembly/src/assembler/mod.rs
@@ -77,12 +77,12 @@ pub enum ArtifactKind {
///
///
/// * If you have a single executable module you want to compile, just call [Assembler::compile] or
-/// [Assembler::compile_ast], depending on whether you have source code in raw or parsed form.
+/// [Assembler::compile_ast], depending on whether you have source code in raw or parsed form.
///
/// * If you want to link your executable to a few other modules that implement supporting
-/// procedures, build the assembler with them first, using the various builder methods on
-/// [Assembler], e.g. [Assembler::with_module], [Assembler::with_library], etc. Then, call
-/// [Assembler::compile] or [Assembler::compile_ast] to get your compiled program.
+/// procedures, build the assembler with them first, using the various builder methods on
+/// [Assembler], e.g. [Assembler::with_module], [Assembler::with_library], etc. Then, call
+/// [Assembler::compile] or [Assembler::compile_ast] to get your compiled program.
pub struct Assembler {
/// The global [ModuleGraph] for this assembler. All new [AssemblyContext]s inherit this graph
/// as a baseline.
diff --git a/assembly/src/assembler/module_graph/rewrites/module.rs b/assembly/src/assembler/module_graph/rewrites/module.rs
index a4055f5a0d..51145e593b 100644
--- a/assembly/src/assembler/module_graph/rewrites/module.rs
+++ b/assembly/src/assembler/module_graph/rewrites/module.rs
@@ -18,8 +18,8 @@ use crate::{
/// added to a [ModuleGraph]. These rewrites include:
///
/// * Resolving, at least partially, all of the invocation targets in procedures of the module, and
-/// rewriting those targets as concretely as possible OR as phantom calls representing procedures
-/// referenced by MAST root for which we have no definition.
+/// rewriting those targets as concretely as possible OR as phantom calls representing procedures
+/// referenced by MAST root for which we have no definition.
pub struct ModuleRewriter<'a, 'b: 'a> {
resolver: &'a NameResolver<'b>,
module_id: ModuleIndex,
diff --git a/assembly/src/ast/module.rs b/assembly/src/ast/module.rs
index ffc85dd4f0..1a5b6af251 100644
--- a/assembly/src/ast/module.rs
+++ b/assembly/src/ast/module.rs
@@ -46,11 +46,11 @@ pub enum ModuleKind {
/// A kernel is like a library module, but is special in a few ways:
///
/// * Its code always executes in the root context, so it is stateful in a way that normal
- /// libraries cannot replicate. This can be used to provide core services that would otherwise
- /// not be possible to implement.
+ /// libraries cannot replicate. This can be used to provide core services that would otherwise
+ /// not be possible to implement.
///
/// * The procedures exported from the kernel may be the target of the `syscall` instruction,
- /// and in fact _must_ be called that way.
+ /// and in fact _must_ be called that way.
///
/// * Kernels may not use `syscall` or `call` instructions internally.
Kernel = 2,
@@ -294,7 +294,7 @@ impl Module {
///
/// * The module was constructed in-memory via AST structures, and not derived from source code.
/// * The module was serialized without debug info, and then deserialized. Without debug info,
- /// the source code is lost when round-tripping through serialization.
+ /// the source code is lost when round-tripping through serialization.
pub fn source_file(&self) -> Option> {
self.source_file.clone()
}
diff --git a/assembly/src/ast/visit.rs b/assembly/src/ast/visit.rs
index af19ec4ba3..5c621e1687 100644
--- a/assembly/src/ast/visit.rs
+++ b/assembly/src/ast/visit.rs
@@ -22,16 +22,15 @@
//! of the visitor, but here are some examples:
//!
//! 1. When implementing a visitor that performs constant folding/propagation, you need to visit the
-//! operands of an expression before the operator, in order to determine whether it is possible to
-//! fold, and if so, what the actual values of the operands are. As a result, this is implemented as
-//! a postorder visitor, so that the AST node corresponding to the expression is rewritten after all
-//! of it's children.
+//! operands of an expression before the operator, in order to determine whether it is possible
+//! to fold, and if so, what the actual values of the operands are. As a result, this is
+//! implemented as a postorder visitor, so that the AST node corresponding to the expression is
+//! rewritten after all of it's children.
//!
//! 2. When implementing an analysis based on lexical scope, it is necessary to "push down" context
-//! from
-//! the root to the leaves of the AST - the context being the contents of each AST nodes inherited
-//! scope. As a result, this is implemented as a preorder traversal, so that the context at each
-//! node can be computed before visiting the children of that node.
+//! from the root to the leaves of the AST - the context being the contents of each AST nodes
+//! inherited scope. As a result, this is implemented as a preorder traversal, so that the
+//! context at each node can be computed before visiting the children of that node.
//!
//! In both cases, the implementor must call the free function corresponding to the _current_ AST
//! node at the appropriate point (i.e. before/after executing the logic for the node), so that the
diff --git a/processor/src/chiplets/mod.rs b/processor/src/chiplets/mod.rs
index 1a90f1801b..0a70095389 100644
--- a/processor/src/chiplets/mod.rs
+++ b/processor/src/chiplets/mod.rs
@@ -37,43 +37,44 @@ mod tests;
/// chiplet selectors.
///
/// The module's trace can be thought of as 5 stacked chiplet segments in the following form:
-/// * Hasher segment: contains the trace and selector for the hasher chiplet *
-/// This segment fills the first rows of the trace up to the length of the hasher `trace_len`.
-/// - column 0: selector column with values set to ZERO
-/// - columns 1-17: execution trace of hash chiplet
+/// * Hasher segment: contains the trace and selector for the hasher chiplet.\
+/// This segment fills the first rows of the trace up to the length of the hasher `trace_len`.
+/// - column 0: selector column with values set to ZERO
+/// - columns 1-17: execution trace of hash chiplet
///
-/// * Bitwise segment: contains the trace and selectors for the bitwise chiplet *
-/// This segment begins at the end of the hasher segment and fills the next rows of the trace for
-/// the `trace_len` of the bitwise chiplet.
-/// - column 0: selector column with values set to ONE
-/// - column 1: selector column with values set to ZERO
-/// - columns 2-14: execution trace of bitwise chiplet
-/// - columns 15-17: unused columns padded with ZERO
+/// * Bitwise segment: contains the trace and selectors for the bitwise chiplet.\
+/// This segment begins at the end of the hasher segment and fills the next rows of the trace for
+/// the `trace_len` of the bitwise chiplet.
+/// - column 0: selector column with values set to ONE
+/// - column 1: selector column with values set to ZERO
+/// - columns 2-14: execution trace of bitwise chiplet
+/// - columns 15-17: unused columns padded with ZERO
///
-/// * Memory segment: contains the trace and selectors for the memory chiplet *
-/// This segment begins at the end of the bitwise segment and fills the next rows of the trace for
-/// the `trace_len` of the memory chiplet.
-/// - column 0-1: selector columns with values set to ONE
-/// - column 2: selector column with values set to ZERO
-/// - columns 3-14: execution trace of memory chiplet
-/// - columns 15-17: unused column padded with ZERO
+/// * Memory segment: contains the trace and selectors for the memory chiplet.\
+/// This segment begins at the end of the bitwise segment and fills the next rows of the trace for
+/// the `trace_len` of the memory chiplet.
+/// - column 0-1: selector columns with values set to ONE
+/// - column 2: selector column with values set to ZERO
+/// - columns 3-14: execution trace of memory chiplet
+/// - columns 15-17: unused column padded with ZERO
///
-/// * Kernel ROM segment: contains the trace and selectors for the kernel ROM chiplet *
-/// This segment begins at the end of the memory segment and fills the next rows of the trace for
-/// the `trace_len` of the kernel ROM chiplet.
-/// - column 0-2: selector columns with values set to ONE
-/// - column 3: selector column with values set to ZERO
-/// - columns 4-9: execution trace of kernel ROM chiplet
-/// - columns 10-17: unused column padded with ZERO
+/// * Kernel ROM segment: contains the trace and selectors for the kernel ROM chiplet.\
+/// This segment begins at the end of the memory segment and fills the next rows of the trace for
+/// the `trace_len` of the kernel ROM chiplet.
+/// - column 0-2: selector columns with values set to ONE
+/// - column 3: selector column with values set to ZERO
+/// - columns 4-9: execution trace of kernel ROM chiplet
+/// - columns 10-17: unused column padded with ZERO
///
-/// * Padding segment: unused *
-/// This segment begins at the end of the kernel ROM segment and fills the rest of the execution
-/// trace minus the number of random rows. When it finishes, the execution trace should have
-/// exactly enough rows remaining for the specified number of random rows.
-/// - columns 0-3: selector columns with values set to ONE
-/// - columns 3-17: unused columns padded with ZERO
+/// * Padding segment: unused.\
+/// This segment begins at the end of the kernel ROM segment and fills the rest of the execution
+/// trace minus the number of random rows. When it finishes, the execution trace should have
+/// exactly enough rows remaining for the specified number of random rows.
+/// - columns 0-3: selector columns with values set to ONE
+/// - columns 3-17: unused columns padded with ZERO
///
/// The following is a pictorial representation of the chiplet module:
+/// ```text
/// +---+-------------------------------------------------------+-------------+
/// | 0 | | |-------------|
/// | . | Hash chiplet | Hash chiplet |-------------|
@@ -111,6 +112,7 @@ mod tests;
/// | . | . | . | . |---------------------------------------------------------|
/// | 1 | 1 | 1 | 1 |---------------------------------------------------------|
/// +---+---+---+---+---------------------------------------------------------+
+/// ```
pub struct Chiplets {
/// Current clock cycle of the VM.
clk: u32,
diff --git a/processor/src/decoder/mod.rs b/processor/src/decoder/mod.rs
index 03f022fa64..98c814d2b0 100644
--- a/processor/src/decoder/mod.rs
+++ b/processor/src/decoder/mod.rs
@@ -309,7 +309,7 @@ where
/// of these columns contains a single binary value, which together form a single opcode.
/// * Hasher state columns h0 through h7. These are multi purpose columns used as follows:
/// - When starting decoding of a new code block (e.g., via JOIN, SPLIT, LOOP, SPAN operations)
-/// these columns are used for providing inputs for the current block's hash computations.
+/// these columns are used for providing inputs for the current block's hash computations.
/// - When finishing decoding of a code block (i.e., via END operation), these columns are used to
/// record the result of the hash computation.
/// - Inside a SPAN block, the first two columns are used to keep track of un-executed operations
diff --git a/processor/src/host/advice/injectors/dsa.rs b/processor/src/host/advice/injectors/dsa.rs
index 778d8e538b..be11d1bd6f 100644
--- a/processor/src/host/advice/injectors/dsa.rs
+++ b/processor/src/host/advice/injectors/dsa.rs
@@ -10,7 +10,7 @@ use super::super::{ExecutionError, Felt, Word};
/// 2. The expanded public key represented as the coefficients of a polynomial of degree < 512.
/// 3. The signature represented as the coefficients of a polynomial of degree < 512.
/// 4. The product of the above two polynomials in the ring of polynomials with coefficients
-/// in the Miden field.
+/// in the Miden field.
///
/// # Errors
/// Will return an error if either:
diff --git a/processor/src/operations/comb_ops.rs b/processor/src/operations/comb_ops.rs
index 16d91d50ee..5fa0c098b5 100644
--- a/processor/src/operations/comb_ops.rs
+++ b/processor/src/operations/comb_ops.rs
@@ -45,17 +45,17 @@ where
/// Here:
///
/// 1. Ti for i in 0..=7 stands for the the value of the i-th trace polynomial for the current
- /// query i.e. T_i(x).
+ /// query i.e. T_i(x).
/// 2. (p0, p1) stands for an extension field element accumulating the values for the quotients
- /// with common denominator (x - z).
+ /// with common denominator (x - z).
/// 3. (r0, r1) stands for an extension field element accumulating the values for the quotients
- /// with common denominator (x - gz).
+ /// with common denominator (x - gz).
/// 4. x_addr is the memory address from which we are loading the Ti's using the MSTREAM
- /// instruction.
+ /// instruction.
/// 5. z_addr is the memory address to the i-th OOD evaluations at z and gz
- /// i.e. T_i(z):= (T_i(z)0, T_i(z)1) and T_i(gz):= (T_i(gz)0, T_i(gz)1).
+ /// i.e. T_i(z):= (T_i(z)0, T_i(z)1) and T_i(gz):= (T_i(gz)0, T_i(gz)1).
/// 6. a_addr is the memory address of the i-th random element alpha_i used in batching
- /// the trace polynomial quotients.
+ /// the trace polynomial quotients.
///
/// The instruction also makes use of the helper registers to hold the values of T_i(z), T_i(gz)
/// and alpha_i during the course of its execution.
diff --git a/processor/src/operations/field_ops.rs b/processor/src/operations/field_ops.rs
index b7ae264ffd..a2b4f5fdc6 100644
--- a/processor/src/operations/field_ops.rs
+++ b/processor/src/operations/field_ops.rs
@@ -171,16 +171,16 @@ where
/// Computes a single turn of exp accumulation for the given inputs. The top 4 elements in the
/// stack is arranged as follows (from the top):
/// - least significant bit of the exponent in the previous trace if there's an expacc call,
- /// otherwise ZERO
+ /// otherwise ZERO
/// - exponent of base for this turn
/// - accumulated power of base so far
/// - number which needs to be shifted to the right
///
/// To perform the operation we do the following:
/// 1. Pops top three elements off the stack and calculate the least significant bit of the
- /// number `b`.
+ /// number `b`.
/// 2. Use this bit to decide if the current `base` raise to the power exponent needs to be
- /// included in the accumulator.
+ /// included in the accumulator.
/// 3. Update exponent with its square and the number b with one right shift.
/// 4. Pushes the calcuted new values to the stack in the mentioned order.
pub(super) fn op_expacc(&mut self) -> Result<(), ExecutionError> {
diff --git a/processor/src/operations/io_ops.rs b/processor/src/operations/io_ops.rs
index de3d9eca02..2f005fbfdb 100644
--- a/processor/src/operations/io_ops.rs
+++ b/processor/src/operations/io_ops.rs
@@ -149,8 +149,8 @@ where
/// The operation works as follows:
/// - The memory address is popped off the stack.
/// - The top stack element is saved into the first element of the word located at the specified
- /// memory address. The remaining 3 elements of the word are not affected. The element is not
- /// removed from the stack.
+ /// memory address. The remaining 3 elements of the word are not affected. The element is not
+ /// removed from the stack.
///
/// Thus, the net result of the operation is that the stack is shifted left by one item.
///
diff --git a/processor/src/trace/utils.rs b/processor/src/trace/utils.rs
index e321aaa344..a3f706c874 100644
--- a/processor/src/trace/utils.rs
+++ b/processor/src/trace/utils.rs
@@ -80,7 +80,7 @@ impl<'a> TraceFragment<'a> {
/// - `main_trace_len` contains the length of the main trace.
/// - `range_trace_len` contains the length of the range checker trace.
/// - `chiplets_trace_len` contains the trace lengths of the all chiplets (hash, bitwise, memory,
-/// kernel ROM)
+/// kernel ROM)
#[derive(Debug, Default, Eq, PartialEq, Clone, Copy)]
pub struct TraceLenSummary {
main_trace_len: usize,
diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs
index 0bbc520c58..3b72a4fe44 100644
--- a/test-utils/src/lib.rs
+++ b/test-utils/src/lib.rs
@@ -167,7 +167,7 @@ macro_rules! assert_assembler_diagnostic {
///
/// Types of failure tests:
/// - Assembly error test: check that attempting to compile the given source causes an
-/// AssemblyError which contains the specified substring.
+/// AssemblyError which contains the specified substring.
/// - Execution error test: check that running a program compiled from the given source causes an
/// ExecutionError which contains the specified substring.
pub struct Test {
diff --git a/test-utils/src/test_builders.rs b/test-utils/src/test_builders.rs
index bf49661935..4cc6fde43d 100644
--- a/test-utils/src/test_builders.rs
+++ b/test-utils/src/test_builders.rs
@@ -9,11 +9,11 @@
///
/// * `source`: a string of one or more operations, e.g. "push.1 push.2".
/// * `stack_inputs` (optional): the initial inputs which must be at the top of the stack before
-/// executing the `source`. Stack inputs can be provided independently without any advice inputs.
+/// executing the `source`. Stack inputs can be provided independently without any advice inputs.
/// * `advice_stack` (optional): the initial advice stack values. When provided, `stack_inputs` and
-/// `merkle_store` are also expected.
+/// `merkle_store` are also expected.
/// * `merkle_store` (optional): the initial merkle set values. When provided, `stack_inputs` and
-/// `advice_stack` are also expected.
+/// `advice_stack` are also expected.
#[macro_export]
macro_rules! build_op_test {
($op_str:expr) => {{
@@ -34,11 +34,11 @@ macro_rules! build_op_test {
///
/// * `source`: a well-formed source string.
/// * `stack_inputs` (optional): the initial inputs which must be at the top of the stack before
-/// executing the `source`. Stack inputs can be provided independently without any advice inputs.
+/// executing the `source`. Stack inputs can be provided independently without any advice inputs.
/// * `advice_stack` (optional): the initial advice stack values. When provided, `stack_inputs` and
-/// `merkle_store` are also expected.
+/// `merkle_store` are also expected.
/// * `merkle_store` (optional): the initial merkle set values. When provided, `stack_inputs` and
-/// `advice_stack` are also expected.
+/// `advice_stack` are also expected.
#[macro_export]
macro_rules! build_test {
($($params:tt)+) => {{
@@ -54,11 +54,11 @@ macro_rules! build_test {
///
/// * `source`: a well-formed source string.
/// * `stack_inputs` (optional): the initial inputs which must be at the top of the stack before
-/// executing the `source`. Stack inputs can be provided independently without any advice inputs.
+/// executing the `source`. Stack inputs can be provided independently without any advice inputs.
/// * `advice_stack` (optional): the initial advice stack values. When provided, `stack_inputs` and
-/// `merkle_store` are also expected.
+/// `merkle_store` are also expected.
/// * `merkle_store` (optional): the initial merkle set values. When provided, `stack_inputs` and
-/// `advice_stack` are also expected.
+/// `advice_stack` are also expected.
#[macro_export]
macro_rules! build_debug_test {
($($params:tt)+) => {{
From b48edd613f6bf67b03c61d42046caf74fa3ff89a Mon Sep 17 00:00:00 2001
From: Andrey
Date: Fri, 28 Jun 2024 00:31:00 +0300
Subject: [PATCH 08/14] refactor: improve comments and docs
---
stdlib/asm/crypto/hashes/rpo.masm | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index 471f3c97bd..9f1a5610ca 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -101,7 +101,7 @@ export.hash_memory_words
movup.4 drop movup.4 drop
end
-#! Computes hash of note inputs starting at the specified memory address.
+#! Computes hash of Felt values starting at the specified memory address.
#!
#! If the number if inputs is 0, procedure returns the empty word: [ZERO, ZERO, ZERO, ZERO].
#!
@@ -116,7 +116,7 @@ export.hash_memory
u32divmod.8 swap
# => [num_inputs/8, num_inputs%8, inputs_ptr]
- # get the end_addr for hash_memory_even proc (end address for pairs of words)
+ # get the end_addr for hash_memory_even procedure (end address for pairs of words)
mul.2 dup.2 add movup.2
# => [inputs_ptr, end_addr, num_inputs%8]
@@ -132,7 +132,7 @@ export.hash_memory
exec.absorb_double_words_from_memory
# => [C', B', A', inputs_ptr', end_addr, num_inputs%8] where inputs_ptr' = end_addr
- # hash remaining input values if there any left
+ # hash remaining input values if there are any left
# if num_inputs%8 is not ZERO
dup.14 push.0 neq
if.true
@@ -238,6 +238,9 @@ export.hash_memory
# => [0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_1_or_0, d_2_or_0, d_3, A']
# or in other words
# => [C, B, A', ... ]
+ # notice that we don't need to check the d_3 value: entering the if.true branch means that
+ # we have number of elements not divisible by 8, so we will have at least one element to
+ # hash here (which turns out to be d_3)
hperm
# => [F, E, D]
From b839e79a77b835d23ff754a75419b7e1876b5c78 Mon Sep 17 00:00:00 2001
From: Andrey
Date: Fri, 28 Jun 2024 15:09:35 +0300
Subject: [PATCH 09/14] refactor: improve comments, add test, update changelog
---
CHANGELOG.md | 1 +
stdlib/asm/crypto/hashes/rpo.masm | 254 +++++++++++++++---------------
stdlib/docs/crypto/hashes/rpo.md | 2 +-
stdlib/tests/crypto/rpo.rs | 69 +++++++-
4 files changed, 195 insertions(+), 131 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8718d8ab51..84c7ec2281 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@
#### Stdlib
- Added `init_no_padding` procedure to `std::crypto::hashes::native` (#1313).
+- [BREAKING] `native` module was renamed to the `pro`, `hash_memory` procedure was renamed to the `hash_memory_words` (#1368).
- Added `hash_memory` procedure to `std::crypto::hashes::rpo` (#1368).
#### VM Internals
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index 9f1a5610ca..11e8916eea 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -103,152 +103,158 @@ end
#! Computes hash of Felt values starting at the specified memory address.
#!
-#! If the number if inputs is 0, procedure returns the empty word: [ZERO, ZERO, ZERO, ZERO].
+#! This procedure divides the hashing process into two parts: hashing pairs of words using
+#! `absorb_double_words_from_memory` procedure and hashing the remaining values using the `hperm`
+#! instruction.
#!
-#! Inputs: [inputs_ptr, num_inputs]
+#! Inputs: [ptr, num_elements]
#! Outputs: [HASH]
+#! Cycles:
+#! - If number of elements divides by 8: 47 cycles + 3 * words
+#! - Else: 180 cycles + 3 * words
+#!
+#! Panics if number of inputs equals 0.
export.hash_memory
# move number of inputs to the top of the stack
swap
- # => [num_inputs, inputs_ptr]
+ # => [num_elements, ptr]
+
+ # check that number of inputs greater than 0
+ dup eq.0 assertz
+ # => [num_elements, ptr]
# get the number of double words
u32divmod.8 swap
- # => [num_inputs/8, num_inputs%8, inputs_ptr]
+ # => [num_elements/8, num_elements%8, ptr]
# get the end_addr for hash_memory_even procedure (end address for pairs of words)
mul.2 dup.2 add movup.2
- # => [inputs_ptr, end_addr, num_inputs%8]
+ # => [ptr, end_addr, num_elements%8]
- # get the capacity element which is equal to num_inputs%8
+ # get the capacity element which is equal to num_elements%8
dup.2
- # => [capacity, inputs_ptr, end_addr, num_inputs%8]
+ # => [capacity, ptr, end_addr, num_elements%8]
# prepare hasher state for RPO permutation
push.0.0.0 padw padw
- # => [C, B, A, inputs_ptr, end_addr, num_inputs%8]
+ # => [C, B, A, ptr, end_addr, num_elements%8]
# hash every pair of words
exec.absorb_double_words_from_memory
- # => [C', B', A', inputs_ptr', end_addr, num_inputs%8] where inputs_ptr' = end_addr
+ # => [C', B', A', ptr', end_addr, num_elements%8] where ptr' = end_addr
# hash remaining input values if there are any left
- # if num_inputs%8 is not ZERO
- dup.14 push.0 neq
+ # if num_elements%8 is ZERO and there are no elements to hash
+ dup.14 eq.0
if.true
- # load the remaining double word
- mem_stream
- # => [E, D, A', inputs_ptr'+2, end_addr, num_inputs%8]
-
- # clean the stack
- movup.12 drop movup.12 drop
- # => [E, D, A', num_inputs%8]
-
- # get the number of elements we need to drop
- # notice that drop_counter could be any number from 1 to 7
- push.8 movup.13 sub movdn.12
- # => [E, D, A', drop_counter]
-
- ### 0th value ########################################################
-
- # we need to drop first value anyway, since number of values is not divisible by 8
- drop
- # => [e_1, e_2, e_3, d_0, d_1, d_2, d_3, A', drop_counter]
-
- # push the padding 0 value
- push.0
- # => [0, e_1, e_2, e_3, d_0, d_1, d_2, d_3, A', drop_counter]
-
- # move the calculated value down the stack
- movdn.6
- # => [e_1, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
-
- ### 1st value ########################################################
-
- # prepare the second element of the E Word (e_1) for cdrop instruction
- push.0 swap
- # => [e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
-
- # push latch variable onto the stack; this will be the control for the cdrop instruction
- push.0
- # => [latch = 0, e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
-
- # get the flag whether the drop counter is equal 1
- dup.14 eq.1
- # => [drop_counter == 1, latch = 0, e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
-
- # update the latch: if drop_counter == 1, latch will become 1
- or
- # => [latch', e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', drop_counter]
-
- # save the latch value
- dup movdn.14
- # => [latch', e_1, 0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', latch', drop_counter]
-
- # if latch == 1, drop 0; otherwise drop e_1
- cdrop
- # => [e_1_or_0, e_2, e_3, d_0, d_1, d_2, 0, d_3, A', latch', drop_counter]
-
- # move the calculated value down the stack
- movdn.6
- # => [e_2, e_3, d_0, d_1, d_2, 0, e_1_or_0, d_3, A', latch', drop_counter]
-
- ### 2nd value ########################################################
-
- # repeat the above process but now compare drop_counter to 2
- push.0 swap
- movup.13 dup.14 eq.2 or
- dup movdn.14
- cdrop movdn.6
- # => [e_3, d_0, d_1, d_2, 0, e_1_or_0, e_2_or_0, d_3, A', latch', drop_counter]
-
- ### 3rd value ########################################################
-
- # repeat the above process but now compare drop_counter to 3
- push.0 swap
- movup.13 dup.14 eq.3 or
- dup movdn.14
- cdrop movdn.6
- # => [d_0, d_1, d_2, 0, e_1_or_0, e_2_or_0, e_3_or_0, d_3, A', latch', drop_counter]
-
- ### 4th value ########################################################
-
- # repeat the above process but now compare drop_counter to 4
- push.0 swap
- movup.13 dup.14 eq.4 or
- dup movdn.14
- cdrop movdn.6
- # => [d_1, d_2, 0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_3, A', latch', drop_counter]
-
- ### 5th value ########################################################
-
- # repeat the above process but now compare drop_counter to 5
- push.0 swap
- movup.13 dup.14 eq.5 or
- dup movdn.14
- cdrop movdn.6
- # => [d_2, 0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_1_or_0, d_3, A', latch', drop_counter]
-
- ### 6th value ########################################################
-
- # repeat the above process but now compare drop_counter to 6
- push.0 swap
- movup.13 movup.14 eq.6 or
- cdrop movdn.6
- # => [0, e_1_or_0, e_2_or_0, e_3_or_0, d_0_or_0, d_1_or_0, d_2_or_0, d_3, A']
- # or in other words
- # => [C, B, A', ... ]
- # notice that we don't need to check the d_3 value: entering the if.true branch means that
- # we have number of elements not divisible by 8, so we will have at least one element to
- # hash here (which turns out to be d_3)
-
- hperm
- # => [F, E, D]
-
- exec.squeeze_digest
- # => [E]
+ # clean the stack
+ exec.squeeze_digest
+ swapw dropw
+ # => [B']
else
- dropw movdnw.2 dropw dropw
- # => [B']
+ # load the remaining double word
+ mem_stream
+ # => [E, D, A', ptr'+2, end_addr, num_elements%8]
+
+ # clean the stack
+ movup.12 drop movup.12 drop
+ # => [E, D, A', num_elements%8]
+
+ # get the number of elements we need to drop
+ # notice that drop_counter could be any number from 1 to 7
+ push.8 movup.13 sub movdn.12
+ # => [E, D, A', drop_counter]
+
+ ### 0th value ########################################################
+
+ # we need to drop first value anyway, since number of values is not divisible by 8
+ # push the padding 0 on to the stack and move it down to the 6th position
+ drop push.0 movdn.6
+ # => [e_2, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', drop_counter]
+
+ ### 1st value ########################################################
+
+ # prepare the second element of the E Word for cdrop instruction
+ push.0 swap
+ # => [e_2, 0, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', drop_counter]
+
+ # push latch variable onto the stack; this will be the control for the cdrop instruction
+ push.0
+ # => [latch = 0, e_2, 0, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', drop_counter]
+
+ # get the flag whether the drop counter is equal 1
+ dup.14 eq.1
+ # => [drop_counter == 1, latch = 0, e_2, 0, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', drop_counter]
+
+ # update the latch: if drop_counter == 1, latch will become 1
+ or
+ # => [latch', e_2, 0, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', drop_counter]
+
+ # save the latch value
+ dup movdn.14
+ # => [latch', e_2, 0, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', latch', drop_counter]
+
+ # if latch == 1, drop 0; otherwise drop e_1
+ cdrop
+ # => [e_2_or_0, e_1, e_0, d_3, d_2, d_1, 0, d_0, A', latch', drop_counter]
+
+ # move the calculated value down the stack
+ movdn.6
+ # => [e_1, e_0, d_3, d_2, d_1, 0, e_2_or_0, d_0, A', latch', drop_counter]
+
+ ### 2nd value ########################################################
+
+ # repeat the above process but now compare drop_counter to 2
+ push.0 swap
+ movup.13 dup.14 eq.2 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [e_0, d_3, d_2, d_1, 0, e_2_or_0, e_1_or_0, d_0, A', latch', drop_counter]
+
+ ### 3rd value ########################################################
+
+ # repeat the above process but now compare drop_counter to 3
+ push.0 swap
+ movup.13 dup.14 eq.3 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [d_3, d_2, d_1, 0, e_2_or_0, e_1_or_0, e_0_or_0, d_0, A', latch', drop_counter]
+
+ ### 4th value ########################################################
+
+ # repeat the above process but now compare drop_counter to 4
+ push.0 swap
+ movup.13 dup.14 eq.4 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [d_2, d_1, 0, e_2_or_0, e_1_or_0, e_0_or_0, d_3_or_0, d_0, A', latch', drop_counter]
+
+ ### 5th value ########################################################
+
+ # repeat the above process but now compare drop_counter to 5
+ push.0 swap
+ movup.13 dup.14 eq.5 or
+ dup movdn.14
+ cdrop movdn.6
+ # => [d_1, 0, e_2_or_0, e_1_or_0, e_0_or_0, d_3_or_0, d_2_or_0, d_0, A', latch', drop_counter]
+
+ ### 6th value ########################################################
+
+ # repeat the above process but now compare drop_counter to 6
+ push.0 swap
+ movup.13 movup.14 eq.6 or
+ cdrop movdn.6
+ # => [0, e_2_or_0, e_1_or_0, e_0_or_0, d_3_or_0, d_2_or_0, d_1_or_0, d_0, A']
+ # or in other words
+ # => [C, B, A', ... ]
+ # notice that we don't need to check the d_0 value: entering the else branch means that
+ # we have number of elements not divisible by 8, so we will have at least one element to
+ # hash here (which turns out to be d_0)
+
+ hperm
+ # => [F, E, D]
+
+ exec.squeeze_digest
+ # => [E]
end
end
\ No newline at end of file
diff --git a/stdlib/docs/crypto/hashes/rpo.md b/stdlib/docs/crypto/hashes/rpo.md
index cafe2d96e5..da22de54cc 100644
--- a/stdlib/docs/crypto/hashes/rpo.md
+++ b/stdlib/docs/crypto/hashes/rpo.md
@@ -5,4 +5,4 @@ Prepares the top of the stack with the hasher initial state.
This pro
| squeeze_digest | Given the hasher state, returns the hash output.
Input: [C, B, A, ...]
Ouptut: [HASH, ...]
where: For the native RPO hasher HASH is B.
Cycles: 9
|
| absorb_double_words_from_memory | Hashes the memory `start_addr` to `end_addr` given an RPO state specified by 3 words.
This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
loop. `end_addr` is not inclusive.
Stack transition:
Input: [C, B, A, start_addr, end_addr, ...]
Output: [C', B', A', end_addr, end_addr ...]
Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
|
| hash_memory_words | Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
Requires `start_addr < end_addr`, `end_addr` is not inclusive.
Stack transition:
Input: [start_addr, end_addr, ...]
Output: [H, ...]
Cycles:
even words: 49 cycles + 3 * words
odd words: 61 cycles + 3 * words
|
-| hash_memory | Computes hash of note inputs starting at the specified memory address.
If the number if inputs is 0, procedure returns the empty word: [ZERO, ZERO, ZERO, ZERO].
Inputs: [inputs_ptr, num_inputs]
Outputs: [HASH]
|
+| hash_memory | Computes hash of Felt values starting at the specified memory address.
This procedure divides the hashing process into two parts: hashing pairs of words using
`absorb_double_words_from_memory` procedure and hashing the remaining values using the `hperm`
instruction.
Inputs: [ptr, num_elements]
Outputs: [HASH]
Cycles:
- If number of elements divides by 8: 47 cycles + 3 * words
- Else: 180 cycles + 3 * words
Panics if number of inputs equals 0.
|
diff --git a/stdlib/tests/crypto/rpo.rs b/stdlib/tests/crypto/rpo.rs
index 3c7bd7244b..d8c920f510 100644
--- a/stdlib/tests/crypto/rpo.rs
+++ b/stdlib/tests/crypto/rpo.rs
@@ -277,7 +277,48 @@ fn test_squeeze_digest() {
#[test]
fn test_hash_memory() {
- let compute_inputs_hash = "
+ // hash fewer than 8 elements
+ let compute_inputs_hash_5 = "
+ use.std::crypto::hashes::rpo
+
+ begin
+ push.1.2.3.4.1000 mem_storew dropw
+ push.5.0.0.0.1001 mem_storew dropw
+
+ push.5.1000
+
+ exec.rpo::hash_memory
+ end
+ ";
+
+ #[rustfmt::skip]
+ let expected_hash: Vec = build_expected_hash(&[
+ 1, 2, 3, 4, 5
+ ]).into_iter().map(|e| e.as_int()).collect();
+ build_test!(compute_inputs_hash_5, &[]).expect_stack(&expected_hash);
+
+ // hash exactly 8 elements
+ let compute_inputs_hash_8 = "
+ use.std::crypto::hashes::rpo
+
+ begin
+ push.1.2.3.4.1000 mem_storew dropw
+ push.5.6.7.8.1001 mem_storew dropw
+
+ push.8.1000
+
+ exec.rpo::hash_memory
+ end
+ ";
+
+ #[rustfmt::skip]
+ let expected_hash: Vec = build_expected_hash(&[
+ 1, 2, 3, 4, 5, 6, 7, 8
+ ]).into_iter().map(|e| e.as_int()).collect();
+ build_test!(compute_inputs_hash_8, &[]).expect_stack(&expected_hash);
+
+ // hash more than 8 elements
+ let compute_inputs_hash_15 = "
use.std::crypto::hashes::rpo
begin
@@ -286,18 +327,34 @@ fn test_hash_memory() {
push.9.10.11.12.1002 mem_storew dropw
push.13.14.15.0.1003 mem_storew dropw
-
push.15.1000
- #######################################################
-
exec.rpo::hash_memory
end
";
#[rustfmt::skip]
let expected_hash: Vec = build_expected_hash(&[
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+ 1, 2, 3, 4,
+ 5, 6, 7, 8,
+ 9, 10, 11, 12,
+ 13, 14, 15
]).into_iter().map(|e| e.as_int()).collect();
- build_test!(compute_inputs_hash, &[]).expect_stack(&expected_hash);
+ build_test!(compute_inputs_hash_15, &[]).expect_stack(&expected_hash);
+}
+
+#[test]
+fn test_hash_memory_fail() {
+ // try to hash 0 values
+ let compute_inputs_hash = "
+ use.std::crypto::hashes::rpo
+
+ begin
+ push.0.1000
+
+ exec.rpo::hash_memory
+ end
+ ";
+
+ assert!(build_test!(compute_inputs_hash, &[]).execute().is_err());
}
From fd05155d7430ff0ca4c25cdd8f8c3f55df577fbc Mon Sep 17 00:00:00 2001
From: Andrey
Date: Sat, 29 Jun 2024 00:37:33 +0300
Subject: [PATCH 10/14] fix: fix the error cleaning
---
stdlib/asm/crypto/hashes/rpo.masm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index 11e8916eea..9b8a3457db 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -149,7 +149,7 @@ export.hash_memory
if.true
# clean the stack
exec.squeeze_digest
- swapw dropw
+ swapw drop drop drop movdn.4
# => [B']
else
# load the remaining double word
From 98ca1ce3f61b946e7b55fd3073081e118fab41ea Mon Sep 17 00:00:00 2001
From: Andrey
Date: Mon, 1 Jul 2024 02:01:59 +0300
Subject: [PATCH 11/14] test: check that other stack values stays unchanged
---
stdlib/tests/crypto/rpo.rs | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/stdlib/tests/crypto/rpo.rs b/stdlib/tests/crypto/rpo.rs
index d8c920f510..d00da8fefc 100644
--- a/stdlib/tests/crypto/rpo.rs
+++ b/stdlib/tests/crypto/rpo.rs
@@ -284,6 +284,7 @@ fn test_hash_memory() {
begin
push.1.2.3.4.1000 mem_storew dropw
push.5.0.0.0.1001 mem_storew dropw
+ push.11
push.5.1000
@@ -292,9 +293,11 @@ fn test_hash_memory() {
";
#[rustfmt::skip]
- let expected_hash: Vec = build_expected_hash(&[
+ let mut expected_hash: Vec = build_expected_hash(&[
1, 2, 3, 4, 5
]).into_iter().map(|e| e.as_int()).collect();
+ // make sure that value `11` stays unchanged
+ expected_hash.push(11);
build_test!(compute_inputs_hash_5, &[]).expect_stack(&expected_hash);
// hash exactly 8 elements
@@ -304,6 +307,7 @@ fn test_hash_memory() {
begin
push.1.2.3.4.1000 mem_storew dropw
push.5.6.7.8.1001 mem_storew dropw
+ push.11
push.8.1000
@@ -312,9 +316,11 @@ fn test_hash_memory() {
";
#[rustfmt::skip]
- let expected_hash: Vec = build_expected_hash(&[
+ let mut expected_hash: Vec = build_expected_hash(&[
1, 2, 3, 4, 5, 6, 7, 8
]).into_iter().map(|e| e.as_int()).collect();
+ // make sure that value `11` stays unchanged
+ expected_hash.push(11);
build_test!(compute_inputs_hash_8, &[]).expect_stack(&expected_hash);
// hash more than 8 elements
@@ -326,6 +332,7 @@ fn test_hash_memory() {
push.5.6.7.8.1001 mem_storew dropw
push.9.10.11.12.1002 mem_storew dropw
push.13.14.15.0.1003 mem_storew dropw
+ push.11
push.15.1000
@@ -334,12 +341,14 @@ fn test_hash_memory() {
";
#[rustfmt::skip]
- let expected_hash: Vec = build_expected_hash(&[
+ let mut expected_hash: Vec = build_expected_hash(&[
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15
]).into_iter().map(|e| e.as_int()).collect();
+ // make sure that value `11` stays unchanged
+ expected_hash.push(11);
build_test!(compute_inputs_hash_15, &[]).expect_stack(&expected_hash);
}
From 4cf59b682321063232685c5ee2af0f4aa666f4ed Mon Sep 17 00:00:00 2001
From: Andrey
Date: Tue, 1 Oct 2024 13:27:53 +0300
Subject: [PATCH 12/14] refactor: impl test for empty inputs, update procedure
docs, fix typo in changelog
---
CHANGELOG.md | 2 +-
stdlib/asm/crypto/hashes/rpo.masm | 30 +++++++++++++++++-------------
stdlib/tests/crypto/rpo.rs | 4 ++--
3 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e53a69d70..788623c9fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -158,7 +158,7 @@
#### Stdlib
- Added `init_no_padding` procedure to `std::crypto::hashes::native` (#1313).
-- [BREAKING] `native` module was renamed to the `pro`, `hash_memory` procedure was renamed to the `hash_memory_words` (#1368).
+- [BREAKING] `native` module was renamed to the `rpo`, `hash_memory` procedure was renamed to the `hash_memory_words` (#1368).
- Added `hash_memory` procedure to `std::crypto::hashes::rpo` (#1368).
#### VM Internals
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index c852de82a7..b0357d50c5 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -5,6 +5,7 @@
#!
#! Input: []
#! Ouptut: [PERM, PERM, PERM, ...]
+#!
#! Cycles: 12
export.init_no_padding
padw padw padw
@@ -14,7 +15,11 @@ end
#!
#! Input: [C, B, A, ...]
#! Ouptut: [HASH, ...]
-#! where: For the native RPO hasher HASH is B.
+#!
+#! Where :
+#! - `A` is the capacity word that will be used by the hashing function.
+#! - `B` is the hash output.
+#!
#! Cycles: 9
export.squeeze_digest
# drop the first rate word (4 cycles)
@@ -32,12 +37,14 @@ end
#! This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
#! loop. `end_addr` is not inclusive.
#!
-#! Stack transition:
#! Input: [C, B, A, start_addr, end_addr, ...]
#! Output: [C', B', A', end_addr, end_addr ...]
-#! Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
#!
-#! Where `A` is the capacity word that will be used by the hashing function, and `B'` the hash output.
+#! Where :
+#! - `A` is the capacity word that will be used by the hashing function.
+#! - `B` is the hash output.
+#!
+#! Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
export.absorb_double_words_from_memory
dup.13 dup.13 neq # (4 cycles )
while.true
@@ -50,12 +57,13 @@ end
#!
#! Requires `start_addr < end_addr`, `end_addr` is not inclusive.
#!
-#! Stack transition:
#! Input: [start_addr, end_addr, ...]
#! Output: [H, ...]
+#!
#! Cycles:
-#! even words: 49 cycles + 3 * words
-#! odd words: 61 cycles + 3 * words
+#! - even words: 49 cycles + 3 * words
+#! - odd words: 61 cycles + 3 * words
+#! where `words` is the `start_addr - end_addr - 1`
export.hash_memory_words
# enforce `start_addr < end_addr`
dup.1 dup.1 u32assert2 u32gt assert
@@ -109,20 +117,16 @@ end
#!
#! Inputs: [ptr, num_elements]
#! Outputs: [HASH]
+#!
#! Cycles:
#! - If number of elements divides by 8: 47 cycles + 3 * words
#! - Else: 180 cycles + 3 * words
-#!
-#! Panics if number of inputs equals 0.
+#! where `words` is the number of quads of input values.
export.hash_memory
# move number of inputs to the top of the stack
swap
# => [num_elements, ptr]
- # check that number of inputs greater than 0
- dup eq.0 assertz
- # => [num_elements, ptr]
-
# get the number of double words
u32divmod.8 swap
# => [num_elements/8, num_elements%8, ptr]
diff --git a/stdlib/tests/crypto/rpo.rs b/stdlib/tests/crypto/rpo.rs
index fcc86e9c34..b1eac29e1d 100644
--- a/stdlib/tests/crypto/rpo.rs
+++ b/stdlib/tests/crypto/rpo.rs
@@ -353,7 +353,7 @@ fn test_hash_memory() {
}
#[test]
-fn test_hash_memory_fail() {
+fn test_hash_memory_empty() {
// try to hash 0 values
let compute_inputs_hash = "
use.std::crypto::hashes::rpo
@@ -365,5 +365,5 @@ fn test_hash_memory_fail() {
end
";
- assert!(build_test!(compute_inputs_hash, &[]).execute().is_err());
+ build_test!(compute_inputs_hash, &[]).expect_stack(&[0; 16]);
}
From b84ae421cd430a039bb505f473890436376ba83c Mon Sep 17 00:00:00 2001
From: Andrey
Date: Wed, 9 Oct 2024 20:51:40 +0300
Subject: [PATCH 13/14] refactor: update doc comments, add test for empty input
---
stdlib/asm/crypto/hashes/rpo.masm | 36 +++++++++---------
stdlib/tests/crypto/rpo.rs | 63 +++++++++++++++++++------------
2 files changed, 57 insertions(+), 42 deletions(-)
diff --git a/stdlib/asm/crypto/hashes/rpo.masm b/stdlib/asm/crypto/hashes/rpo.masm
index b0357d50c5..1035fa464d 100644
--- a/stdlib/asm/crypto/hashes/rpo.masm
+++ b/stdlib/asm/crypto/hashes/rpo.masm
@@ -34,8 +34,8 @@ end
#! Hashes the memory `start_addr` to `end_addr` given an RPO state specified by 3 words.
#!
-#! This requires that `end_addr=start_addr + 2n + 1`, otherwise the procedure will enter an infinite
-#! loop. `end_addr` is not inclusive.
+#! This requires that `end_addr = start_addr + 2n` where n = {0, 1, 2 ...}, otherwise the procedure
+#! will enter an infinite loop.
#!
#! Input: [C, B, A, start_addr, end_addr, ...]
#! Output: [C', B', A', end_addr, end_addr ...]
@@ -44,7 +44,7 @@ end
#! - `A` is the capacity word that will be used by the hashing function.
#! - `B` is the hash output.
#!
-#! Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr - 1`
+#! Cycles: 4 + 3 * words, where `words` is the `start_addr - end_addr`
export.absorb_double_words_from_memory
dup.13 dup.13 neq # (4 cycles )
while.true
@@ -55,7 +55,7 @@ end
#! Hashes the memory `start_addr` to `end_addr`, handles odd number of elements.
#!
-#! Requires `start_addr < end_addr`, `end_addr` is not inclusive.
+#! Requires `start_addr ≤ end_addr`, `end_addr` is not inclusive.
#!
#! Input: [start_addr, end_addr, ...]
#! Output: [H, ...]
@@ -65,48 +65,50 @@ end
#! - odd words: 61 cycles + 3 * words
#! where `words` is the `start_addr - end_addr - 1`
export.hash_memory_words
- # enforce `start_addr < end_addr`
- dup.1 dup.1 u32assert2 u32gt assert
+ # enforce `start_addr ≤ end_addr`
+ dup.1 dup.1 u32assert2 u32gte assert
# figure out if the range is for an odd number of words (9 cycles)
dup.1 dup.1 sub is_odd
- # stack: [is_odd, start_addr, end_addr, ...]
+ # => [is_odd, start_addr, end_addr, ...]
# make the start/end range even (4 cycles)
movup.2 dup.1 sub
- # stack: [end_addr, is_odd, start_addr, ...]
+ # => [end_addr, is_odd, start_addr, ...]
# move start_addr to the right stack position (1 cycles)
movup.2
- # stack: [start_addr, end_addr, is_odd, ...]
+ # => [start_addr, end_addr, is_odd, ...]
# prepare hasher state (14 cycles)
dup.2 mul.4 push.0.0.0 padw padw
- # stack: [C, B, A, start_addr, end_addr, is_odd, ...]
+ # => [C, B, A, start_addr, end_addr, is_odd, ...]
# (4 + 3 * words cycles)
exec.absorb_double_words_from_memory
+ # => [C', B', A', end_addr, end_addr, is_odd, ...]
# (1 cycles)
movup.14
+ # => [is_odd, C', B', A', end_addr, end_addr, ...]
# handle the odd element, if any (12 cycles)
if.true
- # start_addr and end_addr are equal after calling `absorb_double_words_from_memory`, and both point
- # to the last element. Load the last word (6 cycles)
+ # start_addr and end_addr are equal after calling `absorb_double_words_from_memory`, and both
+ # point to the last element. Load the last word (6 cycles)
dropw dup.9 mem_loadw
+ # => [D, A', end_addr, end_addr, ...]
- # set the padding (4 cycles)
- padw
-
- # (1 cycles)
- hperm
+ # set the padding and compute the permutation (5 cycles)
+ padw hperm
end
exec.squeeze_digest
+ # => [HASH, end_addr, end_addr, ...]
# drop start_addr/end_addr (4 cycles)
movup.4 drop movup.4 drop
+ # => [HASH]
end
#! Computes hash of Felt values starting at the specified memory address.
diff --git a/stdlib/tests/crypto/rpo.rs b/stdlib/tests/crypto/rpo.rs
index b1eac29e1d..affc6d9d9c 100644
--- a/stdlib/tests/crypto/rpo.rs
+++ b/stdlib/tests/crypto/rpo.rs
@@ -23,27 +23,6 @@ fn test_invalid_end_addr() {
err_msg: None,
}
);
-
- // address range can not contain zero elements
- let empty_range = "
- use.std::crypto::hashes::rpo
-
- begin
- push.1000 # end address
- push.1000 # start address
-
- exec.rpo::hash_memory_words
- end
- ";
- let test = build_test!(empty_range, &[]);
- expect_exec_error!(
- test,
- ExecutionError::FailedAssertion {
- clk: 18.into(),
- err_code: 0,
- err_msg: None,
- }
- );
}
#[test]
@@ -354,16 +333,50 @@ fn test_hash_memory() {
#[test]
fn test_hash_memory_empty() {
- // try to hash 0 values
- let compute_inputs_hash = "
+ // absorb_double_words_from_memory
+ let source = "
+ use.std::crypto::hashes::rpo
+
+ begin
+ push.1000 # end address
+ push.1000 # start address
+ padw padw padw # hasher state
+
+ exec.rpo::absorb_double_words_from_memory
+ end
+ ";
+
+ let mut expected_stack = vec![0; 12];
+ expected_stack.push(1000);
+ expected_stack.push(1000);
+
+ build_test!(source, &[]).expect_stack(&expected_stack);
+
+ // hash_memory_words
+ let source = "
+ use.std::crypto::hashes::rpo
+
+ begin
+ push.1000 # end address
+ push.1000 # start address
+
+ exec.rpo::hash_memory_words
+ end
+ ";
+
+ build_test!(source, &[]).expect_stack(&[0; 4]);
+
+ // hash_memory
+ let source = "
use.std::crypto::hashes::rpo
begin
- push.0.1000
+ push.0 # number of elements to hash
+ push.1000 # start address
exec.rpo::hash_memory
end
";
- build_test!(compute_inputs_hash, &[]).expect_stack(&[0; 16]);
+ build_test!(source, &[]).expect_stack(&[0; 16]);
}
From bc565fa12d4f1f3fba959f1c46f9ea0eb25a5cf7 Mon Sep 17 00:00:00 2001
From: Andrey
Date: Thu, 10 Oct 2024 01:00:30 +0300
Subject: [PATCH 14/14] refactor: fix clippy errors
---
assembly/src/assembler/basic_block_builder.rs | 8 ++++----
assembly/src/assembler/module_graph/debug.rs | 8 ++++----
assembly/src/assembler/module_graph/mod.rs | 2 +-
assembly/src/ast/attribute/set.rs | 4 ++--
assembly/src/ast/visit.rs | 4 ++--
assembly/src/compile.rs | 12 ++++++------
assembly/src/library/path.rs | 10 +++++-----
assembly/src/parser/mod.rs | 2 +-
assembly/src/parser/token.rs | 2 +-
assembly/src/sema/passes/const_eval.rs | 4 ++--
assembly/src/sema/passes/verify_invoke.rs | 4 ++--
core/src/mast/node/basic_block_node/mod.rs | 4 ++--
core/src/mast/node/call_node.rs | 6 +++---
core/src/mast/node/dyn_node.rs | 6 +++---
core/src/mast/node/external.rs | 6 +++---
core/src/mast/node/join_node.rs | 4 ++--
core/src/mast/node/loop_node.rs | 4 ++--
core/src/mast/node/mod.rs | 4 ++--
core/src/mast/node/split_node.rs | 4 ++--
core/src/mast/serialization/basic_blocks.rs | 2 +-
processor/src/host/advice/mod.rs | 2 +-
processor/src/host/mod.rs | 2 +-
prover/src/gpu/metal/mod.rs | 2 +-
23 files changed, 53 insertions(+), 53 deletions(-)
diff --git a/assembly/src/assembler/basic_block_builder.rs b/assembly/src/assembler/basic_block_builder.rs
index 1113e1fead..3246484d21 100644
--- a/assembly/src/assembler/basic_block_builder.rs
+++ b/assembly/src/assembler/basic_block_builder.rs
@@ -60,7 +60,7 @@ impl<'a> BasicBlockBuilder<'a> {
}
/// Accessors
-impl<'a> BasicBlockBuilder<'a> {
+impl BasicBlockBuilder<'_> {
/// Returns a reference to the internal [`MastForestBuilder`].
pub fn mast_forest_builder(&self) -> &MastForestBuilder {
self.mast_forest_builder
@@ -73,7 +73,7 @@ impl<'a> BasicBlockBuilder<'a> {
}
/// Operations
-impl<'a> BasicBlockBuilder<'a> {
+impl BasicBlockBuilder<'_> {
/// Adds the specified operation to the list of basic block operations.
pub fn push_op(&mut self, op: Operation) {
self.ops.push(op);
@@ -96,7 +96,7 @@ impl<'a> BasicBlockBuilder<'a> {
}
/// Decorators
-impl<'a> BasicBlockBuilder<'a> {
+impl BasicBlockBuilder<'_> {
/// Add the specified decorator to the list of basic block decorators.
pub fn push_decorator(&mut self, decorator: Decorator) -> Result<(), AssemblyError> {
let decorator_id = self.mast_forest_builder.ensure_decorator(decorator)?;
@@ -159,7 +159,7 @@ impl<'a> BasicBlockBuilder<'a> {
}
/// Span Constructors
-impl<'a> BasicBlockBuilder<'a> {
+impl BasicBlockBuilder<'_> {
/// Creates and returns a new basic block node from the operations and decorators currently in
/// this builder.
///
diff --git a/assembly/src/assembler/module_graph/debug.rs b/assembly/src/assembler/module_graph/debug.rs
index bf584fad1b..eea58adf48 100644
--- a/assembly/src/assembler/module_graph/debug.rs
+++ b/assembly/src/assembler/module_graph/debug.rs
@@ -14,7 +14,7 @@ impl fmt::Debug for ModuleGraph {
#[doc(hidden)]
struct DisplayModuleGraph<'a>(&'a ModuleGraph);
-impl<'a> fmt::Debug for DisplayModuleGraph<'a> {
+impl fmt::Debug for DisplayModuleGraph<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_set()
.entries(self.0.modules.iter().enumerate().flat_map(|(module_index, m)| {
@@ -56,7 +56,7 @@ impl<'a> fmt::Debug for DisplayModuleGraph<'a> {
#[doc(hidden)]
struct DisplayModuleGraphNodes<'a>(&'a Vec);
-impl<'a> fmt::Debug for DisplayModuleGraphNodes<'a> {
+impl fmt::Debug for DisplayModuleGraphNodes<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_list()
.entries(self.0.iter().enumerate().flat_map(|(module_index, m)| {
@@ -111,7 +111,7 @@ struct DisplayModuleGraphNode<'a> {
ty: GraphNodeType,
}
-impl<'a> fmt::Debug for DisplayModuleGraphNode<'a> {
+impl fmt::Debug for DisplayModuleGraphNode<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Node")
.field("id", &format_args!("{}:{}", &self.module.as_usize(), &self.index.as_usize()))
@@ -128,7 +128,7 @@ struct DisplayModuleGraphNodeWithEdges<'a> {
out_edges: &'a [GlobalProcedureIndex],
}
-impl<'a> fmt::Debug for DisplayModuleGraphNodeWithEdges<'a> {
+impl fmt::Debug for DisplayModuleGraphNodeWithEdges<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Edge")
.field(
diff --git a/assembly/src/assembler/module_graph/mod.rs b/assembly/src/assembler/module_graph/mod.rs
index c96617a314..f8116f9985 100644
--- a/assembly/src/assembler/module_graph/mod.rs
+++ b/assembly/src/assembler/module_graph/mod.rs
@@ -39,7 +39,7 @@ pub enum ProcedureWrapper<'a> {
Info(&'a ProcedureInfo),
}
-impl<'a> ProcedureWrapper<'a> {
+impl ProcedureWrapper<'_> {
/// Returns the name of the procedure.
pub fn name(&self) -> &ProcedureName {
match self {
diff --git a/assembly/src/ast/attribute/set.rs b/assembly/src/ast/attribute/set.rs
index bbf69698a5..f215f96db0 100644
--- a/assembly/src/ast/attribute/set.rs
+++ b/assembly/src/ast/attribute/set.rs
@@ -197,7 +197,7 @@ pub struct AttributeSetOccupiedEntry<'a> {
set: &'a mut AttributeSet,
index: usize,
}
-impl<'a> AttributeSetOccupiedEntry<'a> {
+impl AttributeSetOccupiedEntry<'_> {
#[inline]
pub fn get(&self) -> &Attribute {
&self.set.attrs[self.index]
@@ -228,7 +228,7 @@ pub struct AttributeSetVacantEntry<'a> {
key: Ident,
index: usize,
}
-impl<'a> AttributeSetVacantEntry<'a> {
+impl AttributeSetVacantEntry<'_> {
pub fn insert(self, attr: Attribute) {
if self.key != attr.id() {
self.set.insert(attr);
diff --git a/assembly/src/ast/visit.rs b/assembly/src/ast/visit.rs
index b9d60cbe65..ecd11fb86e 100644
--- a/assembly/src/ast/visit.rs
+++ b/assembly/src/ast/visit.rs
@@ -139,7 +139,7 @@ pub trait Visit {
}
}
-impl<'a, V, T> Visit for &'a mut V
+impl Visit for &mut V
where
V: ?Sized + Visit,
{
@@ -575,7 +575,7 @@ pub trait VisitMut {
}
}
-impl<'a, V, T> VisitMut for &'a mut V
+impl VisitMut for &mut V
where
V: ?Sized + VisitMut,
{
diff --git a/assembly/src/compile.rs b/assembly/src/compile.rs
index 1d2fda3a45..2e36858cdd 100644
--- a/assembly/src/compile.rs
+++ b/assembly/src/compile.rs
@@ -130,7 +130,7 @@ impl Compile for Module {
}
}
-impl<'a> Compile for &'a Module {
+impl Compile for &Module {
#[inline(always)]
fn compile_with_options(
self,
@@ -197,7 +197,7 @@ impl Compile for Arc {
}
}
-impl<'a> Compile for &'a str {
+impl Compile for &str {
#[inline(always)]
fn compile_with_options(
self,
@@ -208,7 +208,7 @@ impl<'a> Compile for &'a str {
}
}
-impl<'a> Compile for &'a String {
+impl Compile for &String {
#[inline(always)]
fn compile_with_options(
self,
@@ -251,7 +251,7 @@ impl Compile for Box {
}
}
-impl<'a> Compile for Cow<'a, str> {
+impl Compile for Cow<'_, str> {
#[inline(always)]
fn compile_with_options(
self,
@@ -265,7 +265,7 @@ impl<'a> Compile for Cow<'a, str> {
// COMPILE IMPLEMENTATIONS FOR BYTES
// ------------------------------------------------------------------------------------------------
-impl<'a> Compile for &'a [u8] {
+impl Compile for &[u8] {
#[inline]
fn compile_with_options(
self,
@@ -350,7 +350,7 @@ where
// ------------------------------------------------------------------------------------------------
#[cfg(feature = "std")]
-impl<'a> Compile for &'a std::path::Path {
+impl Compile for &std::path::Path {
fn compile_with_options(
self,
source_manager: &dyn SourceManager,
diff --git a/assembly/src/library/path.rs b/assembly/src/library/path.rs
index a77ea1b287..22e5fe8479 100644
--- a/assembly/src/library/path.rs
+++ b/assembly/src/library/path.rs
@@ -65,9 +65,9 @@ impl<'a> LibraryPathComponent<'a> {
}
}
-impl<'a> Eq for LibraryPathComponent<'a> {}
+impl Eq for LibraryPathComponent<'_> {}
-impl<'a> PartialEq for LibraryPathComponent<'a> {
+impl PartialEq for LibraryPathComponent<'_> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Namespace(a), Self::Namespace(b)) => a == b,
@@ -77,13 +77,13 @@ impl<'a> PartialEq for LibraryPathComponent<'a> {
}
}
-impl<'a> PartialEq for LibraryPathComponent<'a> {
+impl PartialEq for LibraryPathComponent<'_> {
fn eq(&self, other: &str) -> bool {
self.as_ref().eq(other)
}
}
-impl<'a> AsRef for LibraryPathComponent<'a> {
+impl AsRef for LibraryPathComponent<'_> {
fn as_ref(&self) -> &str {
match self {
Self::Namespace(ns) => ns.as_str(),
@@ -92,7 +92,7 @@ impl<'a> AsRef for LibraryPathComponent<'a> {
}
}
-impl<'a> fmt::Display for LibraryPathComponent<'a> {
+impl fmt::Display for LibraryPathComponent<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.as_ref())
}
diff --git a/assembly/src/parser/mod.rs b/assembly/src/parser/mod.rs
index d91f9e1024..d61e5619a1 100644
--- a/assembly/src/parser/mod.rs
+++ b/assembly/src/parser/mod.rs
@@ -304,7 +304,7 @@ mod module_walker {
}
}
- impl<'a> Iterator for WalkModules<'a> {
+ impl Iterator for WalkModules<'_> {
type Item = Result;
fn next(&mut self) -> Option {
diff --git a/assembly/src/parser/token.rs b/assembly/src/parser/token.rs
index 8251278716..602e274912 100644
--- a/assembly/src/parser/token.rs
+++ b/assembly/src/parser/token.rs
@@ -316,7 +316,7 @@ pub enum Token<'input> {
Eof,
}
-impl<'input> fmt::Display for Token<'input> {
+impl fmt::Display for Token<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Token::Add => write!(f, "add"),
diff --git a/assembly/src/sema/passes/const_eval.rs b/assembly/src/sema/passes/const_eval.rs
index f76de03ad2..8394bc5402 100644
--- a/assembly/src/sema/passes/const_eval.rs
+++ b/assembly/src/sema/passes/const_eval.rs
@@ -17,7 +17,7 @@ impl<'analyzer> ConstEvalVisitor<'analyzer> {
}
}
-impl<'analyzer> ConstEvalVisitor<'analyzer> {
+impl ConstEvalVisitor<'_> {
fn eval_const(&mut self, imm: &mut Immediate) -> ControlFlow<()>
where
T: TryFrom,
@@ -45,7 +45,7 @@ impl<'analyzer> ConstEvalVisitor<'analyzer> {
}
}
-impl<'analyzer> VisitMut for ConstEvalVisitor<'analyzer> {
+impl VisitMut for ConstEvalVisitor<'_> {
fn visit_mut_immediate_u8(&mut self, imm: &mut Immediate) -> ControlFlow<()> {
self.eval_const(imm)
}
diff --git a/assembly/src/sema/passes/verify_invoke.rs b/assembly/src/sema/passes/verify_invoke.rs
index a1c38ba8ca..16c7ac5ba5 100644
--- a/assembly/src/sema/passes/verify_invoke.rs
+++ b/assembly/src/sema/passes/verify_invoke.rs
@@ -43,7 +43,7 @@ impl<'a> VerifyInvokeTargets<'a> {
}
}
-impl<'a> VerifyInvokeTargets<'a> {
+impl VerifyInvokeTargets<'_> {
fn resolve_local(&mut self, name: &ProcedureName) -> ControlFlow<()> {
if !self.procedures.contains(name) {
self.analyzer
@@ -72,7 +72,7 @@ impl<'a> VerifyInvokeTargets<'a> {
}
}
-impl<'a> VisitMut for VerifyInvokeTargets<'a> {
+impl VisitMut for VerifyInvokeTargets<'_> {
fn visit_mut_inst(&mut self, inst: &mut Span) -> ControlFlow<()> {
let span = inst.span();
match &**inst {
diff --git a/core/src/mast/node/basic_block_node/mod.rs b/core/src/mast/node/basic_block_node/mod.rs
index 81f0afa0a5..726decbc72 100644
--- a/core/src/mast/node/basic_block_node/mod.rs
+++ b/core/src/mast/node/basic_block_node/mod.rs
@@ -247,7 +247,7 @@ struct BasicBlockNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> PrettyPrint for BasicBlockNodePrettyPrint<'a> {
+impl PrettyPrint for BasicBlockNodePrettyPrint<'_> {
#[rustfmt::skip]
fn render(&self) -> crate::prettier::Document {
use crate::prettier::*;
@@ -295,7 +295,7 @@ impl<'a> PrettyPrint for BasicBlockNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for BasicBlockNodePrettyPrint<'a> {
+impl fmt::Display for BasicBlockNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::prettier::PrettyPrint;
self.pretty_print(f)
diff --git a/core/src/mast/node/call_node.rs b/core/src/mast/node/call_node.rs
index c028a32456..7f207d386f 100644
--- a/core/src/mast/node/call_node.rs
+++ b/core/src/mast/node/call_node.rs
@@ -201,7 +201,7 @@ struct CallNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> CallNodePrettyPrint<'a> {
+impl CallNodePrettyPrint<'_> {
/// Concatenates the provided decorators in a single line. If the list of decorators is not
/// empty, prepends `prepend` and appends `append` to the decorator document.
fn concatenate_decorators(
@@ -240,7 +240,7 @@ impl<'a> CallNodePrettyPrint<'a> {
}
}
-impl<'a> PrettyPrint for CallNodePrettyPrint<'a> {
+impl PrettyPrint for CallNodePrettyPrint<'_> {
fn render(&self) -> Document {
let call_or_syscall = {
let callee_digest = self.mast_forest[self.node.callee].digest();
@@ -265,7 +265,7 @@ impl<'a> PrettyPrint for CallNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for CallNodePrettyPrint<'a> {
+impl fmt::Display for CallNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::prettier::PrettyPrint;
self.pretty_print(f)
diff --git a/core/src/mast/node/dyn_node.rs b/core/src/mast/node/dyn_node.rs
index 34e87610b8..91afeea798 100644
--- a/core/src/mast/node/dyn_node.rs
+++ b/core/src/mast/node/dyn_node.rs
@@ -91,7 +91,7 @@ struct DynNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> DynNodePrettyPrint<'a> {
+impl DynNodePrettyPrint<'_> {
/// Concatenates the provided decorators in a single line. If the list of decorators is not
/// empty, prepends `prepend` and appends `append` to the decorator document.
fn concatenate_decorators(
@@ -130,7 +130,7 @@ impl<'a> DynNodePrettyPrint<'a> {
}
}
-impl<'a> crate::prettier::PrettyPrint for DynNodePrettyPrint<'a> {
+impl crate::prettier::PrettyPrint for DynNodePrettyPrint<'_> {
fn render(&self) -> crate::prettier::Document {
let dyn_text = const_text("dyn");
@@ -144,7 +144,7 @@ impl<'a> crate::prettier::PrettyPrint for DynNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for DynNodePrettyPrint<'a> {
+impl fmt::Display for DynNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.pretty_print(f)
}
diff --git a/core/src/mast/node/external.rs b/core/src/mast/node/external.rs
index 3b3f23e403..d966008009 100644
--- a/core/src/mast/node/external.rs
+++ b/core/src/mast/node/external.rs
@@ -89,7 +89,7 @@ struct ExternalNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> ExternalNodePrettyPrint<'a> {
+impl ExternalNodePrettyPrint<'_> {
/// Concatenates the provided decorators in a single line. If the list of decorators is not
/// empty, prepends `prepend` and appends `append` to the decorator document.
fn concatenate_decorators(
@@ -128,7 +128,7 @@ impl<'a> ExternalNodePrettyPrint<'a> {
}
}
-impl<'a> crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'a> {
+impl crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'_> {
fn render(&self) -> crate::prettier::Document {
let external = const_text("external")
+ const_text(".")
@@ -144,7 +144,7 @@ impl<'a> crate::prettier::PrettyPrint for ExternalNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for ExternalNodePrettyPrint<'a> {
+impl fmt::Display for ExternalNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::prettier::PrettyPrint;
self.pretty_print(f)
diff --git a/core/src/mast/node/join_node.rs b/core/src/mast/node/join_node.rs
index 17aaccd8ec..d3d04b4510 100644
--- a/core/src/mast/node/join_node.rs
+++ b/core/src/mast/node/join_node.rs
@@ -142,7 +142,7 @@ struct JoinNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> PrettyPrint for JoinNodePrettyPrint<'a> {
+impl PrettyPrint for JoinNodePrettyPrint<'_> {
#[rustfmt::skip]
fn render(&self) -> crate::prettier::Document {
use crate::prettier::*;
@@ -195,7 +195,7 @@ impl<'a> PrettyPrint for JoinNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for JoinNodePrettyPrint<'a> {
+impl fmt::Display for JoinNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::prettier::PrettyPrint;
self.pretty_print(f)
diff --git a/core/src/mast/node/loop_node.rs b/core/src/mast/node/loop_node.rs
index 08933ac521..6091ce034d 100644
--- a/core/src/mast/node/loop_node.rs
+++ b/core/src/mast/node/loop_node.rs
@@ -131,7 +131,7 @@ struct LoopNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> crate::prettier::PrettyPrint for LoopNodePrettyPrint<'a> {
+impl crate::prettier::PrettyPrint for LoopNodePrettyPrint<'_> {
fn render(&self) -> crate::prettier::Document {
use crate::prettier::*;
@@ -175,7 +175,7 @@ impl<'a> crate::prettier::PrettyPrint for LoopNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for LoopNodePrettyPrint<'a> {
+impl fmt::Display for LoopNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::prettier::PrettyPrint;
self.pretty_print(f)
diff --git a/core/src/mast/node/mod.rs b/core/src/mast/node/mod.rs
index cbb3192f40..2163565742 100644
--- a/core/src/mast/node/mod.rs
+++ b/core/src/mast/node/mod.rs
@@ -273,7 +273,7 @@ impl<'a> MastNodePrettyPrint<'a> {
}
}
-impl<'a> PrettyPrint for MastNodePrettyPrint<'a> {
+impl PrettyPrint for MastNodePrettyPrint<'_> {
fn render(&self) -> Document {
self.node_pretty_print.render()
}
@@ -289,7 +289,7 @@ impl<'a> MastNodeDisplay<'a> {
}
}
-impl<'a> fmt::Display for MastNodeDisplay<'a> {
+impl fmt::Display for MastNodeDisplay<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.node_display.fmt(f)
}
diff --git a/core/src/mast/node/split_node.rs b/core/src/mast/node/split_node.rs
index 6b1b96e0cc..8a46fcdc70 100644
--- a/core/src/mast/node/split_node.rs
+++ b/core/src/mast/node/split_node.rs
@@ -144,7 +144,7 @@ struct SplitNodePrettyPrint<'a> {
mast_forest: &'a MastForest,
}
-impl<'a> PrettyPrint for SplitNodePrettyPrint<'a> {
+impl PrettyPrint for SplitNodePrettyPrint<'_> {
#[rustfmt::skip]
fn render(&self) -> crate::prettier::Document {
use crate::prettier::*;
@@ -190,7 +190,7 @@ impl<'a> PrettyPrint for SplitNodePrettyPrint<'a> {
}
}
-impl<'a> fmt::Display for SplitNodePrettyPrint<'a> {
+impl fmt::Display for SplitNodePrettyPrint<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::prettier::PrettyPrint;
self.pretty_print(f)
diff --git a/core/src/mast/serialization/basic_blocks.rs b/core/src/mast/serialization/basic_blocks.rs
index e32caa6e99..86cf884717 100644
--- a/core/src/mast/serialization/basic_blocks.rs
+++ b/core/src/mast/serialization/basic_blocks.rs
@@ -67,7 +67,7 @@ impl<'a> BasicBlockDataDecoder<'a> {
}
/// Decoding methods
-impl<'a> BasicBlockDataDecoder<'a> {
+impl BasicBlockDataDecoder<'_> {
pub fn decode_operations_and_decorators(
&self,
ops_offset: NodeDataOffset,
diff --git a/processor/src/host/advice/mod.rs b/processor/src/host/advice/mod.rs
index 6dacc08b45..4eba93fe7c 100644
--- a/processor/src/host/advice/mod.rs
+++ b/processor/src/host/advice/mod.rs
@@ -718,7 +718,7 @@ pub trait AdviceProvider: Sized {
R: Borrow;
}
-impl<'a, T> AdviceProvider for &'a mut T
+impl AdviceProvider for &mut T
where
T: AdviceProvider,
{
diff --git a/processor/src/host/mod.rs b/processor/src/host/mod.rs
index 10366e7c66..4e4289b331 100644
--- a/processor/src/host/mod.rs
+++ b/processor/src/host/mod.rs
@@ -176,7 +176,7 @@ pub trait Host {
}
}
-impl<'a, H> Host for &'a mut H
+impl Host for &mut H
where
H: Host,
{
diff --git a/prover/src/gpu/metal/mod.rs b/prover/src/gpu/metal/mod.rs
index ab7132834e..930253b5fc 100644
--- a/prover/src/gpu/metal/mod.rs
+++ b/prover/src/gpu/metal/mod.rs
@@ -688,7 +688,7 @@ where
E: FieldElement,
I: IntoIterator- >;
-impl<'a, 'b, E, I, const N: usize> Iterator for SegmentIterator<'a, 'b, E, I, N>
+impl Iterator for SegmentIterator
where
E: FieldElement,
I: IntoIterator
- >,