From ce7ef8a2b3e9e4f256826d46ae38855ee542dfa5 Mon Sep 17 00:00:00 2001 From: Jort Date: Mon, 4 May 2026 19:22:56 -0700 Subject: [PATCH 01/15] [jsonrpc] vm error visibility indexing --- crates/sui-core/src/authority.rs | 129 +++++++++++++----- .../sui-core/src/authority/authority_store.rs | 19 ++- .../src/authority/authority_store_pruner.rs | 2 + .../src/authority/authority_store_tables.rs | 14 ++ .../src/authority/authority_test_utils.rs | 8 +- crates/sui-core/src/checkpoints/mod.rs | 7 + crates/sui-core/src/execution_cache.rs | 7 +- .../unit_tests/writeback_cache_tests.rs | 34 +++++ .../src/execution_cache/writeback_cache.rs | 34 ++++- crates/sui-core/src/transaction_outputs.rs | 5 + sui-execution/src/executor.rs | 4 +- sui-execution/src/latest.rs | 6 +- sui-execution/src/v0.rs | 5 +- sui-execution/src/v1.rs | 5 +- sui-execution/src/v2.rs | 5 +- sui-execution/src/v3.rs | 5 +- 16 files changed, 234 insertions(+), 55 deletions(-) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index 02b67ce8b4fc..ff09332351b7 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -139,7 +139,7 @@ use sui_types::effects::{ InputConsensusObject, SignedTransactionEffects, TransactionEffects, TransactionEffectsAPI, TransactionEvents, VerifiedSignedTransactionEffects, }; -use sui_types::error::{ExecutionError, SuiErrorKind, UserInputError}; +use sui_types::error::{ExecutionError, ExecutionErrorContext, SuiErrorKind, UserInputError}; use sui_types::event::EventID; use sui_types::executable_transaction::VerifiedExecutableTransaction; use sui_types::execution_status::ExecutionErrorKind; @@ -1461,7 +1461,7 @@ impl AuthorityState { certificate: &VerifiedExecutableTransaction, mut execution_env: ExecutionEnv, epoch_store: &Arc, - ) -> ExecutionOutput<(TransactionEffects, Option)> { + ) -> ExecutionOutput<(TransactionEffects, Option)> { let _scope = monitored_scope("Execution::try_execute_immediately"); let _metrics_guard = self.metrics.internal_execution_latency.start_timer(); @@ -1640,7 +1640,10 @@ impl AuthorityState { &self, certificate: &VerifiedCertificate, execution_env: ExecutionEnv, - ) -> (VerifiedSignedTransactionEffects, Option) { + ) -> ( + VerifiedSignedTransactionEffects, + Option, + ) { let epoch_store = self.epoch_store_for_testing(); let (effects, execution_error_opt) = self .try_execute_immediately( @@ -1658,7 +1661,10 @@ impl AuthorityState { &self, executable: &VerifiedExecutableTransaction, execution_env: ExecutionEnv, - ) -> (VerifiedSignedTransactionEffects, Option) { + ) -> ( + VerifiedSignedTransactionEffects, + Option, + ) { let epoch_store = self.epoch_store_for_testing(); let (effects, execution_error_opt) = self .try_execute_immediately(executable, execution_env, &epoch_store) @@ -1734,7 +1740,7 @@ impl AuthorityState { ) -> ExecutionOutput<( TransactionOutputs, Vec, - Option, + Option, )> { let _scope = monitored_scope("Execution::process_certificate"); let tx_digest = *certificate.digest(); @@ -1905,40 +1911,69 @@ impl AuthorityState { rewritten_inputs: Option>, signer: SuiAddress, tx_digest: TransactionDigest, + is_fullnode: bool, ) -> ( InnerTemporaryStore, SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ) { - let (inner_temp_store, gas_status, effects, timings, execution_error) = executor - // TODO only run this function on FullNodes, use `execute_transaction_to_effects` on validators. - .execute_transaction_to_effects_and_execution_error( - store, - protocol_config, - self.metrics.execution_metrics.clone(), - enable_expensive_checks, - execution_params, - epoch_id, - epoch_timestamp_ms, - input_objects, - gas_data, + if is_fullnode { + let (inner_temp_store, gas_status, effects, timings, execution_error) = executor + .execute_transaction_to_effects_and_execution_error( + store, + protocol_config, + self.metrics.execution_metrics.clone(), + enable_expensive_checks, + execution_params, + epoch_id, + epoch_timestamp_ms, + input_objects, + gas_data, + gas_status, + kind, + rewritten_inputs, + signer, + tx_digest, + &mut None, + ); + + ( + inner_temp_store, gas_status, - kind, - rewritten_inputs, - signer, - tx_digest, - &mut None, - ); + effects, + timings, + execution_error, + ) + } else { + let (inner_temp_store, gas_status, effects, timings, execution_failure) = executor + .execute_transaction_to_effects( + store, + protocol_config, + self.metrics.execution_metrics.clone(), + enable_expensive_checks, + execution_params, + epoch_id, + epoch_timestamp_ms, + input_objects, + gas_data, + gas_status, + kind, + rewritten_inputs, + signer, + tx_digest, + &mut None, + ); - ( - inner_temp_store, - gas_status, - effects, - timings, - execution_error, - ) + ( + inner_temp_store, + gas_status, + effects, + timings, + execution_failure.map_err(ExecutionErrorContext::from), + ) + } } /// execute_certificate validates the transaction input, and executes the certificate, @@ -1961,7 +1996,7 @@ impl AuthorityState { ) -> ExecutionOutput<( TransactionOutputs, Vec, - Option, + Option, )> { let _scope = monitored_scope("Execution::prepare_certificate"); let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer(); @@ -2024,8 +2059,7 @@ impl AuthorityState { let tracking_store = TrackingBackingStore::new(self.get_backing_store().as_ref()); - #[allow(unused_mut)] - let (inner_temp_store, _, mut effects, timings, execution_error_opt) = self + let (inner_temp_store, _, effects, timings, execution_error_result) = self .execute_transaction_to_effects( &**epoch_store.executor(), &tracking_store, @@ -2048,8 +2082,11 @@ impl AuthorityState { rewritten_inputs, signer, tx_digest, + self.is_fullnode(epoch_store), ); + let execution_error_opt = execution_error_result.err(); + let object_funds_checker = self.object_funds_checker.load(); if let Some(object_funds_checker) = object_funds_checker.as_ref() && !object_funds_checker.should_commit_object_funds_withdraws( @@ -2127,6 +2164,9 @@ impl AuthorityState { ); } + #[cfg(msim)] + let mut effects = effects; + fail_point_arg!("simulate_fork_during_execution", |( forked_validators, full_halt, @@ -2159,6 +2199,10 @@ impl AuthorityState { &tracking_store.into_read_objects(), ); + let execution_error_metadata = execution_error_opt + .as_ref() + .and_then(ExecutionErrorContext::metadata_with_source); + // index certificate let _ = self .post_process_one_tx(certificate, &effects, &inner_temp_store, epoch_store) @@ -2174,6 +2218,7 @@ impl AuthorityState { effects, inner_temp_store, unchanged_loaded_runtime_objects, + execution_error_metadata, ); let elapsed = prepare_certificate_start_time.elapsed().as_micros() as f64; @@ -2187,7 +2232,7 @@ impl AuthorityState { ); } - ExecutionOutput::Success((transaction_outputs, timings, execution_error_opt.err())) + ExecutionOutput::Success((transaction_outputs, timings, execution_error_opt)) } pub fn prepare_certificate_for_benchmark( @@ -2209,7 +2254,10 @@ impl AuthorityState { epoch_store, ) .unwrap(); - Ok((transaction_outputs, execution_error_opt)) + Ok(( + transaction_outputs, + execution_error_opt.map(ExecutionError::from), + )) } #[instrument(skip_all)] @@ -2339,7 +2387,14 @@ impl AuthorityState { let execution_error_source = execution_result .as_ref() .err() - .and_then(|e| e.source().as_ref().map(|e| e.to_string())); + .and_then(|e| std::error::Error::source(e).map(|e| e.to_string())); + if let Some(error) = execution_result.as_ref().err() { + debug!( + tx_digest = ?tx_digest, + execution_error_kind = ?error.kind(), + "dry run transaction execution failed" + ); + } let response = DryRunTransactionBlockResponse { suggested_gas_price, diff --git a/crates/sui-core/src/authority/authority_store.rs b/crates/sui-core/src/authority/authority_store.rs index 48160736004f..994915e7eac2 100644 --- a/crates/sui-core/src/authority/authority_store.rs +++ b/crates/sui-core/src/authority/authority_store.rs @@ -22,7 +22,7 @@ use move_core_types::resolver::{ModuleResolver, SerializedPackage}; use serde::{Deserialize, Serialize}; use sui_config::node::AuthorityStorePruningConfig; use sui_macros::fail_point_arg; -use sui_types::error::{SuiErrorKind, UserInputError}; +use sui_types::error::{ExecutionErrorMetadata, SuiErrorKind, UserInputError}; use sui_types::execution::TypeLayoutStore; use sui_types::global_state_hash::GlobalStateHash; use sui_types::message_envelope::Message; @@ -344,6 +344,13 @@ impl AuthorityStore { .get(digest) } + pub fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Result, TypedStoreError> { + self.perpetual_tables.execution_error_metadata.get(digest) + } + pub fn multi_get_effects<'a>( &self, effects_digests: impl Iterator, @@ -791,6 +798,7 @@ impl AuthorityStore { written, events, unchanged_loaded_runtime_objects, + execution_error_metadata, locks_to_delete, new_locks_to_init, .. @@ -863,6 +871,15 @@ impl AuthorityStore { )?; } + if let Some(metadata) = execution_error_metadata + && !metadata.is_empty() + { + write_batch.insert_batch( + &self.perpetual_tables.execution_error_metadata, + [(transaction_digest, metadata)], + )?; + } + self.initialize_live_object_markers_impl(write_batch, new_locks_to_init, false)?; // Note: deletes locks for received objects as well (but not for objects that were in diff --git a/crates/sui-core/src/authority/authority_store_pruner.rs b/crates/sui-core/src/authority/authority_store_pruner.rs index 619fb81f0f1d..282537af3b0d 100644 --- a/crates/sui-core/src/authority/authority_store_pruner.rs +++ b/crates/sui-core/src/authority/authority_store_pruner.rs @@ -300,6 +300,8 @@ impl AuthorityStorePruner { &perpetual_db.unchanged_loaded_runtime_objects, transactions.iter(), )?; + perpetual_batch + .delete_batch(&perpetual_db.execution_error_metadata, transactions.iter())?; perpetual_batch.delete_batch(&perpetual_db.effects, effect_digests)?; let mut checkpoints_batch = checkpoint_db.tables.certified_checkpoints.batch(); diff --git a/crates/sui-core/src/authority/authority_store_tables.rs b/crates/sui-core/src/authority/authority_store_tables.rs index 7b306afbca75..faf182db319b 100644 --- a/crates/sui-core/src/authority/authority_store_tables.rs +++ b/crates/sui-core/src/authority/authority_store_tables.rs @@ -11,6 +11,7 @@ use std::path::Path; use std::sync::atomic::AtomicU64; use sui_types::base_types::SequenceNumber; use sui_types::effects::{TransactionEffects, TransactionEvents}; +use sui_types::error::ExecutionErrorMetadata; use sui_types::global_state_hash::GlobalStateHash; use sui_types::storage::MarkerValue; use typed_store::metrics::SamplingInterval; @@ -100,6 +101,9 @@ pub struct AuthorityPerpetualTables { // Loaded (and unchanged) runtime object references. pub(crate) unchanged_loaded_runtime_objects: DBMap>, + // Local execution error metadata, keyed by the digest of the transaction that produced it. + pub(crate) execution_error_metadata: DBMap, + /// DEPRECATED in favor of the table of the same name in authority_per_epoch_store. /// Please do not add new accessors/callsites. /// When transaction is executed via checkpoint executor, we store association here @@ -331,6 +335,16 @@ impl AuthorityPerpetualTables { digest_prefix.clone(), ), ), + ( + "execution_error_metadata".to_string(), + ThConfig::new_with_rm_prefix( + 32, + mutexes, + uniform_key, + KeySpaceConfig::default().with_relocation_filter(|_, _| Decision::Remove), + digest_prefix.clone(), + ), + ), ( "executed_transactions_to_checkpoint".to_string(), ThConfig::new_with_rm_prefix( diff --git a/crates/sui-core/src/authority/authority_test_utils.rs b/crates/sui-core/src/authority/authority_test_utils.rs index 68ce7706e400..d36c18fa79a7 100644 --- a/crates/sui-core/src/authority/authority_test_utils.rs +++ b/crates/sui-core/src/authority/authority_test_utils.rs @@ -120,7 +120,7 @@ pub async fn execute_from_consensus( .try_execute_executable_for_test(&executable, env) .await; let effects = result.inner().data().clone(); - (effects, execution_error_opt) + (effects, execution_error_opt.map(ExecutionError::from)) } /// This is the primary test helper for executing transactions end-to-end. @@ -221,7 +221,11 @@ pub async fn submit_and_execute_with_error( execution_error_opt = fullnode_execution_error_opt; } - Ok((executable, result.into_inner(), execution_error_opt)) + Ok(( + executable, + result.into_inner(), + execution_error_opt.map(ExecutionError::from), + )) } /// Enqueues multiple transactions for execution after they've been through consensus. diff --git a/crates/sui-core/src/checkpoints/mod.rs b/crates/sui-core/src/checkpoints/mod.rs index c03918092818..dfe16eb96e48 100644 --- a/crates/sui-core/src/checkpoints/mod.rs +++ b/crates/sui-core/src/checkpoints/mod.rs @@ -4190,6 +4190,13 @@ mod tests { unimplemented!() } + fn get_execution_error_metadata( + &self, + _digest: &TransactionDigest, + ) -> Option { + unimplemented!() + } + fn transaction_executed_in_last_epoch(&self, _: &TransactionDigest, _: EpochId) -> bool { unimplemented!() } diff --git a/crates/sui-core/src/execution_cache.rs b/crates/sui-core/src/execution_cache.rs index d23584acb60a..9ed9099721a7 100644 --- a/crates/sui-core/src/execution_cache.rs +++ b/crates/sui-core/src/execution_cache.rs @@ -26,7 +26,7 @@ use sui_protocol_config::ProtocolVersion; use sui_types::base_types::{FullObjectID, VerifiedExecutionData}; use sui_types::digests::{TransactionDigest, TransactionEffectsDigest}; use sui_types::effects::{TransactionEffects, TransactionEvents}; -use sui_types::error::{SuiError, SuiErrorKind, SuiResult, UserInputError}; +use sui_types::error::{ExecutionErrorMetadata, SuiError, SuiErrorKind, SuiResult, UserInputError}; use sui_types::executable_transaction::VerifiedExecutableTransaction; use sui_types::messages_checkpoint::CheckpointSequenceNumber; use sui_types::object::Object; @@ -534,6 +534,11 @@ pub trait TransactionCacheRead: Send + Sync { digest: &TransactionDigest, ) -> Option>; + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option; + fn take_accumulator_events(&self, digest: &TransactionDigest) -> Option>; fn notify_read_executed_effects_digests<'a>( diff --git a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs index 7638fdeaa594..2fcb46fc2167 100644 --- a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs +++ b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs @@ -157,6 +157,7 @@ impl Scenario { effects, events, unchanged_loaded_runtime_objects: Default::default(), + execution_error_metadata: None, accumulator_events: Default::default(), markers: Default::default(), wrapped: Default::default(), @@ -551,6 +552,39 @@ async fn test_committed() { .await; } +#[tokio::test] +async fn test_execution_error_metadata_round_trip() { + telemetry_subscribers::init_for_testing(); + Scenario::iterate(|mut s| async move { + let mut metadata = BTreeMap::new(); + metadata.insert( + "source".to_string(), + "Object runtime cached objects limit reached".to_string(), + ); + s.outputs.execution_error_metadata = Some(metadata.clone()); + + let tx = s.do_tx().await; + assert_eq!( + s.cache.get_execution_error_metadata(&tx), + Some(metadata.clone()) + ); + + s.commit(tx).await.unwrap(); + assert_eq!( + s.cache.get_execution_error_metadata(&tx), + Some(metadata.clone()) + ); + + s.reset_cache(); + assert_eq!( + s.store.get_execution_error_metadata(&tx).unwrap(), + Some(metadata.clone()) + ); + assert_eq!(s.cache.get_execution_error_metadata(&tx), Some(metadata)); + }) + .await; +} + #[tokio::test] async fn test_mutated() { telemetry_subscribers::init_for_testing(); diff --git a/crates/sui-core/src/execution_cache/writeback_cache.rs b/crates/sui-core/src/execution_cache/writeback_cache.rs index 6bfaeb3faee6..a047b1961eb8 100644 --- a/crates/sui-core/src/execution_cache/writeback_cache.rs +++ b/crates/sui-core/src/execution_cache/writeback_cache.rs @@ -76,7 +76,7 @@ use sui_types::base_types::{ use sui_types::bridge::{Bridge, get_bridge}; use sui_types::digests::{ObjectDigest, TransactionDigest, TransactionEffectsDigest}; use sui_types::effects::{TransactionEffects, TransactionEvents}; -use sui_types::error::{SuiError, SuiErrorKind, SuiResult, UserInputError}; +use sui_types::error::{ExecutionErrorMetadata, SuiError, SuiErrorKind, SuiResult, UserInputError}; use sui_types::executable_transaction::VerifiedExecutableTransaction; use sui_types::global_state_hash::GlobalStateHash; use sui_types::message_envelope::Message; @@ -233,6 +233,8 @@ struct UncommittedData { unchanged_loaded_runtime_objects: DashMap>, + execution_error_metadata: DashMap, + executed_effects_digests: DashMap, // Transaction outputs that have not yet been written to the DB. Items are removed from this @@ -253,6 +255,7 @@ impl UncommittedData { pending_transaction_writes: DashMap::with_shard_amount(2048), transaction_events: DashMap::with_shard_amount(2048), unchanged_loaded_runtime_objects: DashMap::with_shard_amount(2048), + execution_error_metadata: DashMap::with_shard_amount(2048), total_transaction_inserts: AtomicU64::new(0), total_transaction_commits: AtomicU64::new(0), } @@ -266,6 +269,7 @@ impl UncommittedData { self.pending_transaction_writes.clear(); self.transaction_events.clear(); self.unchanged_loaded_runtime_objects.clear(); + self.execution_error_metadata.clear(); self.total_transaction_inserts .store(0, std::sync::atomic::Ordering::Relaxed); self.total_transaction_commits @@ -282,6 +286,7 @@ impl UncommittedData { && self.executed_effects_digests.is_empty() && self.transaction_events.is_empty() && self.unchanged_loaded_runtime_objects.is_empty() + && self.execution_error_metadata.is_empty() && self .total_transaction_inserts .load(std::sync::atomic::Ordering::Relaxed) @@ -913,6 +918,7 @@ impl WritebackCache { wrapped, events, unchanged_loaded_runtime_objects, + execution_error_metadata, .. } = &*tx_outputs; @@ -988,6 +994,15 @@ impl WritebackCache { .unchanged_loaded_runtime_objects .insert(tx_digest, unchanged_loaded_runtime_objects.clone()); + if let Some(metadata) = execution_error_metadata + && !metadata.is_empty() + { + self.metrics.record_cache_write("execution_error_metadata"); + self.dirty + .execution_error_metadata + .insert(tx_digest, metadata.clone()); + } + self.metrics.record_cache_write("executed_effects_digests"); self.dirty .executed_effects_digests @@ -1190,6 +1205,8 @@ impl WritebackCache { .remove(&tx_digest) .expect("unchanged_loaded_runtime_objects must exist"); + self.dirty.execution_error_metadata.remove(&tx_digest); + self.dirty .executed_effects_digests .remove(&tx_digest) @@ -2309,6 +2326,21 @@ impl TransactionCacheRead for WritebackCache { }) } + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option { + self.dirty + .execution_error_metadata + .get(digest) + .map(|b| b.clone()) + .or_else(|| { + self.store + .get_execution_error_metadata(digest) + .expect("db error") + }) + } + fn take_accumulator_events(&self, digest: &TransactionDigest) -> Option> { self.dirty .pending_transaction_writes diff --git a/crates/sui-core/src/transaction_outputs.rs b/crates/sui-core/src/transaction_outputs.rs index f46fb41ffef7..25f6403635e7 100644 --- a/crates/sui-core/src/transaction_outputs.rs +++ b/crates/sui-core/src/transaction_outputs.rs @@ -7,6 +7,7 @@ use std::sync::Arc; use sui_types::accumulator_event::AccumulatorEvent; use sui_types::base_types::{FullObjectID, ObjectRef}; use sui_types::effects::{TransactionEffects, TransactionEffectsAPI, TransactionEvents}; +use sui_types::error::ExecutionErrorMetadata; use sui_types::full_checkpoint_content::ObjectSet; use sui_types::inner_temporary_store::{InnerTemporaryStore, WrittenObjects}; use sui_types::storage::{FullObjectKey, MarkerValue, ObjectKey}; @@ -19,6 +20,7 @@ pub struct TransactionOutputs { pub effects: TransactionEffects, pub events: TransactionEvents, pub unchanged_loaded_runtime_objects: Vec, + pub execution_error_metadata: Option, pub accumulator_events: Mutex>>, pub markers: Vec<(FullObjectKey, MarkerValue)>, @@ -36,6 +38,7 @@ impl TransactionOutputs { effects: TransactionEffects, inner_temporary_store: InnerTemporaryStore, unchanged_loaded_runtime_objects: Vec, + execution_error_metadata: Option, ) -> TransactionOutputs { let InnerTemporaryStore { input_objects, @@ -186,6 +189,7 @@ impl TransactionOutputs { effects, events, unchanged_loaded_runtime_objects, + execution_error_metadata, accumulator_events: Mutex::new(Some(accumulator_events)), markers, wrapped, @@ -210,6 +214,7 @@ impl TransactionOutputs { effects, events: TransactionEvents { data: vec![] }, unchanged_loaded_runtime_objects: vec![], + execution_error_metadata: None, accumulator_events: Mutex::new(Some(vec![])), markers: vec![], wrapped: vec![], diff --git a/sui-execution/src/executor.rs b/sui-execution/src/executor.rs index 6f2c5fea138e..bca9205bbd96 100644 --- a/sui-execution/src/executor.rs +++ b/sui-execution/src/executor.rs @@ -13,7 +13,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::ExecutionError, + error::{ExecutionError, ExecutionErrorContext}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -79,7 +79,7 @@ pub trait Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ); fn dev_inspect_transaction( diff --git a/sui-execution/src/latest.rs b/sui-execution/src/latest.rs index df1e26b5f5cb..c8a6ff29221d 100644 --- a/sui-execution/src/latest.rs +++ b/sui-execution/src/latest.rs @@ -14,7 +14,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorTrait, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, ExecutionErrorTrait, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -134,10 +134,10 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ) { let (store_out, gas_status_out, effects, timings, result) = - execute_transaction_to_effects::>( + execute_transaction_to_effects::>( store, input_objects, gas, diff --git a/sui-execution/src/v0.rs b/sui-execution/src/v0.rs index 6018b95880b7..4fa12c52150f 100644 --- a/sui-execution/src/v0.rs +++ b/sui-execution/src/v0.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -205,7 +205,7 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ) { let gas_coins = gas.payment; let (inner_temp_store, gas_status, effects, result) = @@ -228,6 +228,7 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } + let result = result.map_err(ExecutionErrorContext::from); (inner_temp_store, gas_status, effects, vec![], result) } diff --git a/sui-execution/src/v1.rs b/sui-execution/src/v1.rs index 1cd6fe851b64..e7cb300856c1 100644 --- a/sui-execution/src/v1.rs +++ b/sui-execution/src/v1.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -205,7 +205,7 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ) { let gas_coins = gas.payment; let (inner_temp_store, gas_status, effects, result) = @@ -228,6 +228,7 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } + let result = result.map_err(ExecutionErrorContext::from); (inner_temp_store, gas_status, effects, vec![], result) } diff --git a/sui-execution/src/v2.rs b/sui-execution/src/v2.rs index 3da3e41f09ea..a76f962e04fc 100644 --- a/sui-execution/src/v2.rs +++ b/sui-execution/src/v2.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -205,7 +205,7 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ) { let gas_coins = gas.payment; let (inner_temp_store, gas_status, effects, result) = @@ -228,6 +228,7 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } + let result = result.map_err(ExecutionErrorContext::from); (inner_temp_store, gas_status, effects, vec![], result) } diff --git a/sui-execution/src/v3.rs b/sui-execution/src/v3.rs index ca3d4d72b8c9..b850082a154a 100644 --- a/sui-execution/src/v3.rs +++ b/sui-execution/src/v3.rs @@ -14,7 +14,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, gas::SuiGasStatus, inner_temporary_store::InnerTemporaryStore, @@ -139,7 +139,7 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionError>, + Result<(), ExecutionErrorContext>, ) { let (inner_temp_store, gas_status, effects, timings, result) = execute_transaction_to_effects::( @@ -162,6 +162,7 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(protocol_config, transaction_digest, error); } + let result = result.map_err(ExecutionErrorContext::from); (inner_temp_store, gas_status, effects, timings, result) } From c32b90fe14232e359467adfd3b2ea376f1d878d1 Mon Sep 17 00:00:00 2001 From: Jort Date: Mon, 18 May 2026 12:03:37 -0700 Subject: [PATCH 02/15] fix --- crates/sui-core/src/authority.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index ff09332351b7..ccd79f6e4682 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -2059,7 +2059,8 @@ impl AuthorityState { let tracking_store = TrackingBackingStore::new(self.get_backing_store().as_ref()); - let (inner_temp_store, _, effects, timings, execution_error_result) = self + #[allow(unused_mut)] + let (inner_temp_store, _, mut effects, timings, execution_error_result) = self .execute_transaction_to_effects( &**epoch_store.executor(), &tracking_store, @@ -2164,9 +2165,6 @@ impl AuthorityState { ); } - #[cfg(msim)] - let mut effects = effects; - fail_point_arg!("simulate_fork_during_execution", |( forked_validators, full_halt, @@ -2388,13 +2386,6 @@ impl AuthorityState { .as_ref() .err() .and_then(|e| std::error::Error::source(e).map(|e| e.to_string())); - if let Some(error) = execution_result.as_ref().err() { - debug!( - tx_digest = ?tx_digest, - execution_error_kind = ?error.kind(), - "dry run transaction execution failed" - ); - } let response = DryRunTransactionBlockResponse { suggested_gas_price, From c55ac5f5fb2e50009e8c12118a862b6d332cfb0d Mon Sep 17 00:00:00 2001 From: Jort Date: Mon, 18 May 2026 15:52:56 -0700 Subject: [PATCH 03/15] replay fix --- crates/sui-replay-2/src/execution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/sui-replay-2/src/execution.rs b/crates/sui-replay-2/src/execution.rs index 7fd7a6ee267e..d831360b80ce 100644 --- a/crates/sui-replay-2/src/execution.rs +++ b/crates/sui-replay-2/src/execution.rs @@ -175,7 +175,7 @@ pub fn execute_transaction_to_effects( debug!(op = "execute_tx", phase = "end", "execution"); Ok(( - result, + result.map_err(ExecutionError::from), TxnContextAndEffects { txn_data, execution_effects: effects, From ab0c0e32d15b538c1f2f2a2b026062720c97455a Mon Sep 17 00:00:00 2001 From: Jort Date: Mon, 18 May 2026 16:10:50 -0700 Subject: [PATCH 04/15] test validator doesnt store, no rows created on empty metadata --- .../unit_tests/writeback_cache_tests.rs | 21 ++++ .../src/unit_tests/authority_tests.rs | 97 ++++++++++++++++++- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs index 2fcb46fc2167..19e9e89c4ed7 100644 --- a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs +++ b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs @@ -564,6 +564,7 @@ async fn test_execution_error_metadata_round_trip() { s.outputs.execution_error_metadata = Some(metadata.clone()); let tx = s.do_tx().await; + assert!(s.cache.dirty.execution_error_metadata.contains_key(&tx)); assert_eq!( s.cache.get_execution_error_metadata(&tx), Some(metadata.clone()) @@ -585,6 +586,26 @@ async fn test_execution_error_metadata_round_trip() { .await; } +#[tokio::test] +async fn test_empty_execution_error_metadata_is_ignored() { + telemetry_subscribers::init_for_testing(); + Scenario::iterate(|mut s| async move { + s.outputs.execution_error_metadata = Some(BTreeMap::new()); + + let tx = s.do_tx().await; + assert!(!s.cache.dirty.execution_error_metadata.contains_key(&tx)); + assert_eq!(s.cache.get_execution_error_metadata(&tx), None); + + s.commit(tx).await.unwrap(); + assert_eq!(s.cache.get_execution_error_metadata(&tx), None); + + s.reset_cache(); + assert_eq!(s.store.get_execution_error_metadata(&tx).unwrap(), None); + assert_eq!(s.cache.get_execution_error_metadata(&tx), None); + }) + .await; +} + #[tokio::test] async fn test_mutated() { telemetry_subscribers::init_for_testing(); diff --git a/crates/sui-core/src/unit_tests/authority_tests.rs b/crates/sui-core/src/unit_tests/authority_tests.rs index 9a2efb0fd851..ea105bf7e419 100644 --- a/crates/sui-core/src/unit_tests/authority_tests.rs +++ b/crates/sui-core/src/unit_tests/authority_tests.rs @@ -34,7 +34,7 @@ use sui_protocol_config::{ Chain, ExecutionTimeEstimateParams, PerObjectCongestionControlMode, ProtocolConfig, ProtocolVersion, }; -use sui_types::effects::TransactionEffects; +use sui_types::effects::{TransactionEffects, TransactionEffectsAPI}; use sui_types::epoch_data::EpochData; use sui_types::error::UserInputError; use sui_types::execution::SharedInput; @@ -5398,6 +5398,101 @@ async fn test_function_not_found() { assert_eq!(execution_error_source, Some("Could not resolve function 'bad_function' in module '0x0000000000000000000000000000000000000000000000000000000000000001::option'".to_string()),) } +#[tokio::test] +async fn test_validator_execution_does_not_store_error_metadata() { + let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); + let gas_object_id = ObjectID::random(); + let (validator, fullnode, _) = + init_state_with_ids_and_object_basics_with_fullnode(vec![(sender, gas_object_id)]).await; + + let mut builder = ProgrammableTransactionBuilder::new(); + builder + .move_call( + ObjectID::from_single_byte(1), + ident_str!("option").to_owned(), + ident_str!("bad_function").to_owned(), + vec![], + vec![], + ) + .unwrap(); + let kind = TransactionKind::programmable(builder.finish()); + + let rgp = validator.reference_gas_price_for_testing().unwrap(); + let txn_data = TransactionData::new_with_gas_coins( + kind, + sender, + vec![ + validator + .get_object(&gas_object_id) + .await + .unwrap() + .compute_object_reference(), + ], + TEST_ONLY_GAS_UNIT_FOR_PUBLISH * rgp, + rgp, + ); + + let transaction = to_sender_signed_transaction(txn_data, &sender_key); + let executable = create_executable_transaction(&validator, transaction).unwrap(); + let env = ExecutionEnv::new().with_assigned_versions(AssignedVersions::new(vec![], None)); + + let (validator_effects, validator_execution_error) = validator + .try_execute_executable_for_test(&executable, env.clone()) + .await; + let (fullnode_effects, fullnode_execution_error) = fullnode + .try_execute_executable_for_test(&executable, env) + .await; + + let validator_effects = validator_effects.inner().data(); + let fullnode_effects = fullnode_effects.inner().data(); + assert_eq!(validator_effects.status(), fullnode_effects.status()); + assert_eq!( + validator_effects.transaction_digest(), + fullnode_effects.transaction_digest() + ); + assert_eq!( + validator_effects.gas_cost_summary(), + fullnode_effects.gas_cost_summary() + ); + assert_eq!(validator_effects.created(), fullnode_effects.created()); + assert_eq!(validator_effects.mutated(), fullnode_effects.mutated()); + assert_eq!(validator_effects.deleted(), fullnode_effects.deleted()); + assert_eq!(validator_effects.wrapped(), fullnode_effects.wrapped()); + assert!(matches!( + validator_effects.status(), + ExecutionStatus::Failure(ExecutionFailure { + error: ExecutionErrorKind::FunctionNotFound, + command: Some(0), + }) + )); + + assert_eq!( + validator_execution_error.and_then(|error| error.metadata_with_source()), + None + ); + assert_eq!( + validator + .get_transaction_cache_reader() + .get_execution_error_metadata(executable.digest()), + None, + ); + + let fullnode_metadata = fullnode_execution_error + .and_then(|error| error.metadata_with_source()) + .unwrap(); + assert!( + fullnode_metadata + .get("source") + .is_some_and(|source| source.contains("bad_function")) + ); + assert_eq!( + fullnode + .get_transaction_cache_reader() + .get_execution_error_metadata(executable.digest()), + Some(fullnode_metadata), + ); +} + #[tokio::test] async fn test_arity_mismatch() { let (sender, sender_key): (_, AccountKeyPair) = get_key_pair(); From 075964c3f9b9b913872571b9e7e2521441564975 Mon Sep 17 00:00:00 2001 From: Jort Date: Tue, 19 May 2026 12:40:53 -0700 Subject: [PATCH 05/15] Track execution error metadata sidecar --- crates/sui-core/src/authority.rs | 102 +++++++++--------- .../sui-core/src/authority/authority_store.rs | 2 +- .../src/authority/authority_test_utils.rs | 8 +- .../unit_tests/writeback_cache_tests.rs | 14 +-- .../src/execution_cache/writeback_cache.rs | 4 +- .../src/unit_tests/authority_tests.rs | 23 ++-- crates/sui-types/src/error.rs | 41 ++++++- 7 files changed, 116 insertions(+), 78 deletions(-) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index ccd79f6e4682..afb664ed68c8 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -139,7 +139,9 @@ use sui_types::effects::{ InputConsensusObject, SignedTransactionEffects, TransactionEffects, TransactionEffectsAPI, TransactionEvents, VerifiedSignedTransactionEffects, }; -use sui_types::error::{ExecutionError, ExecutionErrorContext, SuiErrorKind, UserInputError}; +use sui_types::error::{ + ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiErrorKind, UserInputError, +}; use sui_types::event::EventID; use sui_types::executable_transaction::VerifiedExecutableTransaction; use sui_types::execution_status::ExecutionErrorKind; @@ -1461,7 +1463,7 @@ impl AuthorityState { certificate: &VerifiedExecutableTransaction, mut execution_env: ExecutionEnv, epoch_store: &Arc, - ) -> ExecutionOutput<(TransactionEffects, Option)> { + ) -> ExecutionOutput<(TransactionEffects, Option)> { let _scope = monitored_scope("Execution::try_execute_immediately"); let _metrics_guard = self.metrics.internal_execution_latency.start_timer(); @@ -1640,10 +1642,7 @@ impl AuthorityState { &self, certificate: &VerifiedCertificate, execution_env: ExecutionEnv, - ) -> ( - VerifiedSignedTransactionEffects, - Option, - ) { + ) -> (VerifiedSignedTransactionEffects, Option) { let epoch_store = self.epoch_store_for_testing(); let (effects, execution_error_opt) = self .try_execute_immediately( @@ -1661,10 +1660,7 @@ impl AuthorityState { &self, executable: &VerifiedExecutableTransaction, execution_env: ExecutionEnv, - ) -> ( - VerifiedSignedTransactionEffects, - Option, - ) { + ) -> (VerifiedSignedTransactionEffects, Option) { let epoch_store = self.epoch_store_for_testing(); let (effects, execution_error_opt) = self .try_execute_immediately(executable, execution_env, &epoch_store) @@ -1740,7 +1736,7 @@ impl AuthorityState { ) -> ExecutionOutput<( TransactionOutputs, Vec, - Option, + Option, )> { let _scope = monitored_scope("Execution::process_certificate"); let tx_digest = *certificate.digest(); @@ -1917,8 +1913,12 @@ impl AuthorityState { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ) { + // Fullnodes retain source errors and VM metadata as sidecar data for richer user-facing + // error reporting. Validators use the lean execution path and intentionally return no + // sidecar metadata so effects stay independent of non-consensus data. if is_fullnode { let (inner_temp_store, gas_status, effects, timings, execution_error) = executor .execute_transaction_to_effects_and_execution_error( @@ -1939,12 +1939,18 @@ impl AuthorityState { &mut None, ); + let execution_error_metadata = execution_error + .as_ref() + .err() + .and_then(ExecutionErrorContext::metadata_with_source); + ( inner_temp_store, gas_status, effects, timings, - execution_error, + execution_error.map_err(ExecutionError::from), + execution_error_metadata, ) } else { let (inner_temp_store, gas_status, effects, timings, execution_failure) = executor @@ -1971,7 +1977,8 @@ impl AuthorityState { gas_status, effects, timings, - execution_failure.map_err(ExecutionErrorContext::from), + execution_failure.map_err(ExecutionError::from), + None, ) } } @@ -1996,7 +2003,7 @@ impl AuthorityState { ) -> ExecutionOutput<( TransactionOutputs, Vec, - Option, + Option, )> { let _scope = monitored_scope("Execution::prepare_certificate"); let _metrics_guard = self.metrics.prepare_certificate_latency.start_timer(); @@ -2060,31 +2067,37 @@ impl AuthorityState { let tracking_store = TrackingBackingStore::new(self.get_backing_store().as_ref()); #[allow(unused_mut)] - let (inner_temp_store, _, mut effects, timings, execution_error_result) = self - .execute_transaction_to_effects( - &**epoch_store.executor(), - &tracking_store, - protocol_config, - // TODO: would be nice to pass the whole NodeConfig here, but it creates a - // cyclic dependency w/ sui-adapter - self.config - .expensive_safety_check_config - .enable_deep_per_tx_sui_conservation_check(), - execution_params, - &epoch_store.epoch_start_config().epoch_data().epoch_id(), - epoch_store - .epoch_start_config() - .epoch_data() - .epoch_start_timestamp(), - input_objects, - gas_data, - gas_status, - kind, - rewritten_inputs, - signer, - tx_digest, - self.is_fullnode(epoch_store), - ); + let ( + inner_temp_store, + _, + mut effects, + timings, + execution_error_result, + execution_error_metadata, + ) = self.execute_transaction_to_effects( + &**epoch_store.executor(), + &tracking_store, + protocol_config, + // TODO: would be nice to pass the whole NodeConfig here, but it creates a + // cyclic dependency w/ sui-adapter + self.config + .expensive_safety_check_config + .enable_deep_per_tx_sui_conservation_check(), + execution_params, + &epoch_store.epoch_start_config().epoch_data().epoch_id(), + epoch_store + .epoch_start_config() + .epoch_data() + .epoch_start_timestamp(), + input_objects, + gas_data, + gas_status, + kind, + rewritten_inputs, + signer, + tx_digest, + self.is_fullnode(epoch_store), + ); let execution_error_opt = execution_error_result.err(); @@ -2197,10 +2210,6 @@ impl AuthorityState { &tracking_store.into_read_objects(), ); - let execution_error_metadata = execution_error_opt - .as_ref() - .and_then(ExecutionErrorContext::metadata_with_source); - // index certificate let _ = self .post_process_one_tx(certificate, &effects, &inner_temp_store, epoch_store) @@ -2252,10 +2261,7 @@ impl AuthorityState { epoch_store, ) .unwrap(); - Ok(( - transaction_outputs, - execution_error_opt.map(ExecutionError::from), - )) + Ok((transaction_outputs, execution_error_opt)) } #[instrument(skip_all)] diff --git a/crates/sui-core/src/authority/authority_store.rs b/crates/sui-core/src/authority/authority_store.rs index 994915e7eac2..676bad96aab2 100644 --- a/crates/sui-core/src/authority/authority_store.rs +++ b/crates/sui-core/src/authority/authority_store.rs @@ -872,7 +872,7 @@ impl AuthorityStore { } if let Some(metadata) = execution_error_metadata - && !metadata.is_empty() + && !metadata.attributes.is_empty() { write_batch.insert_batch( &self.perpetual_tables.execution_error_metadata, diff --git a/crates/sui-core/src/authority/authority_test_utils.rs b/crates/sui-core/src/authority/authority_test_utils.rs index d36c18fa79a7..68ce7706e400 100644 --- a/crates/sui-core/src/authority/authority_test_utils.rs +++ b/crates/sui-core/src/authority/authority_test_utils.rs @@ -120,7 +120,7 @@ pub async fn execute_from_consensus( .try_execute_executable_for_test(&executable, env) .await; let effects = result.inner().data().clone(); - (effects, execution_error_opt.map(ExecutionError::from)) + (effects, execution_error_opt) } /// This is the primary test helper for executing transactions end-to-end. @@ -221,11 +221,7 @@ pub async fn submit_and_execute_with_error( execution_error_opt = fullnode_execution_error_opt; } - Ok(( - executable, - result.into_inner(), - execution_error_opt.map(ExecutionError::from), - )) + Ok((executable, result.into_inner(), execution_error_opt)) } /// Enqueues multiple transactions for execution after they've been through consensus. diff --git a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs index 19e9e89c4ed7..b57c529c57b7 100644 --- a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs +++ b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs @@ -23,6 +23,7 @@ use sui_types::{ }; use sui_types::{ effects::{TestEffectsBuilder, TransactionEffectsAPI}, + error::ExecutionErrorMetadata, event::Event, }; use tokio::sync::RwLock; @@ -556,11 +557,12 @@ async fn test_committed() { async fn test_execution_error_metadata_round_trip() { telemetry_subscribers::init_for_testing(); Scenario::iterate(|mut s| async move { - let mut metadata = BTreeMap::new(); - metadata.insert( - "source".to_string(), - "Object runtime cached objects limit reached".to_string(), - ); + let metadata = ExecutionErrorMetadata { + attributes: BTreeMap::from([( + "source".to_string(), + "Object runtime cached objects limit reached".to_string(), + )]), + }; s.outputs.execution_error_metadata = Some(metadata.clone()); let tx = s.do_tx().await; @@ -590,7 +592,7 @@ async fn test_execution_error_metadata_round_trip() { async fn test_empty_execution_error_metadata_is_ignored() { telemetry_subscribers::init_for_testing(); Scenario::iterate(|mut s| async move { - s.outputs.execution_error_metadata = Some(BTreeMap::new()); + s.outputs.execution_error_metadata = Some(ExecutionErrorMetadata::default()); let tx = s.do_tx().await; assert!(!s.cache.dirty.execution_error_metadata.contains_key(&tx)); diff --git a/crates/sui-core/src/execution_cache/writeback_cache.rs b/crates/sui-core/src/execution_cache/writeback_cache.rs index a047b1961eb8..75ef37d6eb94 100644 --- a/crates/sui-core/src/execution_cache/writeback_cache.rs +++ b/crates/sui-core/src/execution_cache/writeback_cache.rs @@ -233,6 +233,8 @@ struct UncommittedData { unchanged_loaded_runtime_objects: DashMap>, + /// Error metadata originating from `ExecutionErrorContext`, retained with transaction + /// data until pruning. Includes source errors and VM-level details when available. execution_error_metadata: DashMap, executed_effects_digests: DashMap, @@ -995,7 +997,7 @@ impl WritebackCache { .insert(tx_digest, unchanged_loaded_runtime_objects.clone()); if let Some(metadata) = execution_error_metadata - && !metadata.is_empty() + && !metadata.attributes.is_empty() { self.metrics.record_cache_write("execution_error_metadata"); self.dirty diff --git a/crates/sui-core/src/unit_tests/authority_tests.rs b/crates/sui-core/src/unit_tests/authority_tests.rs index ea105bf7e419..cecfeb65e3d2 100644 --- a/crates/sui-core/src/unit_tests/authority_tests.rs +++ b/crates/sui-core/src/unit_tests/authority_tests.rs @@ -5466,10 +5466,7 @@ async fn test_validator_execution_does_not_store_error_metadata() { }) )); - assert_eq!( - validator_execution_error.and_then(|error| error.metadata_with_source()), - None - ); + assert!(validator_execution_error.is_some()); assert_eq!( validator .get_transaction_cache_reader() @@ -5477,20 +5474,22 @@ async fn test_validator_execution_does_not_store_error_metadata() { None, ); - let fullnode_metadata = fullnode_execution_error - .and_then(|error| error.metadata_with_source()) + let fullnode_source = fullnode_execution_error + .as_ref() + .and_then(|error| std::error::Error::source(error)) + .map(ToString::to_string) + .unwrap(); + assert!(fullnode_source.contains("bad_function")); + let fullnode_metadata = fullnode + .get_transaction_cache_reader() + .get_execution_error_metadata(executable.digest()) .unwrap(); assert!( fullnode_metadata + .attributes .get("source") .is_some_and(|source| source.contains("bad_function")) ); - assert_eq!( - fullnode - .get_transaction_cache_reader() - .get_execution_error_metadata(executable.digest()), - Some(fullnode_metadata), - ); } #[tokio::test] diff --git a/crates/sui-types/src/error.rs b/crates/sui-types/src/error.rs index f963a4fbfb4f..c5ef9f0c38f8 100644 --- a/crates/sui-types/src/error.rs +++ b/crates/sui-types/src/error.rs @@ -1166,7 +1166,38 @@ impl std::fmt::Debug for SuiError { } pub(crate) type BoxError = Box; -pub type ExecutionErrorMetadata = BTreeMap; + +#[derive(Clone, Eq, PartialEq, JsonSchema, Serialize, Deserialize, prost::Message)] +pub struct ExecutionErrorMetadata { + #[prost(btree_map = "string, string", tag = "1")] + pub attributes: BTreeMap, +} + +#[cfg(test)] +mod execution_error_metadata_tests { + use super::ExecutionErrorMetadata; + use prost::Message; + use std::collections::BTreeMap; + + #[test] + fn execution_error_metadata_protobuf_round_trip() { + let metadata = ExecutionErrorMetadata { + attributes: BTreeMap::from([( + "source".to_string(), + "Object runtime cached objects limit reached".to_string(), + )]), + }; + + let encoded = metadata.encode_to_vec(); + let decoded = ExecutionErrorMetadata::decode(encoded.as_slice()).unwrap(); + + assert_eq!(decoded, metadata); + assert_eq!( + decoded.attributes.get("source").map(String::as_str), + Some("Object runtime cached objects limit reached") + ); + } +} /// A trait for execution errors that provides common methods for accessing error information and creating new errors. pub trait ExecutionErrorTrait: @@ -1311,10 +1342,12 @@ impl ExecutionErrorContext { pub fn metadata_with_source(&self) -> Option { let mut metadata = self.metadata.clone(); if let Some(source) = self.source.as_ref() { - metadata.insert("source".to_string(), source.to_string()); + metadata + .attributes + .insert("source".to_string(), source.to_string()); } - (!metadata.is_empty()).then_some(metadata) + (!metadata.attributes.is_empty()).then_some(metadata) } pub fn to_execution_status(&self) -> (ExecutionErrorKind, Option) { @@ -1387,7 +1420,7 @@ impl From for ExecutionErrorContext { } = *inner; Self { kind, - metadata: BTreeMap::new(), + metadata: ExecutionErrorMetadata::default(), source, command, } From c296ef6e412fba6de0938b9cada47fffacf143e1 Mon Sep 17 00:00:00 2001 From: Jort Date: Tue, 19 May 2026 14:47:56 -0700 Subject: [PATCH 06/15] Down-convert replay execution status errors --- crates/simulacrum/src/epoch_state.rs | 7 ++++++- crates/sui-replay/src/replay.rs | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/crates/simulacrum/src/epoch_state.rs b/crates/simulacrum/src/epoch_state.rs index 4f1639d0ab89..294b6390a38a 100644 --- a/crates/simulacrum/src/epoch_state.rs +++ b/crates/simulacrum/src/epoch_state.rs @@ -170,6 +170,11 @@ impl EpochState { tx_digest, &mut None, ); - Ok((inner_temp_store, gas_status, effects, result)) + Ok(( + inner_temp_store, + gas_status, + effects, + result.map_err(sui_types::error::ExecutionError::from), + )) } } diff --git a/crates/sui-replay/src/replay.rs b/crates/sui-replay/src/replay.rs index 407a908fc1cb..afbdbb0c2470 100644 --- a/crates/sui-replay/src/replay.rs +++ b/crates/sui-replay/src/replay.rs @@ -834,7 +834,7 @@ impl LocalExec { required_objects: all_required_objects, local_exec_temporary_store: Some(inner_store), local_exec_effects: effects, - local_exec_status: Some(result), + local_exec_status: Some(result.map_err(ExecutionError::from)), }) } @@ -1015,7 +1015,7 @@ impl LocalExec { required_objects, local_exec_temporary_store: None, // We dont capture it for cert exec run local_exec_effects: effects, - local_exec_status: Some(exec_res), + local_exec_status: Some(exec_res.map_err(ExecutionError::from)), }) } From c165a1c895480f7e32b22a42b28a04e8534f31e6 Mon Sep 17 00:00:00 2001 From: Jort Date: Tue, 19 May 2026 15:25:06 -0700 Subject: [PATCH 07/15] nit --- crates/sui-core/src/authority.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index afb664ed68c8..217ee90e97fd 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -2072,7 +2072,7 @@ impl AuthorityState { _, mut effects, timings, - execution_error_result, + execution_error_opt, execution_error_metadata, ) = self.execute_transaction_to_effects( &**epoch_store.executor(), @@ -2099,7 +2099,7 @@ impl AuthorityState { self.is_fullnode(epoch_store), ); - let execution_error_opt = execution_error_result.err(); + let execution_error_opt = execution_error_opt.err(); let object_funds_checker = self.object_funds_checker.load(); if let Some(object_funds_checker) = object_funds_checker.as_ref() From 06842bbb65ed317ff13e44b49314b449b0664c5a Mon Sep 17 00:00:00 2001 From: Jort Date: Wed, 27 May 2026 14:32:57 -0700 Subject: [PATCH 08/15] do not leak ExecutionErrorContext, proto from sui-apis, flexible table --- Cargo.lock | 15 ++--- crates/simulacrum/src/epoch_state.rs | 47 +++++++------- crates/sui-core/src/authority.rs | 53 ++++++++-------- .../sui-core/src/authority/authority_store.rs | 21 ++++++- .../src/authority/authority_store_tables.rs | 61 ++++++++++++++++++- .../data_ingestion_handler.rs | 2 + .../unit_tests/writeback_cache_tests.rs | 7 +-- .../src/execution_cache/writeback_cache.rs | 2 +- crates/sui-core/src/storage.rs | 18 +++++- .../src/unit_tests/authority_tests.rs | 4 +- crates/sui-genesis-builder/src/lib.rs | 4 +- .../src/v2alpha/list_checkpoints.rs | 1 + crates/sui-replay-2/src/execution.rs | 41 +++++++------ crates/sui-replay/src/replay.rs | 10 +-- crates/sui-types/src/error.rs | 45 +++++--------- crates/sui-types/src/execution_status.rs | 4 +- .../sui-types/src/full_checkpoint_content.rs | 4 ++ crates/sui-types/src/rpc_proto_conversions.rs | 27 ++++++++ crates/sui-types/src/storage/read_store.rs | 30 +++++++++ .../src/test_checkpoint_data_builder.rs | 1 + external-crates/move/Cargo.lock | 12 ++++ sui-execution/src/executor.rs | 5 +- sui-execution/src/latest.rs | 21 ++++++- sui-execution/src/v0.rs | 18 +++++- sui-execution/src/v1.rs | 18 +++++- sui-execution/src/v2.rs | 18 +++++- sui-execution/src/v3.rs | 18 +++++- 27 files changed, 356 insertions(+), 151 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a944292c9125..12fb87addbd0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -660,7 +660,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", - "itertools 0.14.0", + "itertools 0.13.0", "serde", "serde_json", "serde_with", @@ -9852,7 +9852,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -11333,7 +11333,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" dependencies = [ "heck 0.4.1", - "itertools 0.14.0", + "itertools 0.10.5", "log", "multimap", "once_cell", @@ -11355,7 +11355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.117", @@ -11368,7 +11368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", - "itertools 0.14.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.117", @@ -11566,7 +11566,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls", - "socket2 0.6.3", + "socket2 0.5.6", "thiserror 2.0.17", "tokio", "tracing", @@ -14583,7 +14583,6 @@ dependencies = [ [[package]] name = "sui-crypto" version = "0.3.0" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd#f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd" dependencies = [ "ark-bn254", "ark-ff 0.4.2", @@ -16545,7 +16544,6 @@ dependencies = [ [[package]] name = "sui-rpc" version = "0.3.1" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd#f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd" dependencies = [ "base64 0.22.1", "bcs", @@ -16732,7 +16730,6 @@ dependencies = [ [[package]] name = "sui-sdk-types" version = "0.3.1" -source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd#f7487a58c6c31f07da08ba1c0cd81ebb8fe90ddd" dependencies = [ "base64ct", "bcs", diff --git a/crates/simulacrum/src/epoch_state.rs b/crates/simulacrum/src/epoch_state.rs index 294b6390a38a..c925a19c9241 100644 --- a/crates/simulacrum/src/epoch_state.rs +++ b/crates/simulacrum/src/epoch_state.rs @@ -150,31 +150,26 @@ impl EpochState { let transaction_data = transaction.data().transaction_data(); let (kind, signer, gas_data) = transaction_data.execution_parts(); - let (inner_temp_store, gas_status, effects, _timings, result) = self - .executor - .execute_transaction_to_effects_and_execution_error( - store.backing_store(), - &self.protocol_config, - self.execution_metrics.clone(), - false, // enable_expensive_checks - // TODO: Integrate with early execution error - ExecutionOrEarlyError::Ok(()), - &self.epoch_start_state.epoch(), - self.epoch_start_state.epoch_start_timestamp_ms(), - checked_input_objects, - gas_data, - gas_status, - kind, - None, // compat_args - signer, - tx_digest, - &mut None, - ); - Ok(( - inner_temp_store, - gas_status, - effects, - result.map_err(sui_types::error::ExecutionError::from), - )) + let (inner_temp_store, gas_status, effects, _timings, result, _execution_error_metadata) = + self.executor + .execute_transaction_to_effects_and_execution_error( + store.backing_store(), + &self.protocol_config, + self.execution_metrics.clone(), + false, // enable_expensive_checks + // TODO: Integrate with early execution error + ExecutionOrEarlyError::Ok(()), + &self.epoch_start_state.epoch(), + self.epoch_start_state.epoch_start_timestamp_ms(), + checked_input_objects, + gas_data, + gas_status, + kind, + None, // compat_args + signer, + tx_digest, + &mut None, + ); + Ok((inner_temp_store, gas_status, effects, result)) } } diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index 217ee90e97fd..a05a3922296a 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -139,9 +139,7 @@ use sui_types::effects::{ InputConsensusObject, SignedTransactionEffects, TransactionEffects, TransactionEffectsAPI, TransactionEvents, VerifiedSignedTransactionEffects, }; -use sui_types::error::{ - ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiErrorKind, UserInputError, -}; +use sui_types::error::{ExecutionError, ExecutionErrorMetadata, SuiErrorKind, UserInputError}; use sui_types::event::EventID; use sui_types::executable_transaction::VerifiedExecutableTransaction; use sui_types::execution_status::ExecutionErrorKind; @@ -1920,36 +1918,37 @@ impl AuthorityState { // error reporting. Validators use the lean execution path and intentionally return no // sidecar metadata so effects stay independent of non-consensus data. if is_fullnode { - let (inner_temp_store, gas_status, effects, timings, execution_error) = executor - .execute_transaction_to_effects_and_execution_error( - store, - protocol_config, - self.metrics.execution_metrics.clone(), - enable_expensive_checks, - execution_params, - epoch_id, - epoch_timestamp_ms, - input_objects, - gas_data, - gas_status, - kind, - rewritten_inputs, - signer, - tx_digest, - &mut None, - ); - - let execution_error_metadata = execution_error - .as_ref() - .err() - .and_then(ExecutionErrorContext::metadata_with_source); + let ( + inner_temp_store, + gas_status, + effects, + timings, + execution_error, + execution_error_metadata, + ) = executor.execute_transaction_to_effects_and_execution_error( + store, + protocol_config, + self.metrics.execution_metrics.clone(), + enable_expensive_checks, + execution_params, + epoch_id, + epoch_timestamp_ms, + input_objects, + gas_data, + gas_status, + kind, + rewritten_inputs, + signer, + tx_digest, + &mut None, + ); ( inner_temp_store, gas_status, effects, timings, - execution_error.map_err(ExecutionError::from), + execution_error, execution_error_metadata, ) } else { diff --git a/crates/sui-core/src/authority/authority_store.rs b/crates/sui-core/src/authority/authority_store.rs index 676bad96aab2..44012b6259b0 100644 --- a/crates/sui-core/src/authority/authority_store.rs +++ b/crates/sui-core/src/authority/authority_store.rs @@ -19,9 +19,11 @@ use fastcrypto::hash::{HashFunction, MultisetHash, Sha3_256}; use futures::stream::FuturesUnordered; use move_core_types::account_address::AccountAddress; use move_core_types::resolver::{ModuleResolver, SerializedPackage}; +use prost::Message as _; use serde::{Deserialize, Serialize}; use sui_config::node::AuthorityStorePruningConfig; use sui_macros::fail_point_arg; +use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata as RpcExecutionErrorMetadata; use sui_types::error::{ExecutionErrorMetadata, SuiErrorKind, UserInputError}; use sui_types::execution::TypeLayoutStore; use sui_types::global_state_hash::GlobalStateHash; @@ -348,7 +350,19 @@ impl AuthorityStore { &self, digest: &TransactionDigest, ) -> Result, TypedStoreError> { - self.perpetual_tables.execution_error_metadata.get(digest) + self.perpetual_tables + .execution_error_metadata + .get(digest)? + .map(|bytes| { + RpcExecutionErrorMetadata::decode(bytes.as_slice()) + .map(|metadata| ExecutionErrorMetadata::from(&metadata)) + }) + .transpose() + .map_err(|err| { + TypedStoreError::SerializationError(format!( + "failed to decode execution error metadata: {err}" + )) + }) } pub fn multi_get_effects<'a>( @@ -872,11 +886,12 @@ impl AuthorityStore { } if let Some(metadata) = execution_error_metadata - && !metadata.attributes.is_empty() + && !metadata.is_empty() { + let metadata: RpcExecutionErrorMetadata = metadata.into(); write_batch.insert_batch( &self.perpetual_tables.execution_error_metadata, - [(transaction_digest, metadata)], + [(transaction_digest, metadata.encode_to_vec())], )?; } diff --git a/crates/sui-core/src/authority/authority_store_tables.rs b/crates/sui-core/src/authority/authority_store_tables.rs index faf182db319b..afea862315bf 100644 --- a/crates/sui-core/src/authority/authority_store_tables.rs +++ b/crates/sui-core/src/authority/authority_store_tables.rs @@ -11,7 +11,6 @@ use std::path::Path; use std::sync::atomic::AtomicU64; use sui_types::base_types::SequenceNumber; use sui_types::effects::{TransactionEffects, TransactionEvents}; -use sui_types::error::ExecutionErrorMetadata; use sui_types::global_state_hash::GlobalStateHash; use sui_types::storage::MarkerValue; use typed_store::metrics::SamplingInterval; @@ -102,7 +101,7 @@ pub struct AuthorityPerpetualTables { pub(crate) unchanged_loaded_runtime_objects: DBMap>, // Local execution error metadata, keyed by the digest of the transaction that produced it. - pub(crate) execution_error_metadata: DBMap, + pub(crate) execution_error_metadata: DBMap>, /// DEPRECATED in favor of the table of the same name in authority_per_epoch_store. /// Please do not add new accessors/callsites. @@ -946,3 +945,61 @@ fn effects_table_config(db_options: DBOptions) -> DBOptions { read_size_from_env(ENV_VAR_EFFECTS_BLOCK_CACHE_SIZE).unwrap_or(1024), ) } + +#[cfg(test)] +mod tests { + use prost::Message as _; + use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata as RpcExecutionErrorMetadata; + use sui_types::digests::TransactionDigest; + use sui_types::error::ExecutionErrorMetadata; + use typed_store::DBMapUtils; + use typed_store::rocks::{DBMap, MetricConf}; + use typed_store::traits::Map; + + #[derive(Clone, PartialEq, prost::Message)] + struct FutureExecutionErrorMetadata { + #[prost(string, optional, tag = "1")] + message: Option, + #[prost(string, optional, tag = "2")] + future_field: Option, + } + + #[tokio::test] + async fn execution_error_metadata_table_accepts_future_proto_schema() { + #[derive(DBMapUtils)] + struct ExecutionErrorMetadataTables { + execution_error_metadata: DBMap>, + } + + let tempdir = tempfile::tempdir().unwrap(); + let tables = ExecutionErrorMetadataTables::open_tables_read_write( + tempdir.path().to_owned(), + MetricConf::new("test_execution_error_metadata"), + None, + None, + ); + let digest = TransactionDigest::random(); + let future_metadata = FutureExecutionErrorMetadata { + message: Some("Object runtime cached objects limit reached".to_string()), + future_field: Some("new metadata added by a future schema".to_string()), + }; + + tables + .execution_error_metadata + .insert(&digest, &future_metadata.encode_to_vec()) + .unwrap(); + + let stored_metadata = tables + .execution_error_metadata + .get(&digest) + .unwrap() + .unwrap(); + let rpc_metadata = RpcExecutionErrorMetadata::decode(stored_metadata.as_slice()).unwrap(); + let metadata = ExecutionErrorMetadata::from(&rpc_metadata); + + assert_eq!( + metadata.message.as_deref(), + Some("Object runtime cached objects limit reached") + ); + } +} diff --git a/crates/sui-core/src/checkpoints/checkpoint_executor/data_ingestion_handler.rs b/crates/sui-core/src/checkpoints/checkpoint_executor/data_ingestion_handler.rs index bc865f3de6ef..053934e176cd 100644 --- a/crates/sui-core/src/checkpoints/checkpoint_executor/data_ingestion_handler.rs +++ b/crates/sui-core/src/checkpoints/checkpoint_executor/data_ingestion_handler.rs @@ -123,6 +123,8 @@ pub(crate) fn load_checkpoint( signatures: tx.tx_signatures().to_vec(), effects: fx.clone(), events, + execution_error_metadata: transaction_cache_reader + .get_execution_error_metadata(tx.digest()), unchanged_loaded_runtime_objects: transaction_cache_reader .get_unchanged_loaded_runtime_objects(tx.digest()) // We don't write empty sets to the DB to save space, so if this load went through diff --git a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs index b57c529c57b7..f4922f7bb883 100644 --- a/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs +++ b/crates/sui-core/src/execution_cache/unit_tests/writeback_cache_tests.rs @@ -557,12 +557,7 @@ async fn test_committed() { async fn test_execution_error_metadata_round_trip() { telemetry_subscribers::init_for_testing(); Scenario::iterate(|mut s| async move { - let metadata = ExecutionErrorMetadata { - attributes: BTreeMap::from([( - "source".to_string(), - "Object runtime cached objects limit reached".to_string(), - )]), - }; + let metadata = ExecutionErrorMetadata::new("Object runtime cached objects limit reached"); s.outputs.execution_error_metadata = Some(metadata.clone()); let tx = s.do_tx().await; diff --git a/crates/sui-core/src/execution_cache/writeback_cache.rs b/crates/sui-core/src/execution_cache/writeback_cache.rs index 75ef37d6eb94..c6c81bc0a3ee 100644 --- a/crates/sui-core/src/execution_cache/writeback_cache.rs +++ b/crates/sui-core/src/execution_cache/writeback_cache.rs @@ -997,7 +997,7 @@ impl WritebackCache { .insert(tx_digest, unchanged_loaded_runtime_objects.clone()); if let Some(metadata) = execution_error_metadata - && !metadata.attributes.is_empty() + && !metadata.is_empty() { self.metrics.record_cache_write("execution_error_metadata"); self.dirty diff --git a/crates/sui-core/src/storage.rs b/crates/sui-core/src/storage.rs index b6dae65260db..b86014f7ed3c 100644 --- a/crates/sui-core/src/storage.rs +++ b/crates/sui-core/src/storage.rs @@ -19,7 +19,7 @@ use sui_types::base_types::TransactionDigest; use sui_types::committee::Committee; use sui_types::committee::EpochId; use sui_types::effects::{TransactionEffects, TransactionEvents}; -use sui_types::error::{SuiErrorKind, SuiResult}; +use sui_types::error::{ExecutionErrorMetadata, SuiErrorKind, SuiResult}; use sui_types::full_checkpoint_content::ObjectSet; use sui_types::messages_checkpoint::CheckpointContentsDigest; use sui_types::messages_checkpoint::CheckpointDigest; @@ -245,6 +245,15 @@ impl ReadStore for RocksDbStore { .get_unchanged_loaded_runtime_objects(digest) } + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option { + self.cache_traits + .transaction_cache_reader + .get_execution_error_metadata(digest) + } + fn get_transaction_checkpoint( &self, digest: &TransactionDigest, @@ -489,6 +498,13 @@ impl ReadStore for RestReadStore { self.rocks.get_unchanged_loaded_runtime_objects(digest) } + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option { + self.rocks.get_execution_error_metadata(digest) + } + fn get_transaction_checkpoint( &self, digest: &TransactionDigest, diff --git a/crates/sui-core/src/unit_tests/authority_tests.rs b/crates/sui-core/src/unit_tests/authority_tests.rs index cecfeb65e3d2..bc8c48639345 100644 --- a/crates/sui-core/src/unit_tests/authority_tests.rs +++ b/crates/sui-core/src/unit_tests/authority_tests.rs @@ -5486,8 +5486,8 @@ async fn test_validator_execution_does_not_store_error_metadata() { .unwrap(); assert!( fullnode_metadata - .attributes - .get("source") + .message + .as_deref() .is_some_and(|source| source.contains("bad_function")) ); } diff --git a/crates/sui-genesis-builder/src/lib.rs b/crates/sui-genesis-builder/src/lib.rs index 3a0635bf8b17..0356f6cd44ec 100644 --- a/crates/sui-genesis-builder/src/lib.rs +++ b/crates/sui-genesis-builder/src/lib.rs @@ -919,8 +919,8 @@ fn create_genesis_transaction( let (kind, signer, mut gas_data) = transaction_data.execution_parts(); gas_data.payment = vec![]; let input_objects = CheckedInputObjects::new_for_genesis(vec![]); - let (inner_temp_store, _, effects, _timings, _execution_error) = executor - .execute_transaction_to_effects_and_execution_error( + let (inner_temp_store, _, effects, _timings, _execution_error, _execution_error_metadata) = + executor.execute_transaction_to_effects_and_execution_error( &InMemoryStorage::new(Vec::new()), protocol_config, metrics, diff --git a/crates/sui-kv-rpc/src/v2alpha/list_checkpoints.rs b/crates/sui-kv-rpc/src/v2alpha/list_checkpoints.rs index 02d7148c2b0e..7e1ea44ffa07 100644 --- a/crates/sui-kv-rpc/src/v2alpha/list_checkpoints.rs +++ b/crates/sui-kv-rpc/src/v2alpha/list_checkpoints.rs @@ -499,6 +499,7 @@ fn render_full_checkpoint( signatures: tx.signatures.unwrap_or_default(), effects, events: tx.events, + execution_error_metadata: None, unchanged_loaded_runtime_objects: tx.unchanged_loaded_runtime_objects, }) }) diff --git a/crates/sui-replay-2/src/execution.rs b/crates/sui-replay-2/src/execution.rs index d831360b80ce..92c721f5738f 100644 --- a/crates/sui-replay-2/src/execution.rs +++ b/crates/sui-replay-2/src/execution.rs @@ -129,25 +129,26 @@ pub fn execute_transaction_to_effects( Some(error) => ExecutionOrEarlyError::Err(error), None => ExecutionOrEarlyError::Ok(()), }; - let (inner_store, gas_status, effects, _execution_timing, result) = executor - .executor - .execute_transaction_to_effects_and_execution_error( - &store, - protocol_config, - executor.execution_metrics.clone(), - false, // expensive checks - execution_params, - &epoch, - epoch_start_timestamp, - input_objects, - txn_data.gas_data().clone(), - gas_status, - txn_data.kind().clone(), - None, // compat_args - txn_data.sender(), - digest, - trace_builder_opt, - ); + let (inner_store, gas_status, effects, _execution_timing, result, _execution_error_metadata) = + executor + .executor + .execute_transaction_to_effects_and_execution_error( + &store, + protocol_config, + executor.execution_metrics.clone(), + false, // expensive checks + execution_params, + &epoch, + epoch_start_timestamp, + input_objects, + txn_data.gas_data().clone(), + gas_status, + txn_data.kind().clone(), + None, // compat_args + txn_data.sender(), + digest, + trace_builder_opt, + ); let ReplayStore { object_cache, checkpoint: _, @@ -175,7 +176,7 @@ pub fn execute_transaction_to_effects( debug!(op = "execute_tx", phase = "end", "execution"); Ok(( - result.map_err(ExecutionError::from), + result, TxnContextAndEffects { txn_data, execution_effects: effects, diff --git a/crates/sui-replay/src/replay.rs b/crates/sui-replay/src/replay.rs index afbdbb0c2470..53c7f35f5f63 100644 --- a/crates/sui-replay/src/replay.rs +++ b/crates/sui-replay/src/replay.rs @@ -792,8 +792,8 @@ impl LocalExec { Some(error) => ExecutionOrEarlyError::Err(error), None => ExecutionOrEarlyError::Ok(()), }; - let (inner_store, gas_status, effects, _timings, result) = executor - .execute_transaction_to_effects_and_execution_error( + let (inner_store, gas_status, effects, _timings, result, _execution_error_metadata) = + executor.execute_transaction_to_effects_and_execution_error( &self, protocol_config, metrics.clone(), @@ -834,7 +834,7 @@ impl LocalExec { required_objects: all_required_objects, local_exec_temporary_store: Some(inner_store), local_exec_effects: effects, - local_exec_status: Some(result.map_err(ExecutionError::from)), + local_exec_status: Some(result), }) } @@ -988,7 +988,7 @@ impl LocalExec { Some(error) => ExecutionOrEarlyError::Err(error), None => ExecutionOrEarlyError::Ok(()), }; - let (_, _, effects, _timings, exec_res) = executor + let (_, _, effects, _timings, exec_res, _execution_error_metadata) = executor .execute_transaction_to_effects_and_execution_error( &store, &protocol_config, @@ -1015,7 +1015,7 @@ impl LocalExec { required_objects, local_exec_temporary_store: None, // We dont capture it for cert exec run local_exec_effects: effects, - local_exec_status: Some(exec_res.map_err(ExecutionError::from)), + local_exec_status: Some(exec_res), }) } diff --git a/crates/sui-types/src/error.rs b/crates/sui-types/src/error.rs index c5ef9f0c38f8..1ea6c2ed97f0 100644 --- a/crates/sui-types/src/error.rs +++ b/crates/sui-types/src/error.rs @@ -1167,35 +1167,24 @@ impl std::fmt::Debug for SuiError { pub(crate) type BoxError = Box; -#[derive(Clone, Eq, PartialEq, JsonSchema, Serialize, Deserialize, prost::Message)] +/// Additional fullnode execution details captured for failed transactions. +/// This metadata is stored as a non-consensus sidecar and can be different across fullnode versions. +/// Not a part of chain state. +#[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct ExecutionErrorMetadata { - #[prost(btree_map = "string, string", tag = "1")] - pub attributes: BTreeMap, + /// Human-readable execution error detail intended for diagnostics and user-facing APIs. + pub message: Option, } -#[cfg(test)] -mod execution_error_metadata_tests { - use super::ExecutionErrorMetadata; - use prost::Message; - use std::collections::BTreeMap; - - #[test] - fn execution_error_metadata_protobuf_round_trip() { - let metadata = ExecutionErrorMetadata { - attributes: BTreeMap::from([( - "source".to_string(), - "Object runtime cached objects limit reached".to_string(), - )]), - }; - - let encoded = metadata.encode_to_vec(); - let decoded = ExecutionErrorMetadata::decode(encoded.as_slice()).unwrap(); +impl ExecutionErrorMetadata { + pub fn new(source: impl Into) -> Self { + Self { + message: Some(source.into()), + } + } - assert_eq!(decoded, metadata); - assert_eq!( - decoded.attributes.get("source").map(String::as_str), - Some("Object runtime cached objects limit reached") - ); + pub fn is_empty(&self) -> bool { + self.message.as_deref().is_none_or(str::is_empty) } } @@ -1342,12 +1331,10 @@ impl ExecutionErrorContext { pub fn metadata_with_source(&self) -> Option { let mut metadata = self.metadata.clone(); if let Some(source) = self.source.as_ref() { - metadata - .attributes - .insert("source".to_string(), source.to_string()); + metadata.message.get_or_insert_with(|| source.to_string()); } - (!metadata.attributes.is_empty()).then_some(metadata) + (!metadata.is_empty()).then_some(metadata) } pub fn to_execution_status(&self) -> (ExecutionErrorKind, Option) { diff --git a/crates/sui-types/src/execution_status.rs b/crates/sui-types/src/execution_status.rs index bc89aebdc4b7..37fcde8c534c 100644 --- a/crates/sui-types/src/execution_status.rs +++ b/crates/sui-types/src/execution_status.rs @@ -3,7 +3,9 @@ use crate::ObjectID; use crate::base_types::SuiAddress; -use crate::error::{BoxError, ExecutionError, ExecutionErrorMetadata, ExecutionErrorTrait}; +pub(crate) use crate::error::{ + BoxError, ExecutionError, ExecutionErrorMetadata, ExecutionErrorTrait, +}; use move_binary_format::file_format::{CodeOffset, TypeParameterIndex}; use move_core_types::language_storage::ModuleId; use serde::{Deserialize, Serialize}; diff --git a/crates/sui-types/src/full_checkpoint_content.rs b/crates/sui-types/src/full_checkpoint_content.rs index 21b1d9afb924..26a3909eba8b 100644 --- a/crates/sui-types/src/full_checkpoint_content.rs +++ b/crates/sui-types/src/full_checkpoint_content.rs @@ -5,6 +5,7 @@ use std::collections::BTreeMap; use crate::base_types::{ExecutionData, ObjectID, ObjectRef}; use crate::effects::{TransactionEffects, TransactionEffectsAPI, TransactionEvents}; +use crate::error::ExecutionErrorMetadata; use crate::messages_checkpoint::{CertifiedCheckpointSummary, CheckpointContents}; use crate::object::Object; use crate::signature::GenericSignature; @@ -217,6 +218,8 @@ pub struct ExecutedTransaction { pub effects: TransactionEffects, /// The events, if any, emitted by this transactions during execution pub events: Option, + /// Additional metadata captured when local execution fails. + pub execution_error_metadata: Option, pub unchanged_loaded_runtime_objects: Vec, } @@ -472,6 +475,7 @@ impl From for Checkpoint { events: tx.events, // lossy + execution_error_metadata: None, unchanged_loaded_runtime_objects: Vec::new(), } }) diff --git a/crates/sui-types/src/rpc_proto_conversions.rs b/crates/sui-types/src/rpc_proto_conversions.rs index 77168b7c0f19..bc4e7fa259b8 100644 --- a/crates/sui-types/src/rpc_proto_conversions.rs +++ b/crates/sui-types/src/rpc_proto_conversions.rs @@ -220,6 +220,7 @@ impl TryFrom<&ExecutedTransaction> for crate::full_checkpoint_content::ExecutedT .iter() .map(TryInto::try_into) .collect::>()?, + execution_error_metadata: None, }) } } @@ -1184,6 +1185,32 @@ impl From for ExecutionStatus { // ExecutionError // +pub use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata; + +impl From for ExecutionErrorMetadata { + fn from(metadata: crate::error::ExecutionErrorMetadata) -> Self { + let mut message = Self::default(); + message.message = metadata.message; + message + } +} + +impl From<&crate::execution_status::ExecutionErrorMetadata> for ExecutionErrorMetadata { + fn from(metadata: &crate::error::ExecutionErrorMetadata) -> Self { + let mut message = Self::default(); + message.message = metadata.message.clone(); + message + } +} + +impl From<&ExecutionErrorMetadata> for crate::execution_status::ExecutionErrorMetadata { + fn from(metadata: &ExecutionErrorMetadata) -> Self { + Self { + message: metadata.message.clone(), + } + } +} + fn size_error(size: u64, max_size: u64) -> SizeError { let mut message = SizeError::default(); message.size = Some(size); diff --git a/crates/sui-types/src/storage/read_store.rs b/crates/sui-types/src/storage/read_store.rs index 9fc66ecbe15d..c2d4bd0067d2 100644 --- a/crates/sui-types/src/storage/read_store.rs +++ b/crates/sui-types/src/storage/read_store.rs @@ -11,6 +11,7 @@ use crate::digests::{ }; use crate::dynamic_field::DynamicFieldType; use crate::effects::{TransactionEffects, TransactionEvents}; +use crate::error::ExecutionErrorMetadata; use crate::full_checkpoint_content::{Checkpoint, ExecutedTransaction, ObjectSet}; use crate::messages_checkpoint::{ CheckpointContents, CheckpointSequenceNumber, VerifiedCheckpoint, @@ -146,6 +147,13 @@ pub trait ReadStore: ObjectStore { digest: &TransactionDigest, ) -> Option>; + fn get_execution_error_metadata( + &self, + _digest: &TransactionDigest, + ) -> Option { + None + } + fn get_transaction_checkpoint( &self, digest: &TransactionDigest, @@ -222,6 +230,7 @@ pub trait ReadStore: ObjectStore { signatures: tx.tx_signatures().to_vec(), effects: fx.clone(), events, + execution_error_metadata: self.get_execution_error_metadata(tx.digest()), unchanged_loaded_runtime_objects: self .get_unchanged_loaded_runtime_objects(tx.digest()) //TODO Do we throw an error or just stub in an empty vector? @@ -360,6 +369,13 @@ impl ReadStore for &T { (*self).get_unchanged_loaded_runtime_objects(digest) } + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option { + (*self).get_execution_error_metadata(digest) + } + fn get_transaction_checkpoint( &self, digest: &TransactionDigest, @@ -478,6 +494,13 @@ impl ReadStore for Box { (**self).get_unchanged_loaded_runtime_objects(digest) } + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option { + (**self).get_execution_error_metadata(digest) + } + fn get_transaction_checkpoint( &self, digest: &TransactionDigest, @@ -596,6 +619,13 @@ impl ReadStore for Arc { (**self).get_unchanged_loaded_runtime_objects(digest) } + fn get_execution_error_metadata( + &self, + digest: &TransactionDigest, + ) -> Option { + (**self).get_execution_error_metadata(digest) + } + fn get_transaction_checkpoint( &self, digest: &TransactionDigest, diff --git a/crates/sui-types/src/test_checkpoint_data_builder.rs b/crates/sui-types/src/test_checkpoint_data_builder.rs index 7d192c570982..4729314b9709 100644 --- a/crates/sui-types/src/test_checkpoint_data_builder.rs +++ b/crates/sui-types/src/test_checkpoint_data_builder.rs @@ -648,6 +648,7 @@ impl TestCheckpointBuilder { signatures: sender_signed.tx_signatures, effects: tx.effects, events: tx.events, + execution_error_metadata: None, unchanged_loaded_runtime_objects: Vec::new(), } }) diff --git a/external-crates/move/Cargo.lock b/external-crates/move/Cargo.lock index 3f948397c4de..2f24361317bb 100644 --- a/external-crates/move/Cargo.lock +++ b/external-crates/move/Cargo.lock @@ -6287,3 +6287,15 @@ dependencies = [ "cc", "pkg-config", ] + +[[patch.unused]] +name = "sui-crypto" +version = "0.3.0" + +[[patch.unused]] +name = "sui-rpc" +version = "0.3.1" + +[[patch.unused]] +name = "sui-sdk-types" +version = "0.3.1" diff --git a/sui-execution/src/executor.rs b/sui-execution/src/executor.rs index bca9205bbd96..dc577424f7dc 100644 --- a/sui-execution/src/executor.rs +++ b/sui-execution/src/executor.rs @@ -13,7 +13,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext}, + error::{ExecutionError, ExecutionErrorMetadata}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -79,7 +79,8 @@ pub trait Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ); fn dev_inspect_transaction( diff --git a/sui-execution/src/latest.rs b/sui-execution/src/latest.rs index c8a6ff29221d..ab06cffed9b5 100644 --- a/sui-execution/src/latest.rs +++ b/sui-execution/src/latest.rs @@ -14,7 +14,10 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, ExecutionErrorTrait, SuiError, SuiResult}, + error::{ + ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, ExecutionErrorTrait, + SuiError, SuiResult, + }, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -134,7 +137,8 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ) { let (store_out, gas_status_out, effects, timings, result) = execute_transaction_to_effects::>( @@ -158,7 +162,18 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } - (store_out, gas_status_out, effects, timings, result) + let execution_error_metadata = result + .as_ref() + .err() + .and_then(ExecutionErrorContext::metadata_with_source); + ( + store_out, + gas_status_out, + effects, + timings, + result.map_err(ExecutionError::from), + execution_error_metadata, + ) } fn dev_inspect_transaction( diff --git a/sui-execution/src/v0.rs b/sui-execution/src/v0.rs index 4fa12c52150f..26bc69bb7529 100644 --- a/sui-execution/src/v0.rs +++ b/sui-execution/src/v0.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -205,7 +205,8 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ) { let gas_coins = gas.payment; let (inner_temp_store, gas_status, effects, result) = @@ -229,7 +230,18 @@ impl executor::Executor for Executor { log_execution_error(transaction_digest, error); } let result = result.map_err(ExecutionErrorContext::from); - (inner_temp_store, gas_status, effects, vec![], result) + let execution_error_metadata = result + .as_ref() + .err() + .and_then(ExecutionErrorContext::metadata_with_source); + ( + inner_temp_store, + gas_status, + effects, + vec![], + result.map_err(ExecutionError::from), + execution_error_metadata, + ) } fn update_genesis_state( diff --git a/sui-execution/src/v1.rs b/sui-execution/src/v1.rs index e7cb300856c1..477563a50aed 100644 --- a/sui-execution/src/v1.rs +++ b/sui-execution/src/v1.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -205,7 +205,8 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ) { let gas_coins = gas.payment; let (inner_temp_store, gas_status, effects, result) = @@ -229,7 +230,18 @@ impl executor::Executor for Executor { log_execution_error(transaction_digest, error); } let result = result.map_err(ExecutionErrorContext::from); - (inner_temp_store, gas_status, effects, vec![], result) + let execution_error_metadata = result + .as_ref() + .err() + .and_then(ExecutionErrorContext::metadata_with_source); + ( + inner_temp_store, + gas_status, + effects, + vec![], + result.map_err(ExecutionError::from), + execution_error_metadata, + ) } fn update_genesis_state( diff --git a/sui-execution/src/v2.rs b/sui-execution/src/v2.rs index a76f962e04fc..63e026daf988 100644 --- a/sui-execution/src/v2.rs +++ b/sui-execution/src/v2.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -205,7 +205,8 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ) { let gas_coins = gas.payment; let (inner_temp_store, gas_status, effects, result) = @@ -229,7 +230,18 @@ impl executor::Executor for Executor { log_execution_error(transaction_digest, error); } let result = result.map_err(ExecutionErrorContext::from); - (inner_temp_store, gas_status, effects, vec![], result) + let execution_error_metadata = result + .as_ref() + .err() + .and_then(ExecutionErrorContext::metadata_with_source); + ( + inner_temp_store, + gas_status, + effects, + vec![], + result.map_err(ExecutionError::from), + execution_error_metadata, + ) } fn update_genesis_state( diff --git a/sui-execution/src/v3.rs b/sui-execution/src/v3.rs index b850082a154a..3ae9d95cfce5 100644 --- a/sui-execution/src/v3.rs +++ b/sui-execution/src/v3.rs @@ -14,7 +14,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, gas::SuiGasStatus, inner_temporary_store::InnerTemporaryStore, @@ -139,7 +139,8 @@ impl executor::Executor for Executor { SuiGasStatus, TransactionEffects, Vec, - Result<(), ExecutionErrorContext>, + Result<(), ExecutionError>, + Option, ) { let (inner_temp_store, gas_status, effects, timings, result) = execute_transaction_to_effects::( @@ -163,7 +164,18 @@ impl executor::Executor for Executor { log_execution_error(protocol_config, transaction_digest, error); } let result = result.map_err(ExecutionErrorContext::from); - (inner_temp_store, gas_status, effects, timings, result) + let execution_error_metadata = result + .as_ref() + .err() + .and_then(ExecutionErrorContext::metadata_with_source); + ( + inner_temp_store, + gas_status, + effects, + timings, + result.map_err(ExecutionError::from), + execution_error_metadata, + ) } fn dev_inspect_transaction( From 05c92a5d556da0d33466738f2128fa42a0f27bb5 Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 10:20:17 -0700 Subject: [PATCH 09/15] move ExecutionErrorMetadata in rpc proto conversions --- crates/sui-types/src/rpc_proto_conversions.rs | 58 ++++++++++--------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/crates/sui-types/src/rpc_proto_conversions.rs b/crates/sui-types/src/rpc_proto_conversions.rs index bc4e7fa259b8..91d5959c4cd7 100644 --- a/crates/sui-types/src/rpc_proto_conversions.rs +++ b/crates/sui-types/src/rpc_proto_conversions.rs @@ -1181,36 +1181,11 @@ impl From for ExecutionStatus { } } + // // ExecutionError // -pub use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata; - -impl From for ExecutionErrorMetadata { - fn from(metadata: crate::error::ExecutionErrorMetadata) -> Self { - let mut message = Self::default(); - message.message = metadata.message; - message - } -} - -impl From<&crate::execution_status::ExecutionErrorMetadata> for ExecutionErrorMetadata { - fn from(metadata: &crate::error::ExecutionErrorMetadata) -> Self { - let mut message = Self::default(); - message.message = metadata.message.clone(); - message - } -} - -impl From<&ExecutionErrorMetadata> for crate::execution_status::ExecutionErrorMetadata { - fn from(metadata: &ExecutionErrorMetadata) -> Self { - Self { - message: metadata.message.clone(), - } - } -} - fn size_error(size: u64, max_size: u64) -> SizeError { let mut message = SizeError::default(); message.size = Some(size); @@ -1422,6 +1397,37 @@ impl From for ExecutionError { } } +// +// ExecutionErrorMetadata +// + +pub use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata; + +impl From for ExecutionErrorMetadata { + fn from(metadata: crate::error::ExecutionErrorMetadata) -> Self { + let mut message = Self::default(); + message.message = metadata.message; + message + } +} + +impl From<&crate::execution_status::ExecutionErrorMetadata> for ExecutionErrorMetadata { + fn from(metadata: &crate::error::ExecutionErrorMetadata) -> Self { + let mut message = Self::default(); + message.message = metadata.message.clone(); + message + } +} + +impl From<&ExecutionErrorMetadata> for crate::execution_status::ExecutionErrorMetadata { + fn from(metadata: &ExecutionErrorMetadata) -> Self { + Self { + message: metadata.message.clone(), + } + } +} + + // // CommandArgumentError // From 56d1e3d82e084d201bfbd919272c89527044a6af Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 10:27:23 -0700 Subject: [PATCH 10/15] revert to execution error source() --- crates/sui-core/src/authority.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/sui-core/src/authority.rs b/crates/sui-core/src/authority.rs index a05a3922296a..dd96263062df 100644 --- a/crates/sui-core/src/authority.rs +++ b/crates/sui-core/src/authority.rs @@ -2390,7 +2390,7 @@ impl AuthorityState { let execution_error_source = execution_result .as_ref() .err() - .and_then(|e| std::error::Error::source(e).map(|e| e.to_string())); + .and_then(|e| e.source().as_ref().map(|e| e.to_string())); let response = DryRunTransactionBlockResponse { suggested_gas_price, From 430602168ae0febcfe56051bf8ee10710cca4f60 Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 10:40:20 -0700 Subject: [PATCH 11/15] document bytes in authority store, remove less useful test --- .../src/authority/authority_store_tables.rs | 59 +------------------ 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/crates/sui-core/src/authority/authority_store_tables.rs b/crates/sui-core/src/authority/authority_store_tables.rs index afea862315bf..5324d1c65419 100644 --- a/crates/sui-core/src/authority/authority_store_tables.rs +++ b/crates/sui-core/src/authority/authority_store_tables.rs @@ -101,6 +101,7 @@ pub struct AuthorityPerpetualTables { pub(crate) unchanged_loaded_runtime_objects: DBMap>, // Local execution error metadata, keyed by the digest of the transaction that produced it. + // Values are encoded `sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata` bytes. pub(crate) execution_error_metadata: DBMap>, /// DEPRECATED in favor of the table of the same name in authority_per_epoch_store. @@ -945,61 +946,3 @@ fn effects_table_config(db_options: DBOptions) -> DBOptions { read_size_from_env(ENV_VAR_EFFECTS_BLOCK_CACHE_SIZE).unwrap_or(1024), ) } - -#[cfg(test)] -mod tests { - use prost::Message as _; - use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata as RpcExecutionErrorMetadata; - use sui_types::digests::TransactionDigest; - use sui_types::error::ExecutionErrorMetadata; - use typed_store::DBMapUtils; - use typed_store::rocks::{DBMap, MetricConf}; - use typed_store::traits::Map; - - #[derive(Clone, PartialEq, prost::Message)] - struct FutureExecutionErrorMetadata { - #[prost(string, optional, tag = "1")] - message: Option, - #[prost(string, optional, tag = "2")] - future_field: Option, - } - - #[tokio::test] - async fn execution_error_metadata_table_accepts_future_proto_schema() { - #[derive(DBMapUtils)] - struct ExecutionErrorMetadataTables { - execution_error_metadata: DBMap>, - } - - let tempdir = tempfile::tempdir().unwrap(); - let tables = ExecutionErrorMetadataTables::open_tables_read_write( - tempdir.path().to_owned(), - MetricConf::new("test_execution_error_metadata"), - None, - None, - ); - let digest = TransactionDigest::random(); - let future_metadata = FutureExecutionErrorMetadata { - message: Some("Object runtime cached objects limit reached".to_string()), - future_field: Some("new metadata added by a future schema".to_string()), - }; - - tables - .execution_error_metadata - .insert(&digest, &future_metadata.encode_to_vec()) - .unwrap(); - - let stored_metadata = tables - .execution_error_metadata - .get(&digest) - .unwrap() - .unwrap(); - let rpc_metadata = RpcExecutionErrorMetadata::decode(stored_metadata.as_slice()).unwrap(); - let metadata = ExecutionErrorMetadata::from(&rpc_metadata); - - assert_eq!( - metadata.message.as_deref(), - Some("Object runtime cached objects limit reached") - ); - } -} From 15ef267f64b965201aa41c9a2d58d451714b1c1e Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 10:42:49 -0700 Subject: [PATCH 12/15] move ExecutionErrorMetadata in rpc proto to the bottom of error section --- crates/sui-types/src/rpc_proto_conversions.rs | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/crates/sui-types/src/rpc_proto_conversions.rs b/crates/sui-types/src/rpc_proto_conversions.rs index 91d5959c4cd7..67ebe7b6a8d3 100644 --- a/crates/sui-types/src/rpc_proto_conversions.rs +++ b/crates/sui-types/src/rpc_proto_conversions.rs @@ -1397,37 +1397,6 @@ impl From for ExecutionError { } } -// -// ExecutionErrorMetadata -// - -pub use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata; - -impl From for ExecutionErrorMetadata { - fn from(metadata: crate::error::ExecutionErrorMetadata) -> Self { - let mut message = Self::default(); - message.message = metadata.message; - message - } -} - -impl From<&crate::execution_status::ExecutionErrorMetadata> for ExecutionErrorMetadata { - fn from(metadata: &crate::error::ExecutionErrorMetadata) -> Self { - let mut message = Self::default(); - message.message = metadata.message.clone(); - message - } -} - -impl From<&ExecutionErrorMetadata> for crate::execution_status::ExecutionErrorMetadata { - fn from(metadata: &ExecutionErrorMetadata) -> Self { - Self { - message: metadata.message.clone(), - } - } -} - - // // CommandArgumentError // @@ -1567,6 +1536,36 @@ impl From for MoveLocation { } } +// +// ExecutionErrorMetadata +// + +pub use sui_rpc::proto::sui::rpc::v2::ExecutionErrorMetadata; + +impl From for ExecutionErrorMetadata { + fn from(metadata: crate::error::ExecutionErrorMetadata) -> Self { + let mut message = Self::default(); + message.message = metadata.message; + message + } +} + +impl From<&crate::execution_status::ExecutionErrorMetadata> for ExecutionErrorMetadata { + fn from(metadata: &crate::error::ExecutionErrorMetadata) -> Self { + let mut message = Self::default(); + message.message = metadata.message.clone(); + message + } +} + +impl From<&ExecutionErrorMetadata> for crate::execution_status::ExecutionErrorMetadata { + fn from(metadata: &ExecutionErrorMetadata) -> Self { + Self { + message: metadata.message.clone(), + } + } +} + // // AuthorityQuorumSignInfo aka ValidatorAggregatedSignature // From 0ed0ba6fbacc3f770e25191dd4eac0f7ab76bd1e Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 10:52:20 -0700 Subject: [PATCH 13/15] drop context from older execution versions --- sui-execution/src/v0.rs | 11 +++-------- sui-execution/src/v1.rs | 11 +++-------- sui-execution/src/v2.rs | 11 +++-------- sui-execution/src/v3.rs | 11 +++-------- 4 files changed, 12 insertions(+), 32 deletions(-) diff --git a/sui-execution/src/v0.rs b/sui-execution/src/v0.rs index 26bc69bb7529..49200b132206 100644 --- a/sui-execution/src/v0.rs +++ b/sui-execution/src/v0.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -229,18 +229,13 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } - let result = result.map_err(ExecutionErrorContext::from); - let execution_error_metadata = result - .as_ref() - .err() - .and_then(ExecutionErrorContext::metadata_with_source); ( inner_temp_store, gas_status, effects, vec![], - result.map_err(ExecutionError::from), - execution_error_metadata, + result, + None, ) } diff --git a/sui-execution/src/v1.rs b/sui-execution/src/v1.rs index 477563a50aed..4746ae9eea5d 100644 --- a/sui-execution/src/v1.rs +++ b/sui-execution/src/v1.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -229,18 +229,13 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } - let result = result.map_err(ExecutionErrorContext::from); - let execution_error_metadata = result - .as_ref() - .err() - .and_then(ExecutionErrorContext::metadata_with_source); ( inner_temp_store, gas_status, effects, vec![], - result.map_err(ExecutionError::from), - execution_error_metadata, + result, + None, ) } diff --git a/sui-execution/src/v2.rs b/sui-execution/src/v2.rs index 63e026daf988..d580ce98dc7d 100644 --- a/sui-execution/src/v2.rs +++ b/sui-execution/src/v2.rs @@ -15,7 +15,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, execution_status::ExecutionFailure, gas::SuiGasStatus, @@ -229,18 +229,13 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(transaction_digest, error); } - let result = result.map_err(ExecutionErrorContext::from); - let execution_error_metadata = result - .as_ref() - .err() - .and_then(ExecutionErrorContext::metadata_with_source); ( inner_temp_store, gas_status, effects, vec![], - result.map_err(ExecutionError::from), - execution_error_metadata, + result, + None, ) } diff --git a/sui-execution/src/v3.rs b/sui-execution/src/v3.rs index 3ae9d95cfce5..9626822cb580 100644 --- a/sui-execution/src/v3.rs +++ b/sui-execution/src/v3.rs @@ -14,7 +14,7 @@ use sui_types::{ committee::EpochId, digests::TransactionDigest, effects::TransactionEffects, - error::{ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, SuiError, SuiResult}, + error::{ExecutionError, ExecutionErrorMetadata, SuiError, SuiResult}, execution::{ExecutionResult, TypeLayoutStore}, gas::SuiGasStatus, inner_temporary_store::InnerTemporaryStore, @@ -163,18 +163,13 @@ impl executor::Executor for Executor { if let Err(error) = &result { log_execution_error(protocol_config, transaction_digest, error); } - let result = result.map_err(ExecutionErrorContext::from); - let execution_error_metadata = result - .as_ref() - .err() - .and_then(ExecutionErrorContext::metadata_with_source); ( inner_temp_store, gas_status, effects, timings, - result.map_err(ExecutionError::from), - execution_error_metadata, + result, + None, ) } From ddcdc1c1bf34a7538f251fafa80a6f7533a4caf2 Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 11:12:10 -0700 Subject: [PATCH 14/15] move context to sui-execution --- crates/sui-types/src/error.rs | 131 +++-------------------------- sui-execution/src/error_context.rs | 120 ++++++++++++++++++++++++++ sui-execution/src/latest.rs | 3 +- sui-execution/src/lib.rs | 1 + 4 files changed, 133 insertions(+), 122 deletions(-) create mode 100644 sui-execution/src/error_context.rs diff --git a/crates/sui-types/src/error.rs b/crates/sui-types/src/error.rs index 1ea6c2ed97f0..d50bc8d93601 100644 --- a/crates/sui-types/src/error.rs +++ b/crates/sui-types/src/error.rs @@ -1165,7 +1165,7 @@ impl std::fmt::Debug for SuiError { } } -pub(crate) type BoxError = Box; +pub type BoxError = Box; /// Additional fullnode execution details captured for failed transactions. /// This metadata is stored as a non-consensus sidecar and can be different across fullnode versions. @@ -1278,6 +1278,15 @@ impl ExecutionError { &self.inner.source } + pub fn into_parts(self) -> (ExecutionErrorKind, Option, Option) { + let ExecutionErrorInner { + kind, + source, + command, + } = *self.inner; + (kind, source, command) + } + pub fn to_execution_status(&self) -> (ExecutionErrorKind, Option) { (self.kind().clone(), self.command()) } @@ -1311,126 +1320,6 @@ impl ExecutionErrorTrait for ExecutionError { } } -#[derive(Debug)] -pub struct ExecutionErrorContext { - kind: ExecutionErrorKind, - metadata: ExecutionErrorMetadata, - source: Option, - command: Option, -} - -impl ExecutionErrorContext { - pub fn kind(&self) -> &ExecutionErrorKind { - &self.kind - } - - pub fn command(&self) -> Option { - self.command - } - - pub fn metadata_with_source(&self) -> Option { - let mut metadata = self.metadata.clone(); - if let Some(source) = self.source.as_ref() { - metadata.message.get_or_insert_with(|| source.to_string()); - } - - (!metadata.is_empty()).then_some(metadata) - } - - pub fn to_execution_status(&self) -> (ExecutionErrorKind, Option) { - (self.kind().clone(), self.command()) - } -} - -impl ExecutionErrorTrait for ExecutionErrorContext { - fn new( - failure: ExecutionFailure, - source: Option, - metadata: ExecutionErrorMetadata, - ) -> Self { - let ExecutionFailure { error, command } = failure; - Self { - kind: error, - metadata, - source, - command, - } - } - - fn with_command_index(self, command: CommandIndex) -> Self { - Self { - command: Some(command), - ..self - } - } - - fn kind(&self) -> &ExecutionErrorKind { - self.kind() - } - - fn command(&self) -> Option { - self.command() - } -} - -impl std::fmt::Display for ExecutionErrorContext { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "ExecutionErrorContext: {:?}", self) - } -} - -impl std::error::Error for ExecutionErrorContext { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.source.as_deref().map(|e| e as _) - } -} - -impl From for ExecutionErrorContext { - fn from(kind: ExecutionErrorKind) -> Self { - ::from_kind(kind) - } -} - -impl From for ExecutionErrorContext { - fn from(value: ExecutionFailure) -> Self { - ::from_execution_failure(value) - } -} - -impl From for ExecutionErrorContext { - fn from(value: ExecutionError) -> Self { - let ExecutionError { inner } = value; - let ExecutionErrorInner { - kind, - source, - command, - } = *inner; - Self { - kind, - metadata: ExecutionErrorMetadata::default(), - source, - command, - } - } -} - -impl From for ExecutionError { - fn from(value: ExecutionErrorContext) -> Self { - let ExecutionErrorContext { - kind, - metadata: _, - source, - command, - } = value; - let err = ExecutionError::new(kind, source); - if let Some(command) = command { - err.with_command_index(command) - } else { - err - } - } -} - impl std::fmt::Display for ExecutionError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "ExecutionError: {:?}", self) diff --git a/sui-execution/src/error_context.rs b/sui-execution/src/error_context.rs new file mode 100644 index 000000000000..b31cceaa3d1a --- /dev/null +++ b/sui-execution/src/error_context.rs @@ -0,0 +1,120 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +use sui_types::error::{BoxError, ExecutionError, ExecutionErrorMetadata, ExecutionErrorTrait}; +use sui_types::execution_status::{CommandIndex, ExecutionErrorKind, ExecutionFailure}; + +#[derive(Debug)] +pub struct ExecutionErrorContext { + kind: ExecutionErrorKind, + metadata: ExecutionErrorMetadata, + source: Option, + command: Option, +} + +impl ExecutionErrorContext { + pub fn kind(&self) -> &ExecutionErrorKind { + &self.kind + } + + pub fn command(&self) -> Option { + self.command + } + + pub fn metadata_with_source(&self) -> Option { + let mut metadata = self.metadata.clone(); + if let Some(source) = self.source.as_ref() { + metadata.message.get_or_insert_with(|| source.to_string()); + } + + (!metadata.is_empty()).then_some(metadata) + } + + pub fn to_execution_status(&self) -> (ExecutionErrorKind, Option) { + (self.kind().clone(), self.command()) + } +} + +impl ExecutionErrorTrait for ExecutionErrorContext { + fn new( + failure: ExecutionFailure, + source: Option, + metadata: ExecutionErrorMetadata, + ) -> Self { + let ExecutionFailure { error, command } = failure; + Self { + kind: error, + metadata, + source, + command, + } + } + + fn with_command_index(self, command: CommandIndex) -> Self { + Self { + command: Some(command), + ..self + } + } + + fn kind(&self) -> &ExecutionErrorKind { + self.kind() + } + + fn command(&self) -> Option { + self.command() + } +} + +impl std::fmt::Display for ExecutionErrorContext { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "ExecutionErrorContext: {:?}", self) + } +} + +impl std::error::Error for ExecutionErrorContext { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.source.as_deref().map(|e| e as _) + } +} + +impl From for ExecutionErrorContext { + fn from(kind: ExecutionErrorKind) -> Self { + ::from_kind(kind) + } +} + +impl From for ExecutionErrorContext { + fn from(value: ExecutionFailure) -> Self { + ::from_execution_failure(value) + } +} + +impl From for ExecutionErrorContext { + fn from(value: ExecutionError) -> Self { + let (kind, source, command) = value.into_parts(); + Self { + kind, + metadata: ExecutionErrorMetadata::default(), + source, + command, + } + } +} + +impl From for ExecutionError { + fn from(value: ExecutionErrorContext) -> Self { + let ExecutionErrorContext { + kind, + metadata: _, + source, + command, + } = value; + let err = ExecutionError::new(kind, source); + if let Some(command) = command { + err.with_command_index(command) + } else { + err + } + } +} diff --git a/sui-execution/src/latest.rs b/sui-execution/src/latest.rs index ab06cffed9b5..adeefd82c337 100644 --- a/sui-execution/src/latest.rs +++ b/sui-execution/src/latest.rs @@ -15,7 +15,7 @@ use sui_types::{ digests::TransactionDigest, effects::TransactionEffects, error::{ - ExecutionError, ExecutionErrorContext, ExecutionErrorMetadata, ExecutionErrorTrait, + ExecutionError, ExecutionErrorMetadata, ExecutionErrorTrait, SuiError, SuiResult, }, execution::{ExecutionResult, TypeLayoutStore}, @@ -27,6 +27,7 @@ use sui_types::{ transaction::{CheckedInputObjects, ProgrammableTransaction, TransactionKind}, }; +use crate::error_context::ExecutionErrorContext; use move_bytecode_verifier_meter::Meter; use move_vm_runtime_latest::runtime::MoveRuntime; use mysten_common::debug_fatal; diff --git a/sui-execution/src/lib.rs b/sui-execution/src/lib.rs index bdd27320a930..63bcfefa52a7 100644 --- a/sui-execution/src/lib.rs +++ b/sui-execution/src/lib.rs @@ -22,6 +22,7 @@ mod v3; #[cfg(test)] mod tests; +mod error_context; pub fn executor( protocol_config: &ProtocolConfig, From d8d05909703ef461d3f65754f27c56639d7ee045 Mon Sep 17 00:00:00 2001 From: Jort Date: Thu, 28 May 2026 11:21:44 -0700 Subject: [PATCH 15/15] dont touch cargo.lock for now --- Cargo.lock | 249 +++++++++++++++++--------------- external-crates/move/Cargo.lock | 12 -- 2 files changed, 136 insertions(+), 125 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12fb87addbd0..f4314782c69a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -660,7 +660,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "alloy-sol-types", - "itertools 0.13.0", + "itertools 0.14.0", "serde", "serde_json", "serde_with", @@ -2753,7 +2753,7 @@ checksum = "230c5f1ca6a325a32553f8640d31ac9b49f2411e901e427570154868b46da4f7" [[package]] name = "bin-version" -version = "1.73.0" +version = "1.74.0" dependencies = [ "const-str", "git-version", @@ -3727,7 +3727,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-build", "tonic-prost", "tonic-rustls", @@ -6076,7 +6076,7 @@ dependencies = [ "time", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-build", "tonic-prost", "tonic-prost-build", @@ -8406,7 +8406,7 @@ dependencies = [ [[package]] name = "minibytes" version = "0.1.0" -source = "git+https://github.com/mystenlabs/tidehunter.git?rev=9a0472f81e71e821e1f4f71e308c2580f16f9e05#9a0472f81e71e821e1f4f71e308c2580f16f9e05" +source = "git+https://github.com/mystenlabs/tidehunter.git?rev=14b04e9d8130c20fdc03a629c02fe50f628cb789#14b04e9d8130c20fdc03a629c02fe50f628cb789" dependencies = [ "bytes", "memmap2 0.7.1", @@ -9431,7 +9431,7 @@ dependencies = [ [[package]] name = "msim" version = "0.1.0" -source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=53016c1a9038154b1e47b96f0a314efa7e7d809b#53016c1a9038154b1e47b96f0a314efa7e7d809b" +source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=2c2ec3ffbc1e559c575dc7de1ff2498d1f6700f6#2c2ec3ffbc1e559c575dc7de1ff2498d1f6700f6" dependencies = [ "ahash 0.7.8", "async-task", @@ -9460,7 +9460,7 @@ dependencies = [ [[package]] name = "msim-macros" version = "0.1.0" -source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=53016c1a9038154b1e47b96f0a314efa7e7d809b#53016c1a9038154b1e47b96f0a314efa7e7d809b" +source = "git+https://github.com/MystenLabs/mysten-sim.git?rev=2c2ec3ffbc1e559c575dc7de1ff2498d1f6700f6#2c2ec3ffbc1e559c575dc7de1ff2498d1f6700f6" dependencies = [ "darling 0.14.2", "proc-macro2", @@ -9541,10 +9541,12 @@ dependencies = [ "mysten-metrics", "once_cell", "parking_lot 0.12.3", + "prost-types 0.14.1", "rand 0.8.5", "serde_json", "sui-macros", "tempfile", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -9599,7 +9601,7 @@ dependencies = [ "sui-tls", "tokio", "tokio-rustls", - "tonic 0.14.5", + "tonic 0.14.6", "tower 0.5.3", "tower-http 0.5.2", "tracing", @@ -9852,7 +9854,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -11332,8 +11334,8 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1" dependencies = [ - "heck 0.4.1", - "itertools 0.10.5", + "heck 0.5.0", + "itertools 0.14.0", "log", "multimap", "once_cell", @@ -11355,7 +11357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -11368,7 +11370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9120690fafc389a67ba3803df527d0ec9cbbc9cc45e4cc20b332996dfb672425" dependencies = [ "anyhow", - "itertools 0.10.5", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.117", @@ -11566,7 +11568,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls", - "socket2 0.5.6", + "socket2 0.6.3", "thiserror 2.0.17", "tokio", "tracing", @@ -13805,7 +13807,7 @@ checksum = "734676eb262c623cec13c3155096e08d1f8f29adce39ba17948b18dad1e54142" [[package]] name = "sui" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anemo", "anyhow", @@ -14068,7 +14070,7 @@ dependencies = [ [[package]] name = "sui-analytics-indexer" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "arrow", @@ -14127,7 +14129,7 @@ dependencies = [ [[package]] name = "sui-analytics-indexer-derive" -version = "1.73.0" +version = "1.74.0" dependencies = [ "proc-macro2", "quote", @@ -14200,7 +14202,7 @@ dependencies = [ [[package]] name = "sui-bridge" -version = "1.73.0" +version = "1.74.0" dependencies = [ "alloy", "alloy-multiprovider-strategy", @@ -14250,7 +14252,7 @@ dependencies = [ "test-cluster", "thiserror 1.0.69", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tower 0.5.3", "tracing", "typed-store", @@ -14259,7 +14261,7 @@ dependencies = [ [[package]] name = "sui-bridge-cli" -version = "1.73.0" +version = "1.74.0" dependencies = [ "alloy", "anyhow", @@ -14355,7 +14357,7 @@ dependencies = [ [[package]] name = "sui-checkpoint-blob-indexer" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -14386,7 +14388,7 @@ dependencies = [ [[package]] name = "sui-cluster-test" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -14515,6 +14517,7 @@ dependencies = [ "reqwest", "roaring", "rstest", + "rustc-hash 2.1.1", "scopeguard", "serde", "serde_json", @@ -14530,6 +14533,7 @@ dependencies = [ "sui-execution", "sui-framework", "sui-genesis-builder", + "sui-inverted-index", "sui-json-rpc-types", "sui-macros", "sui-move", @@ -14583,6 +14587,7 @@ dependencies = [ [[package]] name = "sui-crypto" version = "0.3.0" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=5b41bc701525f1b94f1fe63008d4841bc6fb1065#5b41bc701525f1b94f1fe63008d4841bc6fb1065" dependencies = [ "ark-bn254", "ark-ff 0.4.2", @@ -14590,6 +14595,7 @@ dependencies = [ "ark-snark", "ark-std 0.4.0", "base64ct", + "blst", "bnum", "ed25519-dalek", "itertools 0.14.0", @@ -14656,7 +14662,7 @@ dependencies = [ [[package]] name = "sui-default-config" -version = "1.73.0" +version = "1.74.0" dependencies = [ "quote", "syn 1.0.107", @@ -14664,7 +14670,7 @@ dependencies = [ [[package]] name = "sui-display" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -14688,7 +14694,7 @@ dependencies = [ [[package]] name = "sui-e2e-tests" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -14706,6 +14712,7 @@ dependencies = [ "move-core-types", "mysten-common", "mysten-metrics", + "mysten-network", "p256", "passkey-authenticator", "passkey-client", @@ -14748,7 +14755,7 @@ dependencies = [ "test-cluster", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "url", ] @@ -14824,7 +14831,7 @@ dependencies = [ [[package]] name = "sui-faucet" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "axum 0.8.3", @@ -14836,6 +14843,7 @@ dependencies = [ "serde_json", "shared-crypto", "sui-config", + "sui-futures", "sui-keys", "sui-rpc-api", "sui-sdk", @@ -14850,14 +14858,14 @@ dependencies = [ [[package]] name = "sui-field-count" -version = "1.73.0" +version = "1.74.0" dependencies = [ "sui-field-count-derive", ] [[package]] name = "sui-field-count-derive" -version = "1.73.0" +version = "1.74.0" dependencies = [ "quote", "syn 1.0.107", @@ -14865,7 +14873,7 @@ dependencies = [ [[package]] name = "sui-fork" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -14892,7 +14900,7 @@ dependencies = [ "sui-types", "tempfile", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tracing", "tracing-subscriber", @@ -14924,7 +14932,7 @@ dependencies = [ [[package]] name = "sui-framework-snapshot" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bcs", @@ -14968,7 +14976,7 @@ dependencies = [ [[package]] name = "sui-futures" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "futures", @@ -15028,7 +15036,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -15061,12 +15069,12 @@ dependencies = [ [[package]] name = "sui-indexer-alt-consistent-api" -version = "1.73.0" +version = "1.74.0" dependencies = [ "prost 0.14.1", "prost-types 0.14.1", "protox", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tonic-prost-build", "walkdir", @@ -15074,7 +15082,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-consistent-store" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -15115,7 +15123,7 @@ dependencies = [ "tokio", "tokio-stream", "toml 0.7.4", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-health", "tonic-reflection", "tower 0.5.3", @@ -15187,7 +15195,7 @@ dependencies = [ "test-cluster", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "url", "zstd 0.12.3+zstd.1.5.2", @@ -15195,7 +15203,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-framework" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -15234,7 +15242,7 @@ dependencies = [ "thiserror 1.0.69", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "tracing-subscriber", "url", @@ -15244,7 +15252,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-framework-store-traits" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -15256,7 +15264,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-graphql" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-graphql", @@ -15314,7 +15322,7 @@ dependencies = [ "tokio", "tokio-stream", "toml 0.7.4", - "tonic 0.14.5", + "tonic 0.14.6", "tower-http 0.5.2", "tracing", "url", @@ -15323,7 +15331,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-jsonrpc" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-graphql", @@ -15374,7 +15382,7 @@ dependencies = [ "thiserror 1.0.69", "tokio", "toml 0.7.4", - "tonic 0.14.5", + "tonic 0.14.6", "tower 0.4.13", "tower-http 0.5.2", "tower-layer", @@ -15384,7 +15392,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-metrics" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "axum 0.8.3", @@ -15399,7 +15407,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-object-store" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -15413,7 +15421,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-reader" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-graphql", @@ -15441,7 +15449,7 @@ dependencies = [ "sui-types", "thiserror 1.0.69", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tower 0.5.3", "tracing", "url", @@ -15449,7 +15457,7 @@ dependencies = [ [[package]] name = "sui-indexer-alt-schema" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bcs", @@ -15465,16 +15473,16 @@ dependencies = [ [[package]] name = "sui-inverted-index" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-stream", "bcs", "futures", - "itertools 0.13.0", "move-core-types", "roaring", "sui-types", + "thiserror 1.0.69", "tokio", ] @@ -15677,7 +15685,7 @@ dependencies = [ [[package]] name = "sui-kv-rpc" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-stream", @@ -15698,7 +15706,10 @@ dependencies = [ "prost 0.14.1", "prost-types 0.14.1", "rustls", + "schemars 0.8.21", "serde", + "serde_json", + "serde_yaml 0.8.26", "sui-futures", "sui-inverted-index", "sui-kvstore", @@ -15710,8 +15721,9 @@ dependencies = [ "sui-storage", "sui-types", "telemetry-subscribers", + "thiserror 1.0.69", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tonic-reflection", "tracing", @@ -15719,7 +15731,7 @@ dependencies = [ [[package]] name = "sui-kvstore" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "arc-swap", @@ -15763,7 +15775,7 @@ dependencies = [ "tokio", "tokio-stream", "toml 0.7.4", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tracing", "url", @@ -15771,7 +15783,7 @@ dependencies = [ [[package]] name = "sui-light-client" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -15804,7 +15816,7 @@ dependencies = [ "thiserror 1.0.69", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "url", ] @@ -15821,7 +15833,7 @@ dependencies = [ [[package]] name = "sui-metric-checker" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "backoff", @@ -15858,7 +15870,7 @@ dependencies = [ [[package]] name = "sui-move" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bin-version", @@ -15905,7 +15917,7 @@ dependencies = [ [[package]] name = "sui-move-build" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "fastcrypto", @@ -15931,7 +15943,7 @@ dependencies = [ [[package]] name = "sui-move-lsp" -version = "1.73.0" +version = "1.74.0" dependencies = [ "bin-version", "clap", @@ -16046,7 +16058,7 @@ dependencies = [ [[package]] name = "sui-name-service" -version = "1.73.0" +version = "1.74.0" dependencies = [ "bcs", "move-core-types", @@ -16100,7 +16112,7 @@ dependencies = [ "tempfile", "tokio", "tokio-rustls", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-build", "tonic-health", "tonic-prost", @@ -16113,7 +16125,7 @@ dependencies = [ [[package]] name = "sui-node" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anemo", "anemo-tower", @@ -16168,7 +16180,7 @@ dependencies = [ [[package]] name = "sui-open-rpc" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bcs", @@ -16202,7 +16214,7 @@ dependencies = [ [[package]] name = "sui-oracle" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bcs", @@ -16232,7 +16244,7 @@ dependencies = [ [[package]] name = "sui-package-alt" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -16251,7 +16263,7 @@ dependencies = [ [[package]] name = "sui-package-dump" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bcs", @@ -16267,7 +16279,7 @@ dependencies = [ [[package]] name = "sui-package-management" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "sui-framework-snapshot", @@ -16300,7 +16312,7 @@ dependencies = [ [[package]] name = "sui-pg-db" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -16349,6 +16361,7 @@ dependencies = [ "move-core-types", "move-vm-config", "mysten-common", + "prost-types 0.14.1", "rand 0.8.5", "schemars 0.8.21", "serde", @@ -16496,7 +16509,7 @@ dependencies = [ [[package]] name = "sui-rosetta" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -16537,13 +16550,14 @@ dependencies = [ "test-cluster", "thiserror 1.0.69", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", ] [[package]] name = "sui-rpc" version = "0.3.1" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=5b41bc701525f1b94f1fe63008d4841bc6fb1065#5b41bc701525f1b94f1fe63008d4841bc6fb1065" dependencies = [ "base64 0.22.1", "bcs", @@ -16555,10 +16569,11 @@ dependencies = [ "prost-types 0.14.1", "serde", "serde_json", + "sui-crypto", "sui-sdk-types", "tap", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", "tower 0.5.3", ] @@ -16586,11 +16601,13 @@ dependencies = [ "prost-types 0.14.1", "protox", "rand 0.8.5", + "roaring", "serde", "serde_json", "sui-config", "sui-crypto", "sui-display", + "sui-inverted-index", "sui-macros", "sui-name-service", "sui-package-resolver", @@ -16602,7 +16619,8 @@ dependencies = [ "sui-types", "tap", "tokio", - "tonic 0.14.5", + "tokio-util 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tonic 0.14.6", "tonic-health", "tonic-prost", "tonic-prost-build", @@ -16615,7 +16633,7 @@ dependencies = [ [[package]] name = "sui-rpc-benchmark" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "bb8", @@ -16640,7 +16658,7 @@ dependencies = [ [[package]] name = "sui-rpc-loadgen" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -16661,13 +16679,13 @@ dependencies = [ "sui-types", "telemetry-subscribers", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", ] [[package]] name = "sui-rpc-resolver" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -16686,7 +16704,7 @@ dependencies = [ [[package]] name = "sui-sdk" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "async-trait", @@ -16730,6 +16748,7 @@ dependencies = [ [[package]] name = "sui-sdk-types" version = "0.3.1" +source = "git+https://github.com/MystenLabs/sui-rust-sdk.git?rev=5b41bc701525f1b94f1fe63008d4841bc6fb1065#5b41bc701525f1b94f1fe63008d4841bc6fb1065" dependencies = [ "base64ct", "bcs", @@ -16749,7 +16768,7 @@ dependencies = [ [[package]] name = "sui-security-watchdog" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "arrow-array", @@ -16797,7 +16816,7 @@ dependencies = [ [[package]] name = "sui-single-node-benchmark" -version = "1.73.0" +version = "1.74.0" dependencies = [ "bcs", "clap", @@ -16856,7 +16875,7 @@ dependencies = [ [[package]] name = "sui-source-validation" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "colored", @@ -16899,7 +16918,7 @@ dependencies = [ [[package]] name = "sui-sql-macro" -version = "1.73.0" +version = "1.74.0" dependencies = [ "quote", "syn 1.0.107", @@ -16965,7 +16984,7 @@ dependencies = [ [[package]] name = "sui-surfer" -version = "1.73.0" +version = "1.74.0" dependencies = [ "bcs", "clap", @@ -17087,7 +17106,7 @@ dependencies = [ [[package]] name = "sui-test-validator" -version = "1.73.0" +version = "1.74.0" [[package]] name = "sui-tls" @@ -17113,7 +17132,7 @@ dependencies = [ [[package]] name = "sui-tool" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anemo", "anemo-cli", @@ -17321,7 +17340,7 @@ dependencies = [ "tap", "thiserror 1.0.69", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", "typed-store-error", "url", @@ -17803,7 +17822,7 @@ dependencies = [ "sui-test-transaction-builder", "sui-types", "tokio", - "tonic 0.14.5", + "tonic 0.14.6", "tracing", ] @@ -17962,7 +17981,7 @@ dependencies = [ [[package]] name = "tideconsole" version = "0.1.0" -source = "git+https://github.com/mystenlabs/tidehunter.git?rev=9a0472f81e71e821e1f4f71e308c2580f16f9e05#9a0472f81e71e821e1f4f71e308c2580f16f9e05" +source = "git+https://github.com/mystenlabs/tidehunter.git?rev=14b04e9d8130c20fdc03a629c02fe50f628cb789#14b04e9d8130c20fdc03a629c02fe50f628cb789" dependencies = [ "anyhow", "clap", @@ -17976,7 +17995,7 @@ dependencies = [ [[package]] name = "tidehunter" version = "0.1.0" -source = "git+https://github.com/mystenlabs/tidehunter.git?rev=9a0472f81e71e821e1f4f71e308c2580f16f9e05#9a0472f81e71e821e1f4f71e308c2580f16f9e05" +source = "git+https://github.com/mystenlabs/tidehunter.git?rev=14b04e9d8130c20fdc03a629c02fe50f628cb789#14b04e9d8130c20fdc03a629c02fe50f628cb789" dependencies = [ "arc-swap", "bincode 1.3.3", @@ -17986,6 +18005,7 @@ dependencies = [ "crc32fast", "libc", "lru 0.12.5", + "lz4_flex", "memmap2 0.7.1", "minibytes", "parking_lot 0.12.3", @@ -18442,8 +18462,9 @@ dependencies = [ [[package]] name = "tonic" -version = "0.14.5" -source = "git+https://github.com/hyperium/tonic.git?rev=d6ce69b0d93e1de21b0769e942ace00b48f52e17#d6ce69b0d93e1de21b0769e942ace00b48f52e17" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" dependencies = [ "async-trait", "axum 0.8.3", @@ -18475,9 +18496,9 @@ dependencies = [ [[package]] name = "tonic-build" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40aaccc9f9eccf2cd82ebc111adc13030d23e887244bc9cfa5d1d636049de3" +checksum = "c68f61875ac5293cf72e6c8cf0158086428c82c37229e98c840878f1706b0322" dependencies = [ "prettyplease", "proc-macro2", @@ -18487,32 +18508,33 @@ dependencies = [ [[package]] name = "tonic-health" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a82868bf299e0a1d2e8dce0dc33a46c02d6f045b2c1f1d6cc8dc3d0bf1812ef" +checksum = "fcfab99db777fba2802f0dfa861d1628d1ae916fb199d29819941f139ae85082" dependencies = [ "prost 0.14.1", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", ] [[package]] name = "tonic-prost" -version = "0.14.5" -source = "git+https://github.com/hyperium/tonic.git?rev=d6ce69b0d93e1de21b0769e942ace00b48f52e17#d6ce69b0d93e1de21b0769e942ace00b48f52e17" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" dependencies = [ "bytes", "prost 0.14.1", - "tonic 0.14.5", + "tonic 0.14.6", ] [[package]] name = "tonic-prost-build" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a16cba4043dc3ff43fcb3f96b4c5c154c64cbd18ca8dce2ab2c6a451d058a2" +checksum = "654e5643eff75d7f8c99197ce1440ed19a3474eada74c12bbac488b2cafdae27" dependencies = [ "prettyplease", "proc-macro2", @@ -18526,14 +18548,15 @@ dependencies = [ [[package]] name = "tonic-reflection" -version = "0.14.5" -source = "git+https://github.com/hyperium/tonic.git?rev=d6ce69b0d93e1de21b0769e942ace00b48f52e17#d6ce69b0d93e1de21b0769e942ace00b48f52e17" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acccd136a4bf19810a1fde9c74edc6129b42a66b44d0c1c8aaa67aeb49a146a7" dependencies = [ "prost 0.14.1", "prost-types 0.14.1", "tokio", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tonic-prost", ] @@ -18557,7 +18580,7 @@ dependencies = [ "tokio", "tokio-rustls", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tower 0.5.3", "tower-layer", "tower-service", @@ -18566,9 +18589,9 @@ dependencies = [ [[package]] name = "tonic-web" -version = "0.14.2" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75214f6b6bd28c19aa752ac09fdf0eea546095670906c21fe3940e180a4c43f2" +checksum = "b5e6a1b6319ca4b61a4c0f0c94d439c8f3ed344cca56fe0df40e1fe4be11380b" dependencies = [ "base64 0.22.1", "bytes", @@ -18576,7 +18599,7 @@ dependencies = [ "http-body 1.0.1", "pin-project", "tokio-stream", - "tonic 0.14.5", + "tonic 0.14.6", "tower-layer", "tower-service", "tracing", @@ -18915,7 +18938,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ "cfg-if", - "rand 0.7.3", + "rand 0.8.5", "static_assertions", ] @@ -20302,7 +20325,7 @@ dependencies = [ [[package]] name = "x" -version = "1.73.0" +version = "1.74.0" dependencies = [ "anyhow", "camino", diff --git a/external-crates/move/Cargo.lock b/external-crates/move/Cargo.lock index 2f24361317bb..3f948397c4de 100644 --- a/external-crates/move/Cargo.lock +++ b/external-crates/move/Cargo.lock @@ -6287,15 +6287,3 @@ dependencies = [ "cc", "pkg-config", ] - -[[patch.unused]] -name = "sui-crypto" -version = "0.3.0" - -[[patch.unused]] -name = "sui-rpc" -version = "0.3.1" - -[[patch.unused]] -name = "sui-sdk-types" -version = "0.3.1"