Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions Cargo.lock

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

40 changes: 20 additions & 20 deletions crates/simulacrum/src/epoch_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,26 +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,
);
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))
}
}
125 changes: 88 additions & 37 deletions crates/sui-core/src/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, ExecutionErrorMetadata, SuiErrorKind, UserInputError};
use sui_types::event::EventID;
use sui_types::executable_transaction::VerifiedExecutableTransaction;
use sui_types::execution_status::ExecutionErrorKind;
Expand Down Expand Up @@ -1905,16 +1905,27 @@ impl AuthorityState {
rewritten_inputs: Option<Vec<bool>>,
signer: SuiAddress,
tx_digest: TransactionDigest,
is_fullnode: bool,
) -> (
InnerTemporaryStore,
SuiGasStatus,
TransactionEffects,
Vec<ExecutionTiming>,
Result<(), ExecutionError>,
Option<ExecutionErrorMetadata>,
) {
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.
Comment thread
jordanjennings-mysten marked this conversation as resolved.
.execute_transaction_to_effects_and_execution_error(
// 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 {
Comment thread
jordanjennings-mysten marked this conversation as resolved.
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(),
Expand All @@ -1932,13 +1943,43 @@ impl AuthorityState {
&mut None,
);

(
inner_temp_store,
gas_status,
effects,
timings,
execution_error,
)
(
inner_temp_store,
gas_status,
effects,
timings,
execution_error,
execution_error_metadata,
)
} 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_failure.map_err(ExecutionError::from),
None,
)
}
}

/// execute_certificate validates the transaction input, and executes the certificate,
Expand Down Expand Up @@ -2025,30 +2066,39 @@ 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
.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,
);
let (
inner_temp_store,
_,
mut effects,
timings,
execution_error_opt,
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_opt.err();

let object_funds_checker = self.object_funds_checker.load();
if let Some(object_funds_checker) = object_funds_checker.as_ref()
Expand Down Expand Up @@ -2174,6 +2224,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;
Expand All @@ -2187,7 +2238,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(
Expand Down Expand Up @@ -2339,7 +2390,7 @@ 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()));
Comment thread
jordanjennings-mysten marked this conversation as resolved.
Outdated

let response = DryRunTransactionBlockResponse {
suggested_gas_price,
Expand Down
34 changes: 33 additions & 1 deletion crates/sui-core/src/authority/authority_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ 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_types::error::{SuiErrorKind, UserInputError};
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;
use sui_types::message_envelope::Message;
Expand Down Expand Up @@ -344,6 +346,25 @@ impl AuthorityStore {
.get(digest)
}

pub fn get_execution_error_metadata(
Comment thread
jordanjennings-mysten marked this conversation as resolved.
&self,
digest: &TransactionDigest,
) -> Result<Option<ExecutionErrorMetadata>, TypedStoreError> {
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>(
&self,
effects_digests: impl Iterator<Item = &'a TransactionEffectsDigest>,
Expand Down Expand Up @@ -791,6 +812,7 @@ impl AuthorityStore {
written,
events,
unchanged_loaded_runtime_objects,
execution_error_metadata,
locks_to_delete,
new_locks_to_init,
..
Expand Down Expand Up @@ -863,6 +885,16 @@ impl AuthorityStore {
)?;
}

if let Some(metadata) = execution_error_metadata
&& !metadata.is_empty()
{
let metadata: RpcExecutionErrorMetadata = metadata.into();
write_batch.insert_batch(
&self.perpetual_tables.execution_error_metadata,
[(transaction_digest, metadata.encode_to_vec())],
)?;
}

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
Expand Down
2 changes: 2 additions & 0 deletions crates/sui-core/src/authority/authority_store_pruner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading
Loading