From 136058aaf64bf1b47b1102790cc7ad1f3cc10b4e Mon Sep 17 00:00:00 2001 From: Alden Hu Date: Thu, 10 Oct 2024 14:01:59 -0700 Subject: [PATCH] introduce ChunkResultVerifier (#14912) --- .../src/ledger_update_output.rs | 61 ------ execution/executor/src/chunk_executor.rs | 174 +++++++++--------- .../src/components/chunk_commit_queue.rs | 14 +- .../executor/src/components/chunk_output.rs | 6 +- .../src/components/chunk_result_verifier.rs | 135 ++++++++++++++ execution/executor/src/components/mod.rs | 1 + .../src/components/transaction_chunk.rs | 97 ++++------ execution/executor/src/tests/mod.rs | 7 +- 8 files changed, 271 insertions(+), 224 deletions(-) create mode 100644 execution/executor/src/components/chunk_result_verifier.rs diff --git a/execution/executor-types/src/ledger_update_output.rs b/execution/executor-types/src/ledger_update_output.rs index b2226a2321a45..9bb7f58685447 100644 --- a/execution/executor-types/src/ledger_update_output.rs +++ b/execution/executor-types/src/ledger_update_output.rs @@ -10,7 +10,6 @@ use aptos_storage_interface::cached_state_view::ShardedStateCache; use aptos_types::{ contract_event::ContractEvent, epoch_state::EpochState, - ledger_info::LedgerInfoWithSignatures, proof::accumulator::InMemoryTransactionAccumulator, state_store::{combine_or_add_sharded_state_updates, ShardedStateUpdates}, transaction::{ @@ -72,66 +71,6 @@ impl LedgerUpdateOutput { Ok(()) } - pub fn maybe_select_chunk_ending_ledger_info( - &self, - verified_target_li: &LedgerInfoWithSignatures, - epoch_change_li: Option<&LedgerInfoWithSignatures>, - next_epoch_state: Option<&EpochState>, - ) -> Result> { - if verified_target_li.ledger_info().version() + 1 - == self.transaction_accumulator.num_leaves() - { - // If the chunk corresponds to the target LI, the target LI can be added to storage. - ensure!( - verified_target_li - .ledger_info() - .transaction_accumulator_hash() - == self.transaction_accumulator.root_hash(), - "Root hash in target ledger info does not match local computation. {:?} != {:?}", - verified_target_li, - self.transaction_accumulator, - ); - Ok(Some(verified_target_li.clone())) - } else if let Some(epoch_change_li) = epoch_change_li { - // If the epoch change LI is present, it must match the version of the chunk: - - // Verify that the given ledger info corresponds to the new accumulator. - ensure!( - epoch_change_li.ledger_info().transaction_accumulator_hash() - == self.transaction_accumulator.root_hash(), - "Root hash of a given epoch LI does not match local computation. {:?} vs {:?}", - epoch_change_li, - self.transaction_accumulator, - ); - ensure!( - epoch_change_li.ledger_info().version() + 1 - == self.transaction_accumulator.num_leaves(), - "Version of a given epoch LI does not match local computation. {:?} vs {:?}", - epoch_change_li, - self.transaction_accumulator, - ); - ensure!( - epoch_change_li.ledger_info().ends_epoch(), - "Epoch change LI does not carry validator set. version:{}", - epoch_change_li.ledger_info().version(), - ); - ensure!( - epoch_change_li.ledger_info().next_epoch_state() == next_epoch_state, - "New validator set of a given epoch LI does not match local computation. {:?} vs {:?}", - epoch_change_li.ledger_info().next_epoch_state(), - next_epoch_state, - ); - Ok(Some(epoch_change_li.clone())) - } else { - ensure!( - next_epoch_state.is_none(), - "End of epoch chunk based on local computation but no EoE LedgerInfo provided. version: {:?}", - self.transaction_accumulator.num_leaves().checked_sub(1), - ); - Ok(None) - } - } - pub fn ensure_transaction_infos_match( &self, transaction_infos: &[TransactionInfo], diff --git a/execution/executor/src/chunk_executor.rs b/execution/executor/src/chunk_executor.rs index 134ed64f6cf32..fbe4d1f8d1b32 100644 --- a/execution/executor/src/chunk_executor.rs +++ b/execution/executor/src/chunk_executor.rs @@ -9,14 +9,14 @@ use crate::{ apply_chunk_output::{ensure_no_discard, ensure_no_retry, ApplyChunkOutput}, chunk_commit_queue::{ChunkCommitQueue, ChunkToUpdateLedger}, chunk_output::ChunkOutput, + chunk_result_verifier::{ChunkResultVerifier, StateSyncChunkVerifier}, executed_chunk::ExecutedChunk, - transaction_chunk::TransactionChunkWithProof, + transaction_chunk::{ChunkToApply, ChunkToExecute, TransactionChunk}, }, logging::{LogEntry, LogSchema}, metrics::{APPLY_CHUNK, CHUNK_OTHER_TIMERS, COMMIT_CHUNK, CONCURRENCY_GAUGE, EXECUTE_CHUNK}, }; -use anyhow::{ensure, Result}; -use aptos_crypto::HashValue; +use anyhow::{anyhow, ensure, Result}; use aptos_drop_helper::DEFAULT_DROPPER; use aptos_executor_types::{ ChunkCommitNotification, ChunkExecutorTrait, ParsedTransactionOutput, TransactionReplayer, @@ -33,8 +33,7 @@ use aptos_storage_interface::{ use aptos_types::{ block_executor::config::BlockExecutorConfigFromOnchain, contract_event::ContractEvent, - ledger_info::{LedgerInfo, LedgerInfoWithSignatures}, - proof::TransactionInfoListWithProof, + ledger_info::LedgerInfoWithSignatures, state_store::StateViewId, transaction::{ signature_verified_transaction::SignatureVerifiedTransaction, Transaction, @@ -107,14 +106,36 @@ impl ChunkExecutorTrait for ChunkExecutor { let _timer = EXECUTE_CHUNK.start_timer(); self.maybe_initialize()?; - self.with_inner(|inner| { - inner.enqueue_chunk( - txn_list_with_proof, - verified_target_li, - epoch_change_li, - "execute", - ) - }) + + // Verify input data. + // In consensus-only mode, txn_list_with_proof is fake. + if !cfg!(feature = "consensus-only-perf-test") { + txn_list_with_proof.verify( + verified_target_li.ledger_info(), + txn_list_with_proof.first_transaction_version, + )?; + } + + // Compose enqueue_chunk parameters. + let TransactionListWithProof { + transactions, + events: _, + first_transaction_version: v, + proof: txn_infos_with_proof, + } = txn_list_with_proof; + + let chunk = ChunkToExecute { + transactions, + first_version: v.ok_or_else(|| anyhow!("first version is None"))?, + }; + let chunk_verifier = Arc::new(StateSyncChunkVerifier { + txn_infos_with_proof, + verified_target_li: verified_target_li.clone(), + epoch_change_li: epoch_change_li.cloned(), + }); + + // Call the shared implementation. + self.with_inner(|inner| inner.enqueue_chunk(chunk, chunk_verifier, "execute")) } fn enqueue_chunk_by_transaction_outputs( @@ -126,14 +147,36 @@ impl ChunkExecutorTrait for ChunkExecutor { let _guard = CONCURRENCY_GAUGE.concurrency_with(&["chunk", "enqueue_by_outputs"]); let _timer = APPLY_CHUNK.start_timer(); - self.with_inner(|inner| { - inner.enqueue_chunk( - txn_output_list_with_proof, - verified_target_li, - epoch_change_li, - "apply", + // Verify input data. + THREAD_MANAGER.get_exe_cpu_pool().install(|| { + let _timer = CHUNK_OTHER_TIMERS.timer_with(&["apply_chunk__verify"]); + txn_output_list_with_proof.verify( + verified_target_li.ledger_info(), + txn_output_list_with_proof.first_transaction_output_version, ) - }) + })?; + + // Compose enqueue_chunk parameters. + let TransactionOutputListWithProof { + transactions_and_outputs, + first_transaction_output_version: v, + proof: txn_infos_with_proof, + } = txn_output_list_with_proof; + let (transactions, transaction_outputs) = transactions_and_outputs.into_iter().unzip(); + + let chunk = ChunkToApply { + transactions, + transaction_outputs, + first_version: v.ok_or_else(|| anyhow!("first version is None"))?, + }; + let chunk_verifier = Arc::new(StateSyncChunkVerifier { + txn_infos_with_proof, + verified_target_li: verified_target_li.clone(), + epoch_change_li: epoch_change_li.cloned(), + }); + + // Call the shared implementation. + self.with_inner(|inner| inner.enqueue_chunk(chunk, chunk_verifier, "apply")) } fn update_ledger(&self) -> Result<()> { @@ -197,25 +240,6 @@ impl ChunkExecutorInner { )?) } - fn verify_extends_ledger( - &self, - proof: &TransactionInfoListWithProof, - first_version: Version, - my_root_hash: HashValue, - ) -> Result<()> { - // In consensus-only mode, we cannot verify the proof against the executed output, - // because the proof returned by the remote peer is an empty one. - if cfg!(feature = "consensus-only-perf-test") { - return Ok(()); - } - - let num_overlap = - proof.verify_extends_ledger(first_version, my_root_hash, Some(first_version))?; - assert_eq!(num_overlap, 0, "overlapped chunks"); - - Ok(()) - } - fn commit_chunk_impl(&self) -> Result { let _timer = CHUNK_OTHER_TIMERS.timer_with(&["commit_chunk_impl__total"]); let (persisted_state, chunk) = { @@ -255,42 +279,27 @@ impl ChunkExecutorInner { Ok(chunk) } - fn verify_chunk( - chunk: &Chunk, - ledger_info: &LedgerInfo, - first_version: Version, - ) -> Result<()> { - // In consensus-only mode, the [TransactionListWithProof](transaction list) is *not* - // verified against the proof and the [LedgerInfoWithSignatures](ledger info). - // This is because the [FakeAptosDB] from where these transactions come from - // returns an empty proof and not an actual proof, so proof verification will - // fail regardless. This function does not skip any transactions that may be - // already in the ledger, because it is not necessary as execution is disabled. - if cfg!(feature = "consensus-only-perf-test") { - return Ok(()); - } - - THREAD_MANAGER - .get_exe_cpu_pool() - .install(|| chunk.verify_chunk(ledger_info, first_version)) - } - // ************************* Chunk Executor Implementation ************************* - fn enqueue_chunk( + fn enqueue_chunk( &self, chunk: Chunk, - verified_target_li: &LedgerInfoWithSignatures, - epoch_change_li: Option<&LedgerInfoWithSignatures>, + chunk_verifier: Arc, mode_for_log: &'static str, ) -> Result<()> { let parent_state = self.commit_queue.lock().latest_state(); let first_version = parent_state.next_version(); - Self::verify_chunk(&chunk, verified_target_li.ledger_info(), first_version)?; + ensure!( + chunk.first_version() == parent_state.next_version(), + "Chunk carries unexpected first version. Expected: {}, got: {}", + parent_state.next_version(), + chunk.first_version(), + ); + let num_txns = chunk.len(); let state_view = self.latest_state_view(&parent_state)?; - let (chunk_output, txn_infos_with_proof) = chunk.into_chunk_output::(state_view)?; + let chunk_output = chunk.into_output::(state_view)?; // Calculate state snapshot let (result_state, next_epoch_state, state_checkpoint_output) = @@ -298,7 +307,7 @@ impl ChunkExecutorInner { chunk_output, &self.commit_queue.lock().latest_state(), None, // append_state_checkpoint_to_block - Some(txn_infos_with_proof.state_checkpoint_hashes()), + Some(chunk_verifier.state_checkpoint_hashes()), false, // is_block )?; @@ -309,9 +318,7 @@ impl ChunkExecutorInner { result_state, state_checkpoint_output, next_epoch_state, - verified_target_li: verified_target_li.clone(), - epoch_change_li: epoch_change_li.cloned(), - txn_infos_with_proof, + chunk_verifier, })?; info!( @@ -336,29 +343,24 @@ impl ChunkExecutorInner { result_state, state_checkpoint_output, next_epoch_state, - verified_target_li, - epoch_change_li, - txn_infos_with_proof, + chunk_verifier, } = chunk; let first_version = parent_accumulator.num_leaves(); - self.verify_extends_ledger( - &txn_infos_with_proof, - first_version, - parent_accumulator.root_hash(), - )?; - let (ledger_update_output, to_discard, to_retry) = { let _timer = CHUNK_OTHER_TIMERS.timer_with(&["chunk_update_ledger__calculate"]); - ApplyChunkOutput::calculate_ledger_update(state_checkpoint_output, parent_accumulator)? + ApplyChunkOutput::calculate_ledger_update( + state_checkpoint_output, + parent_accumulator.clone(), + )? }; + ensure!(to_discard.is_empty(), "Unexpected discard."); ensure!(to_retry.is_empty(), "Unexpected retry."); - ledger_update_output - .ensure_transaction_infos_match(&txn_infos_with_proof.transaction_infos)?; - let ledger_info_opt = ledger_update_output.maybe_select_chunk_ending_ledger_info( - &verified_target_li, - epoch_change_li.as_ref(), + chunk_verifier.verify_chunk_result(&parent_accumulator, &ledger_update_output)?; + + let ledger_info_opt = chunk_verifier.maybe_select_chunk_ending_ledger_info( + &ledger_update_output, next_epoch_state.as_ref(), )?; @@ -648,7 +650,7 @@ impl ChunkExecutorInner { ) -> Result<()> { let num_txns = (end_version - begin_version) as usize; let txn_infos: Vec<_> = transaction_infos.drain(..num_txns).collect(); - let txns_and_outputs = multizip(( + let (txns, txn_outs) = multizip(( transactions.drain(..num_txns), txn_infos.iter(), write_sets.drain(..num_txns), @@ -666,10 +668,10 @@ impl ChunkExecutorInner { ), ) }) - .collect(); + .unzip(); let state_view = self.latest_state_view(latest_view.state())?; - let chunk_output = ChunkOutput::by_transaction_output(txns_and_outputs, state_view)?; + let chunk_output = ChunkOutput::by_transaction_output(txns, txn_outs, state_view)?; let (executed_batch, to_discard, to_retry) = chunk_output.apply_to_ledger( latest_view, Some( diff --git a/execution/executor/src/components/chunk_commit_queue.rs b/execution/executor/src/components/chunk_commit_queue.rs index 244e24712ccc9..54c69a2f61afe 100644 --- a/execution/executor/src/components/chunk_commit_queue.rs +++ b/execution/executor/src/components/chunk_commit_queue.rs @@ -4,14 +4,14 @@ #![forbid(unsafe_code)] -use crate::components::executed_chunk::ExecutedChunk; +use crate::components::{ + chunk_result_verifier::ChunkResultVerifier, executed_chunk::ExecutedChunk, +}; use anyhow::{anyhow, ensure, Result}; use aptos_executor_types::state_checkpoint_output::StateCheckpointOutput; use aptos_storage_interface::{state_delta::StateDelta, DbReader, ExecutedTrees}; use aptos_types::{ - epoch_state::EpochState, - ledger_info::LedgerInfoWithSignatures, - proof::{accumulator::InMemoryTransactionAccumulator, TransactionInfoListWithProof}, + epoch_state::EpochState, proof::accumulator::InMemoryTransactionAccumulator, transaction::Version, }; use std::{collections::VecDeque, sync::Arc}; @@ -23,11 +23,9 @@ pub(crate) struct ChunkToUpdateLedger { /// If set, this is the new epoch info that should be changed to if this is committed. pub next_epoch_state: Option, - /// the below are from the input -- can be checked / used only after the transaction accumulator + /// from the input -- can be checked / used only after the transaction accumulator /// is updated. - pub verified_target_li: LedgerInfoWithSignatures, - pub epoch_change_li: Option, - pub txn_infos_with_proof: TransactionInfoListWithProof, + pub chunk_verifier: Arc, } /// It's a two stage pipeline: diff --git a/execution/executor/src/components/chunk_output.rs b/execution/executor/src/components/chunk_output.rs index 65777ef2e0d61..9c5019dd8db64 100644 --- a/execution/executor/src/components/chunk_output.rs +++ b/execution/executor/src/components/chunk_output.rs @@ -116,12 +116,10 @@ impl ChunkOutput { } pub fn by_transaction_output( - transactions_and_outputs: Vec<(Transaction, TransactionOutput)>, + transactions: Vec, + transaction_outputs: Vec, state_view: CachedStateView, ) -> Result { - let (transactions, transaction_outputs): (Vec<_>, Vec<_>) = - transactions_and_outputs.into_iter().unzip(); - update_counters_for_processed_chunk(&transactions, &transaction_outputs, "output"); // collect all accounts touched and dedup diff --git a/execution/executor/src/components/chunk_result_verifier.rs b/execution/executor/src/components/chunk_result_verifier.rs new file mode 100644 index 0000000000000..d9723dc0c57b5 --- /dev/null +++ b/execution/executor/src/components/chunk_result_verifier.rs @@ -0,0 +1,135 @@ +// Copyright (c) Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::{ensure, Result}; +use aptos_crypto::HashValue; +use aptos_executor_types::LedgerUpdateOutput; +use aptos_experimental_runtimes::thread_manager::THREAD_MANAGER; +use aptos_types::{ + epoch_state::EpochState, + ledger_info::LedgerInfoWithSignatures, + proof::{accumulator::InMemoryTransactionAccumulator, TransactionInfoListWithProof}, + transaction::TransactionInfo, +}; + +pub trait ChunkResultVerifier { + fn verify_chunk_result( + &self, + parent_accumulator: &InMemoryTransactionAccumulator, + ledger_update_output: &LedgerUpdateOutput, + ) -> Result<()>; + + fn transaction_infos(&self) -> &[TransactionInfo]; + + fn state_checkpoint_hashes(&self) -> Vec> { + self.transaction_infos() + .iter() + .map(|t| t.state_checkpoint_hash()) + .collect() + } + + fn maybe_select_chunk_ending_ledger_info( + &self, + ledger_update_output: &LedgerUpdateOutput, + next_epoch_state: Option<&EpochState>, + ) -> Result>; +} + +pub struct StateSyncChunkVerifier { + pub txn_infos_with_proof: TransactionInfoListWithProof, + pub verified_target_li: LedgerInfoWithSignatures, + pub epoch_change_li: Option, +} + +impl ChunkResultVerifier for StateSyncChunkVerifier { + fn verify_chunk_result( + &self, + parent_accumulator: &InMemoryTransactionAccumulator, + ledger_update_output: &LedgerUpdateOutput, + ) -> Result<()> { + // In consensus-only mode, we cannot verify the proof against the executed output, + // because the proof returned by the remote peer is an empty one. + if cfg!(feature = "consensus-only-perf-test") { + return Ok(()); + } + + THREAD_MANAGER.get_exe_cpu_pool().install(|| { + let first_version = parent_accumulator.num_leaves(); + + // Verify the chunk extends the parent accumulator. + let parent_root_hash = parent_accumulator.root_hash(); + let num_overlap = self.txn_infos_with_proof.verify_extends_ledger( + first_version, + parent_root_hash, + Some(first_version), + )?; + assert_eq!(num_overlap, 0, "overlapped chunks"); + + // Verify transaction infos match + ledger_update_output + .ensure_transaction_infos_match(&self.txn_infos_with_proof.transaction_infos)?; + + Ok(()) + }) + } + + fn transaction_infos(&self) -> &[TransactionInfo] { + &self.txn_infos_with_proof.transaction_infos + } + + fn maybe_select_chunk_ending_ledger_info( + &self, + ledger_update_output: &LedgerUpdateOutput, + next_epoch_state: Option<&EpochState>, + ) -> Result> { + let li = self.verified_target_li.ledger_info(); + let txn_accumulator = &ledger_update_output.transaction_accumulator; + + if li.version() + 1 == txn_accumulator.num_leaves() { + // If the chunk corresponds to the target LI, the target LI can be added to storage. + ensure!( + li.transaction_accumulator_hash() == txn_accumulator.root_hash(), + "Root hash in target ledger info does not match local computation. {:?} != {:?}", + li, + txn_accumulator, + ); + Ok(Some(self.verified_target_li.clone())) + } else if let Some(epoch_change_li) = &self.epoch_change_li { + // If the epoch change LI is present, it must match the version of the chunk: + let li = epoch_change_li.ledger_info(); + + // Verify that the given ledger info corresponds to the new accumulator. + ensure!( + li.transaction_accumulator_hash() == txn_accumulator.root_hash(), + "Root hash of a given epoch LI does not match local computation. {:?} vs {:?}", + li, + txn_accumulator, + ); + ensure!( + li.version() + 1 == txn_accumulator.num_leaves(), + "Version of a given epoch LI does not match local computation. {:?} vs {:?}", + li, + txn_accumulator, + ); + ensure!( + li.ends_epoch(), + "Epoch change LI does not carry validator set. version:{}", + li.version(), + ); + ensure!( + li.next_epoch_state() == next_epoch_state, + "New validator set of a given epoch LI does not match local computation. {:?} vs {:?}", + li.next_epoch_state(), + next_epoch_state, + ); + Ok(Some(epoch_change_li.clone())) + } else { + ensure!( + next_epoch_state.is_none(), + "End of epoch chunk based on local computation but no EoE LedgerInfo provided. version: {:?}", + txn_accumulator.num_leaves().checked_sub(1), + ); + Ok(None) + } + } +} diff --git a/execution/executor/src/components/mod.rs b/execution/executor/src/components/mod.rs index ae25d94c4933e..e4a96049b339c 100644 --- a/execution/executor/src/components/mod.rs +++ b/execution/executor/src/components/mod.rs @@ -10,5 +10,6 @@ pub mod chunk_commit_queue; pub mod chunk_output; pub mod in_memory_state_calculator_v2; +pub mod chunk_result_verifier; pub mod executed_chunk; pub mod transaction_chunk; diff --git a/execution/executor/src/components/transaction_chunk.rs b/execution/executor/src/components/transaction_chunk.rs index 2346194ea3df4..41b995cfea428 100644 --- a/execution/executor/src/components/transaction_chunk.rs +++ b/execution/executor/src/components/transaction_chunk.rs @@ -11,9 +11,7 @@ use aptos_metrics_core::TimerHelper; use aptos_storage_interface::cached_state_view::CachedStateView; use aptos_types::{ block_executor::config::BlockExecutorConfigFromOnchain, - ledger_info::LedgerInfo, - proof::TransactionInfoListWithProof, - transaction::{TransactionListWithProof, TransactionOutputListWithProof, Version}, + transaction::{Transaction, TransactionOutput, Version}, }; use aptos_vm::VMExecutor; use once_cell::sync::Lazy; @@ -30,12 +28,8 @@ pub static SIG_VERIFY_POOL: Lazy> = Lazy::new(|| { ) }); -pub trait TransactionChunkWithProof { - fn verify_chunk( - &self, - ledger_info: &LedgerInfo, - first_transaction_version: Version, - ) -> Result<()>; +pub trait TransactionChunk { + fn first_version(&self) -> Version; fn len(&self) -> usize; @@ -43,37 +37,27 @@ pub trait TransactionChunkWithProof { self.len() == 0 } - fn into_chunk_output( - self, - state_view: CachedStateView, - ) -> Result<(ChunkOutput, TransactionInfoListWithProof)>; + fn into_output(self, state_view: CachedStateView) -> Result; } -impl TransactionChunkWithProof for TransactionListWithProof { - fn verify_chunk( - &self, - ledger_info: &LedgerInfo, - first_transaction_version: Version, - ) -> Result<()> { - let _timer = CHUNK_OTHER_TIMERS.timer_with(&["verify_txn_chunk"]); +pub struct ChunkToExecute { + pub transactions: Vec, + pub first_version: Version, +} - self.proof - .verify(ledger_info, Some(first_transaction_version)) +impl TransactionChunk for ChunkToExecute { + fn first_version(&self) -> Version { + self.first_version } fn len(&self) -> usize { self.transactions.len() } - fn into_chunk_output( - self, - state_view: CachedStateView, - ) -> Result<(ChunkOutput, TransactionInfoListWithProof)> { - let TransactionListWithProof { + fn into_output(self, state_view: CachedStateView) -> Result { + let ChunkToExecute { transactions, - events: _, - first_transaction_version: _, - proof: txn_infos_with_proof, + first_version: _, } = self; // TODO(skedia) In the chunk executor path, we ideally don't need to verify the signature @@ -91,46 +75,37 @@ impl TransactionChunkWithProof for TransactionListWithProof { }) }; - let chunk_out = { - let _timer = VM_EXECUTE_CHUNK.start_timer(); - - ChunkOutput::by_transaction_execution::( - sig_verified_txns.into(), - state_view, - BlockExecutorConfigFromOnchain::new_no_block_limit(), - )? - }; - - Ok((chunk_out, txn_infos_with_proof)) + let _timer = VM_EXECUTE_CHUNK.start_timer(); + ChunkOutput::by_transaction_execution::( + sig_verified_txns.into(), + state_view, + BlockExecutorConfigFromOnchain::new_no_block_limit(), + ) } } -impl TransactionChunkWithProof for TransactionOutputListWithProof { - fn verify_chunk( - &self, - ledger_info: &LedgerInfo, - first_transaction_version: Version, - ) -> Result<()> { - self.proof - .verify(ledger_info, Some(first_transaction_version)) +pub struct ChunkToApply { + pub transactions: Vec, + pub transaction_outputs: Vec, + pub first_version: Version, +} + +impl TransactionChunk for ChunkToApply { + fn first_version(&self) -> Version { + self.first_version } fn len(&self) -> usize { - self.transactions_and_outputs.len() + self.transactions.len() } - fn into_chunk_output( - self, - state_view: CachedStateView, - ) -> Result<(ChunkOutput, TransactionInfoListWithProof)> { - let TransactionOutputListWithProof { - transactions_and_outputs, - first_transaction_output_version: _, - proof: txn_infos_with_proof, + fn into_output(self, state_view: CachedStateView) -> Result { + let Self { + transactions, + transaction_outputs, + first_version: _, } = self; - let chunk_out = ChunkOutput::by_transaction_output(transactions_and_outputs, state_view)?; - - Ok((chunk_out, txn_infos_with_proof)) + ChunkOutput::by_transaction_output(transactions, transaction_outputs, state_view) } } diff --git a/execution/executor/src/tests/mod.rs b/execution/executor/src/tests/mod.rs index 153427baa1987..d7c65868196a3 100644 --- a/execution/executor/src/tests/mod.rs +++ b/execution/executor/src/tests/mod.rs @@ -450,7 +450,7 @@ fn apply_transaction_by_writeset( ) { let ledger_view: ExecutedTrees = db.reader.get_latest_executed_trees().unwrap(); - let transactions_and_outputs = transactions_and_writesets + let (txns, txn_outs) = transactions_and_writesets .iter() .map(|(txn, write_set)| { ( @@ -474,7 +474,7 @@ fn apply_transaction_by_writeset( TransactionAuxiliaryData::default(), ), ))) - .collect(); + .unzip(); let state_view = ledger_view .verified_state_view( @@ -484,8 +484,7 @@ fn apply_transaction_by_writeset( ) .unwrap(); - let chunk_output = - ChunkOutput::by_transaction_output(transactions_and_outputs, state_view).unwrap(); + let chunk_output = ChunkOutput::by_transaction_output(txns, txn_outs, state_view).unwrap(); let (executed, _, _) = chunk_output.apply_to_ledger(&ledger_view, None).unwrap(); let ExecutedChunk {