Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove FALCON_SIG_TO_STACK event #1703

Merged
merged 10 commits into from
Mar 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- Fix docs on the layout of the auxiliary segment trace (#1694).
- [BREAKING] Updated Winterfell dependency to v0.12 (#1658).
- Update recursive verifier to use `HORNERBASE` (#1665).
- Remove `FALCON_SIG_TO_STACK` event (#1703)


## 0.12.0 (2025-01-22)
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

5 changes: 0 additions & 5 deletions assembly/src/ast/instruction/advice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ pub enum SystemEventNode {
InsertHdword,
InsertHdwordWithDomain,
InsertHperm,
PushSignature { kind: SignatureKind },
}

impl From<&SystemEventNode> for SystemEvent {
Expand All @@ -41,9 +40,6 @@ impl From<&SystemEventNode> for SystemEvent {
InsertHdword => Self::HdwordToMap,
InsertHdwordWithDomain => Self::HdwordToMapWithDomain,
InsertHperm => Self::HpermToMap,
PushSignature { kind } => match kind {
SignatureKind::RpoFalcon512 => Self::FalconSigToStack,
},
}
}
}
Expand All @@ -68,7 +64,6 @@ impl fmt::Display for SystemEventNode {
Self::InsertHdword => write!(f, "insert_hdword"),
Self::InsertHdwordWithDomain => write!(f, "insert_hdword_d"),
Self::InsertHperm => writeln!(f, "insert_hperm"),
Self::PushSignature { kind } => write!(f, "push_sig.{kind}"),
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions assembly/src/parser/grammar.lalrpop
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ extern {
"push_mapval" => Token::PushMapval,
"push_mapvaln" => Token::PushMapvaln,
"push_mtnode" => Token::PushMtnode,
"push_sig" => Token::PushSig,
"push_smtpeek" => Token::PushSmtpeek,
"push_u64div" => Token::PushU64Div,
"push_falcon_div" => Token::PushFalconDiv,
Expand Down Expand Up @@ -677,7 +676,6 @@ SystemEvent: Instruction = {
"adv" "." "push_mapval" => Instruction::SysEvent(SystemEventNode::PushMapVal),
"adv" "." "push_mapvaln" => Instruction::SysEvent(SystemEventNode::PushMapValN),
"adv" "." "push_mtnode" => Instruction::SysEvent(SystemEventNode::PushMtNode),
"adv" "." "push_sig" "." <kind:SignatureKind> => Instruction::SysEvent(SystemEventNode::PushSignature { kind }),
"adv" "." "push_smtpeek" => Instruction::SysEvent(SystemEventNode::PushSmtPeek),
"adv" "." "push_u64div" => Instruction::SysEvent(SystemEventNode::PushU64Div),
"adv" "." "push_falcon_div" => Instruction::SysEvent(SystemEventNode::PushFalconDiv),
Expand Down
4 changes: 0 additions & 4 deletions assembly/src/parser/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ pub enum Token<'input> {
PushMapval,
PushMapvaln,
PushMtnode,
PushSig,
PushSmtpeek,
PushSmtset,
PushSmtget,
Expand Down Expand Up @@ -335,7 +334,6 @@ impl fmt::Display for Token<'_> {
Token::PushMapval => write!(f, "push_mapval"),
Token::PushMapvaln => write!(f, "push_mapvaln"),
Token::PushMtnode => write!(f, "push_mtnode"),
Token::PushSig => write!(f, "push_sig"),
Token::PushSmtpeek => write!(f, "push_smtpeek"),
Token::PushSmtset => write!(f, "push_smtset"),
Token::PushSmtget => write!(f, "push_smtget"),
Expand Down Expand Up @@ -530,7 +528,6 @@ impl<'input> Token<'input> {
| Token::PushMapval
| Token::PushMapvaln
| Token::PushMtnode
| Token::PushSig
| Token::PushSmtpeek
| Token::PushSmtset
| Token::PushSmtget
Expand Down Expand Up @@ -677,7 +674,6 @@ impl<'input> Token<'input> {
("push_mapval", Token::PushMapval),
("push_mapvaln", Token::PushMapvaln),
("push_mtnode", Token::PushMtnode),
("push_sig", Token::PushSig),
("push_smtpeek", Token::PushSmtpeek),
("push_smtset", Token::PushSmtset),
("push_smtget", Token::PushSmtget),
Expand Down
20 changes: 0 additions & 20 deletions core/src/sys_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use core::fmt;
// between 0 and 2^32.
pub use constants::*;

use super::SignatureKind;
#[rustfmt::skip]
mod constants {
pub const EVENT_MERKLE_NODE_MERGE: u32 = 276124218;
Expand All @@ -27,7 +26,6 @@ mod constants {
pub const EVENT_HDWORD_TO_MAP: u32 = 2391452729;
pub const EVENT_HDWORD_TO_MAP_WITH_DOMAIN: u32 = 2822590340;
pub const EVENT_HPERM_TO_MAP: u32 = 3297060969;
pub const EVENT_FALCON_SIG_TO_STACK: u32 = 3419226139;
pub const EVENT_FALCON_DIV: u32 = 3419226155;
}

Expand Down Expand Up @@ -302,21 +300,6 @@ pub enum SystemEvent {
/// Where KEY is computed by extracting the digest elements from hperm([C, A, B]). For example,
/// if C is [0, d, 0, 0], KEY will be set as hash(A || B, d).
HpermToMap,

/// Reads two words from the stack and pushes values onto the advice stack which are required
/// for verification of Falcon DSA in Miden VM.
///
/// Inputs:
/// Operand stack: [PK, MSG, ...]
/// Advice stack: [...]
///
/// Outputs:
/// Operand stack: [PK, MSG, ...]
/// Advice stack: \[SIG_DATA\]
///
/// Where PK is the public key corresponding to the signing key, MSG is the message, SIG_DATA
/// is the signature data.
FalconSigToStack,
}

impl SystemEvent {
Expand All @@ -340,7 +323,6 @@ impl SystemEvent {
SystemEvent::HdwordToMap => EVENT_HDWORD_TO_MAP,
SystemEvent::HdwordToMapWithDomain => EVENT_HDWORD_TO_MAP_WITH_DOMAIN,
SystemEvent::HpermToMap => EVENT_HPERM_TO_MAP,
SystemEvent::FalconSigToStack => EVENT_FALCON_SIG_TO_STACK,
}
}

Expand All @@ -366,7 +348,6 @@ impl SystemEvent {
EVENT_HDWORD_TO_MAP => Some(SystemEvent::HdwordToMap),
EVENT_HDWORD_TO_MAP_WITH_DOMAIN => Some(SystemEvent::HdwordToMapWithDomain),
EVENT_HPERM_TO_MAP => Some(SystemEvent::HpermToMap),
EVENT_FALCON_SIG_TO_STACK => Some(SystemEvent::FalconSigToStack),
_ => None,
}
}
Expand Down Expand Up @@ -399,7 +380,6 @@ impl fmt::Display for SystemEvent {
Self::HdwordToMap => write!(f, "hdword_to_map"),
Self::HdwordToMapWithDomain => write!(f, "hdword_to_map_with_domain"),
Self::HpermToMap => write!(f, "hperm_to_map"),
Self::FalconSigToStack => write!(f, "sig_to_stack.{}", SignatureKind::RpoFalcon512),
}
}
}
1 change: 0 additions & 1 deletion docs/src/user_docs/assembly/io_operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ System events fall into two categories: (1) events which push new data onto the
| adv.push_mtnode | [d, i, R, ... ] | [d, i, R, ... ] | Pushes a node of a Merkle tree with root $R$ at depth $d$ and index $i$ from Merkle store onto the advice stack. |
| adv.push_u64div | [b1, b0, a1, a0, ...] | [b1, b0, a1, a0, ...] | Pushes the result of `u64` division $a / b$ onto the advice stack. Both $a$ and $b$ are represented using 32-bit limbs. The result consists of both the quotient and the remainder. |
| adv.push_ext2intt | [osize, isize, iptr, ... ] | [osize, isize, iptr, ... ] | Given evaluations of a polynomial over some specified domain, interpolates the evaluations into a polynomial in coefficient form and pushes the result into the advice stack. |
| adv.push_sig.*kind* | [K, M, ...] | [K, M, ...] | Pushes values onto the advice stack which are required for verification of a DSA with scheme specified by *kind* against the public key commitment $K$ and message $M$. |
| adv.push_smtpeek | [K, R, ... ] | [K, R, ... ] | Pushes value onto the advice stack which is associated with key $K$ in a Sparse Merkle Tree with root $R$. |
| adv.insert_mem | [K, a, b, ... ] | [K, a, b, ... ] | Reads words $data \leftarrow mem[a] .. mem[b]$ from memory, and save the data into $advice\_map[K] \leftarrow data$. |
| adv.insert_hdword | [B, A, ... ] | [B, A, ... ] | Reads top two words from the stack, computes a key as $K \leftarrow hash(A || b, domain=0)$, and saves the data into $advice\_map[K] \leftarrow [A, B]$. |
Expand Down
2 changes: 1 addition & 1 deletion docs/src/user_docs/stdlib/crypto/dsa.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ The module exposes the following procedures:

| Procedure | Description |
| ----------- | ------------- |
| verify | Verifies a signature against a public key and a message. The procedure gets as inputs the hash of the public key and the hash of the message via the operand stack. The signature is expected to be provided via the advice provider.<br /><br />The signature is valid if and only if the procedure returns.<br /><br />Inputs: `[PK, MSG, ...]`<br />Outputs: `[...]`<br /><br />Where `PK` is the hash of the public key and `MSG` is the hash of the message. Both hashes are expected to be computed using `RPO` hash function.<br /><br /> The procedure relies on the `adv.push_sig` [decorator](../../assembly/io_operations.md#nondeterministic-inputs) to retrieve the signature from the host. The default host implementation assumes that the private-public key pair is loaded into the advice provider, and uses it to generate the signature. However, for production grade implementations, this functionality should be overridden to ensure more secure handling of private keys.|
| verify | Verifies a signature against a public key and a message. The procedure gets as inputs the hash of the public key and the hash of the message via the operand stack. The signature is expected to be provided via the advice provider.<br /><br />The signature is valid if and only if the procedure returns.<br /><br />Stack inputs: `[PK, MSG, ...]`<br />Advice stack inputs: `[SIGNATURE]`<br />Outputs: `[...]`<br /><br />Where `PK` is the hash of the public key and `MSG` is the hash of the message, and `SIGNATURE` is the signature being verified. Both hashes are expected to be computed using `RPO` hash function.<br /><br />|
145 changes: 4 additions & 141 deletions miden/tests/integration/operations/decorators/advice.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
use miden_vm::{Digest, Word};
use processor::ExecutionError;
use rand_chacha::rand_core::SeedableRng;
use test_utils::{
Felt, TRUNCATE_STACK_PROC, build_test,
crypto::{MerkleStore, RpoDigest, rpo_falcon512::SecretKey},
expect_exec_error_matches,
rand::{rand_array, rand_value},
serde::Serializable,
TRUNCATE_STACK_PROC, build_test,
crypto::{MerkleStore, RpoDigest},
rand::rand_value,
};

const ADVICE_PUSH_SIG: &str = "
begin
# => [PK, MSG, ...]

# Calling adv.push_sig.rpo_falcon512 on its own gives an error:
# internal error: entered unreachable code: decorators in and empty SPAN block
# add stack calls to avoid this issue.
push.0
drop

adv.push_sig.rpo_falcon512

# => [PK, MSG, ...]
end";
use vm_core::Felt;

// ADVICE INJECTION
// ================================================================================================
Expand Down Expand Up @@ -329,121 +310,3 @@ fn advice_insert_hdword() {
let test = build_test!(source, &stack_inputs);
test.expect_stack(&[1, 2, 3, 4, 5, 6, 7, 8]);
}

#[test]
fn advice_push_sig_rpo_falcon_512() {
// Generate random keys and message.
let seed: [u8; 32] = rand_array();
let mut rng = rand_chacha::ChaCha20Rng::from_seed(seed);

let secret_key = SecretKey::with_rng(&mut rng);

// let secret_key = SecretKey::new();
let public_key = secret_key.public_key();
let message: Word = rand_array();

let public_key_word: Word = public_key.into();
let public_key_digest: Digest = public_key_word.into();

// Place digest of the public key and the secret key into advice map as a key value pair.
let secret_key_bytes = secret_key.to_bytes();
let secret_key_adv_map =
secret_key_bytes.iter().map(|a| Felt::new(*a as u64)).collect::<Vec<Felt>>();
let advice_map: Vec<(Digest, Vec<Felt>)> = vec![(public_key_digest, secret_key_adv_map)];

// Lay the public key digest and message into the operation stack.
let mut op_stack = vec![];
let message = message.into_iter().map(|a| a.as_int()).collect::<Vec<u64>>();
op_stack.extend_from_slice(&message);
op_stack.extend_from_slice(
&public_key_digest.as_elements().iter().map(|a| a.as_int()).collect::<Vec<u64>>(),
);
let advice_stack = vec![];

let store = MerkleStore::new();
let mut expected_stack = op_stack.clone();
expected_stack.reverse();

let test =
build_test!(ADVICE_PUSH_SIG, &op_stack, &advice_stack, store, advice_map.into_iter());
test.expect_stack(&expected_stack);
}

#[test]
fn advice_push_sig_rpo_falcon_512_bad_key_value() {
// Generate random keys and message.
let seed: [u8; 32] = rand_array();
let mut rng = rand_chacha::ChaCha20Rng::from_seed(seed);

let secret_key = SecretKey::with_rng(&mut rng);
let public_key = secret_key.public_key();
let message: Word = rand_array();

let public_key_word: Word = public_key.into();
let public_key_digest: Digest = public_key_word.into();

// Place digest of the public key and the secret key into advice map as a key value pair.
let secret_key_bytes = secret_key.to_bytes();
let mut secret_key_adv_map =
secret_key_bytes.iter().map(|a| Felt::new(*a as u64)).collect::<Vec<Felt>>();

// Secret key as bytes must have values in the range 0 - 255.
secret_key_adv_map.pop();
secret_key_adv_map.push(Felt::new(257));

let advice_map: Vec<(Digest, Vec<Felt>)> = vec![(public_key_digest, secret_key_adv_map)];

// Lay the public key digest and message into the operation stack.
let mut op_stack = vec![];
let message = message.into_iter().map(|a| a.as_int()).collect::<Vec<u64>>();
op_stack.extend_from_slice(&message);
op_stack.extend_from_slice(
&public_key_digest.as_elements().iter().map(|a| a.as_int()).collect::<Vec<u64>>(),
);
let advice_stack = vec![];

let store = MerkleStore::new();

let test =
build_test!(ADVICE_PUSH_SIG, &op_stack, &advice_stack, store, advice_map.into_iter());
expect_exec_error_matches!(test, ExecutionError::MalformedSignatureKey("RPO Falcon512"));
}

#[test]
fn advice_push_sig_rpo_falcon_512_bad_key_length() {
// Generate random keys and message.
let seed: [u8; 32] = rand_array();
let mut rng = rand_chacha::ChaCha20Rng::from_seed(seed);

let secret_key = SecretKey::with_rng(&mut rng);
let public_key = secret_key.public_key();
let message: Word = rand_array();

let public_key_word: Word = public_key.into();
let public_key_digest: Digest = public_key_word.into();

// Place digest of the public key and the secret key into advice map as a key value pair.
let secret_key_bytes = secret_key.to_bytes();
let mut secret_key_adv_map =
secret_key_bytes.iter().map(|a| Felt::new(*a as u64)).collect::<Vec<Felt>>();

// Secret key as bytes must be at least the correct length.
secret_key_adv_map.pop();
let advice_map: Vec<(Digest, Vec<Felt>)> = vec![(public_key_digest, secret_key_adv_map)];

// Lay the public key digest and message into the operation stack.
let mut op_stack = vec![];
let message = message.into_iter().map(|a| a.as_int()).collect::<Vec<u64>>();
op_stack.extend_from_slice(&message);
op_stack.extend_from_slice(
&public_key_digest.as_elements().iter().map(|a| a.as_int()).collect::<Vec<u64>>(),
);
let advice_stack = vec![];

let store = MerkleStore::new();

let test =
build_test!(ADVICE_PUSH_SIG, &op_stack, &advice_stack, store, advice_map.into_iter());

expect_exec_error_matches!(test, ExecutionError::MalformedSignatureKey("RPO Falcon512"));
}
2 changes: 0 additions & 2 deletions processor/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ pub enum ExecutionError {
err_code: u32,
err_msg: Option<String>,
},
#[error("failed to generate signature: {0}")]
FailedSignatureGeneration(&'static str),
#[error(
"memory address {addr} in context {ctx} was read and written, or written twice, in the same clock cycle {clk}"
)]
Expand Down
Loading
Loading