From ffaff5958358e5d0a1923769e730c27d13bd15a4 Mon Sep 17 00:00:00 2001 From: djole Date: Wed, 11 Mar 2026 15:26:19 +0100 Subject: [PATCH 1/4] feat: add transaction executor factory hook --- .../src/transaction/executor.rs | 66 +++++++++++++++++++ crates/miden-protocol/src/transaction/mod.rs | 8 +++ crates/miden-tx/src/executor/mod.rs | 49 ++++++++++++-- crates/miden-tx/src/executor/notes_checker.rs | 10 ++- crates/miden-tx/src/lib.rs | 4 ++ 5 files changed, 129 insertions(+), 8 deletions(-) create mode 100755 crates/miden-protocol/src/transaction/executor.rs diff --git a/crates/miden-protocol/src/transaction/executor.rs b/crates/miden-protocol/src/transaction/executor.rs new file mode 100755 index 0000000000..e8405a78f2 --- /dev/null +++ b/crates/miden-protocol/src/transaction/executor.rs @@ -0,0 +1,66 @@ +use miden_processor::advice::AdviceInputs; +use miden_processor::{ + ExecutionError, + ExecutionOptions, + ExecutionOutput, + FastProcessor, + FutureMaybeSend, + Host, + Program, + StackInputs, +}; + +/// A transaction-scoped program executor used by `miden-tx`. +pub trait TransactionProgramExecutor: Sized { + /// Execute the provided program against the given host. + fn execute( + self, + program: &Program, + host: &mut H, + ) -> impl FutureMaybeSend>; +} + +/// A factory for constructing transaction program executors. +pub trait TransactionProgramExecutorFactory { + /// The executor type created by this factory. + type Executor: TransactionProgramExecutor; + + /// Create a new executor configured with the provided transaction inputs and options. + fn create_executor( + stack_inputs: StackInputs, + advice_inputs: AdviceInputs, + options: ExecutionOptions, + ) -> Self::Executor; +} + +/// Default factory that executes transactions with `FastProcessor`. +pub struct DefaultTransactionProgramExecutorFactory; + +impl TransactionProgramExecutor for FastProcessor { + fn execute( + self, + program: &Program, + host: &mut H, + ) -> impl FutureMaybeSend> { + FastProcessor::execute(self, program, host) + } +} + +impl TransactionProgramExecutorFactory for DefaultTransactionProgramExecutorFactory { + type Executor = FastProcessor; + + fn create_executor( + stack_inputs: StackInputs, + advice_inputs: AdviceInputs, + options: ExecutionOptions, + ) -> Self::Executor { + FastProcessor::new_with_options(stack_inputs, advice_inputs, options) + } +} + +#[doc(hidden)] +pub use DefaultTransactionProgramExecutorFactory as DefaultProgramExecutorFactory; +#[doc(hidden)] +pub use TransactionProgramExecutor as ProgramExecutor; +#[doc(hidden)] +pub use TransactionProgramExecutorFactory as ProgramExecutorFactory; diff --git a/crates/miden-protocol/src/transaction/mod.rs b/crates/miden-protocol/src/transaction/mod.rs index 977155e755..b8a3215f9b 100644 --- a/crates/miden-protocol/src/transaction/mod.rs +++ b/crates/miden-protocol/src/transaction/mod.rs @@ -4,6 +4,7 @@ use super::vm::AdviceInputs; use super::{Felt, Hasher, WORD_SIZE, Word, ZERO}; mod executed_tx; +mod executor; mod inputs; mod kernel; mod ordered_transactions; @@ -16,6 +17,13 @@ mod tx_header; mod tx_summary; pub use executed_tx::{ExecutedTransaction, TransactionMeasurements}; +#[doc(hidden)] +pub use executor::{DefaultProgramExecutorFactory, ProgramExecutor, ProgramExecutorFactory}; +pub use executor::{ + DefaultTransactionProgramExecutorFactory, + TransactionProgramExecutor, + TransactionProgramExecutorFactory, +}; pub use inputs::{AccountInputs, InputNote, InputNotes, ToInputNoteCommitments, TransactionInputs}; pub use kernel::{TransactionAdviceInputs, TransactionEventId, TransactionKernel, memory}; pub use ordered_transactions::OrderedTransactionHeaders; diff --git a/crates/miden-tx/src/executor/mod.rs b/crates/miden-tx/src/executor/mod.rs index 7ebfcd02e0..c239efe32a 100644 --- a/crates/miden-tx/src/executor/mod.rs +++ b/crates/miden-tx/src/executor/mod.rs @@ -1,8 +1,9 @@ use alloc::collections::BTreeSet; use alloc::sync::Arc; +use core::marker::PhantomData; use miden_processor::advice::AdviceInputs; -use miden_processor::{ExecutionError, FastProcessor, StackInputs}; +use miden_processor::{ExecutionError, StackInputs}; pub use miden_processor::{ExecutionOptions, MastForestStore}; use miden_protocol::account::AccountId; use miden_protocol::assembly::DefaultSourceManager; @@ -10,12 +11,15 @@ use miden_protocol::assembly::debuginfo::SourceManagerSync; use miden_protocol::asset::{Asset, AssetVaultKey}; use miden_protocol::block::BlockNumber; use miden_protocol::transaction::{ + DefaultTransactionProgramExecutorFactory, ExecutedTransaction, InputNote, InputNotes, TransactionArgs, TransactionInputs, TransactionKernel, + TransactionProgramExecutor, + TransactionProgramExecutorFactory, TransactionScript, }; use miden_protocol::vm::StackOutputs; @@ -52,11 +56,18 @@ pub use notes_checker::{ /// The transaction executor uses dynamic dispatch with trait objects for the [DataStore] and /// [TransactionAuthenticator], allowing it to be used with different backend implementations. /// At the moment of execution, the [DataStore] is expected to provide all required MAST nodes. -pub struct TransactionExecutor<'store, 'auth, STORE: 'store, AUTH: 'auth> { +pub struct TransactionExecutor< + 'store, + 'auth, + STORE: 'store, + AUTH: 'auth, + F: TransactionProgramExecutorFactory = DefaultTransactionProgramExecutorFactory, +> { data_store: &'store STORE, authenticator: Option<&'auth AUTH>, source_manager: Arc, exec_options: ExecutionOptions, + _executor_factory: PhantomData, } impl<'store, 'auth, STORE, AUTH> TransactionExecutor<'store, 'auth, STORE, AUTH> @@ -71,6 +82,10 @@ where /// /// The created executor will not have the authenticator or source manager set, and tracing and /// debug mode will be turned off. + /// + /// By default, the executor uses [`FastProcessor`](miden_processor::FastProcessor) for program + /// execution. Use [`with_executor_factory`](Self::with_executor_factory) to plug in a + /// different execution engine. pub fn new(data_store: &'store STORE) -> Self { const _: () = assert!(MIN_TX_EXECUTION_CYCLES <= MAX_TX_EXECUTION_CYCLES); TransactionExecutor { @@ -85,6 +100,30 @@ where false, ) .expect("Must not fail while max cycles is more than min trace length"), + _executor_factory: PhantomData, + } + } +} + +impl<'store, 'auth, STORE, AUTH, F> TransactionExecutor<'store, 'auth, STORE, AUTH, F> +where + STORE: DataStore + 'store + Sync, + AUTH: TransactionAuthenticator + 'auth + Sync, + F: TransactionProgramExecutorFactory, +{ + /// Replaces the transaction program executor factory with a different implementation. + /// + /// This allows plugging in alternative execution engines while preserving the rest of the + /// transaction executor configuration. + pub fn with_executor_factory( + self, + ) -> TransactionExecutor<'store, 'auth, STORE, AUTH, F2> { + TransactionExecutor { + data_store: self.data_store, + authenticator: self.authenticator, + source_manager: self.source_manager, + exec_options: self.exec_options, + _executor_factory: PhantomData, } } @@ -186,8 +225,7 @@ where // instantiate the processor in debug mode only when debug mode is specified via execution // options; this is important because in debug mode execution is almost 100x slower - let processor = - FastProcessor::new_with_options(stack_inputs, advice_inputs, self.exec_options); + let processor = F::create_executor(stack_inputs, advice_inputs, self.exec_options); let output = processor .execute(&TransactionKernel::main(), &mut host) @@ -233,7 +271,8 @@ where let (mut host, stack_inputs, advice_inputs) = self.prepare_transaction(&tx_inputs).await?; - let processor = FastProcessor::new(stack_inputs).with_advice(advice_inputs); + let processor = + F::create_executor(stack_inputs, advice_inputs, ExecutionOptions::default()); let output = processor .execute(&TransactionKernel::tx_script_main(), &mut host) .await diff --git a/crates/miden-tx/src/executor/notes_checker.rs b/crates/miden-tx/src/executor/notes_checker.rs index 0cbddbe041..3f2594f27c 100644 --- a/crates/miden-tx/src/executor/notes_checker.rs +++ b/crates/miden-tx/src/executor/notes_checker.rs @@ -12,6 +12,7 @@ use miden_protocol::transaction::{ TransactionArgs, TransactionInputs, TransactionKernel, + TransactionProgramExecutorFactory, }; use miden_standards::note::{NoteConsumptionStatus, StandardNote}; @@ -73,15 +74,18 @@ impl NoteConsumptionInfo { /// The check is performed using the [NoteConsumptionChecker::check_notes_consumability] procedure. /// Essentially runs the transaction to make sure that provided input notes could be consumed by the /// account. -pub struct NoteConsumptionChecker<'a, STORE, AUTH>(&'a TransactionExecutor<'a, 'a, STORE, AUTH>); +pub struct NoteConsumptionChecker<'a, STORE, AUTH, F: TransactionProgramExecutorFactory>( + &'a TransactionExecutor<'a, 'a, STORE, AUTH, F>, +); -impl<'a, STORE, AUTH> NoteConsumptionChecker<'a, STORE, AUTH> +impl<'a, STORE, AUTH, F> NoteConsumptionChecker<'a, STORE, AUTH, F> where STORE: DataStore + Sync, AUTH: TransactionAuthenticator + Sync, + F: TransactionProgramExecutorFactory, { /// Creates a new [`NoteConsumptionChecker`] instance with the given transaction executor. - pub fn new(tx_executor: &'a TransactionExecutor<'a, 'a, STORE, AUTH>) -> Self { + pub fn new(tx_executor: &'a TransactionExecutor<'a, 'a, STORE, AUTH, F>) -> Self { NoteConsumptionChecker(tx_executor) } diff --git a/crates/miden-tx/src/lib.rs b/crates/miden-tx/src/lib.rs index a756df72b7..2c2f0b9119 100644 --- a/crates/miden-tx/src/lib.rs +++ b/crates/miden-tx/src/lib.rs @@ -21,6 +21,10 @@ pub use executor::{ mod host; pub use host::{AccountProcedureIndexMap, LinkMap, MemoryViewer, ScriptMastForestStore}; +pub use miden_protocol::transaction::{ + TransactionProgramExecutor, + TransactionProgramExecutorFactory, +}; mod prover; pub use prover::{ From d1e99cf29dfcad3386d1048e907b6fcdfd65dbcc Mon Sep 17 00:00:00 2001 From: djole Date: Fri, 13 Mar 2026 20:50:41 +0100 Subject: [PATCH 2/4] fixup: simplify transaction program executor hook --- .../src/transaction/executor.rs | 45 +++++++------------ crates/miden-protocol/src/transaction/mod.rs | 8 +--- crates/miden-tx/src/executor/mod.rs | 34 +++++++------- crates/miden-tx/src/executor/notes_checker.rs | 21 +++++---- crates/miden-tx/src/lib.rs | 18 +++++--- 5 files changed, 60 insertions(+), 66 deletions(-) diff --git a/crates/miden-protocol/src/transaction/executor.rs b/crates/miden-protocol/src/transaction/executor.rs index e8405a78f2..bd4a52c25f 100755 --- a/crates/miden-protocol/src/transaction/executor.rs +++ b/crates/miden-protocol/src/transaction/executor.rs @@ -11,7 +11,16 @@ use miden_processor::{ }; /// A transaction-scoped program executor used by `miden-tx`. -pub trait TransactionProgramExecutor: Sized { +pub trait TransactionProgramExecutor { + /// Create a new executor configured with the provided transaction inputs and options. + fn new( + stack_inputs: StackInputs, + advice_inputs: AdviceInputs, + options: ExecutionOptions, + ) -> Self + where + Self: Sized; + /// Execute the provided program against the given host. fn execute( self, @@ -20,23 +29,15 @@ pub trait TransactionProgramExecutor: Sized { ) -> impl FutureMaybeSend>; } -/// A factory for constructing transaction program executors. -pub trait TransactionProgramExecutorFactory { - /// The executor type created by this factory. - type Executor: TransactionProgramExecutor; - - /// Create a new executor configured with the provided transaction inputs and options. - fn create_executor( +impl TransactionProgramExecutor for FastProcessor { + fn new( stack_inputs: StackInputs, advice_inputs: AdviceInputs, options: ExecutionOptions, - ) -> Self::Executor; -} - -/// Default factory that executes transactions with `FastProcessor`. -pub struct DefaultTransactionProgramExecutorFactory; + ) -> Self { + FastProcessor::new_with_options(stack_inputs, advice_inputs, options) + } -impl TransactionProgramExecutor for FastProcessor { fn execute( self, program: &Program, @@ -46,21 +47,5 @@ impl TransactionProgramExecutor for FastProcessor { } } -impl TransactionProgramExecutorFactory for DefaultTransactionProgramExecutorFactory { - type Executor = FastProcessor; - - fn create_executor( - stack_inputs: StackInputs, - advice_inputs: AdviceInputs, - options: ExecutionOptions, - ) -> Self::Executor { - FastProcessor::new_with_options(stack_inputs, advice_inputs, options) - } -} - -#[doc(hidden)] -pub use DefaultTransactionProgramExecutorFactory as DefaultProgramExecutorFactory; #[doc(hidden)] pub use TransactionProgramExecutor as ProgramExecutor; -#[doc(hidden)] -pub use TransactionProgramExecutorFactory as ProgramExecutorFactory; diff --git a/crates/miden-protocol/src/transaction/mod.rs b/crates/miden-protocol/src/transaction/mod.rs index b8a3215f9b..b4167c9cf2 100644 --- a/crates/miden-protocol/src/transaction/mod.rs +++ b/crates/miden-protocol/src/transaction/mod.rs @@ -18,12 +18,8 @@ mod tx_summary; pub use executed_tx::{ExecutedTransaction, TransactionMeasurements}; #[doc(hidden)] -pub use executor::{DefaultProgramExecutorFactory, ProgramExecutor, ProgramExecutorFactory}; -pub use executor::{ - DefaultTransactionProgramExecutorFactory, - TransactionProgramExecutor, - TransactionProgramExecutorFactory, -}; +pub use executor::ProgramExecutor; +pub use executor::TransactionProgramExecutor; pub use inputs::{AccountInputs, InputNote, InputNotes, ToInputNoteCommitments, TransactionInputs}; pub use kernel::{TransactionAdviceInputs, TransactionEventId, TransactionKernel, memory}; pub use ordered_transactions::OrderedTransactionHeaders; diff --git a/crates/miden-tx/src/executor/mod.rs b/crates/miden-tx/src/executor/mod.rs index c239efe32a..3507a43a07 100644 --- a/crates/miden-tx/src/executor/mod.rs +++ b/crates/miden-tx/src/executor/mod.rs @@ -3,7 +3,7 @@ use alloc::sync::Arc; use core::marker::PhantomData; use miden_processor::advice::AdviceInputs; -use miden_processor::{ExecutionError, StackInputs}; +use miden_processor::{ExecutionError, FastProcessor, StackInputs}; pub use miden_processor::{ExecutionOptions, MastForestStore}; use miden_protocol::account::AccountId; use miden_protocol::assembly::DefaultSourceManager; @@ -11,7 +11,6 @@ use miden_protocol::assembly::debuginfo::SourceManagerSync; use miden_protocol::asset::{Asset, AssetVaultKey}; use miden_protocol::block::BlockNumber; use miden_protocol::transaction::{ - DefaultTransactionProgramExecutorFactory, ExecutedTransaction, InputNote, InputNotes, @@ -19,7 +18,6 @@ use miden_protocol::transaction::{ TransactionInputs, TransactionKernel, TransactionProgramExecutor, - TransactionProgramExecutorFactory, TransactionScript, }; use miden_protocol::vm::StackOutputs; @@ -61,13 +59,13 @@ pub struct TransactionExecutor< 'auth, STORE: 'store, AUTH: 'auth, - F: TransactionProgramExecutorFactory = DefaultTransactionProgramExecutorFactory, + P: TransactionProgramExecutor = FastProcessor, > { data_store: &'store STORE, authenticator: Option<&'auth AUTH>, source_manager: Arc, exec_options: ExecutionOptions, - _executor_factory: PhantomData, + _processor: PhantomData

, } impl<'store, 'auth, STORE, AUTH> TransactionExecutor<'store, 'auth, STORE, AUTH> @@ -84,7 +82,7 @@ where /// debug mode will be turned off. /// /// By default, the executor uses [`FastProcessor`](miden_processor::FastProcessor) for program - /// execution. Use [`with_executor_factory`](Self::with_executor_factory) to plug in a + /// execution. Use [`with_program_executor`](Self::with_program_executor) to plug in a /// different execution engine. pub fn new(data_store: &'store STORE) -> Self { const _: () = assert!(MIN_TX_EXECUTION_CYCLES <= MAX_TX_EXECUTION_CYCLES); @@ -100,30 +98,30 @@ where false, ) .expect("Must not fail while max cycles is more than min trace length"), - _executor_factory: PhantomData, + _processor: PhantomData, } } } -impl<'store, 'auth, STORE, AUTH, F> TransactionExecutor<'store, 'auth, STORE, AUTH, F> +impl<'store, 'auth, STORE, AUTH, P> TransactionExecutor<'store, 'auth, STORE, AUTH, P> where STORE: DataStore + 'store + Sync, AUTH: TransactionAuthenticator + 'auth + Sync, - F: TransactionProgramExecutorFactory, + P: TransactionProgramExecutor, { - /// Replaces the transaction program executor factory with a different implementation. + /// Replaces the transaction program executor with a different implementation. /// /// This allows plugging in alternative execution engines while preserving the rest of the /// transaction executor configuration. - pub fn with_executor_factory( + pub fn with_program_executor( self, - ) -> TransactionExecutor<'store, 'auth, STORE, AUTH, F2> { + ) -> TransactionExecutor<'store, 'auth, STORE, AUTH, P2> { TransactionExecutor { data_store: self.data_store, authenticator: self.authenticator, source_manager: self.source_manager, exec_options: self.exec_options, - _executor_factory: PhantomData, + _processor: PhantomData, } } @@ -225,7 +223,8 @@ where // instantiate the processor in debug mode only when debug mode is specified via execution // options; this is important because in debug mode execution is almost 100x slower - let processor = F::create_executor(stack_inputs, advice_inputs, self.exec_options); + let processor = +

::new(stack_inputs, advice_inputs, self.exec_options); let output = processor .execute(&TransactionKernel::main(), &mut host) @@ -271,8 +270,11 @@ where let (mut host, stack_inputs, advice_inputs) = self.prepare_transaction(&tx_inputs).await?; - let processor = - F::create_executor(stack_inputs, advice_inputs, ExecutionOptions::default()); + let processor =

::new( + stack_inputs, + advice_inputs, + ExecutionOptions::default(), + ); let output = processor .execute(&TransactionKernel::tx_script_main(), &mut host) .await diff --git a/crates/miden-tx/src/executor/notes_checker.rs b/crates/miden-tx/src/executor/notes_checker.rs index 3f2594f27c..79cf2a4fb8 100644 --- a/crates/miden-tx/src/executor/notes_checker.rs +++ b/crates/miden-tx/src/executor/notes_checker.rs @@ -1,7 +1,6 @@ use alloc::collections::BTreeMap; use alloc::vec::Vec; -use miden_processor::FastProcessor; use miden_processor::advice::AdviceInputs; use miden_protocol::account::AccountId; use miden_protocol::block::BlockNumber; @@ -12,11 +11,11 @@ use miden_protocol::transaction::{ TransactionArgs, TransactionInputs, TransactionKernel, - TransactionProgramExecutorFactory, + TransactionProgramExecutor, }; use miden_standards::note::{NoteConsumptionStatus, StandardNote}; -use super::TransactionExecutor; +use super::{ExecutionOptions, TransactionExecutor}; use crate::auth::TransactionAuthenticator; use crate::errors::TransactionCheckerError; use crate::executor::map_execution_error; @@ -74,18 +73,18 @@ impl NoteConsumptionInfo { /// The check is performed using the [NoteConsumptionChecker::check_notes_consumability] procedure. /// Essentially runs the transaction to make sure that provided input notes could be consumed by the /// account. -pub struct NoteConsumptionChecker<'a, STORE, AUTH, F: TransactionProgramExecutorFactory>( - &'a TransactionExecutor<'a, 'a, STORE, AUTH, F>, +pub struct NoteConsumptionChecker<'a, STORE, AUTH, P: TransactionProgramExecutor>( + &'a TransactionExecutor<'a, 'a, STORE, AUTH, P>, ); -impl<'a, STORE, AUTH, F> NoteConsumptionChecker<'a, STORE, AUTH, F> +impl<'a, STORE, AUTH, P> NoteConsumptionChecker<'a, STORE, AUTH, P> where STORE: DataStore + Sync, AUTH: TransactionAuthenticator + Sync, - F: TransactionProgramExecutorFactory, + P: TransactionProgramExecutor, { /// Creates a new [`NoteConsumptionChecker`] instance with the given transaction executor. - pub fn new(tx_executor: &'a TransactionExecutor<'a, 'a, STORE, AUTH, F>) -> Self { + pub fn new(tx_executor: &'a TransactionExecutor<'a, 'a, STORE, AUTH, P>) -> Self { NoteConsumptionChecker(tx_executor) } @@ -341,7 +340,11 @@ where .await .map_err(TransactionCheckerError::TransactionPreparation)?; - let processor = FastProcessor::new(stack_inputs).with_advice(advice_inputs); + let processor =

::new( + stack_inputs, + advice_inputs, + ExecutionOptions::default(), + ); let result = processor .execute(&TransactionKernel::main(), &mut host) .await diff --git a/crates/miden-tx/src/lib.rs b/crates/miden-tx/src/lib.rs index 2c2f0b9119..e34545354b 100644 --- a/crates/miden-tx/src/lib.rs +++ b/crates/miden-tx/src/lib.rs @@ -21,10 +21,7 @@ pub use executor::{ mod host; pub use host::{AccountProcedureIndexMap, LinkMap, MemoryViewer, ScriptMastForestStore}; -pub use miden_protocol::transaction::{ - TransactionProgramExecutor, - TransactionProgramExecutorFactory, -}; +pub use miden_protocol::transaction::TransactionProgramExecutor; mod prover; pub use prover::{ @@ -52,4 +49,15 @@ pub mod auth; // RE-EXPORTS // ================================================================================================ -pub use miden_protocol::utils; +pub mod utils { + pub use miden_protocol::utils::serde::{ + BudgetedReader, + ByteReader, + ByteWriter, + Deserializable, + DeserializationError, + Serializable, + SliceReader, + }; + pub use miden_protocol::utils::*; +} From 0ccc18df8ef0ed150cf168b33262734667720cf1 Mon Sep 17 00:00:00 2001 From: djole Date: Sat, 14 Mar 2026 18:56:01 +0100 Subject: [PATCH 3/4] fixup: address comments --- crates/miden-protocol/src/transaction/mod.rs | 4 --- crates/miden-tx/src/executor/mod.rs | 33 +++++++++---------- crates/miden-tx/src/executor/notes_checker.rs | 19 ++++------- .../src/executor/program_executor.rs} | 10 +++--- crates/miden-tx/src/lib.rs | 15 ++------- 5 files changed, 28 insertions(+), 53 deletions(-) rename crates/{miden-protocol/src/transaction/executor.rs => miden-tx/src/executor/program_executor.rs} (83%) mode change 100755 => 100644 diff --git a/crates/miden-protocol/src/transaction/mod.rs b/crates/miden-protocol/src/transaction/mod.rs index b4167c9cf2..977155e755 100644 --- a/crates/miden-protocol/src/transaction/mod.rs +++ b/crates/miden-protocol/src/transaction/mod.rs @@ -4,7 +4,6 @@ use super::vm::AdviceInputs; use super::{Felt, Hasher, WORD_SIZE, Word, ZERO}; mod executed_tx; -mod executor; mod inputs; mod kernel; mod ordered_transactions; @@ -17,9 +16,6 @@ mod tx_header; mod tx_summary; pub use executed_tx::{ExecutedTransaction, TransactionMeasurements}; -#[doc(hidden)] -pub use executor::ProgramExecutor; -pub use executor::TransactionProgramExecutor; pub use inputs::{AccountInputs, InputNote, InputNotes, ToInputNoteCommitments, TransactionInputs}; pub use kernel::{TransactionAdviceInputs, TransactionEventId, TransactionKernel, memory}; pub use ordered_transactions::OrderedTransactionHeaders; diff --git a/crates/miden-tx/src/executor/mod.rs b/crates/miden-tx/src/executor/mod.rs index 3507a43a07..88837b1ddb 100644 --- a/crates/miden-tx/src/executor/mod.rs +++ b/crates/miden-tx/src/executor/mod.rs @@ -17,7 +17,6 @@ use miden_protocol::transaction::{ TransactionArgs, TransactionInputs, TransactionKernel, - TransactionProgramExecutor, TransactionScript, }; use miden_protocol::vm::StackOutputs; @@ -42,6 +41,9 @@ pub use notes_checker::{ NoteConsumptionInfo, }; +mod program_executor; +pub use program_executor::ProgramExecutor; + // TRANSACTION EXECUTOR // ================================================================================================ @@ -59,13 +61,13 @@ pub struct TransactionExecutor< 'auth, STORE: 'store, AUTH: 'auth, - P: TransactionProgramExecutor = FastProcessor, + EXEC: ProgramExecutor = FastProcessor, > { data_store: &'store STORE, authenticator: Option<&'auth AUTH>, source_manager: Arc, exec_options: ExecutionOptions, - _processor: PhantomData

, + _executor: PhantomData, } impl<'store, 'auth, STORE, AUTH> TransactionExecutor<'store, 'auth, STORE, AUTH> @@ -86,7 +88,7 @@ where /// different execution engine. pub fn new(data_store: &'store STORE) -> Self { const _: () = assert!(MIN_TX_EXECUTION_CYCLES <= MAX_TX_EXECUTION_CYCLES); - TransactionExecutor { + Self { data_store, authenticator: None, source_manager: Arc::new(DefaultSourceManager::default()), @@ -98,30 +100,30 @@ where false, ) .expect("Must not fail while max cycles is more than min trace length"), - _processor: PhantomData, + _executor: PhantomData, } } } -impl<'store, 'auth, STORE, AUTH, P> TransactionExecutor<'store, 'auth, STORE, AUTH, P> +impl<'store, 'auth, STORE, AUTH, EXEC> TransactionExecutor<'store, 'auth, STORE, AUTH, EXEC> where STORE: DataStore + 'store + Sync, AUTH: TransactionAuthenticator + 'auth + Sync, - P: TransactionProgramExecutor, + EXEC: ProgramExecutor, { /// Replaces the transaction program executor with a different implementation. /// /// This allows plugging in alternative execution engines while preserving the rest of the /// transaction executor configuration. - pub fn with_program_executor( + pub fn with_program_executor( self, - ) -> TransactionExecutor<'store, 'auth, STORE, AUTH, P2> { - TransactionExecutor { + ) -> TransactionExecutor<'store, 'auth, STORE, AUTH, EXEC2> { + TransactionExecutor::<'store, 'auth, STORE, AUTH, EXEC2> { data_store: self.data_store, authenticator: self.authenticator, source_manager: self.source_manager, exec_options: self.exec_options, - _processor: PhantomData, + _executor: PhantomData, } } @@ -223,8 +225,7 @@ where // instantiate the processor in debug mode only when debug mode is specified via execution // options; this is important because in debug mode execution is almost 100x slower - let processor = -

::new(stack_inputs, advice_inputs, self.exec_options); + let processor = EXEC::new(stack_inputs, advice_inputs, self.exec_options); let output = processor .execute(&TransactionKernel::main(), &mut host) @@ -270,11 +271,7 @@ where let (mut host, stack_inputs, advice_inputs) = self.prepare_transaction(&tx_inputs).await?; - let processor =

::new( - stack_inputs, - advice_inputs, - ExecutionOptions::default(), - ); + let processor = EXEC::new(stack_inputs, advice_inputs, ExecutionOptions::default()); let output = processor .execute(&TransactionKernel::tx_script_main(), &mut host) .await diff --git a/crates/miden-tx/src/executor/notes_checker.rs b/crates/miden-tx/src/executor/notes_checker.rs index 79cf2a4fb8..33c5870b0d 100644 --- a/crates/miden-tx/src/executor/notes_checker.rs +++ b/crates/miden-tx/src/executor/notes_checker.rs @@ -11,11 +11,10 @@ use miden_protocol::transaction::{ TransactionArgs, TransactionInputs, TransactionKernel, - TransactionProgramExecutor, }; use miden_standards::note::{NoteConsumptionStatus, StandardNote}; -use super::{ExecutionOptions, TransactionExecutor}; +use super::{ExecutionOptions, ProgramExecutor, TransactionExecutor}; use crate::auth::TransactionAuthenticator; use crate::errors::TransactionCheckerError; use crate::executor::map_execution_error; @@ -73,18 +72,18 @@ impl NoteConsumptionInfo { /// The check is performed using the [NoteConsumptionChecker::check_notes_consumability] procedure. /// Essentially runs the transaction to make sure that provided input notes could be consumed by the /// account. -pub struct NoteConsumptionChecker<'a, STORE, AUTH, P: TransactionProgramExecutor>( - &'a TransactionExecutor<'a, 'a, STORE, AUTH, P>, +pub struct NoteConsumptionChecker<'a, STORE, AUTH, EXEC: ProgramExecutor>( + &'a TransactionExecutor<'a, 'a, STORE, AUTH, EXEC>, ); -impl<'a, STORE, AUTH, P> NoteConsumptionChecker<'a, STORE, AUTH, P> +impl<'a, STORE, AUTH, EXEC> NoteConsumptionChecker<'a, STORE, AUTH, EXEC> where STORE: DataStore + Sync, AUTH: TransactionAuthenticator + Sync, - P: TransactionProgramExecutor, + EXEC: ProgramExecutor, { /// Creates a new [`NoteConsumptionChecker`] instance with the given transaction executor. - pub fn new(tx_executor: &'a TransactionExecutor<'a, 'a, STORE, AUTH, P>) -> Self { + pub fn new(tx_executor: &'a TransactionExecutor<'a, 'a, STORE, AUTH, EXEC>) -> Self { NoteConsumptionChecker(tx_executor) } @@ -340,11 +339,7 @@ where .await .map_err(TransactionCheckerError::TransactionPreparation)?; - let processor =

::new( - stack_inputs, - advice_inputs, - ExecutionOptions::default(), - ); + let processor = EXEC::new(stack_inputs, advice_inputs, ExecutionOptions::default()); let result = processor .execute(&TransactionKernel::main(), &mut host) .await diff --git a/crates/miden-protocol/src/transaction/executor.rs b/crates/miden-tx/src/executor/program_executor.rs old mode 100755 new mode 100644 similarity index 83% rename from crates/miden-protocol/src/transaction/executor.rs rename to crates/miden-tx/src/executor/program_executor.rs index bd4a52c25f..20152b87d7 --- a/crates/miden-protocol/src/transaction/executor.rs +++ b/crates/miden-tx/src/executor/program_executor.rs @@ -10,8 +10,9 @@ use miden_processor::{ StackInputs, }; -/// A transaction-scoped program executor used by `miden-tx`. -pub trait TransactionProgramExecutor { +/// A transaction-scoped program executor used by +/// [`TransactionExecutor`](super::TransactionExecutor). +pub trait ProgramExecutor { /// Create a new executor configured with the provided transaction inputs and options. fn new( stack_inputs: StackInputs, @@ -29,7 +30,7 @@ pub trait TransactionProgramExecutor { ) -> impl FutureMaybeSend>; } -impl TransactionProgramExecutor for FastProcessor { +impl ProgramExecutor for FastProcessor { fn new( stack_inputs: StackInputs, advice_inputs: AdviceInputs, @@ -46,6 +47,3 @@ impl TransactionProgramExecutor for FastProcessor { FastProcessor::execute(self, program, host) } } - -#[doc(hidden)] -pub use TransactionProgramExecutor as ProgramExecutor; diff --git a/crates/miden-tx/src/lib.rs b/crates/miden-tx/src/lib.rs index e34545354b..3dd06bdcc5 100644 --- a/crates/miden-tx/src/lib.rs +++ b/crates/miden-tx/src/lib.rs @@ -15,13 +15,13 @@ pub use executor::{ MastForestStore, NoteConsumptionChecker, NoteConsumptionInfo, + ProgramExecutor, TransactionExecutor, TransactionExecutorHost, }; mod host; pub use host::{AccountProcedureIndexMap, LinkMap, MemoryViewer, ScriptMastForestStore}; -pub use miden_protocol::transaction::TransactionProgramExecutor; mod prover; pub use prover::{ @@ -49,15 +49,4 @@ pub mod auth; // RE-EXPORTS // ================================================================================================ -pub mod utils { - pub use miden_protocol::utils::serde::{ - BudgetedReader, - ByteReader, - ByteWriter, - Deserializable, - DeserializationError, - Serializable, - SliceReader, - }; - pub use miden_protocol::utils::*; -} +pub use miden_protocol::utils; From 4ee94c5121b030b5f2d6a52bac9ab081c83ddb93 Mon Sep 17 00:00:00 2001 From: djole Date: Sat, 14 Mar 2026 20:05:38 +0100 Subject: [PATCH 4/4] fixup: add TODO and changelog --- CHANGELOG.md | 1 + crates/miden-tx/src/executor/program_executor.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c75059727f..d627a6c4f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ - Added `InputNoteCommitment::from_parts()` for construction of input note commitments from a nullifier and optional note header ([#2588](https://github.com/0xMiden/protocol/pull/2588)). - Added `bool` schema type to the type registry and updated ACL auth component to use it for boolean config fields ([#2591](https://github.com/0xMiden/protocol/pull/2591)). - Added `component_metadata()` to all account components to expose their metadata ([#2596](https://github.com/0xMiden/protocol/pull/2596)). +- Added `ProgramExecutor` hooks to support DAP and other custom transaction program executors ([#2574](https://github.com/0xMiden/protocol/pull/2574)). ### Changes diff --git a/crates/miden-tx/src/executor/program_executor.rs b/crates/miden-tx/src/executor/program_executor.rs index 20152b87d7..f4dc8eaa1d 100644 --- a/crates/miden-tx/src/executor/program_executor.rs +++ b/crates/miden-tx/src/executor/program_executor.rs @@ -12,6 +12,9 @@ use miden_processor::{ /// A transaction-scoped program executor used by /// [`TransactionExecutor`](super::TransactionExecutor). +/// +/// TODO: Move this trait into `miden-vm` once the executor boundary is +/// consolidated there. pub trait ProgramExecutor { /// Create a new executor configured with the provided transaction inputs and options. fn new(