diff --git a/crates/sui-adapter/src/adapter.rs b/crates/sui-adapter/src/adapter.rs index 79801cfb30752..8ef70fbb8a83b 100644 --- a/crates/sui-adapter/src/adapter.rs +++ b/crates/sui-adapter/src/adapter.rs @@ -639,9 +639,12 @@ fn process_successful_execution( } }, }; + let obj = state_view + .read_object(&id) + .expect("We previously checked all input objects exist").clone(); changes.insert( id, - ObjectChange::Delete(tx_ctx.clone(), version, delete_kind), + ObjectChange::Delete(tx_ctx.clone(), obj, version, delete_kind), ); } diff --git a/crates/sui-json-rpc-types/src/lib.rs b/crates/sui-json-rpc-types/src/lib.rs index 787fba8adbfbb..54b1fef769680 100644 --- a/crates/sui-json-rpc-types/src/lib.rs +++ b/crates/sui-json-rpc-types/src/lib.rs @@ -33,7 +33,7 @@ use tracing::warn; use fastcrypto::encoding::{Base64, Encoding}; use sui_json::SuiJsonValue; use sui_types::base_types::{ - AuthorityName, ObjectDigest, ObjectID, ObjectInfo, ObjectRef, SequenceNumber, SuiAddress, + AuthorityName, ObjectDigest, ObjectID, ObjectType, ObjectInfo, ObjectRef, ObjectRefAndType, SequenceNumber, SuiAddress, TransactionDigest, TransactionEffectsDigest, }; use sui_types::committee::EpochId; @@ -316,7 +316,7 @@ pub enum MoveFunctionArgType { Object(ObjectValueKind), } -#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Debug)] pub struct SuiTransactionResponse { pub certificate: SuiCertifiedTransaction, pub effects: SuiTransactionEffects, @@ -370,7 +370,7 @@ impl Display for SuiParsedTransactionResponse { } #[allow(clippy::large_enum_variant)] -#[derive(Serialize, Deserialize, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Debug)] pub enum SuiExecuteTransactionResponse { ImmediateReturn { tx_digest: TransactionDigest, @@ -587,6 +587,28 @@ impl From for SuiObjectRef { } } +#[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq, Ord, PartialOrd)] +#[serde(rename_all = "camelCase", rename = "ObjectRefAndType")] +pub struct SuiObjectRefAndType { + pub object_ref: ObjectRef, + pub object_type: ObjectType, +} + +// impl SuiObjectRefAndType { +// pub fn to_object_ref_and_type(&self) -> ObjectRefAndType{ +// (self.object_ref, self.object_type) +// } +// } + +impl From for SuiObjectRefAndType { + fn from(oref: ObjectRefAndType) -> Self { + Self { + object_ref: oref.0, + object_type: oref.1 + } + } +} + impl Display for SuiParsedObject { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let type_ = if self.data.type_().is_some() { @@ -1788,7 +1810,7 @@ impl TryFrom for SuiCertifiedTransaction { } /// The certified Transaction Effects which has signatures from >= 2/3 of validators -#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename = "CertifiedTransactionEffects", rename_all = "camelCase")] pub struct SuiCertifiedTransactionEffects { pub transaction_effects_digest: TransactionEffectsDigest, @@ -1831,7 +1853,7 @@ impl SuiCertifiedTransactionEffects { } /// The response from processing a transaction or a certified transaction -#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize, JsonSchema)] +#[derive(Eq, PartialEq, Clone, Debug, Serialize, Deserialize)] #[serde(rename = "TransactionEffects", rename_all = "camelCase")] pub struct SuiTransactionEffects { // The status of the execution @@ -1839,7 +1861,7 @@ pub struct SuiTransactionEffects { pub gas_used: SuiGasCostSummary, // The object references of the shared objects used in this transaction. Empty if no shared objects were used. #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub shared_objects: Vec, + pub shared_objects: Vec, // The transaction digest pub transaction_digest: TransactionDigest, // ObjectRef and owner of new objects created. @@ -1855,10 +1877,10 @@ pub struct SuiTransactionEffects { pub unwrapped: Vec, // Object Refs of objects now deleted (the old refs). #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub deleted: Vec, + pub deleted: Vec, // Object refs of objects now wrapped in other objects. #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub wrapped: Vec, + pub wrapped: Vec, // The updated gas object reference. Have a dedicated field for convenient access. // It's also included in mutated. pub gas_object: OwnedObjectRef, @@ -1931,13 +1953,13 @@ impl Display for SuiTransactionEffects { if !self.deleted.is_empty() { writeln!(writer, "Deleted Objects:")?; for oref in &self.deleted { - writeln!(writer, " - ID: {}", oref.object_id)?; + writeln!(writer, " - ID: {}", oref.object_ref.0)?; } } if !self.wrapped.is_empty() { writeln!(writer, "Wrapped Objects:")?; for oref in &self.wrapped { - writeln!(writer, " - ID: {}", oref.object_id)?; + writeln!(writer, " - ID: {}", oref.object_ref.0)?; } } if !self.unwrapped.is_empty() { @@ -1983,16 +2005,16 @@ impl From for SuiExecutionStatus { } } -fn to_sui_object_ref(refs: Vec) -> Vec { - refs.into_iter().map(SuiObjectRef::from).collect() +fn to_sui_object_ref(refs: Vec) -> Vec { + refs.into_iter().map(SuiObjectRefAndType::from).collect() } -fn to_owned_ref(owned_refs: Vec<(ObjectRef, Owner)>) -> Vec { +fn to_owned_ref(owned_refs: Vec<(ObjectRefAndType, Owner)>) -> Vec { owned_refs .into_iter() .map(|(oref, owner)| OwnedObjectRef { owner, - reference: oref.into(), + reference: oref.0.into(), }) .collect() } diff --git a/crates/sui-types/src/base_types.rs b/crates/sui-types/src/base_types.rs index 40fd302a2f31f..104b051234913 100644 --- a/crates/sui-types/src/base_types.rs +++ b/crates/sui-types/src/base_types.rs @@ -79,6 +79,7 @@ pub struct ObjectID( ); pub type ObjectRef = (ObjectID, SequenceNumber, ObjectDigest); +pub type ObjectRefAndType = (ObjectRef, ObjectType); pub fn random_object_ref() -> ObjectRef { ( diff --git a/crates/sui-types/src/coin.rs b/crates/sui-types/src/coin.rs index d462d52a737fa..033738b6cc5fd 100644 --- a/crates/sui-types/src/coin.rs +++ b/crates/sui-types/src/coin.rs @@ -192,6 +192,7 @@ pub fn update_input_coins( &coin_object.id(), coin_object.version(), DeleteKind::Normal, + coin_object.clone(), ) } } diff --git a/crates/sui-types/src/messages.rs b/crates/sui-types/src/messages.rs index 35dbbad972c2d..e1b313186acc1 100644 --- a/crates/sui-types/src/messages.rs +++ b/crates/sui-types/src/messages.rs @@ -1729,24 +1729,24 @@ pub struct TransactionEffects { /// this transaction. pub modified_at_versions: Vec<(ObjectID, SequenceNumber)>, /// The object references of the shared objects used in this transaction. Empty if no shared objects were used. - pub shared_objects: Vec, + pub shared_objects: Vec, /// The transaction digest pub transaction_digest: TransactionDigest, // TODO: All the SequenceNumbers in the ObjectRefs below equal the same value (the lamport // timestamp of the transaction). Consider factoring this out into one place in the effects. /// ObjectRef and owner of new objects created. - pub created: Vec<(ObjectRef, Owner)>, + pub created: Vec<(ObjectRefAndType, Owner)>, /// ObjectRef and owner of mutated objects, including gas object. - pub mutated: Vec<(ObjectRef, Owner)>, + pub mutated: Vec<(ObjectRefAndType, Owner)>, /// ObjectRef and owner of objects that are unwrapped in this transaction. /// Unwrapped objects are objects that were wrapped into other objects in the past, /// and just got extracted out. - pub unwrapped: Vec<(ObjectRef, Owner)>, + pub unwrapped: Vec<(ObjectRefAndType, Owner)>, /// Object Refs of objects now deleted (the old refs). - pub deleted: Vec, + pub deleted: Vec, /// Object refs of objects now wrapped in other objects. - pub wrapped: Vec, + pub wrapped: Vec, /// The updated gas object reference. Have a dedicated field for convenient access. /// It's also included in mutated. pub gas_object: (ObjectRef, Owner), @@ -1761,7 +1761,7 @@ impl TransactionEffects { /// created and unwrapped objects. In other words, all objects that still exist /// in the object state after this transaction. /// It doesn't include deleted/wrapped objects. - pub fn all_mutated(&self) -> impl Iterator + Clone { + pub fn all_mutated(&self) -> impl Iterator + Clone { self.mutated .iter() .map(|(r, o)| (r, o, WriteKind::Mutate)) @@ -1781,8 +1781,8 @@ impl TransactionEffects { } /// Return an iterator of mutated objects, but excluding the gas object. - pub fn mutated_excluding_gas(&self) -> impl Iterator { - self.mutated.iter().filter(|o| *o != &self.gas_object) + pub fn mutated_excluding_gas(&self) -> impl Iterator { + self.mutated.iter() } pub fn gas_cost_summary(&self) -> &GasCostSummary { @@ -1832,31 +1832,31 @@ impl Display for TransactionEffects { writeln!(writer, "Status : {:?}", self.status)?; if !self.created.is_empty() { writeln!(writer, "Created Objects:")?; - for ((id, _, _), owner) in &self.created { + for (((id, _, _), _), owner) in &self.created { writeln!(writer, " - ID: {} , Owner: {}", id, owner)?; } } if !self.mutated.is_empty() { writeln!(writer, "Mutated Objects:")?; - for ((id, _, _), owner) in &self.mutated { + for (((id, _, _), _), owner) in &self.mutated { writeln!(writer, " - ID: {} , Owner: {}", id, owner)?; } } if !self.deleted.is_empty() { writeln!(writer, "Deleted Objects:")?; - for (id, _, _) in &self.deleted { + for ((id, _, _),_) in &self.deleted { writeln!(writer, " - ID: {}", id)?; } } if !self.wrapped.is_empty() { writeln!(writer, "Wrapped Objects:")?; - for (id, _, _) in &self.wrapped { + for ((id, _, _),_) in &self.wrapped { writeln!(writer, " - ID: {}", id)?; } } if !self.unwrapped.is_empty() { writeln!(writer, "Unwrapped Objects:")?; - for ((id, _, _), owner) in &self.unwrapped { + for (((id, _, _),_), owner) in &self.unwrapped { writeln!(writer, " - ID: {} , Owner: {}", id, owner)?; } } diff --git a/crates/sui-types/src/object.rs b/crates/sui-types/src/object.rs index c0e3af49ae8a2..32273cd92d3c9 100644 --- a/crates/sui-types/src/object.rs +++ b/crates/sui-types/src/object.rs @@ -23,7 +23,7 @@ use crate::messages::InputObjectKind; use crate::move_package::MovePackage; use crate::{ base_types::{ - ObjectDigest, ObjectID, ObjectRef, SequenceNumber, SuiAddress, TransactionDigest, + ObjectDigest, ObjectID, ObjectRef, ObjectType, SequenceNumber, SuiAddress, TransactionDigest, }, gas_coin::GasCoin, }; @@ -449,6 +449,15 @@ impl Object { (self.id(), self.version(), self.digest()) } + pub fn compute_object_type(&self) -> ObjectType{ + let type_ = self + .data + .type_() + .map(|tag| ObjectType::Struct(tag.clone())) + .unwrap_or(ObjectType::Package); + type_ + } + pub fn id(&self) -> ObjectID { use Data::*; diff --git a/crates/sui-types/src/storage.rs b/crates/sui-types/src/storage.rs index 23f9be294c787..1dd876382a934 100644 --- a/crates/sui-types/src/storage.rs +++ b/crates/sui-types/src/storage.rs @@ -46,7 +46,7 @@ pub enum DeleteKind { pub enum ObjectChange { Write(SingleTxContext, Object, WriteKind), - Delete(SingleTxContext, SequenceNumber, DeleteKind), + Delete(SingleTxContext, Object, SequenceNumber, DeleteKind), } #[derive(Clone)] diff --git a/crates/sui-types/src/temporary_store.rs b/crates/sui-types/src/temporary_store.rs index 410824c58eb66..293a31e449da8 100644 --- a/crates/sui-types/src/temporary_store.rs +++ b/crates/sui-types/src/temporary_store.rs @@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use tracing::trace; +use crate::base_types::ObjectRefAndType; use crate::coin::Coin; use crate::event::BalanceChangeType; use crate::storage::SingleTxContext; @@ -41,7 +42,7 @@ pub struct InnerTemporaryStore { pub objects: BTreeMap, pub mutable_inputs: Vec, pub written: BTreeMap, - pub deleted: BTreeMap, + pub deleted: BTreeMap, } impl InnerTemporaryStore { @@ -98,7 +99,7 @@ pub struct TemporaryStore { // into written directly. written: BTreeMap, // Objects written /// Objects actively deleted. - deleted: BTreeMap, + deleted: BTreeMap, /// Ordered sequence of events emitted by execution events: Vec, gas_charged: Option<(SuiAddress, ObjectID, GasCostSummary)>, @@ -193,7 +194,7 @@ impl TemporaryStore { written.insert(id, (obj.compute_object_reference(), obj, kind)); } - for (id, (ctx, mut version, kind)) in self.deleted { + for (id, (ctx, mut version, kind, obj)) in self.deleted { // Update the version, post-delete. version.increment_to(self.lamport_timestamp); @@ -227,7 +228,7 @@ impl TemporaryStore { }, }; events.push(event); - deleted.insert(id, (version, kind)); + deleted.insert(id, (version, kind, obj)); } // Combine object events with move events. @@ -491,7 +492,7 @@ impl TemporaryStore { pub fn to_effects( mut self, - shared_object_refs: Vec, + shared_object_refs: Vec, transaction_digest: &TransactionDigest, transaction_dependencies: Vec, gas_cost_summary: GasCostSummary, @@ -507,7 +508,7 @@ impl TemporaryStore { } }); - self.deleted.iter_mut().for_each(|(id, (_, version, _))| { + self.deleted.iter_mut().for_each(|(id, (_, version, _, _))| { modified_at_versions.push((*id, *version)); }); @@ -527,21 +528,21 @@ impl TemporaryStore { let mut unwrapped = vec![]; for (object_ref, object, kind) in inner.written.values() { match kind { - WriteKind::Mutate => mutated.push((*object_ref, object.owner)), - WriteKind::Create => created.push((*object_ref, object.owner)), - WriteKind::Unwrap => unwrapped.push((*object_ref, object.owner)), + WriteKind::Mutate => mutated.push(((*object_ref, object.compute_object_type()), object.owner)), + WriteKind::Create => created.push(((*object_ref, object.compute_object_type()), object.owner)), + WriteKind::Unwrap => unwrapped.push(((*object_ref, object.compute_object_type()), object.owner)), } } let mut deleted = vec![]; let mut wrapped = vec![]; - for (id, (version, kind)) in &inner.deleted { + for (id, (version, kind, obj)) in &inner.deleted { match kind { DeleteKind::Normal | DeleteKind::UnwrapThenDelete => { - deleted.push((*id, *version, ObjectDigest::OBJECT_DIGEST_DELETED)) + deleted.push(((*id, *version, ObjectDigest::OBJECT_DIGEST_DELETED), obj.compute_object_type())) } DeleteKind::Wrap => { - wrapped.push((*id, *version, ObjectDigest::OBJECT_DIGEST_WRAPPED)) + wrapped.push(((*id, *version, ObjectDigest::OBJECT_DIGEST_WRAPPED), obj.compute_object_type())) } } } @@ -693,6 +694,7 @@ impl TemporaryStore { id: &ObjectID, version: SequenceNumber, kind: DeleteKind, + object: Object ) { // there should be no deletion after write debug_assert!(self.written.get(id).is_none()); @@ -708,7 +710,7 @@ impl TemporaryStore { // For object deletion, we will increment the version when converting the store to effects // so the object will eventually show up in the parent_sync table with a new version. - self.deleted.insert(*id, (ctx.clone(), version, kind)); + self.deleted.insert(*id, (ctx.clone(), version, kind, object)); } /// Resets any mutations and deletions recorded in the store. @@ -733,12 +735,13 @@ impl TemporaryStore { pub fn apply_object_changes(&mut self, changes: BTreeMap) { for (id, change) in changes { + let _obj = self.read_object(&id); match change { ObjectChange::Write(ctx, new_value, kind) => { self.write_object(&ctx, new_value, kind) } - ObjectChange::Delete(ctx, version, kind) => { - self.delete_object(&ctx, &id, version, kind) + ObjectChange::Delete(ctx, obj, version, kind) => { + self.delete_object(&ctx, &id, version, kind, obj) } } }