From cf2a573c6c117227992ad272e5034f063441ee1f Mon Sep 17 00:00:00 2001 From: Xun Li Date: Thu, 24 Oct 2024 13:03:35 -0700 Subject: [PATCH] Support system tx in replay (#20016) ## Description Describe the changes or additions included in this PR. ## 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: --- crates/sui-replay/src/replay.rs | 61 +++++++++++++++------------------ 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/crates/sui-replay/src/replay.rs b/crates/sui-replay/src/replay.rs index b41e0eddf3b0e..eed08a0c297a3 100644 --- a/crates/sui-replay/src/replay.rs +++ b/crates/sui-replay/src/replay.rs @@ -707,17 +707,6 @@ impl LocalExec { expensive_safety_check_config: ExpensiveSafetyCheckConfig, ) -> Result { let tx_digest = &tx_info.tx_digest; - // TODO: Support system transactions. - if tx_info.sender_signed_data.transaction_data().is_system_tx() { - warn!( - "System TX replay not supported: {}, skipping transaction", - tx_digest - ); - return Err(ReplayEngineError::TransactionNotSupported { - digest: *tx_digest, - reason: "System transaction".to_string(), - }); - } // Before protocol version 16, the generation of effects depends on the wrapped tombstones. // It is not possible to retrieve such data for replay. if tx_info.protocol_version.as_u64() < 16 { @@ -759,30 +748,32 @@ impl LocalExec { let expensive_checks = true; let transaction_kind = override_transaction_kind.unwrap_or(tx_info.kind.clone()); let certificate_deny_set = HashSet::new(); - let (inner_store, gas_status, effects, result) = if let Ok(gas_status) = SuiGasStatus::new( - tx_info.gas_budget, - tx_info.gas_price, - tx_info.reference_gas_price, - protocol_config, - ) { - executor.execute_transaction_to_effects( - &self, + let gas_status = if tx_info.kind.is_system_tx() { + SuiGasStatus::new_unmetered() + } else { + SuiGasStatus::new( + tx_info.gas_budget, + tx_info.gas_price, + tx_info.reference_gas_price, protocol_config, - metrics.clone(), - expensive_checks, - &certificate_deny_set, - &tx_info.executed_epoch, - tx_info.epoch_start_timestamp, - CheckedInputObjects::new_for_replay(input_objects.clone()), - tx_info.gas.clone(), - gas_status, - transaction_kind.clone(), - tx_info.sender, - *tx_digest, ) - } else { - unreachable!("Transaction was valid so gas status must be valid"); + .expect("Failed to create gas status") }; + let (inner_store, gas_status, effects, result) = executor.execute_transaction_to_effects( + &self, + protocol_config, + metrics.clone(), + expensive_checks, + &certificate_deny_set, + &tx_info.executed_epoch, + tx_info.epoch_start_timestamp, + CheckedInputObjects::new_for_replay(input_objects.clone()), + tx_info.gas.clone(), + gas_status, + transaction_kind.clone(), + tx_info.sender, + *tx_digest, + ); if let Err(err) = self.pretty_print_for_tracing( &gas_status, @@ -1798,7 +1789,11 @@ impl LocalExec { self.multi_download_and_store(&shared_refs).await?; // Download gas (although this should already be in cache from modified at versions?) - let gas_refs: Vec<_> = tx_info.gas.iter().map(|w| (w.0, w.1)).collect(); + let gas_refs: Vec<_> = tx_info + .gas + .iter() + .filter_map(|w| (w.0 != ObjectID::ZERO).then_some((w.0, w.1))) + .collect(); self.multi_download_and_store(&gas_refs).await?; // Fetch the input objects we know from the raw transaction