Skip to content

Commit

Permalink
Extract object loading from transaction input checking (#14579)
Browse files Browse the repository at this point in the history
This PR
- Is primarily intended to support the creation of an in-memory object
  cache (coming soon).
- Makes it easier to use multi-gets for transaction loads.
- Simplifies handling of deleted shared objects and receivables.
- Will prevent inadvertently loading the same object multiple times.
- Will reduce the proliferation of special purpose traits (e.g.
  MarkerTableQuery which is removed in this PR).

## Description 

Describe the changes or additions included in this PR.

## Test Plan 

How did you test the new or updated feature?

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [ ] protocol change
- [ ] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes

---------

Co-authored-by: Xun Li <lxfind@gmail.com>
  • Loading branch information
mystenmark and lxfind authored Nov 8, 2023
1 parent 28c2c33 commit 7201e68
Show file tree
Hide file tree
Showing 37 changed files with 1,305 additions and 687 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions crates/simulacrum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ publish = false
edition = "2021"

[dependencies]
async-trait.workspace = true
anyhow.workspace = true
bcs.workspace = true
fastcrypto.workspace = true
Expand All @@ -17,6 +18,7 @@ rand.workspace = true
serde.workspace = true
tracing.workspace = true
prometheus.workspace = true
futures.workspace = true

move-bytecode-utils.workspace = true
narwhal-config.workspace = true
Expand Down
33 changes: 25 additions & 8 deletions crates/simulacrum/src/epoch_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use sui_types::{
epoch_start_sui_system_state::{EpochStartSystemState, EpochStartSystemStateTrait},
SuiSystemState, SuiSystemStateTrait,
},
transaction::VerifiedTransaction,
transaction::{TransactionDataAPI, VerifiedTransaction},
};

use crate::store::InMemoryStore;
Expand Down Expand Up @@ -92,20 +92,37 @@ impl EpochState {
TransactionEffects,
Result<(), sui_types::error::ExecutionError>,
)> {
let tx_digest = *transaction.digest();
let tx_data = &transaction.data().intent_message().value;
let input_object_kinds = tx_data.input_objects()?;
let receiving_object_refs = tx_data.receiving_objects();

sui_transaction_checks::deny::check_transaction_for_signing(
tx_data,
transaction.tx_signatures(),
&input_object_kinds,
&receiving_object_refs,
deny_config,
store,
)?;

let (input_objects, receiving_objects) = store.read_objects_for_synchronous_execution(
&tx_digest,
&input_object_kinds,
&receiving_object_refs,
)?;

// Run the transaction input checks that would run when submitting the txn to a validator
// for signing
let (gas_status, input_objects) = sui_transaction_checks::check_transaction_input(
store,
let (gas_status, checked_input_objects) = sui_transaction_checks::check_transaction_input(
&self.protocol_config,
self.epoch_start_state.reference_gas_price(),
self.epoch(),
transaction.data().transaction_data(),
transaction.tx_signatures(),
deny_config,
input_objects,
receiving_objects,
&self.bytecode_verifier_metrics,
)?;

let tx_digest = *transaction.digest();
let transaction_data = transaction.data().transaction_data();
let (kind, signer, gas) = transaction_data.execution_parts();
Ok(self.executor.execute_transaction_to_effects(
Expand All @@ -116,7 +133,7 @@ impl EpochState {
&HashSet::new(), // certificate_deny_set
&self.epoch_start_state.epoch(),
self.epoch_start_state.epoch_start_timestamp_ms(),
input_objects,
checked_input_objects,
gas,
gas_status,
kind,
Expand Down
89 changes: 50 additions & 39 deletions crates/simulacrum/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@ use std::collections::{BTreeMap, HashMap};
use sui_config::genesis;
use sui_types::storage::{get_module, load_package_object_from_object_store, PackageObjectArc};
use sui_types::{
base_types::{AuthorityName, ObjectID, SequenceNumber, SuiAddress},
base_types::{AuthorityName, ObjectID, ObjectRef, SequenceNumber, SuiAddress},
committee::{Committee, EpochId},
crypto::{AccountKeyPair, AuthorityKeyPair},
digests::{ObjectDigest, TransactionDigest, TransactionEventsDigest},
effects::{TransactionEffects, TransactionEffectsAPI, TransactionEvents},
error::SuiError,
error::{SuiError, SuiResult, UserInputError},
messages_checkpoint::{
CheckpointContents, CheckpointContentsDigest, CheckpointDigest, CheckpointSequenceNumber,
VerifiedCheckpoint,
},
object::{Object, Owner},
storage::{
BackingPackageStore, ChildObjectResolver, MarkerTableQuery, ObjectStore, ParentSync,
storage::{BackingPackageStore, ChildObjectResolver, ObjectStore, ParentSync},
transaction::{
InputObjectKind, InputObjects, ObjectReadResult, ReceivingObjectReadResult,
ReceivingObjects, VerifiedTransaction,
},
transaction::VerifiedTransaction,
};

#[derive(Debug, Default)]
Expand Down Expand Up @@ -300,37 +301,6 @@ impl ChildObjectResolver for InMemoryStore {
}
}

impl MarkerTableQuery for InMemoryStore {
fn have_received_object_at_version(
&self,
_object_id: &ObjectID,
_version: sui_types::base_types::VersionNumber,
_epoch_id: EpochId,
) -> Result<bool, SuiError> {
// In simulation, we always have the object don't have a marker table, and we don't need to
// worry about equivocation protection. So we simply return false if ever asked if we
// received this object.
Ok(false)
}

fn get_deleted_shared_object_previous_tx_digest(
&self,
_object_id: &ObjectID,
_version: &SequenceNumber,
_epoch_id: EpochId,
) -> Result<Option<TransactionDigest>, SuiError> {
Ok(None)
}

fn is_shared_object_deleted(
&self,
_object_id: &ObjectID,
_epoch_id: EpochId,
) -> Result<bool, SuiError> {
Ok(false)
}
}

impl GetModule for InMemoryStore {
type Error = SuiError;
type Item = CompiledModule;
Expand Down Expand Up @@ -420,10 +390,51 @@ impl KeyStore {
}
}

// TODO: After we abstract object storage into the ExecutionCache trait, we can replace this with
// sui_core::TransactionInputLoad using an appropriate cache implementation.
impl InMemoryStore {
pub fn read_objects_for_synchronous_execution(
&self,
_tx_digest: &TransactionDigest,
input_object_kinds: &[InputObjectKind],
receiving_object_refs: &[ObjectRef],
) -> SuiResult<(InputObjects, ReceivingObjects)> {
let mut input_objects = Vec::new();
for kind in input_object_kinds {
let obj = match kind {
InputObjectKind::MovePackage(id) => self.get_object(id).cloned(),
InputObjectKind::ImmOrOwnedMoveObject(objref) => {
self.get_object_by_key(&objref.0, objref.1)?
}

InputObjectKind::SharedMoveObject { id, .. } => self.get_object(id).cloned(),
};

input_objects.push(ObjectReadResult::new(
*kind,
obj.ok_or_else(|| kind.object_not_found_error())?.into(),
));
}

let mut receiving_objects = Vec::new();
for objref in receiving_object_refs {
// no need for marker table check in simulacrum
let Some(obj) = self.get_object(&objref.0).cloned() else {
return Err(UserInputError::ObjectNotFound {
object_id: objref.0,
version: Some(objref.1),
}
.into());
};
receiving_objects.push(ReceivingObjectReadResult::new(*objref, obj.into()));
}

Ok((input_objects.into(), receiving_objects.into()))
}
}

pub trait SimulatorStore:
sui_types::storage::BackingPackageStore
+ sui_types::storage::ObjectStore
+ sui_types::storage::MarkerTableQuery
sui_types::storage::BackingPackageStore + sui_types::storage::ObjectStore
{
fn get_checkpoint_by_sequence_number(
&self,
Expand Down
Loading

2 comments on commit 7201e68

@vercel
Copy link

@vercel vercel bot commented on 7201e68 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 7201e68 Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.