diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f3642451..c1081f3cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,10 @@ - Fixed no-std compatibility for remote prover clients ([#1407](https://github.com/0xMiden/miden-node/pull/1407)). - Fixed `AccountProofRequest` to retrieve the latest known state in case specified block number (or chain tip) does not contain account updates ([#1422](https://github.com/0xMiden/miden-node/issues/1422)). - Fixed missing asset setup for full account initialization ([#1461](https://github.com/0xMiden/miden-node/pull/1461)). +- Fixed validator to use pre-stored asset witnesses from the transaction inputs instead of trying to open the partial vault ([#1490](https://github.com/0xMiden/miden-node/pull/1490)). - Fixed `GetNetworkAccountIds` pagination to return the chain tip ([#1489](https://github.com/0xMiden/miden-node/pull/1489)). +- Fixed validator to use pre-stored asset witnesses from the transaction inputs instead of trying to open the partial vault ([#1490](https://github.com/0xMiden/miden-node/pull/1490)). +- Fixed the network monitor counter account to use the storage slot name ([#1492](https://github.com/0xMiden/miden-node/pull/1492)). ## v0.12.6 diff --git a/bin/network-monitor/src/assets/counter_program.masm b/bin/network-monitor/src/assets/counter_program.masm index 175e7e969..9cd6536f4 100644 --- a/bin/network-monitor/src/assets/counter_program.masm +++ b/bin/network-monitor/src/assets/counter_program.masm @@ -1,7 +1,7 @@ # Counter program for network monitoring with note authentication # Storage layout: -# - Slot 0: counter value (u64) -# - Slot 1: authorized wallet account id as [prefix, suffix, 0, 0] +# - OWNER_SLOT: authorized wallet account id as [prefix, suffix, 0, 0] +# - COUNTER_SLOT: counter value (u64) use miden::core::sys use miden::protocol::active_account @@ -11,14 +11,14 @@ use miden::protocol::account_id use miden::protocol::tx -# The slot in this component's storage layout where the counter is stored. const COUNTER_SLOT = word("miden::monitor::counter_contract::counter") +const OWNER_SLOT = word("miden::monitor::counter_contract::owner") # Increment function with note authentication # => [] pub proc increment - # Ensure the note sender matches the authorized wallet stored in slot 1. - push.1 exec.active_account::get_item + # Ensure the note sender matches the authorized wallet. + push.OWNER_SLOT[0..2] exec.active_account::get_item # => [owner_prefix, owner_suffix, 0, 0] exec.active_note::get_sender diff --git a/bin/network-monitor/src/counter.rs b/bin/network-monitor/src/counter.rs index 4c89c74f8..48539adb6 100644 --- a/bin/network-monitor/src/counter.rs +++ b/bin/network-monitor/src/counter.rs @@ -43,6 +43,7 @@ use tracing::{error, info, instrument, warn}; use crate::COMPONENT; use crate::config::MonitorConfig; +use crate::deploy::counter::COUNTER_SLOT_NAME; use crate::deploy::{MonitorDataStore, create_genesis_aware_rpc_client, get_counter_library}; use crate::status::{ CounterTrackingDetails, @@ -83,7 +84,7 @@ async fn get_genesis_block_header(rpc_client: &mut RpcClient) -> Result = LazyLock::new(|| { +pub static OWNER_SLOT_NAME: LazyLock = LazyLock::new(|| { StorageSlotName::new("miden::monitor::counter_contract::owner") .expect("storage slot name should be valid") }); -static COUNTER_SLOT_NAME: LazyLock = LazyLock::new(|| { +pub static COUNTER_SLOT_NAME: LazyLock = LazyLock::new(|| { StorageSlotName::new("miden::monitor::counter_contract::counter") .expect("storage slot name should be valid") }); diff --git a/bin/network-monitor/src/deploy/mod.rs b/bin/network-monitor/src/deploy/mod.rs index 0a6c4ebe5..29fa4303d 100644 --- a/bin/network-monitor/src/deploy/mod.rs +++ b/bin/network-monitor/src/deploy/mod.rs @@ -199,13 +199,15 @@ pub async fn deploy_counter_account(counter_account: &Account, rpc_url: &Url) -> .await .context("Failed to execute transaction")?; + let tx_inputs = executed_tx.tx_inputs().to_bytes(); + let prover = LocalTransactionProver::default(); let proven_tx = prover.prove(executed_tx).context("Failed to prove transaction")?; let request = ProvenTransaction { transaction: proven_tx.to_bytes(), - transaction_inputs: None, + transaction_inputs: Some(tx_inputs), }; rpc_client diff --git a/crates/ntx-builder/src/actor/execute.rs b/crates/ntx-builder/src/actor/execute.rs index 83c1d09c9..3f3bae70f 100644 --- a/crates/ntx-builder/src/actor/execute.rs +++ b/crates/ntx-builder/src/actor/execute.rs @@ -159,9 +159,10 @@ impl NtxContext { let notes = notes.into_iter().map(Note::from).collect::>(); let (successful, failed) = self.filter_notes(&data_store, notes).await?; let executed = Box::pin(self.execute(&data_store, successful)).await?; + let tx_inputs = executed.tx_inputs().clone(); let proven = Box::pin(self.prove(executed.into())).await?; let tx_id = proven.id(); - self.submit(proven).await?; + self.submit(proven, &tx_inputs).await?; Ok((tx_id, failed)) } .in_current_span() @@ -258,9 +259,9 @@ impl NtxContext { /// Submits the transaction to the block producer. #[instrument(target = COMPONENT, name = "ntx.execute_transaction.submit", skip_all, err)] - async fn submit(&self, tx: ProvenTransaction) -> NtxResult<()> { + async fn submit(&self, tx: ProvenTransaction, tx_inputs: &TransactionInputs) -> NtxResult<()> { self.block_producer - .submit_proven_transaction(tx) + .submit_proven_transaction(tx, tx_inputs) .await .map_err(NtxError::Submission) } diff --git a/crates/ntx-builder/src/actor/mod.rs b/crates/ntx-builder/src/actor/mod.rs index 60e7df54c..e3594be26 100644 --- a/crates/ntx-builder/src/actor/mod.rs +++ b/crates/ntx-builder/src/actor/mod.rs @@ -247,7 +247,7 @@ impl AccountActor { let chain_state = self.chain_state.read().await.clone(); // Find a candidate transaction and execute it. if let Some(tx_candidate) = state.select_candidate(crate::MAX_NOTES_PER_TX, chain_state) { - self.execute_transactions(&mut state, tx_candidate).await; + Box::pin(self.execute_transactions(&mut state, tx_candidate)).await; } else { // No transactions to execute, wait for events. self.mode = ActorMode::NoViableNotes; @@ -281,7 +281,7 @@ impl AccountActor { self.script_cache.clone(), ); - let execution_result = context.execute_transaction(tx_candidate).await; + let execution_result = Box::pin(context.execute_transaction(tx_candidate)).await; match execution_result { // Execution completed without failed notes. Ok((tx_id, failed)) if failed.is_empty() => { diff --git a/crates/ntx-builder/src/block_producer.rs b/crates/ntx-builder/src/block_producer.rs index 7c1af9d8f..a4836a21e 100644 --- a/crates/ntx-builder/src/block_producer.rs +++ b/crates/ntx-builder/src/block_producer.rs @@ -6,7 +6,7 @@ use miden_node_proto::domain::mempool::MempoolEvent; use miden_node_proto::generated::{self as proto}; use miden_node_utils::FlattenResult; use miden_protocol::block::BlockNumber; -use miden_protocol::transaction::ProvenTransaction; +use miden_protocol::transaction::{ProvenTransaction, TransactionInputs}; use miden_tx::utils::Serializable; use tokio_stream::StreamExt; use tonic::Status; @@ -45,10 +45,11 @@ impl BlockProducerClient { pub async fn submit_proven_transaction( &self, proven_tx: ProvenTransaction, + tx_inputs: &TransactionInputs, ) -> Result<(), Status> { let request = proto::transaction::ProvenTransaction { transaction: proven_tx.to_bytes(), - transaction_inputs: None, + transaction_inputs: Some(tx_inputs.to_bytes()), }; self.client.clone().submit_proven_transaction(request).await?; diff --git a/crates/validator/src/tx_validation/data_store.rs b/crates/validator/src/tx_validation/data_store.rs index a48c2e8e6..c12ebfd58 100644 --- a/crates/validator/src/tx_validation/data_store.rs +++ b/crates/validator/src/tx_validation/data_store.rs @@ -74,20 +74,24 @@ impl DataStore for TransactionInputsDataStore { }); } - Result::, _>::from_iter(vault_keys.into_iter().map(|vault_key| { - match self.tx_inputs.account().vault().open(vault_key) { - Ok(vault_proof) => { - AssetWitness::new(vault_proof.into()).map_err(|err| DataStoreError::Other { - error_msg: "failed to open vault asset tree".into(), - source: Some(err.into()), + let stored_witnesses = self.tx_inputs.asset_witnesses(); + + vault_keys + .into_iter() + .map(|vault_key| { + stored_witnesses + .iter() + .find(|w| w.authenticates_asset_vault_key(vault_key)) + .cloned() + .ok_or_else(|| DataStoreError::Other { + error_msg: format!( + "asset witness not found for vault key {vault_key}", + ) + .into(), + source: None, }) - }, - Err(err) => Err(DataStoreError::Other { - error_msg: "failed to open vault".into(), - source: Some(err.into()), - }), - } - })) + }) + .collect() } }