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

Update with latest event handlers PR (miden-vm) #1127

Draft
wants to merge 1 commit into
base: next
Choose a base branch
from
Draft
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
423 changes: 247 additions & 176 deletions Cargo.lock

Large diffs are not rendered by default.

20 changes: 14 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,24 @@ codegen-units = 1
lto = true

[workspace.dependencies]
assembly = { package = "miden-assembly", version = "0.12", default-features = false }
assembly = { package = "miden-assembly", version = "0.13", default-features = false }
assert_matches = { version = "1.5", default-features = false }
miden-crypto = { version = "0.13", default-features = false }
miden-lib = { path = "crates/miden-lib", version = "0.8", default-features = false }
miden-objects = { path = "crates/miden-objects", version = "0.8", default-features = false }
miden-prover = { version = "0.12", default-features = false }
miden-stdlib = { version = "0.12", default-features = false }
miden-prover = { version = "0.13", default-features = false }
miden-stdlib = { version = "0.13", default-features = false }
miden-tx = { path = "crates/miden-tx", version = "0.8", default-features = false }
miden-verifier = { version = "0.12", default-features = false }
miden-verifier = { version = "0.13", default-features = false }
rand = { version = "0.8", default-features = false }
thiserror = { version = "2.0", default-features = false }
vm-core = { package = "miden-core", version = "0.12", default-features = false }
vm-processor = { package = "miden-processor", version = "0.12", default-features = false }
vm-core = { package = "miden-core", version = "0.13", default-features = false }
vm-processor = { package = "miden-processor", version = "0.13", default-features = false }

[patch.crates-io]
assembly = { package = "miden-assembly", git = "https://github.com/0xPolygonMiden/miden-vm", branch = "plafer-1584-event-handlers"}
miden-prover = { git = "https://github.com/0xPolygonMiden/miden-vm", branch = "plafer-1584-event-handlers"}
miden-stdlib = { git = "https://github.com/0xPolygonMiden/miden-vm", branch = "plafer-1584-event-handlers"}
miden-verifier = { git = "https://github.com/0xPolygonMiden/miden-vm", branch = "plafer-1584-event-handlers"}
vm-core = { package = "miden-core", git = "https://github.com/0xPolygonMiden/miden-vm", branch = "plafer-1584-event-handlers"}
vm-processor = { package = "miden-processor", git = "https://github.com/0xPolygonMiden/miden-vm", branch = "plafer-1584-event-handlers"}
1 change: 1 addition & 0 deletions crates/miden-lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ with-debug-info = ["miden-stdlib/with-debug-info"]
[dependencies]
miden-objects = { workspace = true }
miden-stdlib = { workspace = true }
vm-processor = { workspace = true }
thiserror = { workspace = true }

[dev-dependencies]
Expand Down
58 changes: 58 additions & 0 deletions crates/miden-lib/src/account_delta_tracker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use miden_objects::{
account::{AccountDelta, AccountHeader, AccountStorageDelta, AccountVaultDelta},
Felt, ZERO,
};
// ACCOUNT DELTA TRACKER
// ================================================================================================

/// Keeps track of changes made to the account during transaction execution.
///
/// Currently, this tracks:
/// - Changes to the account storage, slots and maps.
/// - Changes to the account vault.
/// - Changes to the account nonce.
///
/// TODO: implement tracking of:
/// - all account storage changes.
/// - account code changes.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AccountDeltaTracker {
storage: AccountStorageDelta,
vault: AccountVaultDelta,
init_nonce: Felt,
nonce_delta: Felt,
}

impl AccountDeltaTracker {
/// Returns a new [AccountDeltaTracker] instantiated for the specified account.
pub fn new(account: &AccountHeader) -> Self {
Self {
storage: AccountStorageDelta::default(),
vault: AccountVaultDelta::default(),
init_nonce: account.nonce(),
nonce_delta: ZERO,
}
}

/// Consumes `self` and returns the resulting [AccountDelta].
pub fn into_delta(self) -> AccountDelta {
let nonce_delta = (self.nonce_delta != ZERO).then_some(self.init_nonce + self.nonce_delta);

AccountDelta::new(self.storage, self.vault, nonce_delta).expect("invalid account delta")
}

/// Tracks nonce delta.
pub fn increment_nonce(&mut self, value: Felt) {
self.nonce_delta += value;
}

/// Get a mutable reference to the current vault delta
pub fn vault_delta(&mut self) -> &mut AccountVaultDelta {
&mut self.vault
}

/// Get a mutable reference to the current storage delta
pub fn storage_delta(&mut self) -> &mut AccountStorageDelta {
&mut self.storage
}
}
172 changes: 169 additions & 3 deletions crates/miden-lib/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
#![no_std]
use alloc::sync::Arc;

#[macro_use]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

use alloc::{
boxed::Box,
collections::{BTreeMap, BTreeSet},
string::String,
sync::Arc,
vec::Vec,
};

use miden_objects::{
account::{AccountDelta, AccountHeader},
assembly::{mast::MastForest, Library},
utils::{serde::Deserializable, sync::LazyLock},
Hasher,
};
use transaction::AccountBeforeIncrementNonceHandler;
use utils::sync::RwLock;
use vm_processor::{AdviceProvider, Digest, EventHandler, Felt, HostLibrary, Word};

mod auth;
pub use auth::AuthScheme;
Expand All @@ -20,17 +32,142 @@ pub mod errors;
pub mod note;
pub mod transaction;

mod account_delta_tracker;
pub use account_delta_tracker::AccountDeltaTracker;
// RE-EXPORTS
// ================================================================================================

pub use miden_objects::utils;
pub use miden_stdlib::StdLibrary;
pub use miden_stdlib::{StdLibrary, FalconSigToStackEventHandler};

// CONSTANTS
// ================================================================================================

const MIDEN_LIB_BYTES: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden.masl"));

// TODO(plafer): Properly move this to miden-lib and remove the other version

#[derive(Debug, thiserror::Error)]
pub enum AuthenticationError {
#[error("signature rejected: {0}")]
RejectedSignature(String),
#[error("unknown public key: {0}")]
UnknownPublicKey(String),
/// Custom error variant for implementors of the
/// [`TransactionAuthenticatior`](crate::auth::TransactionAuthenticator) trait.
#[error("{error_msg}")]
Other {
error_msg: Box<str>,
// thiserror will return this when calling Error::source on DataStoreError.
source: Option<Box<dyn core::error::Error + Send + Sync + 'static>>,
},
}
/// Defines an authenticator for transactions.
///
/// The main purpose of the authenticator is to generate signatures for a given message against
/// a key managed by the authenticator. That is, the authenticator maintains a set of public-
/// private key pairs, and can be requested to generate signatures against any of the managed keys.
///
/// The public keys are defined by [Digest]'s which are the hashes of the actual public keys.
pub trait TransactionAuthenticator: Send + Sync {
/// Retrieves a signature for a specific message as a list of [Felt].
///
/// The request is initiated by the VM as a consequence of the SigToStack advice
/// injector.
///
/// - `pub_key`: The public key used for signature generation.
/// - `message`: The message to sign, usually a commitment to the transaction data.
/// - `account_delta`: An informational parameter describing the changes made to the account up
/// to the point of calling `get_signature()`. This allows the authenticator to review any
/// alterations to the account prior to signing. It should not be directly used in the
/// signature computation.
fn get_signature(
&self,
pub_key: Word,
message: Word,
account_delta: &AccountDelta,
) -> Result<Vec<Felt>, AuthenticationError>;
}

// TODO(plafer): Maybe this can live in `miden-tx`?
pub struct MidenFalconSigner {
/// Account state changes accumulated during transaction execution.
account_delta: Arc<RwLock<AccountDeltaTracker>>,

// TODO(plafer): Remove Option?
/// Serves signature generation requests from the transaction runtime for signatures which are
/// not present in the `generated_signatures` field.
authenticator: Option<Arc<dyn TransactionAuthenticator>>,

/// Contains previously generated signatures (as a message |-> signature map) required for
/// transaction execution.
///
/// If a required signature is not present in this map, the host will attempt to generate the
/// signature using the transaction authenticator.
generated_signatures: BTreeMap<Digest, Vec<Felt>>,
}

impl MidenFalconSigner {
/// Creates a new instance of the Falcon signer.
pub fn new(
account_delta: Arc<RwLock<AccountDeltaTracker>>,
authenticator: Option<Arc<dyn TransactionAuthenticator>>,
) -> Self {
Self {
account_delta,
authenticator,
generated_signatures: BTreeMap::new(),
}
}
}

#[derive(Debug, thiserror::Error)]
pub enum FalconSigError {
#[error("Failed to generate signature: {0}")]
FailedSignatureGeneration(&'static str),
}

impl<A> miden_stdlib::FalconSigner<A> for MidenFalconSigner {
fn sign_message(
&mut self,
pub_key: Word,
msg: Word,
advice_provider: &A,
) -> Result<Vec<Felt>, Box<dyn core::error::Error + Send + Sync + 'static>>
where
A: AdviceProvider,
{
let signature_key = Hasher::merge(&[pub_key.into(), msg.into()]);

let signature = if let Some(signature) = advice_provider.get_mapped_values(&signature_key) {
signature.to_vec()
} else {
let account_delta = self.account_delta.read();
let account_delta = account_delta.clone().into_delta();

let signature: Vec<Felt> = match &self.authenticator {
None => {
return Err(FalconSigError::FailedSignatureGeneration(
"No authenticator assigned to transaction host",
)
.into())
},
Some(authenticator) => {
authenticator.get_signature(pub_key, msg, &account_delta).map_err(|_| {
Box::new(FalconSigError::FailedSignatureGeneration(
"Error generating signature",
))
})
},
}?;

self.generated_signatures.insert(signature_key, signature.clone());
signature
};

Ok(signature)
}
}

// MIDEN LIBRARY
// ================================================================================================

Expand Down Expand Up @@ -67,6 +204,35 @@ impl Default for MidenLib {
}
}

pub struct EventHandlersInputs {
account: AccountHeader,
account_delta: Arc<RwLock<AccountDeltaTracker>>,
account_code_commitments: BTreeSet<Digest>,
}

impl HostLibrary<EventHandlersInputs> for MidenLib {
fn get_event_handlers<A>(&self, inputs: EventHandlersInputs) -> Vec<Box<dyn EventHandler<A>>>
where
A: AdviceProvider + 'static,
{
let EventHandlersInputs { account, account_delta, mut account_code_commitments } = inputs;
// create account delta tracker and code commitments
account_code_commitments.insert(account.code_commitment());
let account_delta = Arc::new(RwLock::new(AccountDeltaTracker::new(&account)));

// create all events
let account_vault_before_add_asset =
AccountBeforeIncrementNonceHandler { account_delta: account_delta.clone() };

// TODO(plafer): Add all events here
vec![Box::new(account_vault_before_add_asset)]
}

fn get_mast_forest(&self) -> Arc<MastForest> {
self.0.mast_forest().clone()
}
}

// TESTS
// ================================================================================================

Expand Down
Loading
Loading