From 3d8da4884f7f731c49dff7581ad4b2e38fa3f8b7 Mon Sep 17 00:00:00 2001 From: Xun Li Date: Mon, 12 Aug 2024 14:06:22 -0700 Subject: [PATCH] [cherrypick] Fix fullnode event resolution (#18961) ## Description Picks https://github.com/MystenLabs/sui/pull/18958 ## Test plan How did you test the new or updated feature? --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [ ] Indexer: - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: - [ ] REST API: --- .../src/transaction_execution_api.rs | 26 ++++++---- crates/sui-types/src/storage/mod.rs | 51 +++++++++++++++++-- 2 files changed, 62 insertions(+), 15 deletions(-) diff --git a/crates/sui-json-rpc/src/transaction_execution_api.rs b/crates/sui-json-rpc/src/transaction_execution_api.rs index 749cb3ebee8a4b..d38a70be4c5536 100644 --- a/crates/sui-json-rpc/src/transaction_execution_api.rs +++ b/crates/sui-json-rpc/src/transaction_execution_api.rs @@ -10,6 +10,12 @@ use fastcrypto::traits::ToFromBytes; use jsonrpsee::core::RpcResult; use jsonrpsee::RpcModule; +use crate::authority_state::StateRead; +use crate::error::{Error, SuiRpcInputError}; +use crate::{ + get_balance_changes_from_effect, get_object_changes, with_tracing, ObjectProviderCache, + SuiRpcModule, +}; use mysten_metrics::spawn_monitored_task; use shared_crypto::intent::{AppId, Intent, IntentMessage, IntentScope, IntentVersion}; use sui_core::authority::AuthorityState; @@ -29,19 +35,13 @@ use sui_types::quorum_driver_types::{ ExecuteTransactionRequestType, ExecuteTransactionRequestV3, ExecuteTransactionResponseV3, }; use sui_types::signature::GenericSignature; +use sui_types::storage::PostExecutionPackageResolver; use sui_types::sui_serde::BigInt; use sui_types::transaction::{ InputObjectKind, Transaction, TransactionData, TransactionDataAPI, TransactionKind, }; use tracing::instrument; -use crate::authority_state::StateRead; -use crate::error::{Error, SuiRpcInputError}; -use crate::{ - get_balance_changes_from_effect, get_object_changes, with_tracing, ObjectProviderCache, - SuiRpcModule, -}; - pub struct TransactionExecutionApi { state: Arc, transaction_orchestrator: Arc>, @@ -117,7 +117,10 @@ impl TransactionExecutionApi { transaction: txn.clone(), include_events: opts.show_events, include_input_objects: opts.show_balance_changes || opts.show_object_changes, - include_output_objects: opts.show_balance_changes || opts.show_object_changes, + include_output_objects: opts.show_balance_changes + || opts.show_object_changes + // In order to resolve events, we may need access to the newly published packages. + || opts.show_events, include_auxiliary_data: false, }; @@ -182,10 +185,13 @@ impl TransactionExecutionApi { let events = if opts.show_events { let epoch_store = self.state.load_epoch_store_one_call_per_task(); - let backing_package_store = self.state.get_backing_package_store(); + let backing_package_store = PostExecutionPackageResolver::new( + self.state.get_backing_package_store().clone(), + &response.output_objects, + ); let mut layout_resolver = epoch_store .executor() - .type_layout_resolver(Box::new(backing_package_store.as_ref())); + .type_layout_resolver(Box::new(backing_package_store)); Some(SuiTransactionBlockEvents::try_from( response.events.unwrap_or_default(), digest, diff --git a/crates/sui-types/src/storage/mod.rs b/crates/sui-types/src/storage/mod.rs index c9de3fd31080ab..93cb31330eb24f 100644 --- a/crates/sui-types/src/storage/mod.rs +++ b/crates/sui-types/src/storage/mod.rs @@ -22,6 +22,10 @@ use itertools::Itertools; use move_binary_format::CompiledModule; use move_core_types::language_storage::ModuleId; pub use object_store_trait::ObjectStore; +pub use read_store::AccountOwnedObjectInfo; +pub use read_store::CoinInfo; +pub use read_store::DynamicFieldIndexInfo; +pub use read_store::DynamicFieldKey; pub use read_store::ReadStore; pub use read_store::RestStateReader; use serde::{Deserialize, Serialize}; @@ -33,11 +37,6 @@ use std::fmt::{Display, Formatter}; use std::sync::Arc; pub use write_store::WriteStore; -pub use read_store::AccountOwnedObjectInfo; -pub use read_store::CoinInfo; -pub use read_store::DynamicFieldIndexInfo; -pub use read_store::DynamicFieldKey; - /// A potential input to a transaction. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum InputKey { @@ -340,6 +339,48 @@ pub fn get_module_by_id( .map(|bytes| CompiledModule::deserialize_with_defaults(&bytes).unwrap())) } +/// A `BackingPackageStore` that resolves packages from a backing store, but also includes any +/// packages that were published in the current transaction execution. This can be used to resolve +/// Move modules right after transaction execution, but newly published packages have not yet been +/// committed to the backing store on a fullnode. +pub struct PostExecutionPackageResolver { + backing_store: Arc, + new_packages: BTreeMap, +} + +impl PostExecutionPackageResolver { + pub fn new( + backing_store: Arc, + output_objects: &Option>, + ) -> Self { + let new_packages = output_objects + .iter() + .flatten() + .filter_map(|o| { + if o.is_package() { + Some((o.id(), PackageObject::new(o.clone()))) + } else { + None + } + }) + .collect(); + Self { + backing_store, + new_packages, + } + } +} + +impl BackingPackageStore for PostExecutionPackageResolver { + fn get_package_object(&self, package_id: &ObjectID) -> SuiResult> { + if let Some(package) = self.new_packages.get(package_id) { + Ok(Some(package.clone())) + } else { + self.backing_store.get_package_object(package_id) + } + } +} + pub trait ParentSync { /// This function is only called by older protocol versions. /// It creates an explicit dependency to tombstones, which is not desired.