diff --git a/consensus/core/src/commit_finalizer.rs b/consensus/core/src/commit_finalizer.rs index e991853dc89da..41bd5f7f8a0fd 100644 --- a/consensus/core/src/commit_finalizer.rs +++ b/consensus/core/src/commit_finalizer.rs @@ -339,9 +339,9 @@ impl CommitFinalizer { } } // Initialize the block state. - blocks_map - .entry(block_ref) - .or_insert_with(|| RwLock::new(BlockState::new(block))); + blocks_map.entry(block_ref).or_insert_with(|| { + RwLock::new(BlockState::new(block, commit_state.commit.commit_ref.index)) + }); } } @@ -477,6 +477,19 @@ impl CommitFinalizer { .map(|(k, v)| (*k, v.clone())) .collect(); + let gc_rounds = self + .pending_commits + .iter() + .map(|c| { + ( + c.commit.commit_ref.index, + self.dag_state + .read() + .calculate_gc_round(c.commit.leader.round), + ) + }) + .collect::>(); + // Number of blocks to process in each task. const BLOCKS_PER_INDIRECT_COMMIT_TASK: usize = 8; @@ -488,6 +501,7 @@ impl CommitFinalizer { for chunk in pending_blocks.chunks(BLOCKS_PER_INDIRECT_COMMIT_TASK) { let context = self.context.clone(); let blocks = self.blocks.clone(); + let gc_rounds = gc_rounds.clone(); let chunk: Vec<(BlockRef, BTreeSet)> = chunk.to_vec(); join_set.spawn(tokio::task::spawn_blocking(move || { @@ -497,6 +511,7 @@ impl CommitFinalizer { let finalized = Self::try_indirect_finalize_pending_transactions_in_block( &context, &blocks, + &gc_rounds, block_ref, pending_transactions, ); @@ -578,6 +593,7 @@ impl CommitFinalizer { fn try_indirect_finalize_pending_transactions_in_block( context: &Arc, blocks: &Arc>>>, + gc_rounds: &[(CommitIndex, Round)], pending_block_ref: BlockRef, pending_transactions: BTreeSet, ) -> Vec { @@ -591,13 +607,11 @@ impl CommitFinalizer { .collect(); let mut finalized_transactions = vec![]; let blocks_map = blocks.read(); - // Use BTreeSet to ensure always visit blocks in the earliest round. - let mut to_visit_blocks = blocks_map - .get(&pending_block_ref) - .unwrap() - .read() - .children - .clone(); + // Use BTreeSet for to_visit_blocks, to visit blocks in the earliest round first. + let (pending_commit_index, mut to_visit_blocks) = { + let block_state = blocks_map.get(&pending_block_ref).unwrap().read(); + (block_state.commit_index, block_state.children.clone()) + }; // Blocks that have been visited. let mut visited = BTreeSet::new(); // Blocks where votes and origin descendants should be ignored for processing. @@ -608,15 +622,15 @@ impl CommitFinalizer { continue; } let curr_block_state = blocks_map.get(&curr_block_ref).unwrap_or_else(|| panic!("Block {curr_block_ref} is either incorrectly gc'ed or failed to be recovered after crash.")).read(); - // The first ancestor of current block should have the same origin / author as the current block. - // If it is not found in the blocks map but have round higher than the pending block, it might have - // voted on the pending block but have been GC'ed. - // Because the GC'ed block might have voted on the pending block and rejected some of the pending transactions, - // we cannot assume current block is voting to accept transactions from the pending block. - let curr_origin_ancestor_ref = curr_block_state.block.ancestors().first().unwrap(); - let skip_votes = curr_block_ref.author == curr_origin_ancestor_ref.author - && pending_block_ref.round < curr_origin_ancestor_ref.round - && !blocks_map.contains_key(curr_origin_ancestor_ref); + // When proposing the current block, if it is possible that the pending block has already been GC'ed, + // then it is possible that the current block does not carry votes for the pending block. + // In this case, skip counting votes from the current block. + let skip_votes = Self::check_gc_at_current_commit( + gc_rounds, + pending_block_ref.round, + pending_commit_index, + curr_block_state.commit_index, + ); // Skip counting votes from the block if it has been marked to be ignored. if ignored.insert(curr_block_ref) { // Skip collecting votes from origin descendants of current block. @@ -683,6 +697,33 @@ impl CommitFinalizer { finalized_transactions } + // Returns true if the pending block round can be GC'ed when proposing blocks in current commit. + fn check_gc_at_current_commit( + gc_rounds: &[(CommitIndex, Round)], + pending_block_round: Round, + pending_commit_index: CommitIndex, + current_commit_index: CommitIndex, + ) -> bool { + assert!( + pending_commit_index <= current_commit_index, + "Pending {pending_commit_index} should be <= current {current_commit_index}" + ); + if pending_commit_index == current_commit_index { + return false; + } + // Since GC round only advances after a commit, when proposing blocks for the current commit, + // the GC round is determined by the commit previous to the current commit. + let (commit_index, gc_round) = *gc_rounds + .get((current_commit_index - 1 - pending_commit_index) as usize) + .unwrap(); + assert_eq!( + commit_index, + current_commit_index - 1, + "Commit index mismatch {commit_index} != {current_commit_index}" + ); + pending_block_round <= gc_round + } + fn pop_finalized_commits(&mut self) -> Vec { let mut finalized_commits = vec![]; @@ -800,10 +841,12 @@ struct BlockState { // Other committed blocks that are origin descendants of this block. // See the comment above append_origin_descendants_from_last_commit() for more details. origin_descendants: Vec, + // Commit which contains this block. + commit_index: CommitIndex, } impl BlockState { - fn new(block: VerifiedBlock) -> Self { + fn new(block: VerifiedBlock, commit_index: CommitIndex) -> Self { let reject_votes: BTreeMap<_, _> = block .transaction_votes() .iter() @@ -817,6 +860,7 @@ impl BlockState { children: BTreeSet::new(), reject_votes, origin_descendants, + commit_index, } } } diff --git a/consensus/core/src/commit_observer.rs b/consensus/core/src/commit_observer.rs index 621c3bbc914c6..230d82d43be92 100644 --- a/consensus/core/src/commit_observer.rs +++ b/consensus/core/src/commit_observer.rs @@ -215,7 +215,7 @@ impl CommitObserver { .recover_commits_to_write(unsent_commits.clone()); info!( - "Recovered {} unsent commits in range [{start_index}..={end_index}]", + "Recovering {} unsent commits in range [{start_index}..={end_index}]", unsent_commits.len() ); @@ -245,9 +245,13 @@ impl CommitObserver { reputation_scores, ); - if !committed_sub_dag.recovered_rejected_transactions { + if !committed_sub_dag.recovered_rejected_transactions && !seen_unfinalized_commit { + info!( + "Starting to recover unfinalized commit from {}", + committed_sub_dag.commit_ref + ); // When the commit has no associated storage entry for rejected transactions, - // even if an empty set, the commit is unfinalized. + // not even an empty set, the commit is unfinalized. seen_unfinalized_commit = true; } diff --git a/consensus/core/src/dag_state.rs b/consensus/core/src/dag_state.rs index 7aad2fb5e73b7..23c5fbe0e2c58 100644 --- a/consensus/core/src/dag_state.rs +++ b/consensus/core/src/dag_state.rs @@ -799,7 +799,8 @@ impl DagState { let mut targets = VecDeque::new(); targets.push_back(root_block); while let Some(block_ref) = targets.pop_front() { - // This is only correct with GC enabled. + // No need to collect and mark blocks at or below GC round. These blocks will not be included in new commits + // and do not need their transactions to be voted on. if block_ref.round <= gc_round { continue; } diff --git a/crates/sui-core/src/checkpoints/mod.rs b/crates/sui-core/src/checkpoints/mod.rs index 1b623b897054c..d09440c8655f9 100644 --- a/crates/sui-core/src/checkpoints/mod.rs +++ b/crates/sui-core/src/checkpoints/mod.rs @@ -22,6 +22,7 @@ use crate::execution_cache::TransactionCacheRead; use crate::execution_scheduler::balance_withdraw_scheduler::BalanceSettlement; use crate::global_state_hasher::GlobalStateHasher; use crate::stake_aggregator::{InsertResult, MultiStakeAggregator}; +use consensus_core::CommitRef; use diffy::create_patch; use itertools::Itertools; use mysten_common::random::get_rng; @@ -61,7 +62,9 @@ use sui_protocol_config::ProtocolVersion; use sui_types::base_types::{AuthorityName, EpochId, TransactionDigest}; use sui_types::committee::StakeUnit; use sui_types::crypto::AuthorityStrongQuorumSignInfo; -use sui_types::digests::{CheckpointContentsDigest, CheckpointDigest, TransactionEffectsDigest}; +use sui_types::digests::{ + CheckpointContentsDigest, CheckpointDigest, Digest, TransactionEffectsDigest, +}; use sui_types::effects::{TransactionEffects, TransactionEffectsAPI}; use sui_types::error::{SuiErrorKind, SuiResult}; use sui_types::gas::GasCostSummary; @@ -105,6 +108,9 @@ pub struct PendingCheckpointInfo { // Computed in calculate_pending_checkpoint_height() from consensus round, // there is no guarantee that this is increasing per checkpoint, because of checkpoint splitting. pub checkpoint_height: CheckpointHeight, + // Consensus commit ref and rejected transactions digest which corresponds to this checkpoint. + pub consensus_commit_ref: CommitRef, + pub rejected_transactions_digest: Digest, } #[derive(Clone, Debug)] @@ -1392,6 +1398,18 @@ impl CheckpointBuilder { pendings: Vec, ) -> CheckpointBuilderResult { let _scope = monitored_scope("CheckpointBuilder::make_checkpoint"); + + let pending_ckpt_str = pendings + .iter() + .map(|p| { + format!( + "height={}, commit={}", + p.details().checkpoint_height, + p.details().consensus_commit_ref + ) + }) + .join("; "); + let last_details = pendings.last().unwrap().details().clone(); // Stores the transactions that should be included in the checkpoint. Transactions will be recorded in the checkpoint @@ -1419,8 +1437,18 @@ impl CheckpointBuilder { ); } + let new_ckpt_str = new_checkpoints + .iter() + .map(|(ckpt, _)| format!("seq={}, digest={}", ckpt.sequence_number(), ckpt.digest())) + .join("; "); + self.write_checkpoints(last_details.checkpoint_height, new_checkpoints) .await?; + info!( + "Made new checkpoint {} from pending checkpoint {}", + new_ckpt_str, pending_ckpt_str + ); + Ok(highest_sequence) } @@ -3795,6 +3823,8 @@ mod tests { timestamp_ms, last_of_epoch: false, checkpoint_height: i, + consensus_commit_ref: CommitRef::default(), + rejected_transactions_digest: Digest::default(), }, } } diff --git a/crates/sui-core/src/consensus_handler.rs b/crates/sui-core/src/consensus_handler.rs index 94bce21df0a85..bd9f535652f9f 100644 --- a/crates/sui-core/src/consensus_handler.rs +++ b/crates/sui-core/src/consensus_handler.rs @@ -169,8 +169,9 @@ impl ConsensusHandlerInitializer { mod additional_consensus_state { use std::marker::PhantomData; + use consensus_core::CommitRef; use fastcrypto::hash::HashFunction as _; - use sui_types::crypto::DefaultHash; + use sui_types::{crypto::DefaultHash, digests::Digest}; use super::*; /// AdditionalConsensusState tracks any in-memory state that is retained by ConsensusHandler @@ -216,7 +217,6 @@ mod additional_consensus_state { self.commit_info_impl( epoch_start_time, - protocol_config, consensus_commit, Some(estimated_commit_period), ) @@ -225,7 +225,6 @@ mod additional_consensus_state { fn commit_info_impl( &self, epoch_start_time: u64, - protocol_config: &ProtocolConfig, consensus_commit: &impl ConsensusCommitAPI, estimated_commit_period: Option, ) -> ConsensusCommitInfo { @@ -246,8 +245,8 @@ mod additional_consensus_state { round: consensus_commit.leader_round(), timestamp, leader_author, - sub_dag_index: consensus_commit.commit_sub_dag_index(), - consensus_commit_digest: consensus_commit.consensus_digest(protocol_config), + consensus_commit_ref: consensus_commit.commit_ref(), + rejected_transactions_digest: consensus_commit.rejected_transactions_digest(), additional_state_digest: Some(self.digest()), estimated_commit_period, skip_consensus_commit_prologue_in_test: false, @@ -269,8 +268,8 @@ mod additional_consensus_state { pub round: u64, pub timestamp: u64, pub leader_author: AuthorityIndex, - pub sub_dag_index: u64, - pub consensus_commit_digest: ConsensusCommitDigest, + pub consensus_commit_ref: CommitRef, + pub rejected_transactions_digest: Digest, additional_state_digest: Option, estimated_commit_period: Option, @@ -290,8 +289,8 @@ mod additional_consensus_state { round: commit_round, timestamp: commit_timestamp, leader_author: 0, - sub_dag_index: 0, - consensus_commit_digest: ConsensusCommitDigest::default(), + consensus_commit_ref: CommitRef::default(), + rejected_transactions_digest: Digest::default(), additional_state_digest: Some(AdditionalConsensusStateDigest::ZERO), estimated_commit_period, skip_consensus_commit_prologue_in_test, @@ -323,6 +322,10 @@ mod additional_consensus_state { .expect("estimated commit period is not available") } + fn consensus_commit_digest(&self) -> ConsensusCommitDigest { + ConsensusCommitDigest::new(self.consensus_commit_ref.digest.into_inner()) + } + fn consensus_commit_prologue_transaction( &self, epoch: u64, @@ -343,7 +346,7 @@ mod additional_consensus_state { epoch, self.round, self.timestamp, - self.consensus_commit_digest, + self.consensus_commit_digest(), ); VerifiedExecutableTransaction::new_system(transaction, epoch) } @@ -357,7 +360,7 @@ mod additional_consensus_state { epoch, self.round, self.timestamp, - self.consensus_commit_digest, + self.consensus_commit_digest(), consensus_determined_version_assignments, ); VerifiedExecutableTransaction::new_system(transaction, epoch) @@ -373,7 +376,7 @@ mod additional_consensus_state { epoch, self.round, self.timestamp, - self.consensus_commit_digest, + self.consensus_commit_digest(), consensus_determined_version_assignments, additional_state_digest, ); @@ -801,7 +804,8 @@ impl ConsensusHandler { info!( %consensus_commit, - "Received consensus output" + "Received consensus output. Rejected transactions: {}", + consensus_commit.rejected_transactions_debug_string(), ); self.last_consensus_stats.index = ExecutionIndices { @@ -1049,12 +1053,19 @@ impl ConsensusHandler { timestamp_ms: commit_info.timestamp, last_of_epoch: final_round && !should_write_random_checkpoint, checkpoint_height, + consensus_commit_ref: commit_info.consensus_commit_ref, + rejected_transactions_digest: commit_info.rejected_transactions_digest, }, }; self.epoch_store .write_pending_checkpoint(&mut state.output, &pending_checkpoint) .expect("failed to write pending checkpoint"); + info!( + "Written pending checkpoint: {:?}", + pending_checkpoint.details, + ); + if should_write_random_checkpoint { let pending_checkpoint = PendingCheckpoint { roots: randomness_schedulables.iter().map(|s| s.key()).collect(), @@ -1062,6 +1073,8 @@ impl ConsensusHandler { timestamp_ms: commit_info.timestamp, last_of_epoch: final_round, checkpoint_height: checkpoint_height + 1, + consensus_commit_ref: commit_info.consensus_commit_ref, + rejected_transactions_digest: commit_info.rejected_transactions_digest, }, }; self.epoch_store @@ -2147,7 +2160,7 @@ impl ConsensusHandler { // Therefore, the transaction sequence number starts from 1 here. let current_tx_index = ExecutionIndices { last_committed_round: commit_info.round, - sub_dag_index: commit_info.sub_dag_index, + sub_dag_index: commit_info.consensus_commit_ref.index.into(), transaction_index: (seq + 1) as u64, }; diff --git a/crates/sui-core/src/consensus_types/consensus_output_api.rs b/crates/sui-core/src/consensus_types/consensus_output_api.rs index 3058b64149e52..f336a4edfdb04 100644 --- a/crates/sui-core/src/consensus_types/consensus_output_api.rs +++ b/crates/sui-core/src/consensus_types/consensus_output_api.rs @@ -1,12 +1,14 @@ // Copyright (c) Mysten Labs, Inc. // SPDX-License-Identifier: Apache-2.0 + use std::{cmp::Ordering, fmt::Display}; -use consensus_core::{BlockAPI, CommitDigest, VerifiedBlock}; +use consensus_core::{BlockAPI, CommitRef, VerifiedBlock}; use consensus_types::block::{BlockRef, TransactionIndex}; -use sui_protocol_config::ProtocolConfig; +use fastcrypto::hash::HashFunction as _; +use itertools::Itertools as _; use sui_types::{ - digests::ConsensusCommitDigest, + digests::Digest, messages_consensus::{AuthorityIndex, ConsensusTransaction}, }; @@ -20,6 +22,9 @@ pub(crate) struct ParsedTransaction { } pub(crate) trait ConsensusCommitAPI: Display { + /// Returns the ref of consensus output. + fn commit_ref(&self) -> CommitRef; + fn reputation_score_sorted_desc(&self) -> Option>; fn leader_round(&self) -> u64; fn leader_author_index(&self) -> AuthorityIndex; @@ -33,11 +38,16 @@ pub(crate) trait ConsensusCommitAPI: Display { /// Returns all accepted and rejected transactions per block in the commit in deterministic order. fn transactions(&self) -> Vec<(BlockRef, Vec)>; - /// Returns the digest of consensus output. - fn consensus_digest(&self, protocol_config: &ProtocolConfig) -> ConsensusCommitDigest; + /// Returns a debug string of all rejected transactions. + fn rejected_transactions_digest(&self) -> Digest; + fn rejected_transactions_debug_string(&self) -> String; } impl ConsensusCommitAPI for consensus_core::CommittedSubDag { + fn commit_ref(&self) -> CommitRef { + self.commit_ref + } + fn reputation_score_sorted_desc(&self) -> Option> { if !self.reputation_scores_desc.is_empty() { Some( @@ -85,15 +95,29 @@ impl ConsensusCommitAPI for consensus_core::CommittedSubDag { .collect() } - fn consensus_digest(&self, protocol_config: &ProtocolConfig) -> ConsensusCommitDigest { - if protocol_config.mysticeti_use_committed_subdag_digest() { - // We port CommitDigest, a consensus space object, into ConsensusCommitDigest, a sui-core space object. - // We assume they always have the same format. - static_assertions::assert_eq_size!(ConsensusCommitDigest, CommitDigest); - ConsensusCommitDigest::new(self.commit_ref.digest.into_inner()) - } else { - ConsensusCommitDigest::default() - } + fn rejected_transactions_digest(&self) -> Digest { + let bytes = bcs::to_bytes(&self.rejected_transactions_by_block).unwrap(); + let mut hasher = sui_types::crypto::DefaultHash::new(); + hasher.update(bytes); + hasher.finalize().digest.into() + } + + fn rejected_transactions_debug_string(&self) -> String { + let str = self + .rejected_transactions_by_block + .iter() + .map(|(block_ref, rejected_transactions)| { + format!( + "{block_ref}: [{}]", + rejected_transactions + .iter() + .map(|tx| tx.to_string()) + .join(",") + ) + }) + .join(", "); + let digest = self.rejected_transactions_digest(); + format!("{str}; digest: {digest}") } } diff --git a/crates/sui-core/src/unit_tests/consensus_test_utils.rs b/crates/sui-core/src/unit_tests/consensus_test_utils.rs index ddce7a52420bc..c10ca2e2659fa 100644 --- a/crates/sui-core/src/unit_tests/consensus_test_utils.rs +++ b/crates/sui-core/src/unit_tests/consensus_test_utils.rs @@ -3,6 +3,23 @@ //! Common test utilities for consensus handler testing +use std::collections::HashSet; +use std::sync::Arc; + +use arc_swap::ArcSwap; +use consensus_core::BlockStatus; +use consensus_types::block::BlockRef; +use parking_lot::Mutex; +use prometheus::Registry; +use sui_types::digests::{Digest, TransactionDigest}; +use sui_types::error::SuiResult; +use sui_types::executable_transaction::VerifiedExecutableTransaction; +use sui_types::messages_consensus::{ + AuthorityIndex, ConsensusPosition, ConsensusTransaction, ConsensusTransactionKind, +}; +use sui_types::sui_system_state::epoch_start_sui_system_state::EpochStartSystemStateTrait; +use sui_types::transaction::{VerifiedCertificate, VerifiedTransaction}; + use crate::authority::authority_per_epoch_store::{ AuthorityPerEpochStore, ExecutionIndicesWithStats, }; @@ -21,22 +38,6 @@ use crate::consensus_throughput_calculator::ConsensusThroughputCalculator; use crate::consensus_types::consensus_output_api::{ConsensusCommitAPI, ParsedTransaction}; use crate::execution_scheduler::SchedulingSource; use crate::mock_consensus::with_block_status; -use arc_swap::ArcSwap; -use consensus_core::BlockStatus; -use consensus_types::block::BlockRef; -use parking_lot::Mutex; -use prometheus::Registry; -use std::collections::HashSet; -use std::sync::Arc; -use sui_protocol_config::ProtocolConfig; -use sui_types::digests::{ConsensusCommitDigest, TransactionDigest}; -use sui_types::error::SuiResult; -use sui_types::executable_transaction::VerifiedExecutableTransaction; -use sui_types::messages_consensus::{ - AuthorityIndex, ConsensusPosition, ConsensusTransaction, ConsensusTransactionKind, -}; -use sui_types::sui_system_state::epoch_start_sui_system_state::EpochStartSystemStateTrait; -use sui_types::transaction::{VerifiedCertificate, VerifiedTransaction}; pub(crate) type CapturedTransactions = Arc, AssignedTxAndVersions, SchedulingSource)>>>; @@ -84,6 +85,10 @@ impl std::fmt::Display for TestConsensusCommit { } impl ConsensusCommitAPI for TestConsensusCommit { + fn commit_ref(&self) -> consensus_core::CommitRef { + consensus_core::CommitRef::default() + } + fn reputation_score_sorted_desc(&self) -> Option> { None } @@ -124,8 +129,12 @@ impl ConsensusCommitAPI for TestConsensusCommit { vec![(block_ref, parsed_txs)] } - fn consensus_digest(&self, _protocol_config: &ProtocolConfig) -> ConsensusCommitDigest { - ConsensusCommitDigest::default() + fn rejected_transactions_digest(&self) -> Digest { + Digest::default() + } + + fn rejected_transactions_debug_string(&self) -> String { + "no rejected transactions from TestConsensusCommit".to_string() } } diff --git a/crates/sui-protocol-config/src/lib.rs b/crates/sui-protocol-config/src/lib.rs index 26598697234c0..86602891f5e59 100644 --- a/crates/sui-protocol-config/src/lib.rs +++ b/crates/sui-protocol-config/src/lib.rs @@ -4287,6 +4287,8 @@ impl ProtocolConfig { cfg.poseidon_bn254_cost_base = Some(260); + cfg.feature_flags.consensus_skip_gced_accept_votes = true; + if chain != Chain::Mainnet { cfg.feature_flags .enable_nitro_attestation_all_nonzero_pcrs_parsing = true; diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_104.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_104.snap index dc0d708b759c2..d33c596bb0c3d 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_104.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Mainnet_version_104.snap @@ -126,6 +126,7 @@ feature_flags: generate_df_type_layouts: true private_generics_verifier_v2: true deprecate_global_storage_ops: true + consensus_skip_gced_accept_votes: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_104.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_104.snap index 725bced022d33..606eb3b0d457d 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_104.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__Testnet_version_104.snap @@ -128,6 +128,7 @@ feature_flags: generate_df_type_layouts: true private_generics_verifier_v2: true deprecate_global_storage_ops: true + consensus_skip_gced_accept_votes: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000 diff --git a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_104.snap b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_104.snap index 17dfc4db9c6dd..9edf7c721e2e6 100644 --- a/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_104.snap +++ b/crates/sui-protocol-config/src/snapshots/sui_protocol_config__test__version_104.snap @@ -131,6 +131,7 @@ feature_flags: generate_df_type_layouts: true private_generics_verifier_v2: true deprecate_global_storage_ops: true + consensus_skip_gced_accept_votes: true max_tx_size_bytes: 131072 max_input_objects: 2048 max_size_written_objects: 5000000