From be3ccc58ef518259d63fab7f3e3613f2a6214268 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:18:42 +0000 Subject: [PATCH 01/16] [loader-v2] Fixing global cache reads & read-before-write on publish (#15285) (#15298) - Enforces read-before-write for module publishes. - Records all module reads in captured reads, not just per-block. - Adds a workload + test to publish and call modules. Co-authored-by: Igor (cherry picked from commit 0a16e9e46d937c963a78658c5ed59360d977e78c) Co-authored-by: George Mitenkov --- aptos-move/aptos-vm-types/src/resolver.rs | 16 +- aptos-move/aptos-vm/src/data_cache.rs | 6 + .../aptos-vm/src/move_vm_ext/resolver.rs | 2 +- .../session/view_with_change_set.rs | 6 + .../src/move_vm_ext/write_op_converter.rs | 16 + .../block-executor/src/captured_reads.rs | 73 +-- aptos-move/block-executor/src/code_cache.rs | 59 +- aptos-move/block-executor/src/view.rs | 7 + aptos-move/e2e-benchmark/src/main.rs | 6 +- aptos-move/e2e-move-tests/src/tests/gas.rs | 6 +- .../framework/src/natives/state_storage.rs | 6 +- crates/transaction-generator-lib/src/args.rs | 6 + .../src/entry_points.rs | 147 +++-- crates/transaction-generator-lib/src/lib.rs | 31 +- .../src/publishing/module_simple.rs | 37 +- .../src/publishing/publish_util.rs | 43 +- .../src/publishing/raw_module_data.rs | 544 +++++++++--------- .../src/workflow_delegator.rs | 8 +- execution/executor-benchmark/src/lib.rs | 13 + .../src/suites/realistic_workloads.rs | 4 +- .../src/packages/simple/sources/Simple.move | 5 + .../testcases/src/load_vs_perf_benchmark.rs | 4 +- 22 files changed, 604 insertions(+), 441 deletions(-) diff --git a/aptos-move/aptos-vm-types/src/resolver.rs b/aptos-move/aptos-vm-types/src/resolver.rs index 8f2fb475bb5ec..e71673588eace 100644 --- a/aptos-move/aptos-vm-types/src/resolver.rs +++ b/aptos-move/aptos-vm-types/src/resolver.rs @@ -176,8 +176,13 @@ pub trait TModuleView { /// Allows to query state information, e.g. its usage. pub trait StateStorageView { + type Key; + fn id(&self) -> StateViewId; + /// Reads the state value from the DB. Used to enforce read-before-write for module writes. + fn read_state_value(&self, state_key: &Self::Key) -> Result<(), StateviewError>; + fn get_usage(&self) -> Result; } @@ -203,7 +208,7 @@ pub trait TExecutorView: + TModuleView + TAggregatorV1View + TDelayedFieldView - + StateStorageView + + StateStorageView { } @@ -212,7 +217,7 @@ impl TExecutorView for A where + TModuleView + TAggregatorV1View + TDelayedFieldView - + StateStorageView + + StateStorageView { } @@ -278,10 +283,17 @@ impl StateStorageView for S where S: StateView, { + type Key = StateKey; + fn id(&self) -> StateViewId { self.id() } + fn read_state_value(&self, state_key: &Self::Key) -> Result<(), StateviewError> { + self.get_state_value(state_key)?; + Ok(()) + } + fn get_usage(&self) -> Result { self.get_usage().map_err(Into::into) } diff --git a/aptos-move/aptos-vm/src/data_cache.rs b/aptos-move/aptos-vm/src/data_cache.rs index 708e028cc93fe..d2ae08b06194d 100644 --- a/aptos-move/aptos-vm/src/data_cache.rs +++ b/aptos-move/aptos-vm/src/data_cache.rs @@ -312,10 +312,16 @@ impl AsMoveResolver for S { } impl<'e, E: ExecutorView> StateStorageView for StorageAdapter<'e, E> { + type Key = StateKey; + fn id(&self) -> StateViewId { self.executor_view.id() } + fn read_state_value(&self, state_key: &Self::Key) -> Result<(), StateviewError> { + self.executor_view.read_state_value(state_key) + } + fn get_usage(&self) -> Result { self.executor_view.get_usage() } diff --git a/aptos-move/aptos-vm/src/move_vm_ext/resolver.rs b/aptos-move/aptos-vm/src/move_vm_ext/resolver.rs index 1791a38bb08d6..938a75be430c0 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/resolver.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/resolver.rs @@ -23,7 +23,7 @@ pub trait AptosMoveResolver: + ModuleResolver + ResourceResolver + ResourceGroupResolver - + StateStorageView + + StateStorageView + TableResolver + AsExecutorView + AsResourceGroupView diff --git a/aptos-move/aptos-vm/src/move_vm_ext/session/view_with_change_set.rs b/aptos-move/aptos-vm/src/move_vm_ext/session/view_with_change_set.rs index 06862df40c7aa..e1ccb6f506d91 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/session/view_with_change_set.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/session/view_with_change_set.rs @@ -318,10 +318,16 @@ impl<'r> TModuleView for ExecutorViewWithChangeSet<'r> { } impl<'r> StateStorageView for ExecutorViewWithChangeSet<'r> { + type Key = StateKey; + fn id(&self) -> StateViewId { self.base_executor_view.id() } + fn read_state_value(&self, state_key: &Self::Key) -> Result<(), StateviewError> { + self.base_executor_view.read_state_value(state_key) + } + fn get_usage(&self) -> Result { Err(StateviewError::Other( "Unexpected access to get_usage()".to_string(), diff --git a/aptos-move/aptos-vm/src/move_vm_ext/write_op_converter.rs b/aptos-move/aptos-vm/src/move_vm_ext/write_op_converter.rs index 56b1a33161d62..e00783bec99a0 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/write_op_converter.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/write_op_converter.rs @@ -105,6 +105,22 @@ impl<'r> WriteOpConverter<'r> { )?; let state_key = StateKey::module_id(&module_id); + + // Enforce read-before-write: + // Modules can live in global cache, and so the DB may not see a module read even + // when it gets republished. This violates read-before-write property. Here, we on + // purpose enforce this by registering a read to the DB directly. + // Note that we also do it here so that in case of storage errors, only a single + // transaction fails (e.g., if doing this read before commit in block executor we + // have no way to alter the transaction outputs at that point). + self.remote.read_state_value(&state_key).map_err(|err| { + let msg = format!( + "Error when enforcing read-before-write for module {}::{}: {:?}", + addr, name, err + ); + PartialVMError::new(StatusCode::STORAGE_ERROR).with_message(msg) + })?; + writes.insert(state_key, ModuleWrite::new(module_id, write_op)); } Ok(writes) diff --git a/aptos-move/block-executor/src/captured_reads.rs b/aptos-move/block-executor/src/captured_reads.rs index 516b0855c39c4..3deff5419c8a6 100644 --- a/aptos-move/block-executor/src/captured_reads.rs +++ b/aptos-move/block-executor/src/captured_reads.rs @@ -292,13 +292,16 @@ impl DelayedFieldRead { } } -/// Represents a module read, either from immutable cross-block cache, or from code [SyncCodeCache] -/// used by block executor (per-block cache). This way, when transaction needs to read a module -/// from [SyncCodeCache] it can first check the read-set here. +/// Represents a module read, either from global module cache that spans multiple blocks, or from +/// per-block cache used by block executor to add committed modules. When transaction reads a +/// module, it should first check the read-set here, to ensure that if some module A has been read, +/// the same A is read again within the same transaction. enum ModuleRead { - /// Read from the cross-block module cache. - GlobalCache, - /// Read from per-block cache ([SyncCodeCache]) used by parallel execution. + /// Read from the global module cache. Modules in this cache have storage version, but require + /// different validation - a check that they have not been overridden. + GlobalCache(Arc>), + /// Read from per-block cache that contains committed (by specified transaction) and newly + /// loaded from storage (i.e., not yet moved to global module cache) modules. PerBlockCache(Option<(Arc>, Option)>), } @@ -615,8 +618,8 @@ where } /// Records the read to global cache that spans across multiple blocks. - pub(crate) fn capture_global_cache_read(&mut self, key: K) { - self.module_reads.insert(key, ModuleRead::GlobalCache); + pub(crate) fn capture_global_cache_read(&mut self, key: K, read: Arc>) { + self.module_reads.insert(key, ModuleRead::GlobalCache(read)); } /// Records the read to per-block level cache. @@ -629,22 +632,19 @@ where .insert(key, ModuleRead::PerBlockCache(read)); } - /// If the module has been previously read from [SyncCodeCache], returns it. Returns a panic - /// error if the read was cached for the global cross-module cache (we do not capture values - /// for those). + /// If the module has been previously read, returns it. pub(crate) fn get_module_read( &self, key: &K, - ) -> Result>, Option)>>, PanicError> { - Ok(match self.module_reads.get(key) { + ) -> CacheRead>, Option)>> { + match self.module_reads.get(key) { Some(ModuleRead::PerBlockCache(read)) => CacheRead::Hit(read.clone()), - Some(ModuleRead::GlobalCache) => { - return Err(PanicError::CodeInvariantError( - "Global module cache reads do not capture values".to_string(), - )); + Some(ModuleRead::GlobalCache(read)) => { + // From global cache, we return a storage version. + CacheRead::Hit(Some((read.clone(), None))) }, None => CacheRead::Miss, - }) + } } /// For every module read that was captured, checks if the reads are still the same: @@ -661,7 +661,7 @@ where } self.module_reads.iter().all(|(key, read)| match read { - ModuleRead::GlobalCache => global_module_cache.contains_valid(key), + ModuleRead::GlobalCache(_) => global_module_cache.contains_valid(key), ModuleRead::PerBlockCache(previous) => { let current_version = per_block_module_cache.get_module_version(key); let previous_version = previous.as_ref().map(|(_, version)| *version); @@ -1537,20 +1537,6 @@ mod test { ); } - #[test] - fn test_global_cache_module_reads_are_not_recorded() { - let mut captured_reads = CapturedReads::< - TestTransactionType, - u32, - MockDeserializedCode, - MockVerifiedCode, - MockExtension, - >::new(); - - captured_reads.capture_global_cache_read(0); - assert!(captured_reads.get_module_read(&0).is_err()) - } - #[test] fn test_global_cache_module_reads() { let mut captured_reads = CapturedReads::< @@ -1563,11 +1549,13 @@ mod test { let mut global_module_cache = GlobalModuleCache::empty(); let per_block_module_cache = SyncModuleCache::empty(); - global_module_cache.insert(0, mock_verified_code(0, MockExtension::new(8))); - captured_reads.capture_global_cache_read(0); + let module_0 = mock_verified_code(0, MockExtension::new(8)); + global_module_cache.insert(0, module_0.clone()); + captured_reads.capture_global_cache_read(0, module_0); - global_module_cache.insert(1, mock_verified_code(1, MockExtension::new(8))); - captured_reads.capture_global_cache_read(1); + let module_1 = mock_verified_code(1, MockExtension::new(8)); + global_module_cache.insert(1, module_1.clone()); + captured_reads.capture_global_cache_read(1, module_1); assert!(captured_reads.validate_module_reads(&global_module_cache, &per_block_module_cache)); @@ -1613,18 +1601,18 @@ mod test { captured_reads.capture_per_block_cache_read(0, Some((a, Some(2)))); assert!(matches!( captured_reads.get_module_read(&0), - Ok(CacheRead::Hit(Some(_))) + CacheRead::Hit(Some(_)) )); captured_reads.capture_per_block_cache_read(1, None); assert!(matches!( captured_reads.get_module_read(&1), - Ok(CacheRead::Hit(None)) + CacheRead::Hit(None) )); assert!(matches!( captured_reads.get_module_read(&2), - Ok(CacheRead::Miss) + CacheRead::Miss )); } @@ -1701,8 +1689,9 @@ mod test { let per_block_module_cache = SyncModuleCache::empty(); // Module exists in global cache. - global_module_cache.insert(0, mock_verified_code(0, MockExtension::new(8))); - captured_reads.capture_global_cache_read(0); + let m = mock_verified_code(0, MockExtension::new(8)); + global_module_cache.insert(0, m.clone()); + captured_reads.capture_global_cache_read(0, m); assert!(captured_reads.validate_module_reads(&global_module_cache, &per_block_module_cache)); // Assume we republish this module: validation must fail. diff --git a/aptos-move/block-executor/src/code_cache.rs b/aptos-move/block-executor/src/code_cache.rs index 753d4fafb3fe5..081147ce45ae9 100644 --- a/aptos-move/block-executor/src/code_cache.rs +++ b/aptos-move/block-executor/src/code_cache.rs @@ -136,44 +136,39 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> ModuleCache Self::Version, )>, > { - // First, look up the module in the cross-block global module cache. Record the read for - // later validation in case the read module is republished. - if let Some(module) = self.global_module_cache.get_valid(key) { - match &self.latest_view { - ViewState::Sync(state) => state - .captured_reads - .borrow_mut() - .capture_global_cache_read(key.clone()), - ViewState::Unsync(state) => { - state.read_set.borrow_mut().capture_module_read(key.clone()) - }, - } - return Ok(Some((module, Self::Version::default()))); - } - - // Global cache miss: check module cache in versioned/unsync maps. match &self.latest_view { ViewState::Sync(state) => { // Check the transaction-level cache with already read modules first. - let cache_read = state.captured_reads.borrow().get_module_read(key)?; - match cache_read { - CacheRead::Hit(read) => Ok(read), - CacheRead::Miss => { - // If the module has not been accessed by this transaction, go to the - // module cache and record the read. - let read = state - .versioned_map - .module_cache() - .get_module_or_build_with(key, builder)?; - state - .captured_reads - .borrow_mut() - .capture_per_block_cache_read(key.clone(), read.clone()); - Ok(read) - }, + if let CacheRead::Hit(read) = state.captured_reads.borrow().get_module_read(key) { + return Ok(read); } + + // Otherwise, it is a miss. Check global cache. + if let Some(module) = self.global_module_cache.get_valid(key) { + state + .captured_reads + .borrow_mut() + .capture_global_cache_read(key.clone(), module.clone()); + return Ok(Some((module, Self::Version::default()))); + } + + // If not global cache, check per-block cache. + let read = state + .versioned_map + .module_cache() + .get_module_or_build_with(key, builder)?; + state + .captured_reads + .borrow_mut() + .capture_per_block_cache_read(key.clone(), read.clone()); + Ok(read) }, ViewState::Unsync(state) => { + if let Some(module) = self.global_module_cache.get_valid(key) { + state.read_set.borrow_mut().capture_module_read(key.clone()); + return Ok(Some((module, Self::Version::default()))); + } + let read = state .unsync_map .module_cache() diff --git a/aptos-move/block-executor/src/view.rs b/aptos-move/block-executor/src/view.rs index 0659662c09e89..660faf6142104 100644 --- a/aptos-move/block-executor/src/view.rs +++ b/aptos-move/block-executor/src/view.rs @@ -1622,10 +1622,17 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TModuleView impl<'a, T: Transaction, S: TStateView, X: Executable> StateStorageView for LatestView<'a, T, S, X> { + type Key = T::Key; + fn id(&self) -> StateViewId { self.base_view.id() } + fn read_state_value(&self, state_key: &Self::Key) -> Result<(), StateviewError> { + self.base_view.get_state_value(state_key)?; + Ok(()) + } + fn get_usage(&self) -> Result { self.base_view.get_usage() } diff --git a/aptos-move/e2e-benchmark/src/main.rs b/aptos-move/e2e-benchmark/src/main.rs index 6ac46ffd3f785..76e98fc61d63f 100644 --- a/aptos-move/e2e-benchmark/src/main.rs +++ b/aptos-move/e2e-benchmark/src/main.rs @@ -50,7 +50,8 @@ fn execute_and_time_entry_point( let mut rng = StdRng::seed_from_u64(14); let entry_fun = entry_point .create_payload( - package.get_module_id(entry_point.module_name()), + package, + entry_point.module_name(), Some(&mut rng), Some(publisher_address), ) @@ -221,7 +222,8 @@ fn main() { &publisher, 1, init_entry_point.create_payload( - package.get_module_id(init_entry_point.module_name()), + &package, + init_entry_point.module_name(), Some(&mut rng), Some(publisher.address()), ), diff --git a/aptos-move/e2e-move-tests/src/tests/gas.rs b/aptos-move/e2e-move-tests/src/tests/gas.rs index 240d2a30ecc35..19ec6e939aec9 100644 --- a/aptos-move/e2e-move-tests/src/tests/gas.rs +++ b/aptos-move/e2e-move-tests/src/tests/gas.rs @@ -684,7 +684,8 @@ fn test_txn_generator_workloads_calibrate_gas() { runner.harness.run_transaction_payload( &publisher, init_entry_point.create_payload( - package.get_module_id(init_entry_point.module_name()), + &package, + init_entry_point.module_name(), Some(&mut rng), Some(publisher.address()), ), @@ -695,7 +696,8 @@ fn test_txn_generator_workloads_calibrate_gas() { &format!("entry_point_{entry_point:?}"), &user, entry_point.create_payload( - package.get_module_id(entry_point.module_name()), + &package, + entry_point.module_name(), Some(&mut rng), Some(publisher.address()), ), diff --git a/aptos-move/framework/src/natives/state_storage.rs b/aptos-move/framework/src/natives/state_storage.rs index 6f65cf3bc70c3..11f48877255d8 100644 --- a/aptos-move/framework/src/natives/state_storage.rs +++ b/aptos-move/framework/src/natives/state_storage.rs @@ -5,7 +5,7 @@ use aptos_gas_schedule::gas_params::natives::aptos_framework::*; use aptos_native_interface::{ RawSafeNative, SafeNativeBuilder, SafeNativeContext, SafeNativeResult, }; -use aptos_types::vm_status::StatusCode; +use aptos_types::{state_store::state_key::StateKey, vm_status::StatusCode}; use aptos_vm_types::resolver::StateStorageView; use better_any::{Tid, TidAble}; use move_binary_format::errors::PartialVMError; @@ -20,11 +20,11 @@ use std::collections::VecDeque; /// Exposes the ability to query state storage utilization info to native functions. #[derive(Tid)] pub struct NativeStateStorageContext<'a> { - resolver: &'a dyn StateStorageView, + resolver: &'a dyn StateStorageView, } impl<'a> NativeStateStorageContext<'a> { - pub fn new(resolver: &'a dyn StateStorageView) -> Self { + pub fn new(resolver: &'a dyn StateStorageView) -> Self { Self { resolver } } } diff --git a/crates/transaction-generator-lib/src/args.rs b/crates/transaction-generator-lib/src/args.rs index b19bf2651e8b4..fb0cc7779d427 100644 --- a/crates/transaction-generator-lib/src/args.rs +++ b/crates/transaction-generator-lib/src/args.rs @@ -21,6 +21,7 @@ pub enum TransactionTypeArg { AccountGenerationLargePool, Batch100Transfer, PublishPackage, + RepublishAndCall, // Simple EntryPoints NoOp, NoOpFeePayer, @@ -166,6 +167,11 @@ impl TransactionTypeArg { milestone_every: 1000, }) }, + TransactionTypeArg::RepublishAndCall => TransactionType::CallCustomModulesMix { + entry_points: vec![(EntryPoints::Nop, 1), (EntryPoints::Republish, 1)], + num_modules: module_working_set_size, + use_account_pool: sender_use_account_pool, + }, TransactionTypeArg::NoOp => call_custom_module(EntryPoints::Nop), TransactionTypeArg::NoOpFeePayer => call_custom_module(EntryPoints::NopFeePayer), TransactionTypeArg::NoOp2Signers => call_custom_module(EntryPoints::Nop), diff --git a/crates/transaction-generator-lib/src/entry_points.rs b/crates/transaction-generator-lib/src/entry_points.rs index 6c5f5a014243e..424c7c713188b 100644 --- a/crates/transaction-generator-lib/src/entry_points.rs +++ b/crates/transaction-generator-lib/src/entry_points.rs @@ -16,11 +16,46 @@ use aptos_sdk::{ types::{transaction::SignedTransaction, LocalAccount}, }; use async_trait::async_trait; -use rand::rngs::StdRng; +use rand::{rngs::StdRng, Rng}; use std::{borrow::Borrow, sync::Arc}; pub struct EntryPointTransactionGenerator { - pub entry_point: EntryPoints, + entry_points: Vec<(EntryPoints, usize)>, + total_weight: usize, +} + +impl EntryPointTransactionGenerator { + pub fn new_singleton(entry_point: EntryPoints) -> Self { + Self::new(vec![(entry_point, 1)]) + } + + pub fn new(entry_points: Vec<(EntryPoints, usize)>) -> Self { + let total_weight = entry_points.iter().map(|(_, weight)| weight).sum(); + + Self { + entry_points, + total_weight, + } + } + + fn pick_random( + entry_points: &[(EntryPoints, usize)], + total_weight: usize, + rng: &mut StdRng, + ) -> usize { + let mut picked = if entry_points.len() > 1 { + rng.gen_range(0, total_weight) + } else { + 0 + }; + for (index, (_, weight)) in entry_points.iter().enumerate() { + if picked < *weight { + return index; + } + picked -= *weight; + } + unreachable!(); + } } #[async_trait] @@ -32,16 +67,20 @@ impl UserModuleTransactionGenerator for EntryPointTransactionGenerator { txn_factory: &TransactionFactory, rng: &mut StdRng, ) -> Vec { - if let Some(initial_entry_point) = self.entry_point.initialize_entry_point() { - let payload = initial_entry_point.create_payload( - package.get_module_id(initial_entry_point.module_name()), - Some(rng), - Some(&publisher.address()), - ); - vec![publisher.sign_with_transaction_builder(txn_factory.payload(payload))] - } else { - vec![] + let mut result = vec![]; + + for (entry_point, _) in &self.entry_points { + if let Some(initial_entry_point) = entry_point.initialize_entry_point() { + let payload = initial_entry_point.create_payload( + package, + initial_entry_point.module_name(), + Some(rng), + Some(&publisher.address()), + ); + result.push(publisher.sign_with_transaction_builder(txn_factory.payload(payload))) + } } + result } async fn create_generator_fn( @@ -51,48 +90,56 @@ impl UserModuleTransactionGenerator for EntryPointTransactionGenerator { txn_executor: &dyn ReliableTransactionSubmitter, rng: &mut StdRng, ) -> Arc { - let entry_point = self.entry_point; + let entry_points = self.entry_points.clone(); + let total_weight = self.total_weight; - let additional_signers = match entry_point.multi_sig_additional_num() { - MultiSigConfig::Random(num) => { - root_account - .approve_funds( - (num as u64) - * txn_factory.get_max_gas_amount() - * txn_factory.get_gas_unit_price(), - "creating random multi-sig accounts", - ) - .await; + let mut additional_signers = vec![]; + for (entry_point, _) in &entry_points { + additional_signers.push(match entry_point.multi_sig_additional_num() { + MultiSigConfig::Random(num) => { + root_account + .approve_funds( + (num as u64) + * txn_factory.get_max_gas_amount() + * txn_factory.get_gas_unit_price(), + "creating random multi-sig accounts", + ) + .await; - let new_accounts = Arc::new( - (0..num) - .map(|_| LocalAccount::generate(rng)) - .collect::>(), - ); - txn_executor - .execute_transactions( - &new_accounts - .iter() - .map(|to| { - create_account_transaction( - root_account.get_root_account().borrow(), - to.address(), - txn_factory, - 0, - ) - }) + let new_accounts = Arc::new( + (0..num) + .map(|_| LocalAccount::generate(rng)) .collect::>(), - ) - .await - .unwrap(); - Some(new_accounts) - }, - _ => None, - }; + ); + txn_executor + .execute_transactions( + &new_accounts + .iter() + .map(|to| { + create_account_transaction( + root_account.get_root_account().borrow(), + to.address(), + txn_factory, + 0, + ) + }) + .collect::>(), + ) + .await + .unwrap(); + Some(new_accounts) + }, + _ => None, + }); + } Arc::new(move |account, package, publisher, txn_factory, rng| { + let entry_point_idx = Self::pick_random(&entry_points, total_weight, rng); + let entry_point = entry_points[entry_point_idx].0; + let payload = entry_point.create_payload( - package.get_module_id(entry_point.module_name()), + package, + entry_point.module_name(), Some(rng), Some(&publisher.address()), ); @@ -101,7 +148,11 @@ impl UserModuleTransactionGenerator for EntryPointTransactionGenerator { Some(match entry_point.multi_sig_additional_num() { MultiSigConfig::None => account.sign_with_transaction_builder(builder), MultiSigConfig::Random(_) => account.sign_multi_agent_with_transaction_builder( - additional_signers.as_ref().unwrap().iter().collect(), + additional_signers[entry_point_idx] + .as_ref() + .unwrap() + .iter() + .collect(), builder, ), MultiSigConfig::Publisher => { diff --git a/crates/transaction-generator-lib/src/lib.rs b/crates/transaction-generator-lib/src/lib.rs index f9094ba4266ab..ad50d97223633 100644 --- a/crates/transaction-generator-lib/src/lib.rs +++ b/crates/transaction-generator-lib/src/lib.rs @@ -54,7 +54,7 @@ pub use publishing::module_simple::EntryPoints; pub const SEND_AMOUNT: u64 = 1; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub enum TransactionType { CoinTransfer { invalid_transaction_ratio: usize, @@ -75,6 +75,11 @@ pub enum TransactionType { num_modules: usize, use_account_pool: bool, }, + CallCustomModulesMix { + entry_points: Vec<(EntryPoints, usize)>, + num_modules: usize, + use_account_pool: bool, + }, BatchTransfer { batch_size: usize, }, @@ -337,9 +342,27 @@ pub async fn create_txn_generator_creator( txn_executor, *num_modules, entry_point.package_name(), - &mut EntryPointTransactionGenerator { - entry_point: *entry_point, - }, + &mut EntryPointTransactionGenerator::new_singleton(*entry_point), + ) + .await, + ), + *use_account_pool, + &accounts_pool, + ), + TransactionType::CallCustomModulesMix { + entry_points, + num_modules, + use_account_pool, + } => wrap_accounts_pool( + Box::new( + CustomModulesDelegationGeneratorCreator::new( + txn_factory.clone(), + init_txn_factory.clone(), + &root_account, + txn_executor, + *num_modules, + entry_points[0].0.package_name(), + &mut EntryPointTransactionGenerator::new(entry_points.clone()), ) .await, ), diff --git a/crates/transaction-generator-lib/src/publishing/module_simple.rs b/crates/transaction-generator-lib/src/publishing/module_simple.rs index 0bc7b959fb408..f1b338bb23a16 100644 --- a/crates/transaction-generator-lib/src/publishing/module_simple.rs +++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs @@ -126,6 +126,8 @@ pub enum AutomaticArgs { // More info in the Simple.move #[derive(Debug, Copy, Clone)] pub enum EntryPoints { + /// Republish the module + Republish, /// Empty (NoOp) function Nop, /// Empty (NoOp) function, signed by publisher as fee-payer @@ -277,7 +279,8 @@ pub enum EntryPoints { impl EntryPoints { pub fn package_name(&self) -> &'static str { match self { - EntryPoints::Nop + EntryPoints::Republish + | EntryPoints::Nop | EntryPoints::NopFeePayer | EntryPoints::Nop2Signers | EntryPoints::Nop5Signers @@ -334,7 +337,8 @@ impl EntryPoints { pub fn module_name(&self) -> &'static str { match self { - EntryPoints::Nop + EntryPoints::Republish + | EntryPoints::Nop | EntryPoints::NopFeePayer | EntryPoints::Nop2Signers | EntryPoints::Nop5Signers @@ -394,11 +398,20 @@ impl EntryPoints { pub fn create_payload( &self, - module_id: ModuleId, + package: &Package, + module_name: &str, rng: Option<&mut StdRng>, other: Option<&AccountAddress>, ) -> TransactionPayload { + let module_id = package.get_module_id(module_name); match self { + EntryPoints::Republish => { + let (metadata_serialized, code) = package.get_publish_args(); + get_payload(module_id, ident_str!("publish_p").to_owned(), vec![ + bcs::to_bytes(&metadata_serialized).unwrap(), + bcs::to_bytes(&code).unwrap(), + ]) + }, // 0 args EntryPoints::Nop | EntryPoints::NopFeePayer => { get_payload_void(module_id, ident_str!("nop").to_owned()) @@ -765,6 +778,7 @@ impl EntryPoints { pub fn multi_sig_additional_num(&self) -> MultiSigConfig { match self { + EntryPoints::Republish => MultiSigConfig::Publisher, EntryPoints::NopFeePayer => MultiSigConfig::FeePayerPublisher, EntryPoints::Nop2Signers => MultiSigConfig::Random(1), EntryPoints::Nop5Signers => MultiSigConfig::Random(4), @@ -784,6 +798,7 @@ impl EntryPoints { pub fn automatic_args(&self) -> AutomaticArgs { match self { + EntryPoints::Republish => AutomaticArgs::Signer, EntryPoints::Nop | EntryPoints::NopFeePayer | EntryPoints::Step @@ -879,18 +894,26 @@ const GEN_ENTRY_POINTS: &[EntryPoints; 12] = &[ EntryPoints::BytesMakeOrChange { data_length: None }, ]; -pub fn rand_simple_function(rng: &mut StdRng, module_id: ModuleId) -> TransactionPayload { +pub fn rand_simple_function( + package: &Package, + module_name: &str, + rng: &mut StdRng, +) -> TransactionPayload { SIMPLE_ENTRY_POINTS .choose(rng) .unwrap() - .create_payload(module_id, Some(rng), None) + .create_payload(package, module_name, Some(rng), None) } -pub fn rand_gen_function(rng: &mut StdRng, module_id: ModuleId) -> TransactionPayload { +pub fn rand_gen_function( + package: &Package, + module_name: &str, + rng: &mut StdRng, +) -> TransactionPayload { GEN_ENTRY_POINTS .choose(rng) .unwrap() - .create_payload(module_id, Some(rng), None) + .create_payload(package, module_name, Some(rng), None) } // diff --git a/crates/transaction-generator-lib/src/publishing/publish_util.rs b/crates/transaction-generator-lib/src/publishing/publish_util.rs index 68924e485ada2..4549b85cf327d 100644 --- a/crates/transaction-generator-lib/src/publishing/publish_util.rs +++ b/crates/transaction-generator-lib/src/publishing/publish_util.rs @@ -184,13 +184,30 @@ impl Package { module_simple::scramble(self.get_mut_module("simple"), fn_count, rng) } - // Return a transaction payload to publish the current package - pub fn publish_transaction_payload(&self) -> TransactionPayload { + pub fn get_publish_args(&self) -> (Vec, Vec>) { match self { - Self::Simple(modules, metadata) => publish_transaction_payload(modules, metadata), + Self::Simple(modules, metadata) => { + let metadata_serialized = + bcs::to_bytes(metadata).expect("PackageMetadata must serialize"); + let mut code: Vec> = vec![]; + for (_, module) in modules { + let mut module_code: Vec = vec![]; + module + .serialize(&mut module_code) + .expect("Module must serialize"); + code.push(module_code); + } + (metadata_serialized, code) + }, } } + // Return a transaction payload to publish the current package + pub fn publish_transaction_payload(&self) -> TransactionPayload { + let (metadata_serialized, code) = self.get_publish_args(); + aptos_stdlib::code_publish_package_txn(metadata_serialized, code) + } + // Return a transaction to use the current package pub fn use_random_transaction( &self, @@ -198,8 +215,8 @@ impl Package { account: &LocalAccount, txn_factory: &TransactionFactory, ) -> SignedTransaction { - // let payload = module_simple::rand_gen_function(rng, module_id); - let payload = module_simple::rand_simple_function(rng, self.get_module_id("simple")); + // let payload = module_simple::rand_gen_function(self, "simple", rng); + let payload = module_simple::rand_simple_function(self, "simple", rng); account.sign_with_transaction_builder(txn_factory.payload(payload)) } @@ -321,19 +338,3 @@ fn update( } (new_modules, metadata) } - -fn publish_transaction_payload( - modules: &[(String, CompiledModule)], - metadata: &PackageMetadata, -) -> TransactionPayload { - let metadata = bcs::to_bytes(metadata).expect("PackageMetadata must serialize"); - let mut code: Vec> = vec![]; - for (_, module) in modules { - let mut module_code: Vec = vec![]; - module - .serialize(&mut module_code) - .expect("Module must serialize"); - code.push(module_code); - } - aptos_stdlib::code_publish_package_txn(metadata, code) -} diff --git a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs index 4deb1a72d1709..bc18986f4005a 100644 --- a/crates/transaction-generator-lib/src/publishing/raw_module_data.rs +++ b/crates/transaction-generator-lib/src/publishing/raw_module_data.rs @@ -739,10 +739,10 @@ pub static MODULES_COMPLEX: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_SIMPLE_METADATA: Lazy> = Lazy::new(|| { vec![ 13, 71, 101, 110, 101, 114, 105, 99, 77, 111, 100, 117, 108, 101, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 64, 69, 53, 53, 57, 68, 57, 51, 68, 67, 55, 70, 65, - 56, 70, 70, 66, 70, 53, 70, 65, 57, 48, 49, 52, 57, 69, 49, 65, 56, 48, - 56, 55, 57, 67, 65, 52, 56, 50, 66, 67, 52, 67, 48, 50, 48, 51, 51, 50, - 53, 53, 52, 67, 50, 67, 48, 52, 49, 56, 67, 54, 56, 56, 53, 69, 132, 1, + 0, 0, 0, 0, 0, 64, 69, 70, 50, 54, 66, 50, 69, 50, 55, 66, 69, 54, + 50, 53, 68, 56, 67, 56, 50, 48, 50, 57, 53, 48, 50, 51, 49, 70, 69, 55, + 68, 51, 55, 50, 69, 49, 65, 66, 66, 50, 69, 49, 52, 65, 65, 50, 69, 54, + 66, 66, 51, 54, 55, 68, 67, 49, 69, 67, 53, 57, 54, 53, 48, 68, 132, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 77, 139, 59, 14, 194, 48, 16, 68, 251, 61, 133, 229, 30, 135, 11, 80, 208, 64, 197, 9, 162, 20, 43, 123, 64, 86, 156, 93, 203, 134, 80, 32, 238, 142, 45, 1, 138, 102, 154, 249, 188, 49, 179, 159, @@ -764,215 +764,219 @@ pub static PACKAGE_SIMPLE_METADATA: Lazy> = Lazy::new(|| { #[rustfmt::skip] pub static SCRIPT_SIMPLE: Lazy> = Lazy::new(|| { - vec![ - 161, 28, 235, 11, 7, 0, 0, 10, 2, 5, 0, 4, 6, 4, 34, 1, 6, 12, - 0, 5, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 1, 3, 11, 0, 1, 2, - ] + vec![ + 161, 28, 235, 11, 7, 0, 0, 10, 2, 5, 0, 4, 6, 4, 34, 1, 6, 12, + 0, 5, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 1, 3, 11, 0, 1, 2, + ] }); #[rustfmt::skip] pub static MODULE_SIMPLE_SIMPLE: Lazy> = Lazy::new(|| { vec![ - 161, 28, 235, 11, 7, 0, 0, 10, 12, 1, 0, 16, 2, 16, 46, 3, 62, 193, - 1, 4, 255, 1, 10, 5, 137, 2, 169, 2, 7, 178, 4, 192, 4, 8, 242, 8, - 64, 6, 178, 9, 105, 16, 155, 10, 93, 10, 248, 10, 51, 12, 171, 11, 215, 15, - 13, 130, 27, 16, 0, 0, 1, 9, 1, 15, 1, 20, 1, 22, 1, 29, 1, 33, - 1, 40, 0, 1, 8, 0, 0, 3, 8, 0, 0, 5, 7, 0, 0, 6, 8, 0, - 1, 8, 4, 1, 6, 1, 0, 10, 6, 0, 0, 11, 8, 0, 2, 14, 7, 0, - 0, 17, 8, 0, 3, 19, 4, 2, 3, 1, 0, 1, 0, 21, 0, 1, 0, 1, - 4, 23, 0, 2, 0, 1, 2, 24, 3, 4, 0, 1, 0, 25, 7, 1, 0, 1, - 0, 26, 9, 1, 0, 1, 0, 27, 11, 12, 0, 1, 0, 28, 14, 1, 0, 1, - 5, 30, 0, 16, 1, 6, 1, 1, 31, 17, 1, 1, 6, 1, 0, 32, 0, 1, - 0, 1, 6, 34, 19, 19, 0, 1, 0, 35, 14, 1, 0, 1, 0, 36, 0, 1, - 0, 1, 0, 37, 0, 1, 0, 1, 0, 38, 14, 1, 0, 1, 0, 39, 23, 1, - 0, 1, 7, 41, 25, 3, 1, 0, 1, 0, 42, 14, 1, 0, 1, 0, 43, 27, - 1, 0, 1, 0, 44, 23, 1, 0, 1, 3, 45, 1, 30, 2, 3, 4, 1, 3, - 46, 31, 32, 2, 3, 2, 1, 0, 47, 34, 1, 0, 1, 0, 48, 34, 1, 0, - 1, 0, 49, 0, 1, 0, 1, 0, 50, 37, 1, 0, 1, 0, 51, 38, 1, 0, - 1, 0, 52, 0, 1, 0, 1, 0, 53, 14, 1, 0, 1, 0, 54, 41, 1, 0, - 1, 0, 55, 0, 1, 0, 1, 7, 15, 8, 15, 16, 24, 20, 29, 21, 29, 1, - 6, 12, 0, 1, 5, 1, 10, 2, 1, 8, 7, 1, 2, 4, 8, 2, 8, 6, - 7, 8, 6, 3, 2, 7, 10, 2, 6, 10, 2, 4, 3, 3, 7, 10, 2, 2, - 2, 6, 12, 10, 2, 2, 7, 10, 2, 8, 0, 4, 6, 8, 6, 6, 8, 6, - 6, 8, 1, 6, 8, 1, 1, 6, 3, 4, 6, 3, 6, 3, 6, 3, 6, 3, - 2, 6, 12, 3, 1, 8, 5, 1, 11, 4, 1, 9, 0, 2, 7, 11, 4, 1, - 9, 0, 9, 0, 5, 5, 6, 12, 8, 3, 7, 8, 3, 3, 1, 3, 4, 10, - 3, 3, 3, 10, 3, 1, 8, 1, 8, 3, 3, 3, 3, 3, 1, 1, 1, 3, - 6, 12, 3, 3, 1, 10, 3, 1, 6, 9, 0, 4, 10, 3, 3, 3, 10, 2, - 4, 6, 12, 3, 8, 7, 10, 2, 6, 7, 8, 6, 7, 3, 7, 8, 7, 7, - 10, 2, 8, 2, 8, 6, 2, 3, 3, 1, 11, 9, 2, 9, 0, 9, 1, 3, - 7, 11, 9, 2, 9, 0, 9, 1, 9, 0, 9, 1, 1, 7, 9, 1, 7, 5, - 6, 12, 8, 8, 7, 11, 9, 2, 3, 3, 3, 3, 7, 3, 2, 6, 12, 5, - 5, 8, 2, 8, 6, 10, 2, 7, 8, 6, 1, 8, 8, 2, 8, 6, 6, 8, - 6, 6, 8, 6, 3, 3, 3, 7, 8, 6, 2, 6, 12, 6, 12, 5, 6, 12, - 6, 12, 6, 12, 6, 12, 6, 12, 3, 7, 8, 6, 8, 2, 8, 6, 5, 8, - 2, 3, 8, 7, 8, 6, 7, 3, 2, 6, 12, 8, 7, 3, 8, 2, 8, 6, - 7, 8, 7, 2, 5, 7, 8, 1, 6, 115, 105, 109, 112, 108, 101, 12, 66, 121, - 116, 101, 82, 101, 115, 111, 117, 114, 99, 101, 4, 100, 97, 116, 97, 7, 67, 111, - 117, 110, 116, 101, 114, 5, 99, 111, 117, 110, 116, 4, 68, 97, 116, 97, 10, 69, - 118, 101, 110, 116, 83, 116, 111, 114, 101, 13, 115, 105, 109, 112, 108, 101, 95, 101, - 118, 101, 110, 116, 115, 11, 69, 118, 101, 110, 116, 72, 97, 110, 100, 108, 101, 5, - 101, 118, 101, 110, 116, 11, 83, 105, 109, 112, 108, 101, 69, 118, 101, 110, 116, 8, - 82, 101, 115, 111, 117, 114, 99, 101, 2, 105, 100, 4, 110, 97, 109, 101, 6, 83, - 116, 114, 105, 110, 103, 6, 115, 116, 114, 105, 110, 103, 8, 101, 118, 101, 110, 116, - 95, 105, 100, 10, 84, 97, 98, 108, 101, 83, 116, 111, 114, 101, 13, 116, 97, 98, - 108, 101, 95, 101, 110, 116, 114, 105, 101, 115, 5, 84, 97, 98, 108, 101, 5, 116, - 97, 98, 108, 101, 6, 100, 111, 117, 98, 108, 101, 6, 115, 105, 103, 110, 101, 114, - 10, 97, 100, 100, 114, 101, 115, 115, 95, 111, 102, 4, 117, 116, 102, 56, 11, 97, - 112, 112, 101, 110, 100, 95, 100, 97, 116, 97, 20, 98, 121, 116, 101, 115, 95, 109, - 97, 107, 101, 95, 111, 114, 95, 99, 104, 97, 110, 103, 101, 14, 99, 111, 112, 121, - 95, 112, 97, 115, 116, 97, 95, 114, 101, 102, 11, 101, 109, 105, 116, 95, 101, 118, - 101, 110, 116, 115, 7, 97, 99, 99, 111, 117, 110, 116, 16, 110, 101, 119, 95, 101, - 118, 101, 110, 116, 95, 104, 97, 110, 100, 108, 101, 10, 101, 109, 105, 116, 95, 101, - 118, 101, 110, 116, 11, 103, 101, 116, 95, 99, 111, 117, 110, 116, 101, 114, 5, 101, - 114, 114, 111, 114, 16, 105, 110, 118, 97, 108, 105, 100, 95, 97, 114, 103, 117, 109, - 101, 110, 116, 21, 103, 101, 116, 95, 102, 114, 111, 109, 95, 114, 97, 110, 100, 111, - 109, 95, 99, 111, 110, 115, 116, 4, 104, 97, 108, 102, 11, 105, 110, 105, 116, 95, - 109, 111, 100, 117, 108, 101, 15, 108, 111, 111, 112, 95, 97, 114, 105, 116, 104, 109, - 101, 116, 105, 99, 8, 108, 111, 111, 112, 95, 98, 99, 115, 3, 98, 99, 115, 8, - 116, 111, 95, 98, 121, 116, 101, 115, 8, 108, 111, 111, 112, 95, 110, 111, 112, 14, - 109, 97, 107, 101, 95, 111, 114, 95, 99, 104, 97, 110, 103, 101, 20, 109, 97, 107, - 101, 95, 111, 114, 95, 99, 104, 97, 110, 103, 101, 95, 116, 97, 98, 108, 101, 3, - 110, 101, 119, 23, 98, 111, 114, 114, 111, 119, 95, 109, 117, 116, 95, 119, 105, 116, - 104, 95, 100, 101, 102, 97, 117, 108, 116, 8, 109, 97, 120, 105, 109, 105, 122, 101, - 8, 109, 105, 110, 105, 109, 105, 122, 101, 3, 110, 111, 112, 13, 110, 111, 112, 95, - 50, 95, 115, 105, 103, 110, 101, 114, 115, 13, 110, 111, 112, 95, 53, 95, 115, 105, - 103, 110, 101, 114, 115, 10, 114, 101, 115, 101, 116, 95, 100, 97, 116, 97, 6, 115, - 101, 116, 95, 105, 100, 8, 115, 101, 116, 95, 110, 97, 109, 101, 11, 115, 116, 101, - 112, 95, 115, 105, 103, 110, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 161, 28, 235, 11, 7, 0, 0, 10, 12, 1, 0, 18, 2, 18, 46, 3, 64, 205, + 1, 4, 141, 2, 10, 5, 151, 2, 187, 2, 7, 210, 4, 227, 4, 8, 181, 9, + 64, 6, 245, 9, 105, 16, 222, 10, 93, 10, 187, 11, 51, 12, 238, 11, 233, 15, + 13, 215, 27, 16, 0, 0, 1, 9, 1, 15, 1, 20, 1, 22, 1, 29, 1, 33, + 1, 40, 1, 53, 0, 1, 8, 0, 0, 3, 8, 0, 0, 5, 7, 0, 0, 6, + 8, 0, 1, 8, 4, 1, 6, 1, 0, 10, 6, 0, 0, 11, 8, 0, 2, 14, + 7, 0, 0, 17, 8, 0, 3, 19, 4, 2, 3, 1, 0, 1, 0, 21, 0, 1, + 0, 1, 4, 23, 0, 2, 0, 1, 2, 24, 3, 4, 0, 1, 0, 25, 7, 1, + 0, 1, 0, 26, 9, 1, 0, 1, 0, 27, 11, 12, 0, 1, 0, 28, 14, 1, + 0, 1, 5, 30, 0, 16, 1, 6, 1, 1, 31, 17, 1, 1, 6, 1, 0, 32, + 0, 1, 0, 1, 6, 34, 19, 19, 0, 1, 0, 35, 14, 1, 0, 1, 0, 36, + 0, 1, 0, 1, 0, 37, 0, 1, 0, 1, 0, 38, 14, 1, 0, 1, 0, 39, + 23, 1, 0, 1, 7, 41, 25, 3, 1, 0, 1, 0, 42, 14, 1, 0, 1, 0, + 43, 27, 1, 0, 1, 0, 44, 23, 1, 0, 1, 3, 45, 1, 30, 2, 3, 4, + 1, 3, 46, 31, 32, 2, 3, 2, 1, 0, 47, 34, 1, 0, 1, 0, 48, 34, + 1, 0, 1, 0, 49, 0, 1, 0, 1, 0, 50, 37, 1, 0, 1, 0, 51, 38, + 1, 0, 1, 0, 52, 39, 1, 0, 1, 8, 54, 40, 1, 0, 1, 0, 55, 0, + 1, 0, 1, 0, 56, 14, 1, 0, 1, 0, 57, 43, 1, 0, 1, 0, 58, 0, + 1, 0, 1, 7, 15, 8, 15, 16, 24, 20, 29, 21, 29, 1, 6, 12, 0, 1, + 5, 1, 10, 2, 1, 8, 7, 1, 2, 4, 8, 2, 8, 6, 7, 8, 6, 3, + 2, 7, 10, 2, 6, 10, 2, 4, 3, 3, 7, 10, 2, 2, 2, 6, 12, 10, + 2, 2, 7, 10, 2, 8, 0, 4, 6, 8, 6, 6, 8, 6, 6, 8, 1, 6, + 8, 1, 1, 6, 3, 4, 6, 3, 6, 3, 6, 3, 6, 3, 2, 6, 12, 3, + 1, 8, 5, 1, 11, 4, 1, 9, 0, 2, 7, 11, 4, 1, 9, 0, 9, 0, + 5, 5, 6, 12, 8, 3, 7, 8, 3, 3, 1, 3, 4, 10, 3, 3, 3, 10, + 3, 1, 8, 1, 8, 3, 3, 3, 3, 3, 1, 1, 1, 3, 6, 12, 3, 3, + 1, 10, 3, 1, 6, 9, 0, 4, 10, 3, 3, 3, 10, 2, 4, 6, 12, 3, + 8, 7, 10, 2, 6, 7, 8, 6, 7, 3, 7, 8, 7, 7, 10, 2, 8, 2, + 8, 6, 2, 3, 3, 1, 11, 9, 2, 9, 0, 9, 1, 3, 7, 11, 9, 2, + 9, 0, 9, 1, 9, 0, 9, 1, 1, 7, 9, 1, 7, 5, 6, 12, 8, 8, + 7, 11, 9, 2, 3, 3, 3, 3, 7, 3, 2, 6, 12, 5, 5, 8, 2, 8, + 6, 10, 2, 7, 8, 6, 1, 8, 8, 2, 8, 6, 6, 8, 6, 6, 8, 6, + 3, 3, 3, 7, 8, 6, 2, 6, 12, 6, 12, 5, 6, 12, 6, 12, 6, 12, + 6, 12, 6, 12, 4, 6, 12, 6, 12, 10, 2, 10, 10, 2, 3, 6, 12, 10, + 2, 10, 10, 2, 3, 7, 8, 6, 8, 2, 8, 6, 5, 8, 2, 3, 8, 7, + 8, 6, 7, 3, 2, 6, 12, 8, 7, 3, 8, 2, 8, 6, 7, 8, 7, 2, + 5, 7, 8, 1, 6, 115, 105, 109, 112, 108, 101, 12, 66, 121, 116, 101, 82, 101, + 115, 111, 117, 114, 99, 101, 4, 100, 97, 116, 97, 7, 67, 111, 117, 110, 116, 101, + 114, 5, 99, 111, 117, 110, 116, 4, 68, 97, 116, 97, 10, 69, 118, 101, 110, 116, + 83, 116, 111, 114, 101, 13, 115, 105, 109, 112, 108, 101, 95, 101, 118, 101, 110, 116, + 115, 11, 69, 118, 101, 110, 116, 72, 97, 110, 100, 108, 101, 5, 101, 118, 101, 110, + 116, 11, 83, 105, 109, 112, 108, 101, 69, 118, 101, 110, 116, 8, 82, 101, 115, 111, + 117, 114, 99, 101, 2, 105, 100, 4, 110, 97, 109, 101, 6, 83, 116, 114, 105, 110, + 103, 6, 115, 116, 114, 105, 110, 103, 8, 101, 118, 101, 110, 116, 95, 105, 100, 10, + 84, 97, 98, 108, 101, 83, 116, 111, 114, 101, 13, 116, 97, 98, 108, 101, 95, 101, + 110, 116, 114, 105, 101, 115, 5, 84, 97, 98, 108, 101, 5, 116, 97, 98, 108, 101, + 6, 100, 111, 117, 98, 108, 101, 6, 115, 105, 103, 110, 101, 114, 10, 97, 100, 100, + 114, 101, 115, 115, 95, 111, 102, 4, 117, 116, 102, 56, 11, 97, 112, 112, 101, 110, + 100, 95, 100, 97, 116, 97, 20, 98, 121, 116, 101, 115, 95, 109, 97, 107, 101, 95, + 111, 114, 95, 99, 104, 97, 110, 103, 101, 14, 99, 111, 112, 121, 95, 112, 97, 115, + 116, 97, 95, 114, 101, 102, 11, 101, 109, 105, 116, 95, 101, 118, 101, 110, 116, 115, + 7, 97, 99, 99, 111, 117, 110, 116, 16, 110, 101, 119, 95, 101, 118, 101, 110, 116, + 95, 104, 97, 110, 100, 108, 101, 10, 101, 109, 105, 116, 95, 101, 118, 101, 110, 116, + 11, 103, 101, 116, 95, 99, 111, 117, 110, 116, 101, 114, 5, 101, 114, 114, 111, 114, + 16, 105, 110, 118, 97, 108, 105, 100, 95, 97, 114, 103, 117, 109, 101, 110, 116, 21, + 103, 101, 116, 95, 102, 114, 111, 109, 95, 114, 97, 110, 100, 111, 109, 95, 99, 111, + 110, 115, 116, 4, 104, 97, 108, 102, 11, 105, 110, 105, 116, 95, 109, 111, 100, 117, + 108, 101, 15, 108, 111, 111, 112, 95, 97, 114, 105, 116, 104, 109, 101, 116, 105, 99, + 8, 108, 111, 111, 112, 95, 98, 99, 115, 3, 98, 99, 115, 8, 116, 111, 95, 98, + 121, 116, 101, 115, 8, 108, 111, 111, 112, 95, 110, 111, 112, 14, 109, 97, 107, 101, + 95, 111, 114, 95, 99, 104, 97, 110, 103, 101, 20, 109, 97, 107, 101, 95, 111, 114, + 95, 99, 104, 97, 110, 103, 101, 95, 116, 97, 98, 108, 101, 3, 110, 101, 119, 23, + 98, 111, 114, 114, 111, 119, 95, 109, 117, 116, 95, 119, 105, 116, 104, 95, 100, 101, + 102, 97, 117, 108, 116, 8, 109, 97, 120, 105, 109, 105, 122, 101, 8, 109, 105, 110, + 105, 109, 105, 122, 101, 3, 110, 111, 112, 13, 110, 111, 112, 95, 50, 95, 115, 105, + 103, 110, 101, 114, 115, 13, 110, 111, 112, 95, 53, 95, 115, 105, 103, 110, 101, 114, + 115, 9, 112, 117, 98, 108, 105, 115, 104, 95, 112, 4, 99, 111, 100, 101, 19, 112, + 117, 98, 108, 105, 115, 104, 95, 112, 97, 99, 107, 97, 103, 101, 95, 116, 120, 110, + 10, 114, 101, 115, 101, 116, 95, 100, 97, 116, 97, 6, 115, 101, 116, 95, 105, 100, + 8, 115, 101, 116, 95, 110, 97, 109, 101, 11, 115, 116, 101, 112, 95, 115, 105, 103, + 110, 101, 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 171, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 171, 205, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 10, 2, 9, 8, 1, 35, 69, 103, 137, 171, 205, 239, 10, 2, 6, 5, 104, 101, - 108, 108, 111, 10, 3, 81, 10, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, - 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, - 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, - 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 20, 99, 111, - 109, 112, 105, 108, 97, 116, 105, 111, 110, 95, 109, 101, 116, 97, 100, 97, 116, 97, - 9, 0, 3, 50, 46, 48, 3, 50, 46, 49, 18, 97, 112, 116, 111, 115, 58, 58, - 109, 101, 116, 97, 100, 97, 116, 97, 95, 118, 49, 42, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 29, 69, 67, 79, 85, 78, 84, 69, 82, 95, 82, 69, 83, 79, 85, - 82, 67, 69, 95, 78, 79, 84, 95, 80, 82, 69, 83, 69, 78, 84, 0, 0, 0, - 0, 2, 1, 2, 10, 2, 1, 2, 1, 4, 3, 2, 2, 1, 2, 10, 2, 3, - 2, 1, 7, 11, 4, 1, 8, 5, 6, 2, 3, 12, 3, 13, 8, 7, 2, 8, - 2, 5, 2, 1, 16, 3, 8, 2, 1, 18, 11, 9, 2, 3, 3, 0, 1, 4, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 2, 9, 8, 1, + 35, 69, 103, 137, 171, 205, 239, 10, 2, 6, 5, 104, 101, 108, 108, 111, 10, 3, + 81, 10, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 20, 99, 111, 109, 112, 105, 108, 97, + 116, 105, 111, 110, 95, 109, 101, 116, 97, 100, 97, 116, 97, 9, 0, 3, 50, 46, + 48, 3, 50, 46, 49, 18, 97, 112, 116, 111, 115, 58, 58, 109, 101, 116, 97, 100, + 97, 116, 97, 95, 118, 49, 42, 1, 1, 0, 0, 0, 0, 0, 0, 0, 29, 69, + 67, 79, 85, 78, 84, 69, 82, 95, 82, 69, 83, 79, 85, 82, 67, 69, 95, 78, + 79, 84, 95, 80, 82, 69, 83, 69, 78, 84, 0, 0, 0, 0, 2, 1, 2, 10, + 2, 1, 2, 1, 4, 3, 2, 2, 1, 2, 10, 2, 3, 2, 1, 7, 11, 4, + 1, 8, 5, 6, 2, 3, 12, 3, 13, 8, 7, 2, 8, 2, 5, 2, 1, 16, + 3, 8, 2, 1, 18, 11, 9, 2, 3, 3, 0, 1, 4, 1, 4, 6, 44, 10, + 0, 17, 1, 41, 4, 3, 17, 7, 0, 18, 2, 12, 1, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 1, 17, 2, 11, 1, 18, 4, 12, 2, 11, 0, 11, 2, + 45, 4, 2, 11, 0, 17, 1, 42, 4, 12, 3, 10, 3, 16, 0, 16, 1, 65, + 5, 6, 2, 0, 0, 0, 0, 0, 0, 0, 24, 12, 4, 10, 3, 16, 0, 16, + 1, 65, 5, 10, 4, 35, 4, 41, 10, 3, 15, 0, 15, 1, 49, 255, 68, 5, + 5, 28, 11, 3, 1, 5, 16, 3, 0, 0, 0, 8, 31, 10, 1, 65, 5, 12, + 2, 10, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 26, 10, 0, 12, + 4, 10, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, 12, 3, 10, 1, 11, + 3, 66, 5, 20, 12, 5, 11, 4, 11, 5, 68, 5, 11, 2, 6, 1, 0, 0, + 0, 0, 0, 0, 0, 23, 12, 2, 5, 3, 11, 0, 1, 11, 1, 1, 2, 4, + 1, 4, 1, 0, 10, 20, 10, 0, 17, 1, 41, 0, 4, 13, 11, 0, 17, 1, + 42, 0, 15, 2, 12, 2, 11, 1, 11, 2, 21, 2, 11, 1, 18, 0, 12, 3, + 11, 0, 11, 3, 45, 0, 5, 12, 5, 0, 0, 0, 13, 101, 10, 0, 16, 3, + 12, 4, 10, 1, 16, 3, 12, 5, 11, 4, 20, 10, 5, 20, 35, 4, 92, 11, + 5, 12, 4, 10, 2, 16, 4, 12, 5, 10, 5, 20, 10, 1, 16, 3, 20, 35, + 4, 67, 11, 0, 1, 11, 1, 1, 11, 2, 1, 11, 4, 1, 11, 5, 12, 4, + 11, 3, 16, 4, 12, 5, 10, 4, 20, 10, 5, 20, 35, 4, 62, 11, 5, 1, + 10, 4, 12, 5, 10, 4, 10, 5, 33, 4, 57, 11, 5, 1, 11, 4, 12, 7, + 11, 7, 2, 11, 4, 1, 11, 5, 12, 7, 5, 55, 11, 4, 1, 10, 5, 12, + 4, 5, 47, 11, 3, 1, 11, 0, 16, 3, 12, 7, 10, 4, 11, 7, 34, 4, + 87, 11, 4, 1, 11, 5, 1, 11, 2, 16, 4, 12, 4, 11, 1, 16, 3, 12, + 5, 5, 37, 11, 1, 1, 11, 2, 1, 5, 37, 11, 5, 1, 10, 1, 16, 3, + 12, 4, 10, 3, 16, 4, 12, 5, 5, 17, 6, 0, 0, 1, 3, 18, 38, 10, + 0, 17, 1, 12, 2, 10, 2, 41, 3, 3, 35, 10, 0, 12, 3, 11, 0, 56, + 0, 18, 3, 12, 4, 11, 3, 11, 4, 45, 3, 11, 2, 42, 3, 12, 5, 10, + 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 32, 11, 1, 6, 1, 0, + 0, 0, 0, 0, 0, 0, 23, 12, 1, 10, 5, 15, 5, 10, 1, 18, 5, 56, + 1, 5, 18, 11, 5, 1, 2, 11, 0, 1, 5, 15, 9, 1, 4, 1, 1, 2, + 15, 11, 0, 17, 1, 12, 1, 10, 1, 41, 1, 4, 12, 11, 1, 43, 1, 16, + 4, 20, 1, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 17, 10, 39, 11, 1, + 4, 0, 20, 29, 7, 2, 12, 2, 11, 0, 1, 14, 2, 65, 19, 12, 3, 10, + 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 34, 3, 12, 5, 28, 10, 1, 10, + 3, 38, 3, 17, 5, 21, 11, 3, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, + 12, 1, 7, 2, 12, 5, 14, 5, 11, 1, 66, 19, 20, 1, 2, 12, 1, 4, 1, 4, 6, 44, 10, 0, 17, 1, 41, 4, 3, 17, 7, 0, 18, 2, 12, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 17, 2, 11, 1, 18, 4, 12, 2, 11, 0, 11, 2, 45, 4, 2, 11, 0, 17, 1, 42, 4, 12, 3, 10, 3, - 16, 0, 16, 1, 65, 5, 6, 2, 0, 0, 0, 0, 0, 0, 0, 24, 12, 4, - 10, 3, 16, 0, 16, 1, 65, 5, 10, 4, 35, 4, 41, 10, 3, 15, 0, 15, - 1, 49, 255, 68, 5, 5, 28, 11, 3, 1, 5, 16, 3, 0, 0, 0, 8, 31, - 10, 1, 65, 5, 12, 2, 10, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, - 4, 26, 10, 0, 12, 4, 10, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, - 12, 3, 10, 1, 11, 3, 66, 5, 20, 12, 5, 11, 4, 11, 5, 68, 5, 11, - 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, 12, 2, 5, 3, 11, 0, 1, - 11, 1, 1, 2, 4, 1, 4, 1, 0, 10, 20, 10, 0, 17, 1, 41, 0, 4, - 13, 11, 0, 17, 1, 42, 0, 15, 2, 12, 2, 11, 1, 11, 2, 21, 2, 11, - 1, 18, 0, 12, 3, 11, 0, 11, 3, 45, 0, 5, 12, 5, 0, 0, 0, 13, - 101, 10, 0, 16, 3, 12, 4, 10, 1, 16, 3, 12, 5, 11, 4, 20, 10, 5, - 20, 35, 4, 92, 11, 5, 12, 4, 10, 2, 16, 4, 12, 5, 10, 5, 20, 10, - 1, 16, 3, 20, 35, 4, 67, 11, 0, 1, 11, 1, 1, 11, 2, 1, 11, 4, - 1, 11, 5, 12, 4, 11, 3, 16, 4, 12, 5, 10, 4, 20, 10, 5, 20, 35, - 4, 62, 11, 5, 1, 10, 4, 12, 5, 10, 4, 10, 5, 33, 4, 57, 11, 5, - 1, 11, 4, 12, 7, 11, 7, 2, 11, 4, 1, 11, 5, 12, 7, 5, 55, 11, - 4, 1, 10, 5, 12, 4, 5, 47, 11, 3, 1, 11, 0, 16, 3, 12, 7, 10, - 4, 11, 7, 34, 4, 87, 11, 4, 1, 11, 5, 1, 11, 2, 16, 4, 12, 4, - 11, 1, 16, 3, 12, 5, 5, 37, 11, 1, 1, 11, 2, 1, 5, 37, 11, 5, - 1, 10, 1, 16, 3, 12, 4, 10, 3, 16, 4, 12, 5, 5, 17, 6, 0, 0, - 1, 3, 18, 38, 10, 0, 17, 1, 12, 2, 10, 2, 41, 3, 3, 35, 10, 0, - 12, 3, 11, 0, 56, 0, 18, 3, 12, 4, 11, 3, 11, 4, 45, 3, 11, 2, - 42, 3, 12, 5, 10, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 32, - 11, 1, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, 12, 1, 10, 5, 15, 5, - 10, 1, 18, 5, 56, 1, 5, 18, 11, 5, 1, 2, 11, 0, 1, 5, 15, 9, - 1, 4, 1, 1, 2, 15, 11, 0, 17, 1, 12, 1, 10, 1, 41, 1, 4, 12, - 11, 1, 43, 1, 16, 4, 20, 1, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, - 17, 10, 39, 11, 1, 4, 0, 20, 29, 7, 2, 12, 2, 11, 0, 1, 14, 2, - 65, 19, 12, 3, 10, 3, 6, 0, 0, 0, 0, 0, 0, 0, 0, 34, 3, 12, - 5, 28, 10, 1, 10, 3, 38, 3, 17, 5, 21, 11, 3, 6, 1, 0, 0, 0, - 0, 0, 0, 0, 23, 12, 1, 7, 2, 12, 5, 14, 5, 11, 1, 66, 19, 20, - 1, 2, 12, 1, 4, 1, 4, 6, 44, 10, 0, 17, 1, 41, 4, 3, 17, 7, - 0, 18, 2, 12, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 17, 2, - 11, 1, 18, 4, 12, 2, 11, 0, 11, 2, 45, 4, 2, 11, 0, 17, 1, 42, - 4, 12, 3, 10, 3, 16, 0, 16, 1, 65, 5, 6, 2, 0, 0, 0, 0, 0, - 0, 0, 26, 12, 4, 10, 3, 16, 0, 16, 1, 65, 5, 10, 4, 36, 4, 41, - 10, 3, 15, 0, 15, 1, 69, 5, 1, 5, 28, 11, 3, 1, 5, 16, 13, 0, - 0, 0, 21, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, 18, 1, 12, 1, 11, - 0, 11, 1, 45, 1, 2, 14, 1, 4, 0, 22, 76, 6, 0, 0, 0, 0, 0, - 0, 0, 0, 12, 2, 11, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, - 3, 10, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 75, 11, 1, 6, - 1, 0, 0, 0, 0, 0, 0, 0, 23, 12, 1, 11, 2, 6, 1, 0, 0, 0, - 0, 0, 0, 0, 22, 12, 4, 11, 3, 6, 1, 0, 0, 0, 0, 0, 0, 0, - 22, 12, 5, 10, 4, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 11, 4, 23, - 12, 3, 10, 5, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 10, 5, 23, 12, - 4, 10, 4, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 2, 10, 4, 10, - 2, 36, 4, 72, 10, 2, 10, 5, 36, 12, 7, 11, 7, 4, 69, 11, 5, 10, - 3, 36, 12, 8, 11, 8, 4, 66, 10, 3, 11, 4, 36, 12, 9, 11, 9, 3, - 61, 5, 6, 11, 1, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 1, 5, - 6, 9, 12, 9, 5, 58, 9, 12, 8, 5, 52, 9, 12, 7, 5, 46, 2, 15, - 1, 4, 0, 26, 45, 64, 19, 0, 0, 0, 0, 0, 0, 0, 0, 12, 3, 11, - 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 4, 10, 4, 10, 2, 35, - 4, 18, 13, 3, 10, 4, 68, 19, 11, 4, 6, 1, 0, 0, 0, 0, 0, 0, - 0, 22, 12, 4, 5, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 10, - 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 44, 14, 3, 56, 2, 12, - 6, 11, 2, 12, 4, 14, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 66, 5, - 20, 52, 12, 5, 11, 4, 11, 5, 22, 12, 2, 11, 1, 6, 1, 0, 0, 0, - 0, 0, 0, 0, 23, 12, 1, 5, 20, 2, 17, 1, 4, 0, 19, 10, 10, 1, - 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, 4, 9, 11, 1, 6, 1, 0, 0, - 0, 0, 0, 0, 0, 23, 12, 1, 5, 0, 2, 18, 1, 4, 1, 4, 28, 40, - 10, 0, 17, 1, 41, 4, 4, 28, 11, 0, 17, 1, 42, 4, 12, 4, 10, 4, - 15, 3, 12, 5, 11, 1, 11, 5, 21, 10, 4, 15, 6, 12, 6, 11, 2, 11, - 6, 21, 11, 4, 15, 0, 15, 1, 12, 7, 11, 3, 11, 7, 21, 2, 11, 3, - 18, 2, 12, 8, 11, 1, 11, 2, 11, 8, 18, 4, 12, 9, 11, 0, 11, 9, - 45, 4, 5, 27, 19, 0, 0, 1, 6, 33, 48, 10, 0, 17, 1, 12, 3, 10, - 3, 41, 6, 3, 45, 11, 0, 12, 4, 56, 3, 18, 6, 12, 5, 11, 4, 11, - 5, 45, 6, 11, 3, 42, 6, 15, 7, 12, 6, 10, 2, 6, 0, 0, 0, 0, - 0, 0, 0, 0, 36, 4, 42, 11, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, - 23, 12, 2, 10, 1, 10, 2, 22, 12, 7, 10, 6, 11, 7, 6, 0, 0, 0, - 0, 0, 0, 0, 0, 56, 4, 12, 9, 10, 9, 20, 6, 1, 0, 0, 0, 0, - 0, 0, 0, 22, 11, 9, 21, 5, 18, 11, 6, 1, 2, 11, 0, 1, 5, 14, - 22, 1, 4, 1, 4, 35, 86, 10, 1, 41, 4, 4, 6, 11, 0, 1, 2, 10, - 0, 17, 1, 41, 4, 4, 11, 5, 23, 7, 0, 18, 2, 12, 2, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 7, 1, 17, 2, 11, 2, 18, 4, 12, 3, 10, 0, - 11, 3, 45, 4, 10, 0, 17, 1, 43, 4, 16, 0, 16, 1, 65, 5, 10, 1, - 43, 4, 16, 0, 16, 1, 65, 5, 36, 4, 75, 11, 0, 17, 1, 43, 4, 16, - 0, 16, 1, 20, 12, 4, 11, 1, 42, 4, 12, 5, 14, 4, 65, 5, 10, 5, - 16, 0, 16, 1, 65, 5, 36, 4, 67, 8, 12, 6, 11, 6, 4, 64, 10, 5, - 15, 0, 15, 1, 14, 4, 17, 3, 5, 46, 11, 5, 1, 2, 10, 5, 16, 0, - 16, 1, 65, 5, 6, 16, 39, 0, 0, 0, 0, 0, 0, 35, 12, 6, 5, 56, - 11, 1, 43, 4, 16, 0, 16, 1, 20, 12, 4, 11, 0, 17, 1, 42, 4, 12, - 5, 5, 46, 23, 1, 4, 1, 4, 36, 76, 10, 1, 41, 4, 4, 6, 11, 0, - 1, 2, 10, 0, 17, 1, 41, 4, 4, 11, 5, 23, 7, 0, 18, 2, 12, 2, - 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 17, 2, 11, 2, 18, 4, 12, - 3, 10, 0, 11, 3, 45, 4, 10, 0, 17, 1, 43, 4, 10, 1, 43, 4, 12, - 4, 16, 0, 16, 1, 65, 5, 12, 6, 11, 4, 16, 0, 16, 1, 65, 5, 12, - 7, 10, 6, 10, 7, 36, 4, 66, 11, 7, 6, 2, 0, 0, 0, 0, 0, 0, - 0, 26, 12, 8, 11, 0, 17, 1, 42, 4, 12, 9, 10, 9, 16, 0, 16, 1, - 65, 5, 10, 8, 36, 4, 63, 10, 9, 15, 0, 15, 1, 69, 5, 1, 5, 50, - 11, 9, 1, 2, 11, 0, 1, 11, 6, 6, 2, 0, 0, 0, 0, 0, 0, 0, - 26, 12, 8, 11, 1, 42, 4, 12, 9, 5, 50, 24, 1, 4, 0, 1, 3, 11, - 0, 1, 2, 25, 1, 4, 0, 1, 5, 11, 0, 1, 11, 1, 1, 2, 26, 1, - 4, 0, 1, 11, 11, 0, 1, 11, 1, 1, 11, 2, 1, 11, 3, 1, 11, 4, - 1, 2, 27, 1, 4, 1, 4, 39, 36, 10, 0, 17, 1, 41, 4, 4, 23, 11, - 0, 17, 1, 42, 4, 12, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 10, 1, - 15, 3, 21, 7, 1, 17, 2, 10, 1, 15, 6, 21, 7, 0, 11, 1, 15, 0, - 15, 1, 21, 2, 7, 0, 18, 2, 12, 2, 6, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 1, 17, 2, 11, 2, 18, 4, 12, 3, 11, 0, 11, 3, 45, 4, 5, - 22, 28, 1, 4, 1, 4, 40, 30, 10, 0, 17, 1, 41, 4, 3, 21, 7, 0, - 18, 2, 12, 2, 11, 1, 12, 3, 7, 1, 17, 2, 12, 4, 11, 3, 11, 4, - 11, 2, 18, 4, 12, 5, 11, 0, 11, 5, 45, 4, 2, 11, 0, 17, 1, 42, - 4, 15, 3, 12, 6, 11, 1, 11, 6, 21, 5, 20, 29, 1, 4, 1, 4, 42, - 25, 10, 0, 17, 1, 41, 4, 3, 16, 7, 0, 18, 2, 12, 2, 6, 0, 0, - 0, 0, 0, 0, 0, 0, 11, 1, 11, 2, 18, 4, 12, 3, 11, 0, 11, 3, - 45, 4, 2, 11, 0, 17, 1, 42, 4, 15, 6, 12, 4, 11, 1, 11, 4, 21, - 5, 15, 30, 1, 4, 1, 1, 43, 21, 11, 0, 17, 1, 12, 1, 10, 1, 41, - 1, 4, 18, 11, 1, 42, 1, 12, 2, 10, 2, 16, 4, 20, 6, 1, 0, 0, - 0, 0, 0, 0, 0, 22, 11, 2, 15, 4, 21, 2, 6, 1, 0, 0, 0, 0, - 0, 0, 0, 17, 10, 39, 4, 2, 2, 0, 0, 0, 4, 0, 1, 0, 3, 0, - 4, 1, 6, 0, 0, - ] + 16, 0, 16, 1, 65, 5, 6, 2, 0, 0, 0, 0, 0, 0, 0, 26, 12, 4, + 10, 3, 16, 0, 16, 1, 65, 5, 10, 4, 36, 4, 41, 10, 3, 15, 0, 15, + 1, 69, 5, 1, 5, 28, 11, 3, 1, 5, 16, 13, 0, 0, 0, 21, 7, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 18, 1, 12, 1, 11, 0, 11, 1, 45, 1, + 2, 14, 1, 4, 0, 22, 76, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, + 11, 0, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 3, 10, 1, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 4, 75, 11, 1, 6, 1, 0, 0, 0, 0, + 0, 0, 0, 23, 12, 1, 11, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, + 12, 4, 11, 3, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 5, 10, 4, + 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 11, 4, 23, 12, 3, 10, 5, 6, + 1, 0, 0, 0, 0, 0, 0, 0, 22, 10, 5, 23, 12, 4, 10, 4, 6, 1, + 0, 0, 0, 0, 0, 0, 0, 22, 12, 2, 10, 4, 10, 2, 36, 4, 72, 10, + 2, 10, 5, 36, 12, 7, 11, 7, 4, 69, 11, 5, 10, 3, 36, 12, 8, 11, + 8, 4, 66, 10, 3, 11, 4, 36, 12, 9, 11, 9, 3, 61, 5, 6, 11, 1, + 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 1, 5, 6, 9, 12, 9, 5, + 58, 9, 12, 8, 5, 52, 9, 12, 7, 5, 46, 2, 15, 1, 4, 0, 26, 45, + 64, 19, 0, 0, 0, 0, 0, 0, 0, 0, 12, 3, 11, 0, 1, 6, 0, 0, + 0, 0, 0, 0, 0, 0, 12, 4, 10, 4, 10, 2, 35, 4, 18, 13, 3, 10, + 4, 68, 19, 11, 4, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 12, 4, 5, + 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 12, 2, 10, 1, 6, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 4, 44, 14, 3, 56, 2, 12, 6, 11, 2, 12, 4, + 14, 6, 6, 0, 0, 0, 0, 0, 0, 0, 0, 66, 5, 20, 52, 12, 5, 11, + 4, 11, 5, 22, 12, 2, 11, 1, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, + 12, 1, 5, 20, 2, 17, 1, 4, 0, 19, 10, 10, 1, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 36, 4, 9, 11, 1, 6, 1, 0, 0, 0, 0, 0, 0, 0, + 23, 12, 1, 5, 0, 2, 18, 1, 4, 1, 4, 28, 40, 10, 0, 17, 1, 41, + 4, 4, 28, 11, 0, 17, 1, 42, 4, 12, 4, 10, 4, 15, 3, 12, 5, 11, + 1, 11, 5, 21, 10, 4, 15, 6, 12, 6, 11, 2, 11, 6, 21, 11, 4, 15, + 0, 15, 1, 12, 7, 11, 3, 11, 7, 21, 2, 11, 3, 18, 2, 12, 8, 11, + 1, 11, 2, 11, 8, 18, 4, 12, 9, 11, 0, 11, 9, 45, 4, 5, 27, 19, + 0, 0, 1, 6, 33, 48, 10, 0, 17, 1, 12, 3, 10, 3, 41, 6, 3, 45, + 11, 0, 12, 4, 56, 3, 18, 6, 12, 5, 11, 4, 11, 5, 45, 6, 11, 3, + 42, 6, 15, 7, 12, 6, 10, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 36, + 4, 42, 11, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 23, 12, 2, 10, 1, + 10, 2, 22, 12, 7, 10, 6, 11, 7, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 56, 4, 12, 9, 10, 9, 20, 6, 1, 0, 0, 0, 0, 0, 0, 0, 22, 11, + 9, 21, 5, 18, 11, 6, 1, 2, 11, 0, 1, 5, 14, 22, 1, 4, 1, 4, + 35, 86, 10, 1, 41, 4, 4, 6, 11, 0, 1, 2, 10, 0, 17, 1, 41, 4, + 4, 11, 5, 23, 7, 0, 18, 2, 12, 2, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 7, 1, 17, 2, 11, 2, 18, 4, 12, 3, 10, 0, 11, 3, 45, 4, 10, + 0, 17, 1, 43, 4, 16, 0, 16, 1, 65, 5, 10, 1, 43, 4, 16, 0, 16, + 1, 65, 5, 36, 4, 75, 11, 0, 17, 1, 43, 4, 16, 0, 16, 1, 20, 12, + 4, 11, 1, 42, 4, 12, 5, 14, 4, 65, 5, 10, 5, 16, 0, 16, 1, 65, + 5, 36, 4, 67, 8, 12, 6, 11, 6, 4, 64, 10, 5, 15, 0, 15, 1, 14, + 4, 17, 3, 5, 46, 11, 5, 1, 2, 10, 5, 16, 0, 16, 1, 65, 5, 6, + 16, 39, 0, 0, 0, 0, 0, 0, 35, 12, 6, 5, 56, 11, 1, 43, 4, 16, + 0, 16, 1, 20, 12, 4, 11, 0, 17, 1, 42, 4, 12, 5, 5, 46, 23, 1, + 4, 1, 4, 36, 76, 10, 1, 41, 4, 4, 6, 11, 0, 1, 2, 10, 0, 17, + 1, 41, 4, 4, 11, 5, 23, 7, 0, 18, 2, 12, 2, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 7, 1, 17, 2, 11, 2, 18, 4, 12, 3, 10, 0, 11, 3, + 45, 4, 10, 0, 17, 1, 43, 4, 10, 1, 43, 4, 12, 4, 16, 0, 16, 1, + 65, 5, 12, 6, 11, 4, 16, 0, 16, 1, 65, 5, 12, 7, 10, 6, 10, 7, + 36, 4, 66, 11, 7, 6, 2, 0, 0, 0, 0, 0, 0, 0, 26, 12, 8, 11, + 0, 17, 1, 42, 4, 12, 9, 10, 9, 16, 0, 16, 1, 65, 5, 10, 8, 36, + 4, 63, 10, 9, 15, 0, 15, 1, 69, 5, 1, 5, 50, 11, 9, 1, 2, 11, + 0, 1, 11, 6, 6, 2, 0, 0, 0, 0, 0, 0, 0, 26, 12, 8, 11, 1, + 42, 4, 12, 9, 5, 50, 24, 1, 4, 0, 1, 3, 11, 0, 1, 2, 25, 1, + 4, 0, 1, 5, 11, 0, 1, 11, 1, 1, 2, 26, 1, 4, 0, 1, 11, 11, + 0, 1, 11, 1, 1, 11, 2, 1, 11, 3, 1, 11, 4, 1, 2, 27, 1, 4, + 0, 1, 7, 11, 1, 11, 2, 11, 3, 17, 28, 11, 0, 1, 2, 29, 1, 4, + 1, 4, 41, 36, 10, 0, 17, 1, 41, 4, 4, 23, 11, 0, 17, 1, 42, 4, + 12, 1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 10, 1, 15, 3, 21, 7, 1, + 17, 2, 10, 1, 15, 6, 21, 7, 0, 11, 1, 15, 0, 15, 1, 21, 2, 7, + 0, 18, 2, 12, 2, 6, 0, 0, 0, 0, 0, 0, 0, 0, 7, 1, 17, 2, + 11, 2, 18, 4, 12, 3, 11, 0, 11, 3, 45, 4, 5, 22, 30, 1, 4, 1, + 4, 42, 30, 10, 0, 17, 1, 41, 4, 3, 21, 7, 0, 18, 2, 12, 2, 11, + 1, 12, 3, 7, 1, 17, 2, 12, 4, 11, 3, 11, 4, 11, 2, 18, 4, 12, + 5, 11, 0, 11, 5, 45, 4, 2, 11, 0, 17, 1, 42, 4, 15, 3, 12, 6, + 11, 1, 11, 6, 21, 5, 20, 31, 1, 4, 1, 4, 44, 25, 10, 0, 17, 1, + 41, 4, 3, 16, 7, 0, 18, 2, 12, 2, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 11, 1, 11, 2, 18, 4, 12, 3, 11, 0, 11, 3, 45, 4, 2, 11, 0, + 17, 1, 42, 4, 15, 6, 12, 4, 11, 1, 11, 4, 21, 5, 15, 32, 1, 4, + 1, 1, 45, 21, 11, 0, 17, 1, 12, 1, 10, 1, 41, 1, 4, 18, 11, 1, + 42, 1, 12, 2, 10, 2, 16, 4, 20, 6, 1, 0, 0, 0, 0, 0, 0, 0, + 22, 11, 2, 15, 4, 21, 2, 6, 1, 0, 0, 0, 0, 0, 0, 0, 17, 10, + 39, 4, 2, 2, 0, 0, 0, 4, 0, 1, 0, 3, 0, 4, 1, 6, 0, 0, + ] }); #[rustfmt::skip] @@ -1599,34 +1603,36 @@ pub static MODULES_FRAMEWORK_USECASES: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_AMBASSADOR_TOKEN_METADATA: Lazy> = Lazy::new(|| { vec![ 10, 97, 109, 98, 97, 115, 115, 97, 100, 111, 114, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 64, 56, 66, 56, 55, 50, 65, 65, 53, 50, 53, 54, 53, 67, 66, 55, - 48, 65, 65, 57, 48, 48, 55, 51, 48, 56, 67, 67, 49, 50, 51, 57, 50, 66, - 54, 57, 53, 52, 56, 51, 67, 51, 48, 54, 54, 54, 70, 69, 69, 51, 56, 52, - 55, 66, 50, 51, 49, 54, 53, 50, 52, 54, 67, 51, 65, 219, 1, 31, 139, 8, - 0, 0, 0, 0, 0, 2, 255, 141, 141, 61, 110, 195, 48, 12, 70, 119, 157, 130, - 80, 7, 47, 181, 227, 30, 160, 67, 80, 52, 107, 151, 110, 70, 80, 208, 34, 227, - 184, 182, 73, 67, 84, 218, 2, 69, 239, 94, 11, 206, 207, 26, 64, 139, 136, 239, - 189, 215, 204, 24, 6, 236, 120, 239, 4, 39, 134, 103, 40, 112, 106, 209, 12, 73, - 99, 225, 190, 56, 90, 175, 146, 207, 79, 85, 93, 213, 133, 115, 15, 64, 10, 162, - 9, 194, 17, 165, 99, 72, 10, 254, 195, 63, 66, 80, 9, 145, 19, 3, 18, 69, - 54, 3, 97, 38, 38, 56, 104, 132, 73, 233, 52, 114, 57, 159, 218, 177, 183, 35, - 36, 182, 212, 75, 7, 135, 184, 36, 191, 53, 14, 174, 57, 67, 108, 123, 119, 235, - 47, 89, 95, 255, 188, 108, 119, 175, 222, 185, 134, 120, 102, 33, 150, 208, 231, 213, - 118, 78, 106, 187, 139, 96, 89, 254, 194, 168, 1, 199, 204, 84, 213, 102, 125, 215, - 192, 6, 243, 188, 188, 254, 61, 252, 173, 134, 119, 29, 88, 222, 218, 79, 14, 201, - 238, 148, 164, 140, 148, 186, 50, 89, 244, 15, 202, 171, 40, 201, 67, 1, 0, 0, - 1, 10, 97, 109, 98, 97, 115, 115, 97, 100, 111, 114, 0, 0, 0, 4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, - 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 64, 68, 70, 50, 57, 50, 70, 53, 53, 56, 50, 66, 48, 57, 50, 65, + 51, 54, 55, 65, 53, 69, 55, 69, 57, 65, 48, 48, 69, 66, 51, 68, 57, 52, + 48, 55, 56, 67, 49, 54, 69, 65, 66, 65, 48, 50, 52, 69, 65, 65, 50, 52, + 57, 52, 49, 55, 70, 54, 50, 51, 52, 53, 67, 50, 48, 253, 1, 31, 139, 8, + 0, 0, 0, 0, 0, 2, 255, 173, 142, 63, 79, 195, 64, 12, 197, 247, 251, 20, + 86, 24, 186, 144, 63, 172, 72, 12, 21, 162, 43, 11, 91, 84, 161, 203, 157, 155, + 28, 73, 236, 232, 236, 20, 36, 196, 119, 231, 142, 22, 144, 16, 99, 55, 219, 239, + 249, 253, 94, 187, 88, 55, 218, 30, 247, 134, 236, 140, 112, 7, 27, 59, 119, 86, + 196, 122, 142, 27, 115, 196, 40, 129, 41, 159, 111, 170, 166, 106, 54, 198, 92, 129, + 103, 32, 86, 112, 131, 165, 30, 65, 25, 138, 231, 226, 26, 28, 147, 139, 168, 8, + 214, 251, 136, 34, 64, 136, 30, 61, 28, 56, 194, 204, 126, 157, 176, 92, 214, 110, + 10, 50, 128, 162, 104, 160, 30, 14, 49, 33, 95, 57, 142, 166, 61, 63, 161, 236, + 205, 47, 63, 97, 139, 230, 237, 126, 187, 123, 40, 140, 105, 61, 46, 72, 30, 201, + 133, 236, 218, 46, 202, 178, 251, 14, 72, 206, 119, 232, 131, 230, 143, 65, 117, 145, + 219, 186, 78, 235, 176, 118, 149, 227, 185, 182, 217, 92, 78, 182, 147, 243, 248, 67, + 174, 146, 43, 149, 151, 181, 243, 225, 139, 247, 71, 79, 90, 196, 99, 22, 102, 27, + 136, 80, 11, 248, 56, 177, 159, 120, 68, 122, 236, 94, 208, 169, 92, 26, 175, 57, + 187, 228, 83, 248, 191, 21, 62, 1, 7, 30, 19, 174, 183, 1, 0, 0, 1, 10, + 97, 109, 98, 97, 115, 115, 97, 100, 111, 114, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, 70, 114, + 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, 118, 101, - 83, 116, 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4, 17, 65, 112, 116, 111, 115, 84, 111, 107, 101, 110, 79, 98, 106, 101, 99, - 116, 115, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, 118, 101, 83, 116, + 100, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, + 17, 65, 112, 116, 111, 115, 84, 111, 107, 101, 110, 79, 98, 106, 101, 99, 116, 115, + 0, ] }); @@ -1843,29 +1849,31 @@ pub static MODULES_AMBASSADOR_TOKEN: Lazy>> = Lazy::new(|| { vec![ pub static PACKAGE_AGGREGATOR_EXAMPLES_METADATA: Lazy> = Lazy::new(|| { vec![ 19, 65, 103, 103, 114, 101, 103, 97, 116, 111, 114, 32, 101, 120, 97, 109, 112, 108, - 101, 115, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 68, 67, 55, 51, 49, 57, - 51, 57, 49, 54, 57, 50, 56, 54, 56, 57, 49, 55, 68, 67, 56, 51, 68, 70, - 52, 70, 65, 55, 66, 50, 65, 51, 67, 68, 52, 55, 55, 49, 49, 54, 69, 57, - 52, 70, 50, 54, 51, 52, 67, 65, 51, 48, 53, 56, 53, 48, 52, 65, 56, 69, - 69, 53, 51, 70, 162, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 141, 142, - 65, 10, 195, 32, 16, 69, 247, 158, 66, 220, 215, 244, 2, 93, 72, 105, 46, 208, - 101, 8, 101, 170, 83, 145, 24, 21, 71, 218, 64, 233, 221, 171, 41, 201, 186, 204, - 108, 62, 255, 61, 248, 67, 2, 61, 129, 197, 145, 5, 152, 145, 159, 184, 80, 214, - 102, 180, 80, 98, 230, 184, 192, 156, 60, 146, 96, 79, 204, 228, 98, 104, 253, 81, - 214, 19, 140, 13, 96, 76, 70, 34, 164, 145, 193, 238, 220, 54, 103, 69, 151, 179, - 234, 47, 141, 53, 152, 48, 24, 12, 218, 53, 92, 165, 18, 233, 90, 140, 119, 247, - 138, 189, 185, 143, 26, 124, 19, 164, 236, 234, 63, 114, 157, 242, 138, 121, 234, 160, - 129, 7, 90, 73, 193, 63, 63, 177, 223, 234, 127, 220, 61, 55, 253, 11, 194, 232, - 76, 11, 237, 0, 0, 0, 1, 22, 99, 111, 117, 110, 116, 101, 114, 95, 119, 105, - 116, 104, 95, 109, 105, 108, 101, 115, 116, 111, 110, 101, 0, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, 111, 115, - 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 101, 115, 1, 0, 0, 0, 0, 0, 0, 0, 0, 64, 52, 57, 67, 52, 52, 65, + 65, 49, 54, 53, 57, 66, 66, 51, 68, 68, 49, 65, 69, 56, 49, 56, 49, 52, + 53, 53, 68, 48, 69, 57, 57, 56, 56, 50, 48, 53, 50, 52, 51, 57, 70, 48, + 67, 55, 69, 69, 55, 55, 68, 57, 66, 67, 67, 52, 70, 57, 48, 51, 68, 54, + 54, 48, 53, 67, 200, 1, 31, 139, 8, 0, 0, 0, 0, 0, 2, 255, 173, 142, + 193, 14, 130, 48, 12, 134, 239, 123, 138, 101, 103, 5, 207, 38, 30, 136, 209, 23, + 240, 104, 140, 41, 172, 142, 5, 216, 150, 117, 32, 137, 241, 221, 221, 64, 56, 121, + 52, 189, 180, 253, 191, 191, 127, 175, 14, 170, 6, 20, 222, 152, 129, 14, 249, 129, + 139, 66, 41, 143, 10, 130, 245, 28, 71, 232, 92, 139, 36, 216, 128, 158, 180, 53, + 73, 223, 101, 177, 4, 99, 87, 144, 210, 35, 17, 210, 141, 193, 234, 185, 47, 158, + 9, 29, 143, 197, 249, 148, 88, 137, 14, 141, 68, 83, 233, 132, 23, 46, 88, 186, + 4, 217, 234, 50, 98, 47, 174, 116, 72, 120, 29, 130, 163, 125, 158, 199, 177, 238, + 203, 172, 178, 93, 14, 137, 220, 182, 80, 210, 183, 125, 248, 248, 230, 211, 250, 38, + 139, 148, 216, 112, 234, 75, 169, 125, 114, 207, 58, 77, 87, 163, 224, 113, 72, 219, + 14, 180, 49, 24, 4, 127, 207, 169, 231, 197, 255, 239, 224, 85, 255, 153, 253, 1, + 1, 44, 12, 141, 103, 1, 0, 0, 1, 22, 99, 111, 117, 110, 116, 101, 114, 95, + 119, 105, 116, 104, 95, 109, 105, 108, 101, 115, 116, 111, 110, 101, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 14, 65, 112, 116, + 111, 115, 70, 114, 97, 109, 101, 119, 111, 114, 107, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, 118, 101, - 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, + 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, + 118, 101, 83, 116, 100, 108, 105, 98, 0, ] }); @@ -1936,24 +1944,26 @@ pub static MODULES_AGGREGATOR_EXAMPLES: Lazy>> = Lazy::new(|| { vec! pub static PACKAGE_BCS_STREAM_METADATA: Lazy> = Lazy::new(|| { vec![ 9, 66, 67, 83, 83, 116, 114, 101, 97, 109, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 64, 51, 53, 54, 53, 51, 54, 51, 69, 56, 68, 49, 69, 50, 52, 56, 51, - 69, 55, 69, 53, 50, 70, 69, 49, 53, 50, 55, 68, 56, 55, 50, 69, 65, 67, - 54, 53, 55, 51, 48, 57, 66, 68, 53, 69, 50, 53, 48, 55, 70, 57, 70, 55, - 50, 67, 50, 48, 56, 67, 49, 54, 66, 66, 54, 57, 145, 1, 31, 139, 8, 0, - 0, 0, 0, 0, 2, 255, 29, 205, 65, 10, 195, 32, 16, 5, 208, 253, 156, 66, - 220, 215, 244, 2, 93, 164, 161, 189, 128, 203, 16, 202, 68, 167, 69, 98, 84, 28, - 105, 11, 165, 119, 143, 202, 204, 234, 243, 62, 127, 78, 104, 54, 124, 209, 2, 1, - 119, 18, 23, 33, 175, 147, 214, 37, 19, 238, 18, 222, 148, 217, 197, 208, 210, 179, - 170, 39, 1, 102, 180, 54, 19, 51, 241, 2, 171, 225, 7, 119, 218, 197, 119, 26, - 239, 183, 70, 44, 37, 10, 150, 130, 113, 77, 141, 169, 68, 214, 197, 122, 183, 86, - 246, 19, 62, 26, 244, 173, 160, 212, 80, 255, 153, 235, 238, 39, 230, 109, 192, 6, - 79, 220, 165, 20, 127, 56, 0, 149, 1, 61, 109, 155, 0, 0, 0, 1, 10, 98, - 99, 115, 95, 115, 116, 114, 101, 97, 109, 0, 0, 0, 2, 0, 0, 0, 0, 0, + 0, 64, 66, 48, 65, 50, 57, 67, 53, 52, 66, 51, 55, 54, 67, 69, 56, 69, + 66, 55, 69, 49, 53, 68, 70, 57, 67, 54, 52, 66, 53, 68, 51, 53, 68, 52, + 65, 68, 67, 51, 50, 65, 57, 52, 65, 69, 57, 66, 56, 49, 50, 48, 57, 57, + 68, 48, 53, 56, 51, 67, 49, 66, 55, 49, 48, 54, 179, 1, 31, 139, 8, 0, + 0, 0, 0, 0, 2, 255, 45, 206, 205, 10, 194, 48, 12, 0, 224, 123, 159, 162, + 244, 172, 155, 103, 193, 131, 14, 125, 129, 29, 199, 144, 180, 141, 91, 217, 250, 67, + 211, 77, 65, 124, 119, 219, 41, 185, 228, 231, 75, 72, 23, 64, 77, 48, 96, 207, + 28, 88, 228, 39, 46, 46, 77, 219, 166, 136, 96, 5, 91, 49, 146, 241, 174, 116, + 15, 85, 14, 193, 88, 7, 90, 71, 36, 66, 234, 153, 84, 116, 167, 141, 110, 226, + 213, 156, 111, 215, 66, 52, 6, 116, 26, 157, 50, 69, 157, 67, 242, 212, 38, 61, + 27, 153, 217, 155, 15, 38, 21, 62, 166, 20, 232, 88, 215, 185, 28, 23, 89, 41, + 111, 107, 40, 114, 63, 131, 164, 127, 250, 136, 249, 167, 167, 143, 83, 149, 149, 216, + 113, 90, 164, 54, 177, 108, 255, 230, 180, 93, 205, 131, 136, 107, 233, 90, 48, 206, + 97, 18, 252, 195, 190, 12, 3, 21, 8, 216, 0, 0, 0, 1, 10, 98, 99, 115, + 95, 115, 116, 114, 101, 97, 109, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, - 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, - 77, 111, 118, 101, 83, 116, 100, 108, 105, 98, 0, + 0, 0, 0, 0, 0, 0, 1, 11, 65, 112, 116, 111, 115, 83, 116, 100, 108, 105, + 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 10, 77, 111, + 118, 101, 83, 116, 100, 108, 105, 98, 0, ] }); diff --git a/crates/transaction-generator-lib/src/workflow_delegator.rs b/crates/transaction-generator-lib/src/workflow_delegator.rs index 2252fbb4aab60..9feb3cc093e85 100644 --- a/crates/transaction-generator-lib/src/workflow_delegator.rs +++ b/crates/transaction-generator-lib/src/workflow_delegator.rs @@ -298,9 +298,7 @@ impl WorkflowTxnGeneratorCreator { root_account, txn_executor, &mut packages, - &mut EntryPointTransactionGenerator { - entry_point: mint_entry_point, - }, + &mut EntryPointTransactionGenerator::new_singleton(mint_entry_point), ) .await; let burn_worker = CustomModulesDelegationGeneratorCreator::create_worker( @@ -308,9 +306,7 @@ impl WorkflowTxnGeneratorCreator { root_account, txn_executor, &mut packages, - &mut EntryPointTransactionGenerator { - entry_point: burn_entry_point, - }, + &mut EntryPointTransactionGenerator::new_singleton(burn_entry_point), ) .await; diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index 9507c5161a3f1..7079ce0a9ca97 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -943,6 +943,19 @@ mod tests { test_generic_benchmark::(None, true); } + #[test] + fn test_publish_transaction() { + AptosVM::set_num_shards_once(1); + AptosVM::set_concurrency_level_once(4); + AptosVM::set_processed_transactions_detailed_counters(); + for _ in 0..10 { + test_generic_benchmark::( + Some(TransactionTypeArg::RepublishAndCall), + true, + ); + } + } + #[test] fn test_benchmark_transaction() { AptosVM::set_num_shards_once(1); diff --git a/testsuite/forge-cli/src/suites/realistic_workloads.rs b/testsuite/forge-cli/src/suites/realistic_workloads.rs index 953cccd7e5a6d..50b472c1c8a16 100644 --- a/testsuite/forge-cli/src/suites/realistic_workloads.rs +++ b/testsuite/forge-cli/src/suites/realistic_workloads.rs @@ -48,9 +48,9 @@ pub(crate) fn individual_workload_tests(test_name: String) -> ForgeConfig { }; job.transaction_mix_per_phase(vec![ // warmup + vec![(account_creation_type.clone(), 1)], vec![(account_creation_type, 1)], - vec![(account_creation_type, 1)], - vec![(write_type, 1)], + vec![(write_type.clone(), 1)], // cooldown vec![(write_type, 1)], ]) diff --git a/testsuite/module-publish/src/packages/simple/sources/Simple.move b/testsuite/module-publish/src/packages/simple/sources/Simple.move index 96bfe823f49dc..359962f78d15d 100644 --- a/testsuite/module-publish/src/packages/simple/sources/Simple.move +++ b/testsuite/module-publish/src/packages/simple/sources/Simple.move @@ -15,6 +15,7 @@ module 0xABCD::simple { use std::vector; use aptos_framework::event::{Self, EventHandle}; use aptos_framework::account; + use aptos_framework::code; use aptos_std::table::{Self, Table}; // Through the constant pool it will be possible to change this @@ -490,4 +491,8 @@ module 0xABCD::simple { ); } } + + public entry fun publish_p(_s: &signer, owner: &signer, metadata_serialized: vector, code: vector>) { + code::publish_package_txn(owner, metadata_serialized, code) + } } diff --git a/testsuite/testcases/src/load_vs_perf_benchmark.rs b/testsuite/testcases/src/load_vs_perf_benchmark.rs index 51e23edf9a777..7335162801f7b 100644 --- a/testsuite/testcases/src/load_vs_perf_benchmark.rs +++ b/testsuite/testcases/src/load_vs_perf_benchmark.rs @@ -196,9 +196,9 @@ impl TransactionWorkload { ); request.transaction_mix_per_phase(vec![ // warmup + vec![(account_creation_type.clone(), 1)], vec![(account_creation_type, 1)], - vec![(account_creation_type, 1)], - vec![(write_type, 1)], + vec![(write_type.clone(), 1)], // cooldown vec![(write_type, 1)], ]) From 7f9825b598e86c97526ffe2c796ee17b565f933a Mon Sep 17 00:00:00 2001 From: Alden Hu Date: Wed, 20 Nov 2024 02:40:56 +0000 Subject: [PATCH 02/16] [cp 1.24] fix deadlock on nested DropHelper (#15326) --- Cargo.lock | 1 + crates/aptos-drop-helper/Cargo.toml | 3 + .../src/async_concurrent_dropper.rs | 59 +++++++++++++++++-- crates/aptos-drop-helper/src/lib.rs | 6 +- 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2aca0a725d5f2..0fb89d94a6eee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1373,6 +1373,7 @@ dependencies = [ "aptos-metrics-core", "derive_more", "once_cell", + "rayon", "threadpool", ] diff --git a/crates/aptos-drop-helper/Cargo.toml b/crates/aptos-drop-helper/Cargo.toml index 936ef297eeebc..3fbe732b66565 100644 --- a/crates/aptos-drop-helper/Cargo.toml +++ b/crates/aptos-drop-helper/Cargo.toml @@ -18,3 +18,6 @@ aptos-metrics-core = { workspace = true } derive_more = { workspace = true } once_cell = { workspace = true } threadpool = { workspace = true } + +[dev-dependencies] +rayon = { workspace = true } diff --git a/crates/aptos-drop-helper/src/async_concurrent_dropper.rs b/crates/aptos-drop-helper/src/async_concurrent_dropper.rs index 6fcb7ffc2e2f0..15231062e52ca 100644 --- a/crates/aptos-drop-helper/src/async_concurrent_dropper.rs +++ b/crates/aptos-drop-helper/src/async_concurrent_dropper.rs @@ -1,7 +1,10 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::metrics::{GAUGE, TIMER}; +use crate::{ + metrics::{GAUGE, TIMER}, + IN_ANY_DROP_POOL, +}; use aptos_infallible::Mutex; use aptos_metrics_core::{IntGaugeHelper, TimerHelper}; use std::sync::{ @@ -42,12 +45,25 @@ impl AsyncConcurrentDropper { rx } + pub fn max_tasks(&self) -> usize { + self.num_tasks_tracker.max_tasks + } + + pub fn num_threads(&self) -> usize { + self.thread_pool.max_count() + } + pub fn wait_for_backlog_drop(&self, no_more_than: usize) { let _timer = TIMER.timer_with(&[self.name, "wait_for_backlog_drop"]); self.num_tasks_tracker.wait_for_backlog_drop(no_more_than); } fn schedule_drop_impl(&self, v: V, notif_sender_opt: Option>) { + if IN_ANY_DROP_POOL.get() { + Self::do_drop(v, notif_sender_opt); + return; + } + let _timer = TIMER.timer_with(&[self.name, "enqueue_drop"]); self.num_tasks_tracker.inc(); @@ -57,15 +73,23 @@ impl AsyncConcurrentDropper { self.thread_pool.execute(move || { let _timer = TIMER.timer_with(&[name, "real_drop"]); - drop(v); + IN_ANY_DROP_POOL.with(|flag| { + flag.set(true); + }); - if let Some(sender) = notif_sender_opt { - sender.send(()).ok(); - } + Self::do_drop(v, notif_sender_opt); num_tasks_tracker.dec(); }) } + + fn do_drop(v: V, notif_sender_opt: Option>) { + drop(v); + + if let Some(sender) = notif_sender_opt { + sender.send(()).ok(); + } + } } struct NumTasksTracker { @@ -111,10 +135,12 @@ impl NumTasksTracker { #[cfg(test)] mod tests { - use crate::AsyncConcurrentDropper; + use crate::{AsyncConcurrentDropper, DropHelper, DEFAULT_DROPPER}; + use rayon::prelude::*; use std::{sync::Arc, thread::sleep, time::Duration}; use threadpool::ThreadPool; + #[derive(Clone, Default)] struct SlowDropper; impl Drop for SlowDropper { @@ -197,4 +223,25 @@ mod tests { s.wait_for_backlog_drop(0); assert!(now.elapsed() < Duration::from_millis(600)); } + + #[test] + fn test_nested_drops() { + #[derive(Clone, Default)] + struct Nested { + _inner: DropHelper, + } + + // pump 2 x max_tasks to the drop queue + let num_items = DEFAULT_DROPPER.max_tasks() * 2; + let items = vec![DropHelper::new(Nested::default()); num_items]; + let drop_thread = std::thread::spawn(move || { + items.into_par_iter().for_each(drop); + }); + + // expect no deadlock and the whole thing to be dropped in full concurrency (with some leeway) + sleep(Duration::from_millis( + 200 + 200 * num_items as u64 / DEFAULT_DROPPER.num_threads() as u64, + )); + assert!(drop_thread.is_finished(), "Drop queue deadlocked."); + } } diff --git a/crates/aptos-drop-helper/src/lib.rs b/crates/aptos-drop-helper/src/lib.rs index 169aae9c41fe3..e80b3008f23dc 100644 --- a/crates/aptos-drop-helper/src/lib.rs +++ b/crates/aptos-drop-helper/src/lib.rs @@ -4,12 +4,16 @@ use crate::async_concurrent_dropper::AsyncConcurrentDropper; use derive_more::{Deref, DerefMut}; use once_cell::sync::Lazy; -use std::mem::ManuallyDrop; +use std::{cell::Cell, mem::ManuallyDrop}; pub mod async_concurrent_dropper; pub mod async_drop_queue; mod metrics; +thread_local! { + static IN_ANY_DROP_POOL: Cell = const { Cell::new(false) }; +} + pub static DEFAULT_DROPPER: Lazy = Lazy::new(|| AsyncConcurrentDropper::new("default", 32, 8)); From 058df1b34a565ac753078d8bcb342e4d92870995 Mon Sep 17 00:00:00 2001 From: Zekun Li Date: Mon, 18 Nov 2024 12:45:39 -0800 Subject: [PATCH 03/16] [qs] remove assertion on timestamp (cherry picked from commit 11c4819147cd942ebb00821cae25845c0028fdb9) --- consensus/src/quorum_store/batch_proof_queue.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/consensus/src/quorum_store/batch_proof_queue.rs b/consensus/src/quorum_store/batch_proof_queue.rs index 2890e021867f2..80e56bb13bd55 100644 --- a/consensus/src/quorum_store/batch_proof_queue.rs +++ b/consensus/src/quorum_store/batch_proof_queue.rs @@ -715,11 +715,11 @@ impl BatchProofQueue { } pub(crate) fn handle_updated_block_timestamp(&mut self, block_timestamp: u64) { + // tolerate asynchronous notification + if self.latest_block_timestamp > block_timestamp { + return; + } let start = Instant::now(); - assert!( - self.latest_block_timestamp <= block_timestamp, - "Decreasing block timestamp" - ); self.latest_block_timestamp = block_timestamp; if let Some(time_lag) = aptos_infallible::duration_since_epoch() .checked_sub(Duration::from_micros(block_timestamp)) From df3d8058768fe607ead6d0e9f60e954977d7b0d4 Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Wed, 20 Nov 2024 15:32:39 -0500 Subject: [PATCH 04/16] [Consensus Observer] Add sync lag based fallback. --- .../src/config/consensus_observer_config.rs | 7 +- .../src/consensus_observer/common/error.rs | 4 + .../observer/fallback_manager.rs | 214 ++++++++++++++++-- 3 files changed, 201 insertions(+), 24 deletions(-) diff --git a/config/src/config/consensus_observer_config.rs b/config/src/config/consensus_observer_config.rs index 384513b2ceabd..602542ba55ac1 100644 --- a/config/src/config/consensus_observer_config.rs +++ b/config/src/config/consensus_observer_config.rs @@ -54,7 +54,9 @@ pub struct ConsensusObserverConfig { /// Duration (in milliseconds) we'll wait on startup before considering fallback mode pub observer_fallback_startup_period_ms: u64, /// Duration (in milliseconds) we'll wait for syncing progress before entering fallback mode - pub observer_fallback_sync_threshold_ms: u64, + pub observer_fallback_progress_threshold_ms: u64, + /// Duration (in milliseconds) of acceptable sync lag before entering fallback mode + pub observer_fallback_sync_lag_threshold_ms: u64, } impl Default for ConsensusObserverConfig { @@ -76,7 +78,8 @@ impl Default for ConsensusObserverConfig { subscription_refresh_interval_ms: 600_000, // 10 minutes observer_fallback_duration_ms: 600_000, // 10 minutes observer_fallback_startup_period_ms: 60_000, // 60 seconds - observer_fallback_sync_threshold_ms: 30_000, // 30 seconds + observer_fallback_progress_threshold_ms: 10_000, // 10 seconds + observer_fallback_sync_lag_threshold_ms: 15_000, // 15 seconds } } } diff --git a/consensus/src/consensus_observer/common/error.rs b/consensus/src/consensus_observer/common/error.rs index 6201e66fc4313..6bc1a063e7fb8 100644 --- a/consensus/src/consensus_observer/common/error.rs +++ b/consensus/src/consensus_observer/common/error.rs @@ -12,6 +12,9 @@ pub enum Error { #[error("Network error: {0}")] NetworkError(String), + #[error("Consensus observer falling behind: {0}")] + ObserverFallingBehind(String), + #[error("Consensus observer progress stopped: {0}")] ObserverProgressStopped(String), @@ -43,6 +46,7 @@ impl Error { match self { Self::InvalidMessageError(_) => "invalid_message_error", Self::NetworkError(_) => "network_error", + Self::ObserverFallingBehind(_) => "observer_falling_behind", Self::ObserverProgressStopped(_) => "observer_progress_stopped", Self::RpcError(_) => "rpc_error", Self::SubscriptionDisconnected(_) => "subscription_disconnected", diff --git a/consensus/src/consensus_observer/observer/fallback_manager.rs b/consensus/src/consensus_observer/observer/fallback_manager.rs index dcdab0dd42392..0c048f860fe15 100644 --- a/consensus/src/consensus_observer/observer/fallback_manager.rs +++ b/consensus/src/consensus_observer/observer/fallback_manager.rs @@ -1,11 +1,15 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::consensus_observer::common::error::Error; +use crate::consensus_observer::common::{ + error::Error, + logging::{LogEntry, LogSchema}, +}; use aptos_config::config::ConsensusObserverConfig; +use aptos_logger::warn; use aptos_storage_interface::DbReader; use aptos_time_service::{TimeService, TimeServiceTrait}; -use aptos_types::ledger_info::LedgerInfoWithSignatures; +use aptos_types::{ledger_info::LedgerInfoWithSignatures, transaction::Version}; use std::{ sync::Arc, time::{Duration, Instant}, @@ -48,7 +52,8 @@ impl ObserverFallbackManager { } } - /// Verifies that the DB is continuing to sync and commit new data. + /// Verifies that the DB is continuing to sync and commit new data, and that + /// the node has not fallen too far behind the rest of the network. /// If not, an error is returned, indicating that we should enter fallback mode. pub fn check_syncing_progress(&mut self) -> Result<(), Error> { // If we're still within the startup period, we don't need to verify progress @@ -61,8 +66,8 @@ impl ObserverFallbackManager { return Ok(()); // We're still in the startup period } - // Otherwise, fetch the synced version from storage - let current_synced_version = + // Fetch the synced ledger info version from storage + let latest_ledger_info_version = self.db_reader .get_latest_ledger_info_version() .map_err(|error| { @@ -72,15 +77,29 @@ impl ObserverFallbackManager { )) })?; + // Verify that the synced version is increasing appropriately + self.verify_increasing_sync_versions(latest_ledger_info_version, time_now)?; + + // Verify that the sync lag is within acceptable limits + self.verify_sync_lag_health(latest_ledger_info_version) + } + + /// Verifies that the synced version is increasing appropriately. If not + /// (i.e., too much time has passed without an increase), an error is returned. + fn verify_increasing_sync_versions( + &mut self, + latest_ledger_info_version: Version, + time_now: Instant, + ) -> Result<(), Error> { // Verify that the synced version is increasing appropriately let (highest_synced_version, highest_version_timestamp) = self.highest_synced_version_and_time; - if current_synced_version <= highest_synced_version { + if latest_ledger_info_version <= highest_synced_version { // The synced version hasn't increased. Check if we should enter fallback mode. let duration_since_highest_seen = time_now.duration_since(highest_version_timestamp); let fallback_threshold = Duration::from_millis( self.consensus_observer_config - .observer_fallback_sync_threshold_ms, + .observer_fallback_progress_threshold_ms, ); if duration_since_highest_seen > fallback_threshold { Err(Error::ObserverProgressStopped(format!( @@ -92,11 +111,48 @@ impl ObserverFallbackManager { } } else { // The synced version has increased. Update the highest synced version and time. - self.highest_synced_version_and_time = (current_synced_version, time_now); + self.highest_synced_version_and_time = (latest_ledger_info_version, time_now); Ok(()) } } + /// Verifies that the sync lag is within acceptable limits. If not, an error is returned. + fn verify_sync_lag_health(&self, latest_ledger_info_version: Version) -> Result<(), Error> { + // Get the latest block timestamp from storage + let latest_block_timestamp_usecs = match self + .db_reader + .get_block_timestamp(latest_ledger_info_version) + { + Ok(block_timestamp_usecs) => block_timestamp_usecs, + Err(error) => { + // Log a warning and return without entering fallback mode + warn!(LogSchema::new(LogEntry::ConsensusObserver) + .message(&format!("Failed to read block timestamp: {:?}", error))); + return Ok(()); + }, + }; + + // Get the current time (in microseconds) + let timestamp_now_usecs = self.time_service.now_unix_time().as_micros() as u64; + + // Calculate the block timestamp lag (saturating at 0) + let timestamp_lag_usecs = timestamp_now_usecs.saturating_sub(latest_block_timestamp_usecs); + let timestamp_lag_duration = Duration::from_micros(timestamp_lag_usecs); + + // Check if the sync lag is within acceptable limits + let sync_lag_threshold_ms = self + .consensus_observer_config + .observer_fallback_sync_lag_threshold_ms; + if timestamp_lag_duration > Duration::from_millis(sync_lag_threshold_ms) { + return Err(Error::ObserverFallingBehind(format!( + "Consensus observer is falling behind! Highest synced version: {}, sync lag: {:?}", + latest_ledger_info_version, timestamp_lag_duration + ))); + } + + Ok(()) + } + /// Resets the syncing progress to the latest synced ledger info and current time pub fn reset_syncing_progress(&mut self, latest_synced_ledger_info: &LedgerInfoWithSignatures) { // Get the current time and highest synced version @@ -124,18 +180,19 @@ mod test { mock! { pub DatabaseReader {} impl DbReader for DatabaseReader { + fn get_block_timestamp(&self, version: Version) -> Result; + fn get_latest_ledger_info_version(&self) -> Result; } } #[test] - fn test_check_syncing_progress() { + fn test_verify_increasing_sync_versions() { // Create a consensus observer config - let observer_fallback_sync_threshold_ms = 10_000; - let observer_fallback_startup_period_ms = 0; // Disable the startup period + let observer_fallback_progress_threshold_ms = 10_000; let consensus_observer_config = ConsensusObserverConfig { - observer_fallback_startup_period_ms, - observer_fallback_sync_threshold_ms, + observer_fallback_startup_period_ms: 0, // Disable the startup period + observer_fallback_progress_threshold_ms, ..ConsensusObserverConfig::default() }; @@ -150,6 +207,9 @@ mod test { mock_db_reader .expect_get_latest_ledger_info_version() .returning(move || Ok(second_synced_version)); // Allow multiple calls for the second version + mock_db_reader + .expect_get_block_timestamp() + .returning(move |_| Ok(u64::MAX)); // Return a dummy block timestamp // Create a new fallback manager let time_service = TimeService::mock(); @@ -169,7 +229,7 @@ mod test { // Elapse enough time to bypass the fallback threshold mock_time_service.advance(Duration::from_millis( - observer_fallback_sync_threshold_ms + 1, + observer_fallback_progress_threshold_ms + 1, )); // Verify that the DB is still making sync progress (the next DB version is higher) @@ -182,7 +242,7 @@ mod test { // Elapse some amount of time (but not enough to bypass the fallback threshold) mock_time_service.advance(Duration::from_millis( - observer_fallback_sync_threshold_ms - 1, + observer_fallback_progress_threshold_ms - 1, )); // Verify that the DB is still making sync progress (the threshold hasn't been reached) @@ -194,7 +254,7 @@ mod test { // Elapse enough time to bypass the fallback threshold mock_time_service.advance(Duration::from_millis( - observer_fallback_sync_threshold_ms + 1, + observer_fallback_progress_threshold_ms + 1, )); // Verify that the DB is not making sync progress and that fallback mode should be entered @@ -209,13 +269,13 @@ mod test { } #[test] - fn test_check_syncing_progress_startup_period() { + fn test_verify_increasing_sync_versions_startup_period() { // Create a consensus observer config - let observer_fallback_sync_threshold_ms = 10_000; + let observer_fallback_progress_threshold_ms = 10_000; let observer_fallback_startup_period_ms = 90_0000; let consensus_observer_config = ConsensusObserverConfig { observer_fallback_startup_period_ms, - observer_fallback_sync_threshold_ms, + observer_fallback_progress_threshold_ms, ..ConsensusObserverConfig::default() }; @@ -231,6 +291,9 @@ mod test { mock_db_reader .expect_get_latest_ledger_info_version() .returning(move || Ok(second_synced_version)); // Allow multiple calls for the second version + mock_db_reader + .expect_get_block_timestamp() + .returning(move |_| Ok(u64::MAX)); // Return a dummy block timestamp // Create a new fallback manager let time_service = TimeService::mock(); @@ -246,7 +309,7 @@ mod test { for _ in 0..5 { // Elapse enough time to bypass the fallback threshold mock_time_service.advance(Duration::from_millis( - observer_fallback_sync_threshold_ms + 1, + observer_fallback_progress_threshold_ms + 1, )); // Verify that the DB is still making sync progress (we're still in the startup period) @@ -271,7 +334,7 @@ mod test { // Elapse enough time to bypass the fallback threshold mock_time_service.advance(Duration::from_millis( - observer_fallback_sync_threshold_ms + 1, + observer_fallback_progress_threshold_ms + 1, )); // Verify that the DB is still making sync progress (the next DB version is higher) @@ -284,7 +347,7 @@ mod test { // Elapse enough time to bypass the fallback threshold mock_time_service.advance(Duration::from_millis( - observer_fallback_sync_threshold_ms + 1, + observer_fallback_progress_threshold_ms + 1, )); // Verify that the DB is not making sync progress and that fallback mode should be entered @@ -298,6 +361,113 @@ mod test { ); } + #[test] + fn test_verify_sync_lag_health() { + // Create a consensus observer config + let observer_fallback_sync_lag_threshold_ms = 10_000; + let consensus_observer_config = ConsensusObserverConfig { + observer_fallback_startup_period_ms: 0, // Disable the startup period + observer_fallback_progress_threshold_ms: 999_999_999, // Disable the progress check + observer_fallback_sync_lag_threshold_ms, + ..ConsensusObserverConfig::default() + }; + + // Create a mock DB reader with expectations + let time_service = TimeService::mock(); + let latest_block_timestamp = time_service.now_unix_time().as_micros() as u64; + let mut mock_db_reader = MockDatabaseReader::new(); + mock_db_reader + .expect_get_latest_ledger_info_version() + .returning(move || Ok(1)); + mock_db_reader + .expect_get_block_timestamp() + .returning(move |_| Ok(latest_block_timestamp)); + + // Create a new fallback manager + let mut fallback_manager = ObserverFallbackManager::new( + consensus_observer_config, + Arc::new(mock_db_reader), + time_service.clone(), + ); + + // Verify that the DB is making sync progress and that the sync lag is acceptable + assert!(fallback_manager.check_syncing_progress().is_ok()); + + // Elapse some amount of time (but not enough to bypass the sync lag threshold) + let mock_time_service = time_service.into_mock(); + mock_time_service.advance(Duration::from_millis( + observer_fallback_sync_lag_threshold_ms - 1, + )); + + // Verify that the DB is making sync progress and that the sync lag is acceptable + assert!(fallback_manager.check_syncing_progress().is_ok()); + + // Elapse enough time to bypass the sync lag threshold + mock_time_service.advance(Duration::from_millis( + observer_fallback_sync_lag_threshold_ms + 1, + )); + + // Verify that the sync lag is too high and that fallback mode should be entered + assert_matches!( + fallback_manager.check_syncing_progress(), + Err(Error::ObserverFallingBehind(_)) + ); + } + + #[test] + fn test_verify_sync_lag_health_startup_period() { + // Create a consensus observer config + let observer_fallback_sync_lag_threshold_ms = 10_000; + let observer_fallback_startup_period_ms = 90_0000; + let consensus_observer_config = ConsensusObserverConfig { + observer_fallback_startup_period_ms, + observer_fallback_progress_threshold_ms: 999_999_999, // Disable the progress check + observer_fallback_sync_lag_threshold_ms, + ..ConsensusObserverConfig::default() + }; + + // Create a mock DB reader with expectations + let time_service = TimeService::mock(); + let latest_block_timestamp = time_service.now_unix_time().as_micros() as u64; + let mut mock_db_reader = MockDatabaseReader::new(); + mock_db_reader + .expect_get_latest_ledger_info_version() + .returning(move || Ok(1)); + mock_db_reader + .expect_get_block_timestamp() + .returning(move |_| Ok(latest_block_timestamp)); + + // Create a new fallback manager + let mut fallback_manager = ObserverFallbackManager::new( + consensus_observer_config, + Arc::new(mock_db_reader), + time_service.clone(), + ); + + // Verify that the DB is making sync progress and that we're still in the startup period + let mock_time_service = time_service.into_mock(); + for _ in 0..5 { + // Elapse enough time to bypass the sync lag threshold + mock_time_service.advance(Duration::from_millis( + observer_fallback_sync_lag_threshold_ms + 1, + )); + + // Verify that the DB is still making sync progress (we're still in the startup period) + assert!(fallback_manager.check_syncing_progress().is_ok()); + } + + // Elapse enough time to bypass the startup period + mock_time_service.advance(Duration::from_millis( + observer_fallback_startup_period_ms + 1, + )); + + // Verify that the sync lag is too high and that fallback mode should be entered + assert_matches!( + fallback_manager.check_syncing_progress(), + Err(Error::ObserverFallingBehind(_)) + ); + } + #[test] fn test_reset_syncing_progress() { // Create a new fallback manager From a12510d9b95620907796f680dab32f9fc90e9bd9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 18:28:19 +0000 Subject: [PATCH 05/16] Cherrypick #280 (#282) (#15258) (#15341) (cherry picked from commit ea6e45f0eee4b6da2ebf93b9b89d269d334fcf70) Co-authored-by: Sherry Xiao --- aptos-move/aptos-vm/src/aptos_vm.rs | 11 +- aptos-move/e2e-move-tests/src/tests/mod.rs | 1 + .../src/tests/upgrade_compatibility.rs | 164 ++++++++++++++++++ .../move-binary-format/src/compatibility.rs | 31 +++- .../src/compatibility_legacy.rs | 22 ++- .../src/vm_test_harness.rs | 1 + types/src/on_chain_config/timed_features.rs | 10 +- 7 files changed, 224 insertions(+), 16 deletions(-) create mode 100644 aptos-move/e2e-move-tests/src/tests/upgrade_compatibility.rs diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index 9a671addab1a0..7f0dbfde3fdac 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -1652,7 +1652,12 @@ impl AptosVM { let check_friend_linking = !self .features() .is_enabled(FeatureFlag::TREAT_FRIEND_AS_PRIVATE); - let compatability_checks = Compatibility::new(check_struct_layout, check_friend_linking); + let compatibility_checks = Compatibility::new( + check_struct_layout, + check_friend_linking, + self.timed_features() + .is_enabled(TimedFeatureFlag::EntryCompatibility), + ); if self.features().is_loader_v2_enabled() { session.finish_with_module_publishing_and_initialization( @@ -1665,7 +1670,7 @@ impl AptosVM { destination, bundle, modules, - compatability_checks, + compatibility_checks, ) } else { // Check what modules exist before publishing. @@ -1689,7 +1694,7 @@ impl AptosVM { bundle.into_inner(), destination, gas_meter, - compatability_checks, + compatibility_checks, ) })?; diff --git a/aptos-move/e2e-move-tests/src/tests/mod.rs b/aptos-move/e2e-move-tests/src/tests/mod.rs index f9ab23563390c..63a5e1ff70eb5 100644 --- a/aptos-move/e2e-move-tests/src/tests/mod.rs +++ b/aptos-move/e2e-move-tests/src/tests/mod.rs @@ -54,6 +54,7 @@ mod token_event_store; mod token_objects; mod transaction_context; mod type_too_large; +mod upgrade_compatibility; mod vector_numeric_address; mod vm; mod vote; diff --git a/aptos-move/e2e-move-tests/src/tests/upgrade_compatibility.rs b/aptos-move/e2e-move-tests/src/tests/upgrade_compatibility.rs new file mode 100644 index 0000000000000..6bfadbdc289d7 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/upgrade_compatibility.rs @@ -0,0 +1,164 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +//! Tests for upgrade compatibility +//! +//! TODO: currently this contains only tests for friend entry functions, this should be extended +//! to test all compatibility rules in one place. + +// Note: this module uses parameterized tests via the +// [`rstest` crate](https://crates.io/crates/rstest) +// to test for multiple feature combinations. +// +// Currently, we are testing both the old and the new compatibility checker + +use crate::{assert_success, assert_vm_status, MoveHarness}; +use aptos_framework::BuildOptions; +use aptos_package_builder::PackageBuilder; +use aptos_types::{ + account_address::AccountAddress, on_chain_config::FeatureFlag, transaction::TransactionStatus, +}; +use move_core_types::vm_status::StatusCode; +use rstest::rstest; + +#[rstest(use_new_checker, case(false), case(true))] +fn private_non_entry(use_new_checker: bool) { + let result = check_upgrade("fun f(){}", "fun f(u: u16){}", use_new_checker); + assert_success!(result) +} + +#[rstest(use_new_checker, case(false), case(true))] +fn remove_function(use_new_checker: bool) { + let result = check_upgrade("fun f(){}", "", use_new_checker); + assert_success!(result); + + let result = check_upgrade("public fun f(){}", "", use_new_checker); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); + + let result = check_upgrade("public(friend) fun f(){}", "", use_new_checker); + assert_success!(result); + + let result = check_upgrade("entry fun f(){}", "", use_new_checker); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); + + let result = check_upgrade("public entry fun f(){}", "", use_new_checker); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); + + let result = check_upgrade("public(friend) entry fun f(){}", "", use_new_checker); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); +} + +#[rstest(use_new_checker, case(false), case(true))] +fn change_function_signature(use_new_checker: bool) { + let result = check_upgrade("fun f(){}", "fun f(u: u16){}", use_new_checker); + assert_success!(result); + + let result = check_upgrade( + "public fun f(){}", + "public fun f(u: u16){}", + use_new_checker, + ); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); + + let result = check_upgrade( + "public(friend) fun f(){}", + "public(friend) fun f(u: u16){}", + use_new_checker, + ); + assert_success!(result); + + let result = check_upgrade("entry fun f(){}", "entry fun f(u: u16){}", use_new_checker); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); + + let result = check_upgrade( + "public entry fun f(){}", + "public entry fun f(u: u16){}", + use_new_checker, + ); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); + + let result = check_upgrade( + "public(friend) entry fun f(){}", + "public(friend) entry fun f(u: u16){}", + use_new_checker, + ); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE); +} + +#[rstest(use_new_checker, case(false), case(true))] +fn friend_add_entry(use_new_checker: bool) { + let result = check_upgrade( + "public(friend) fun f(){}", + "public(friend) entry fun f(){}", + use_new_checker, + ); + assert_success!(result) +} + +#[rstest(use_new_checker, case(false), case(true))] +fn friend_remove_entry_failure(use_new_checker: bool) { + let result = check_upgrade( + "public(friend) entry fun f(){}", + "public(friend) fun f(){}", + use_new_checker, + ); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE) +} + +#[rstest(use_new_checker, case(false), case(true))] +fn friend_remove_failure(use_new_checker: bool) { + let result = check_upgrade("public(friend) entry fun f(){}", "", use_new_checker); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE) +} + +#[rstest(use_new_checker, case(false), case(true))] +fn friend_entry_change_sig_failure(use_new_checker: bool) { + let result = check_upgrade( + "public(friend) entry fun f(){}", + "public(friend) entry fun f(_s: &signer){}", + use_new_checker, + ); + assert_vm_status!(result, StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE) +} + +fn check_upgrade(old_decls: &str, new_decls: &str, use_new_checker: bool) -> TransactionStatus { + let (enabled, disabled) = if use_new_checker { + (vec![FeatureFlag::USE_COMPATIBILITY_CHECKER_V2], vec![]) + } else { + (vec![], vec![FeatureFlag::USE_COMPATIBILITY_CHECKER_V2]) + }; + let mut builder = PackageBuilder::new("Package"); + let mut h = MoveHarness::new_with_features(enabled, disabled); + let acc = h.new_account_at(AccountAddress::from_hex_literal("0x815").unwrap()); + + // Publish for first time + builder.add_source( + "m.move", + &format!( + r#" + module 0x815::m {{ + {} + }} + "#, + old_decls + ), + ); + let path = builder.write_to_temp().unwrap(); + assert_success!(h.publish_package_with_options(&acc, path.path(), BuildOptions::move_2())); + + // Now upgrade + let mut builder = PackageBuilder::new("Package"); + builder.add_source( + "m.move", + &format!( + r#" + module 0x815::m {{ + {} + }} + "#, + new_decls + ), + ); + let path = builder.write_to_temp().unwrap(); + h.publish_package_with_options(&acc, path.path(), BuildOptions::move_2()) +} diff --git a/third_party/move/move-binary-format/src/compatibility.rs b/third_party/move/move-binary-format/src/compatibility.rs index 35706526ac9d2..be95e220456e6 100644 --- a/third_party/move/move-binary-format/src/compatibility.rs +++ b/third_party/move/move-binary-format/src/compatibility.rs @@ -33,6 +33,8 @@ pub struct Compatibility { pub(crate) check_struct_layout: bool, /// if false, treat `friend` as `private` when `check_struct_and_function_linking`. pub(crate) check_friend_linking: bool, + /// if false, entry function will be treated as regular function. + pub(crate) treat_entry_as_public: bool, } impl Default for Compatibility { @@ -41,6 +43,7 @@ impl Default for Compatibility { check_struct_and_pub_function_linking: true, check_struct_layout: true, check_friend_linking: true, + treat_entry_as_public: true, } } } @@ -55,14 +58,20 @@ impl Compatibility { check_struct_and_pub_function_linking: false, check_struct_layout: false, check_friend_linking: false, + treat_entry_as_public: false, } } - pub fn new(check_struct_layout: bool, check_friend_linking: bool) -> Self { + pub fn new( + check_struct_layout: bool, + check_friend_linking: bool, + treat_entry_as_public: bool, + ) -> Self { Self { check_struct_and_pub_function_linking: true, check_struct_layout, check_friend_linking, + treat_entry_as_public, } } @@ -139,11 +148,8 @@ impl Compatibility { // - if the function visibility is upgraded to public, it is OK // - otherwise, it is considered as incompatible. // - // NOTE: it is possible to relax the compatibility checking for a friend function, i.e., - // we can remove/change a friend function if the function is not used by any module in the - // friend list. But for simplicity, we decided to go to the more restrictive form now and - // we may revisit this in the future. for old_func in old_view.functions() { + // private, non entry function doesn't need to follow any checks here, skip if old_func.visibility() == Visibility::Private && !old_func.is_entry() { // Function not exposed, continue with next one continue; @@ -152,15 +158,28 @@ impl Compatibility { Some(new_func) => new_func, None => { // Function has been removed + // Function is NOT a private, non entry function. if !matches!(old_func.visibility(), Visibility::Friend) + // Above: Either Private Entry, or Public || self.check_friend_linking + // Here we know that the old_function has to be Friend. + // And if friends are not considered private (self.check_friend_linking is true), we can't update. + || (old_func.is_entry() && self.treat_entry_as_public) + // Here we know that the old_func has to be Friend, and the check_friend_linking is set to false. + // We make sure that we don't allow any Entry functions to be deleted, when self.treat_entry_as_public is set (treats entry as public) { errors.push(format!("removed function `{}`", old_func.name())); } continue; }, }; - if matches!(old_func.visibility(), Visibility::Friend) && !self.check_friend_linking { + + if matches!(old_func.visibility(), Visibility::Friend) + && !self.check_friend_linking + // Above: We want to skip linking checks for public(friend) if self.check_friend_linking is set to false. + && !(old_func.is_entry() && self.treat_entry_as_public) + // However, public(friend) entry function still needs to be checked. + { continue; } let is_vis_compatible = match (old_func.visibility(), new_func.visibility()) { diff --git a/third_party/move/move-binary-format/src/compatibility_legacy.rs b/third_party/move/move-binary-format/src/compatibility_legacy.rs index a140863d65137..667dc0e09583b 100644 --- a/third_party/move/move-binary-format/src/compatibility_legacy.rs +++ b/third_party/move/move-binary-format/src/compatibility_legacy.rs @@ -71,17 +71,20 @@ impl Compatibility { // - if the function visibility is upgraded to public, it is OK // - otherwise, it is considered as incompatible. // - // NOTE: it is possible to relax the compatibility checking for a friend function, i.e., - // we can remove/change a friend function if the function is not used by any module in the - // friend list. But for simplicity, we decided to go to the more restrictive form now and - // we may revisit this in the future. for (name, old_func) in &old_module.exposed_functions { let new_func = match new_module.exposed_functions.get(name) { Some(new_func) => new_func, None => { - if matches!(old_func.visibility, Visibility::Friend) { + if matches!(old_func.visibility, Visibility::Friend) + && !(old_func.is_entry && self.treat_entry_as_public) + // self.treat_entry_as_public is false: trying to remove friend + // self.treat_entry_as_public is true: trying to remove Friend non-entry + { + // Report as friend linking error, which would be dismissed when + // self.check_friend_linking is set to false friend_linking = false; } else { + // Otherwise report as function linking error. struct_and_pub_function_linking = false; } continue; @@ -118,9 +121,16 @@ impl Compatibility { &new_func.type_parameters, ) { - if matches!(old_func.visibility, Visibility::Friend) { + if matches!(old_func.visibility, Visibility::Friend) + && (!old_func.is_entry || !self.treat_entry_as_public) + // self.treat_entry_as_public is false: trying to change signature of a friend function + // self.treat_entry_as_public is true: trying to change signature of a friend non-entry function. + { + // Report as friend linking error, which would be dismissed when + // self.check_friend_linking is set to false friend_linking = false; } else { + // Otherwise report as function linking error. struct_and_pub_function_linking = false; } } diff --git a/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs b/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs index da5e6faa106ab..00730088b70a6 100644 --- a/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs +++ b/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs @@ -302,6 +302,7 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> { Compatibility::new( !extra_args.skip_check_struct_layout, !extra_args.skip_check_friend_linking, + false ) }; if vm.vm_config().use_loader_v2 { diff --git a/types/src/on_chain_config/timed_features.rs b/types/src/on_chain_config/timed_features.rs index c3161c47fedac..ea7cafa68a7b9 100644 --- a/types/src/on_chain_config/timed_features.rs +++ b/types/src/on_chain_config/timed_features.rs @@ -15,6 +15,7 @@ pub enum TimedFeatureFlag { DisableInvariantViolationCheckInSwapLoc, LimitTypeTagSize, ModuleComplexityCheck, + EntryCompatibility, } /// Representation of features that are gated by the block timestamps. @@ -43,10 +44,14 @@ impl TimedFeatureOverride { Replay => match flag { LimitTypeTagSize => true, ModuleComplexityCheck => true, + EntryCompatibility => true, // Add overrides for replay here. _ => return None, }, - Testing => false, // Activate all flags + Testing => match flag { + EntryCompatibility => true, + _ => return None, // Activate all flags + }, }) } } @@ -63,6 +68,9 @@ impl TimedFeatureFlag { (ModuleComplexityCheck, TESTNET) => 1719356400000, /* Tuesday, June 21, 2024 16:00:00 AM GMT-07:00 */ (ModuleComplexityCheck, MAINNET) => 1720033200000, /* Wednesday, July 3, 2024 12:00:00 AM GMT-07:00 */ + (EntryCompatibility, TESTNET) => 1730923200000, /* Wednesday, Nov 6, 2024 12:00:00 AM GMT-07:00 */ + (EntryCompatibility, MAINNET) => 1731441600000, /* Tuesday, Nov 12, 2024 12:00:00 AM GMT-07:00 */ + // If unspecified, a timed feature is considered enabled from the very beginning of time. _ => 0, } From 3e614b26bc8e886f30cafc7c65b887dc4ca0f486 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:02:41 +0000 Subject: [PATCH 06/16] [loader-v2] Small cleanups & tests (#15279) (#15343) - Fixed naming for global module cache. - Added more counters, moved some old ones. - Added unit tests for TransactionSliceMetadata + renaming. (cherry picked from commit 47f0bf397eb5ca43257bfa775a6b28e7b7faf8b3) Co-authored-by: George Mitenkov --- Cargo.lock | 1 - .../aptos-debugger/src/aptos_debugger.rs | 2 +- .../src/transaction_bench_state.rs | 2 +- aptos-move/aptos-vm-environment/Cargo.toml | 2 +- .../aptos-vm-environment/src/environment.rs | 4 +- aptos-move/aptos-vm/src/aptos_vm.rs | 2 +- aptos-move/aptos-vm/src/block_executor/mod.rs | 4 +- aptos-move/aptos-vm/src/lib.rs | 4 +- .../sharded_executor_service.rs | 2 +- .../block-executor/src/captured_reads.rs | 10 +- aptos-move/block-executor/src/code_cache.rs | 7 +- .../block-executor/src/code_cache_global.rs | 110 ++++++------ .../src/code_cache_global_manager.rs | 5 +- aptos-move/block-executor/src/counters.rs | 13 +- aptos-move/block-executor/src/executor.rs | 6 +- aptos-move/e2e-tests/src/executor.rs | 2 +- .../executor-benchmark/src/native_executor.rs | 4 +- execution/executor/src/block_executor/mod.rs | 4 +- execution/executor/src/chunk_executor/mod.rs | 3 +- .../src/chunk_executor/transaction_chunk.rs | 3 +- execution/executor/src/db_bootstrapper/mod.rs | 3 +- execution/executor/src/fuzzing.rs | 4 +- execution/executor/src/tests/mock_vm/mod.rs | 4 +- execution/executor/src/tests/mod.rs | 3 +- .../src/workflow/do_get_execution_output.rs | 2 +- .../execution/ptx-executor/src/lib.rs | 4 +- .../move/move-vm/runtime/src/loader/mod.rs | 9 +- .../runtime/src/storage/environment.rs | 5 + .../runtime/src/storage/module_storage.rs | 3 + types/Cargo.toml | 2 +- types/src/block_executor/execution_state.rs | 107 ----------- types/src/block_executor/mod.rs | 2 +- .../transaction_slice_metadata.rs | 169 ++++++++++++++++++ types/src/transaction/webauthn.rs | 2 +- 34 files changed, 298 insertions(+), 211 deletions(-) delete mode 100644 types/src/block_executor/execution_state.rs create mode 100644 types/src/block_executor/transaction_slice_metadata.rs diff --git a/Cargo.lock b/Cargo.lock index 0fb89d94a6eee..adf4fc9c7ea40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4526,7 +4526,6 @@ dependencies = [ "aptos-framework", "aptos-gas-algebra", "aptos-gas-schedule", - "aptos-language-e2e-tests", "aptos-move-stdlib", "aptos-native-interface", "aptos-table-natives", diff --git a/aptos-move/aptos-debugger/src/aptos_debugger.rs b/aptos-move/aptos-debugger/src/aptos_debugger.rs index 636ca6bf10416..b1d00f2e33dde 100644 --- a/aptos-move/aptos-debugger/src/aptos_debugger.rs +++ b/aptos-move/aptos-debugger/src/aptos_debugger.rs @@ -11,7 +11,7 @@ use aptos_types::{ account_address::AccountAddress, block_executor::{ config::{BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig}, - execution_state::TransactionSliceMetadata, + transaction_slice_metadata::TransactionSliceMetadata, }, contract_event::ContractEvent, state_store::TStateView, diff --git a/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs b/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs index 6c95e1a213b3c..d05af15b5ba51 100644 --- a/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs +++ b/aptos-move/aptos-transaction-benchmarks/src/transaction_bench_state.rs @@ -18,8 +18,8 @@ use aptos_language_e2e_tests::{ use aptos_types::{ block_executor::{ config::{BlockExecutorConfig, BlockExecutorConfigFromOnchain}, - execution_state::TransactionSliceMetadata, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, block_metadata::BlockMetadata, on_chain_config::{OnChainConfig, ValidatorSet}, diff --git a/aptos-move/aptos-vm-environment/Cargo.toml b/aptos-move/aptos-vm-environment/Cargo.toml index 2ae1c4c98e7d2..5274a6694c00f 100644 --- a/aptos-move/aptos-vm-environment/Cargo.toml +++ b/aptos-move/aptos-vm-environment/Cargo.toml @@ -31,4 +31,4 @@ once_cell = { workspace = true } sha3 = { workspace = true } [dev-dependencies] -aptos-language-e2e-tests = { workspace = true } +aptos-types = { workspace = true, features = ["testing"] } diff --git a/aptos-move/aptos-vm-environment/src/environment.rs b/aptos-move/aptos-vm-environment/src/environment.rs index 151dc19247ef9..debdd654c92ac 100644 --- a/aptos-move/aptos-vm-environment/src/environment.rs +++ b/aptos-move/aptos-vm-environment/src/environment.rs @@ -272,12 +272,12 @@ fn fetch_config_and_update_hash( #[cfg(test)] pub mod test { use super::*; - use aptos_language_e2e_tests::data_store::FakeDataStore; + use aptos_types::state_store::MockStateView; #[test] fn test_new_environment() { // This creates an empty state. - let state_view = FakeDataStore::default(); + let state_view = MockStateView::empty(); let env = Environment::new(&state_view, false, None); // Check default values. diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index 7f0dbfde3fdac..4f8b70c5cf4eb 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -49,8 +49,8 @@ use aptos_types::{ BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig, BlockExecutorModuleCacheLocalConfig, }, - execution_state::TransactionSliceMetadata, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, block_metadata::BlockMetadata, block_metadata_ext::{BlockMetadataExt, BlockMetadataWithRandomness}, diff --git a/aptos-move/aptos-vm/src/block_executor/mod.rs b/aptos-move/aptos-vm/src/block_executor/mod.rs index 5387978387a48..7aaf6f1fe2272 100644 --- a/aptos-move/aptos-vm/src/block_executor/mod.rs +++ b/aptos-move/aptos-vm/src/block_executor/mod.rs @@ -18,7 +18,9 @@ use aptos_block_executor::{ }; use aptos_infallible::Mutex; use aptos_types::{ - block_executor::{config::BlockExecutorConfig, execution_state::TransactionSliceMetadata}, + block_executor::{ + config::BlockExecutorConfig, transaction_slice_metadata::TransactionSliceMetadata, + }, contract_event::ContractEvent, error::PanicError, executable::ExecutableTestType, diff --git a/aptos-move/aptos-vm/src/lib.rs b/aptos-move/aptos-vm/src/lib.rs index 5fa5971673958..130c47823da86 100644 --- a/aptos-move/aptos-vm/src/lib.rs +++ b/aptos-move/aptos-vm/src/lib.rs @@ -128,8 +128,8 @@ pub use crate::aptos_vm::{AptosSimulationVM, AptosVM}; use crate::sharded_block_executor::{executor_client::ExecutorClient, ShardedBlockExecutor}; use aptos_types::{ block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, - partitioner::PartitionedTransactions, + config::BlockExecutorConfigFromOnchain, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, state_store::StateView, transaction::{ diff --git a/aptos-move/aptos-vm/src/sharded_block_executor/sharded_executor_service.rs b/aptos-move/aptos-vm/src/sharded_block_executor/sharded_executor_service.rs index 7ec39f1d4bf61..21335da8ce17d 100644 --- a/aptos-move/aptos-vm/src/sharded_block_executor/sharded_executor_service.rs +++ b/aptos-move/aptos-vm/src/sharded_block_executor/sharded_executor_service.rs @@ -21,8 +21,8 @@ use aptos_logger::{info, trace}; use aptos_types::{ block_executor::{ config::{BlockExecutorConfig, BlockExecutorLocalConfig}, - execution_state::TransactionSliceMetadata, partitioner::{ShardId, SubBlock, SubBlocksForShard, TransactionWithDependencies}, + transaction_slice_metadata::TransactionSliceMetadata, }, state_store::StateView, transaction::{ diff --git a/aptos-move/block-executor/src/captured_reads.rs b/aptos-move/block-executor/src/captured_reads.rs index 3deff5419c8a6..7a61f5e3fc16c 100644 --- a/aptos-move/block-executor/src/captured_reads.rs +++ b/aptos-move/block-executor/src/captured_reads.rs @@ -648,7 +648,7 @@ where } /// For every module read that was captured, checks if the reads are still the same: - /// 1. Entries read from the global cross-block module cache are still valid. + /// 1. Entries read from the global module cache are not overridden. /// 2. Entries that were not in per-block cache before are still not there. /// 3. Entries that were in per-block cache have the same commit index. pub(crate) fn validate_module_reads( @@ -661,7 +661,7 @@ where } self.module_reads.iter().all(|(key, read)| match read { - ModuleRead::GlobalCache(_) => global_module_cache.contains_valid(key), + ModuleRead::GlobalCache(_) => global_module_cache.contains_not_overridden(key), ModuleRead::PerBlockCache(previous) => { let current_version = per_block_module_cache.get_module_version(key); let previous_version = previous.as_ref().map(|(_, version)| *version); @@ -1560,7 +1560,7 @@ mod test { assert!(captured_reads.validate_module_reads(&global_module_cache, &per_block_module_cache)); // Now, mark one of the entries in invalid. Validations should fail! - global_module_cache.mark_invalid_if_contains(&1); + global_module_cache.mark_overridden(&1); let valid = captured_reads.validate_module_reads(&global_module_cache, &per_block_module_cache); assert!(!valid); @@ -1696,7 +1696,7 @@ mod test { // Assume we republish this module: validation must fail. let a = mock_deserialized_code(100, MockExtension::new(8)); - global_module_cache.mark_invalid_if_contains(&0); + global_module_cache.mark_overridden(&0); per_block_module_cache .insert_deserialized_module( 0, @@ -1713,6 +1713,6 @@ mod test { // Assume we re-read the new correct version. Then validation should pass again. captured_reads.capture_per_block_cache_read(0, Some((a, Some(10)))); assert!(captured_reads.validate_module_reads(&global_module_cache, &per_block_module_cache)); - assert!(!global_module_cache.contains_valid(&0)); + assert!(!global_module_cache.contains_not_overridden(&0)); } } diff --git a/aptos-move/block-executor/src/code_cache.rs b/aptos-move/block-executor/src/code_cache.rs index 081147ce45ae9..6465284f6e770 100644 --- a/aptos-move/block-executor/src/code_cache.rs +++ b/aptos-move/block-executor/src/code_cache.rs @@ -3,6 +3,7 @@ use crate::{ captured_reads::CacheRead, + counters::GLOBAL_MODULE_CACHE_MISS_SECONDS, view::{LatestView, ViewState}, }; use ambassador::delegate_to_methods; @@ -144,7 +145,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> ModuleCache } // Otherwise, it is a miss. Check global cache. - if let Some(module) = self.global_module_cache.get_valid(key) { + if let Some(module) = self.global_module_cache.get(key) { state .captured_reads .borrow_mut() @@ -153,6 +154,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> ModuleCache } // If not global cache, check per-block cache. + let _timer = GLOBAL_MODULE_CACHE_MISS_SECONDS.start_timer(); let read = state .versioned_map .module_cache() @@ -164,11 +166,12 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> ModuleCache Ok(read) }, ViewState::Unsync(state) => { - if let Some(module) = self.global_module_cache.get_valid(key) { + if let Some(module) = self.global_module_cache.get(key) { state.read_set.borrow_mut().capture_module_read(key.clone()); return Ok(Some((module, Self::Version::default()))); } + let _timer = GLOBAL_MODULE_CACHE_MISS_SECONDS.start_timer(); let read = state .unsync_map .module_cache() diff --git a/aptos-move/block-executor/src/code_cache_global.rs b/aptos-move/block-executor/src/code_cache_global.rs index a74e96170c95c..18e0c0679a958 100644 --- a/aptos-move/block-executor/src/code_cache_global.rs +++ b/aptos-move/block-executor/src/code_cache_global.rs @@ -13,12 +13,12 @@ use std::{ }, }; -/// Entry stored in [GlobalModuleCache]. +/// Entry stored in [GlobalModuleCache]. Can be invalidated by module publishing. struct Entry { - /// True if this code is "valid" within the block execution context (i.e., there has been no - /// republishing of this module so far). If false, executor needs to read the module from the - /// sync/unsync module caches. - valid: AtomicBool, + /// False if this code is "valid" within the block execution context (i.e., there has been no + /// republishing of this module so far). If true, executor needs to read the module from the + /// per-block module caches. + overridden: AtomicBool, /// Cached verified module. Must always be verified. module: Arc>, } @@ -37,19 +37,19 @@ where } Ok(Self { - valid: AtomicBool::new(true), + overridden: AtomicBool::new(false), module, }) } - /// Marks the module as invalid. - fn mark_invalid(&self) { - self.valid.store(false, Ordering::Release) + /// Marks the module as overridden. + fn mark_overridden(&self) { + self.overridden.store(true, Ordering::Release) } - /// Returns true if the module is valid. - pub(crate) fn is_valid(&self) -> bool { - self.valid.load(Ordering::Acquire) + /// Returns true if the module is not overridden. + fn is_not_overridden(&self) -> bool { + !self.overridden.load(Ordering::Acquire) } /// Returns the module code stored is this [Entry]. @@ -81,28 +81,30 @@ where } } - /// Returns true if the key exists in cache and the corresponding module is valid. - pub fn contains_valid(&self, key: &K) -> bool { + /// Returns true if the key exists in cache and the corresponding module is not overridden. + pub fn contains_not_overridden(&self, key: &K) -> bool { self.module_cache .get(key) - .is_some_and(|entry| entry.is_valid()) + .is_some_and(|entry| entry.is_not_overridden()) } - /// Marks the cached module (if it exists) as invalid. As a result, all subsequent calls to the - /// cache for the associated key will result in a cache miss. If an entry does not to exist, it - /// is a no-op. - pub fn mark_invalid_if_contains(&self, key: &K) { + /// Marks the cached module (if it exists) as overridden. As a result, all subsequent calls to + /// the cache for the associated key will result in a cache miss. If an entry does not exist, + /// it is a no-op. + pub fn mark_overridden(&self, key: &K) { if let Some(entry) = self.module_cache.get(key) { - entry.mark_invalid(); + entry.mark_overridden(); } } /// Returns the module stored in cache. If the module has not been cached, or it exists but is - /// not valid, [None] is returned. - pub fn get_valid(&self, key: &K) -> Option>> { - self.module_cache - .get(key) - .and_then(|entry| entry.is_valid().then(|| Arc::clone(entry.module_code()))) + /// overridden, [None] is returned. + pub fn get(&self, key: &K) -> Option>> { + self.module_cache.get(key).and_then(|entry| { + entry + .is_not_overridden() + .then(|| Arc::clone(entry.module_code())) + }) } /// Returns the number of entries in the cache. @@ -124,9 +126,9 @@ where /// Inserts modules into the cache. /// Notes: /// 1. Only verified modules are inserted. - /// 2. Valid modules should not be removed, and new modules should have unique ownership. If - /// these constraints are violated, a panic error is returned. - pub fn insert_verified_unsync( + /// 2. Not overridden modules should not be removed, and new modules should have unique + /// ownership. If these constraints are violated, a panic error is returned. + pub fn insert_verified( &mut self, modules: impl Iterator>)>, ) -> Result<(), PanicError> { @@ -134,14 +136,12 @@ where for (key, module) in modules { if let Occupied(entry) = self.module_cache.entry(key.clone()) { - if entry.get().is_valid() { + if entry.get().is_not_overridden() { return Err(PanicError::CodeInvariantError( - "Should never overwrite a valid module".to_string(), + "Should never replace a non-overridden module".to_string(), )); } else { - // Otherwise, remove the invalid entry. - let size = entry.get().module_code().extension().size_in_bytes(); - self.size -= size; + self.size -= entry.get().module_code().extension().size_in_bytes(); entry.remove(); } } @@ -195,36 +195,36 @@ mod test { } #[test] - fn test_entry_mark_invalid() { + fn test_entry_mark_overridden() { let entry = assert_ok!(Entry::new(mock_verified_code(0, MockExtension::new(8)))); - assert!(entry.is_valid()); + assert!(entry.is_not_overridden()); - entry.mark_invalid(); - assert!(!entry.is_valid()); + entry.mark_overridden(); + assert!(!entry.is_not_overridden()); } #[test] - fn test_cache_contains_valid_and_get() { + fn test_cache_is_not_overridden_and_get() { let mut cache = GlobalModuleCache::empty(); // Set the state. cache.insert(0, mock_verified_code(0, MockExtension::new(8))); cache.insert(1, mock_verified_code(1, MockExtension::new(8))); - cache.mark_invalid_if_contains(&1); + cache.mark_overridden(&1); assert_eq!(cache.num_modules(), 2); - assert!(cache.contains_valid(&0)); - assert!(!cache.contains_valid(&1)); - assert!(!cache.contains_valid(&3)); + assert!(cache.contains_not_overridden(&0)); + assert!(!cache.contains_not_overridden(&1)); + assert!(!cache.contains_not_overridden(&3)); - assert!(cache.get_valid(&0).is_some()); - assert!(cache.get_valid(&1).is_none()); - assert!(cache.get_valid(&3).is_none()); + assert!(cache.get(&0).is_some()); + assert!(cache.get(&1).is_none()); + assert!(cache.get(&3).is_none()); } #[test] - fn test_cache_sizes_and_flush_unchecked() { + fn test_cache_sizes_and_flush() { let mut cache = GlobalModuleCache::empty(); assert_eq!(cache.num_modules(), 0); assert_eq!(cache.size_in_bytes(), 0); @@ -245,16 +245,14 @@ mod test { } #[test] - fn test_cache_insert_verified_unchecked() { + fn test_cache_insert_verified() { let mut cache = GlobalModuleCache::empty(); let mut new_modules = vec![]; for i in 0..10 { new_modules.push((i, mock_verified_code(i, MockExtension::new(8)))); } - assert!(cache - .insert_verified_unsync(new_modules.into_iter()) - .is_ok()); + assert_ok!(cache.insert_verified(new_modules.into_iter())); assert_eq!(cache.num_modules(), 10); assert_eq!(cache.size_in_bytes(), 80); @@ -265,14 +263,14 @@ mod test { let mut cache = GlobalModuleCache::empty(); let deserialized_modules = vec![(0, mock_deserialized_code(0, MockExtension::new(8)))]; - assert_ok!(cache.insert_verified_unsync(deserialized_modules.into_iter())); + assert_ok!(cache.insert_verified(deserialized_modules.into_iter())); assert_eq!(cache.num_modules(), 0); assert_eq!(cache.size_in_bytes(), 0); } #[test] - fn test_cache_insert_verified_unchecked_does_not_override_valid_modules() { + fn test_cache_insert_verified_does_not_override_valid_modules() { let mut cache = GlobalModuleCache::empty(); cache.insert(0, mock_verified_code(0, MockExtension::new(8))); @@ -280,20 +278,20 @@ mod test { assert_eq!(cache.size_in_bytes(), 8); let new_modules = vec![(0, mock_verified_code(100, MockExtension::new(32)))]; - assert_err!(cache.insert_verified_unsync(new_modules.into_iter())); + assert_err!(cache.insert_verified(new_modules.into_iter())); } #[test] - fn test_cache_insert_verified_unchecked_overrides_invalid_modules() { + fn test_cache_insert_verified_inserts_overridden_modules() { let mut cache = GlobalModuleCache::empty(); cache.insert(0, mock_verified_code(0, MockExtension::new(8))); - cache.mark_invalid_if_contains(&0); + cache.mark_overridden(&0); assert_eq!(cache.num_modules(), 1); assert_eq!(cache.size_in_bytes(), 8); let new_modules = vec![(0, mock_verified_code(100, MockExtension::new(32)))]; - assert_ok!(cache.insert_verified_unsync(new_modules.into_iter())); + assert_ok!(cache.insert_verified(new_modules.into_iter())); assert_eq!(cache.num_modules(), 1); assert_eq!(cache.size_in_bytes(), 32); diff --git a/aptos-move/block-executor/src/code_cache_global_manager.rs b/aptos-move/block-executor/src/code_cache_global_manager.rs index 084e7134c8c2d..5daaf4c0b7e90 100644 --- a/aptos-move/block-executor/src/code_cache_global_manager.rs +++ b/aptos-move/block-executor/src/code_cache_global_manager.rs @@ -10,7 +10,8 @@ use crate::{ }; use aptos_types::{ block_executor::{ - config::BlockExecutorModuleCacheLocalConfig, execution_state::TransactionSliceMetadata, + config::BlockExecutorModuleCacheLocalConfig, + transaction_slice_metadata::TransactionSliceMetadata, }, error::PanicError, state_store::StateView, @@ -298,7 +299,7 @@ fn prefetch_aptos_framework( // Framework must have been loaded. Drain verified modules from local cache into // global cache. let verified_module_code_iter = code_storage.into_verified_module_code_iter()?; - module_cache.insert_verified_unsync(verified_module_code_iter)?; + module_cache.insert_verified(verified_module_code_iter)?; } Ok(()) } diff --git a/aptos-move/block-executor/src/counters.rs b/aptos-move/block-executor/src/counters.rs index e75d1b3354805..79e98a7af3c53 100644 --- a/aptos-move/block-executor/src/counters.rs +++ b/aptos-move/block-executor/src/counters.rs @@ -198,7 +198,7 @@ pub static EFFECTIVE_BLOCK_GAS: Lazy = Lazy::new(|| { pub static APPROX_BLOCK_OUTPUT_SIZE: Lazy = Lazy::new(|| { register_histogram_vec!( "aptos_execution_approx_block_output_size", - "Historgram for different approx block output sizes - used for evaluting block ouptut limit.", + "Histogram for different approx block output sizes - used for evaluating block output limit.", &["mode"], output_buckets(), ) @@ -350,6 +350,17 @@ pub static GLOBAL_MODULE_CACHE_NUM_MODULES: Lazy = Lazy::new(|| { .unwrap() }); +pub static GLOBAL_MODULE_CACHE_MISS_SECONDS: Lazy = Lazy::new(|| { + register_histogram!( + // metric name + "global_module_cache_miss_seconds", + // metric description + "The time spent in seconds after global module cache miss to access per-block module cache", + time_buckets(), + ) + .unwrap() +}); + pub static STRUCT_NAME_INDEX_MAP_NUM_ENTRIES: Lazy = Lazy::new(|| { register_int_gauge!( "struct_name_index_map_num_entries", diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index c5e85367a9544..ae64a32c7bac4 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -1188,7 +1188,7 @@ where counters::update_state_counters(versioned_cache.stats(), true); module_cache_manager_guard .module_cache_mut() - .insert_verified_unsync(versioned_cache.take_modules_iter()) + .insert_verified(versioned_cache.take_modules_iter()) .map_err(|err| { alert!("[BlockSTM] Encountered panic error: {:?}", err); })?; @@ -1247,7 +1247,7 @@ where })?; let extension = Arc::new(AptosModuleExtension::new(state_value)); - global_module_cache.mark_invalid_if_contains(&id); + global_module_cache.mark_overridden(&id); per_block_module_cache .insert_deserialized_module(id.clone(), compiled_module, extension, Some(txn_idx)) .map_err(|err| { @@ -1668,7 +1668,7 @@ where counters::update_state_counters(unsync_map.stats(), false); module_cache_manager_guard .module_cache_mut() - .insert_verified_unsync(unsync_map.into_modules_iter())?; + .insert_verified(unsync_map.into_modules_iter())?; let block_end_info = if self .config diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index a6245c5508500..5daaafe3b2fd9 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -33,7 +33,7 @@ use aptos_types::{ BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig, BlockExecutorModuleCacheLocalConfig, }, - execution_state::TransactionSliceMetadata, + transaction_slice_metadata::TransactionSliceMetadata, }, block_metadata::BlockMetadata, chain_id::ChainId, diff --git a/execution/executor-benchmark/src/native_executor.rs b/execution/executor-benchmark/src/native_executor.rs index d2d3f12b2f687..ce3ae9faa97d6 100644 --- a/execution/executor-benchmark/src/native_executor.rs +++ b/execution/executor-benchmark/src/native_executor.rs @@ -10,8 +10,8 @@ use aptos_types::{ account_address::AccountAddress, account_config::{DepositEvent, WithdrawEvent}, block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, - partitioner::PartitionedTransactions, + config::BlockExecutorConfigFromOnchain, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, contract_event::ContractEvent, event::EventKey, diff --git a/execution/executor/src/block_executor/mod.rs b/execution/executor/src/block_executor/mod.rs index 352f42d93e643..f60548a94029a 100644 --- a/execution/executor/src/block_executor/mod.rs +++ b/execution/executor/src/block_executor/mod.rs @@ -31,8 +31,8 @@ use aptos_storage_interface::{ }; use aptos_types::{ block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, - partitioner::ExecutableBlock, + config::BlockExecutorConfigFromOnchain, partitioner::ExecutableBlock, + transaction_slice_metadata::TransactionSliceMetadata, }, ledger_info::LedgerInfoWithSignatures, state_store::StateViewId, diff --git a/execution/executor/src/chunk_executor/mod.rs b/execution/executor/src/chunk_executor/mod.rs index b094eb7e5b5c8..7ae0c364a3699 100644 --- a/execution/executor/src/chunk_executor/mod.rs +++ b/execution/executor/src/chunk_executor/mod.rs @@ -29,7 +29,8 @@ use aptos_storage_interface::{ }; use aptos_types::{ block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, + config::BlockExecutorConfigFromOnchain, + transaction_slice_metadata::TransactionSliceMetadata, }, contract_event::ContractEvent, ledger_info::LedgerInfoWithSignatures, diff --git a/execution/executor/src/chunk_executor/transaction_chunk.rs b/execution/executor/src/chunk_executor/transaction_chunk.rs index 974203e2a7f0e..89a3e39ffb285 100644 --- a/execution/executor/src/chunk_executor/transaction_chunk.rs +++ b/execution/executor/src/chunk_executor/transaction_chunk.rs @@ -12,7 +12,8 @@ use aptos_metrics_core::TimerHelper; use aptos_storage_interface::cached_state_view::CachedStateView; use aptos_types::{ block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, + config::BlockExecutorConfigFromOnchain, + transaction_slice_metadata::TransactionSliceMetadata, }, transaction::{Transaction, TransactionOutput, Version}, }; diff --git a/execution/executor/src/db_bootstrapper/mod.rs b/execution/executor/src/db_bootstrapper/mod.rs index 28118993efcad..db0f85c28cb14 100644 --- a/execution/executor/src/db_bootstrapper/mod.rs +++ b/execution/executor/src/db_bootstrapper/mod.rs @@ -19,7 +19,8 @@ use aptos_types::{ account_config::CORE_CODE_ADDRESS, aggregate_signature::AggregateSignature, block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, + config::BlockExecutorConfigFromOnchain, + transaction_slice_metadata::TransactionSliceMetadata, }, block_info::{BlockInfo, GENESIS_EPOCH, GENESIS_ROUND, GENESIS_TIMESTAMP_USECS}, ledger_info::{LedgerInfo, LedgerInfoWithSignatures}, diff --git a/execution/executor/src/fuzzing.rs b/execution/executor/src/fuzzing.rs index c9877f7dd04cb..944463d72508c 100644 --- a/execution/executor/src/fuzzing.rs +++ b/execution/executor/src/fuzzing.rs @@ -9,8 +9,8 @@ use aptos_executor_types::BlockExecutorTrait; use aptos_storage_interface::{chunk_to_commit::ChunkToCommit, DbReader, DbReaderWriter, DbWriter}; use aptos_types::{ block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, - partitioner::PartitionedTransactions, + config::BlockExecutorConfigFromOnchain, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, ledger_info::LedgerInfoWithSignatures, state_store::StateView, diff --git a/execution/executor/src/tests/mock_vm/mod.rs b/execution/executor/src/tests/mock_vm/mod.rs index d7281498bba62..b57ef1b1bf381 100644 --- a/execution/executor/src/tests/mock_vm/mod.rs +++ b/execution/executor/src/tests/mock_vm/mod.rs @@ -11,8 +11,8 @@ use aptos_types::{ account_address::AccountAddress, account_config::NEW_EPOCH_EVENT_V2_MOVE_TYPE_TAG, block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, - partitioner::PartitionedTransactions, + config::BlockExecutorConfigFromOnchain, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, bytes::NumToBytes, chain_id::ChainId, diff --git a/execution/executor/src/tests/mod.rs b/execution/executor/src/tests/mod.rs index 17b953f6d459a..163cbfda435a7 100644 --- a/execution/executor/src/tests/mod.rs +++ b/execution/executor/src/tests/mod.rs @@ -19,7 +19,8 @@ use aptos_types::{ account_address::AccountAddress, aggregate_signature::AggregateSignature, block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, + config::BlockExecutorConfigFromOnchain, + transaction_slice_metadata::TransactionSliceMetadata, }, block_info::BlockInfo, bytes::NumToBytes, diff --git a/execution/executor/src/workflow/do_get_execution_output.rs b/execution/executor/src/workflow/do_get_execution_output.rs index f002b6311d128..936c28fa85e22 100644 --- a/execution/executor/src/workflow/do_get_execution_output.rs +++ b/execution/executor/src/workflow/do_get_execution_output.rs @@ -22,8 +22,8 @@ use aptos_storage_interface::cached_state_view::{CachedStateView, StateCache}; use aptos_types::{ block_executor::{ config::BlockExecutorConfigFromOnchain, - execution_state::TransactionSliceMetadata, partitioner::{ExecutableTransactions, PartitionedTransactions}, + transaction_slice_metadata::TransactionSliceMetadata, }, contract_event::ContractEvent, epoch_state::EpochState, diff --git a/experimental/execution/ptx-executor/src/lib.rs b/experimental/execution/ptx-executor/src/lib.rs index 8c0d24104748f..642dc2c79cf95 100644 --- a/experimental/execution/ptx-executor/src/lib.rs +++ b/experimental/execution/ptx-executor/src/lib.rs @@ -26,8 +26,8 @@ use aptos_infallible::Mutex; use aptos_metrics_core::TimerHelper; use aptos_types::{ block_executor::{ - config::BlockExecutorConfigFromOnchain, execution_state::TransactionSliceMetadata, - partitioner::PartitionedTransactions, + config::BlockExecutorConfigFromOnchain, partitioner::PartitionedTransactions, + transaction_slice_metadata::TransactionSliceMetadata, }, state_store::StateView, transaction::{ diff --git a/third_party/move/move-vm/runtime/src/loader/mod.rs b/third_party/move/move-vm/runtime/src/loader/mod.rs index 171175aa868cf..4b74cc881dac6 100644 --- a/third_party/move/move-vm/runtime/src/loader/mod.rs +++ b/third_party/move/move-vm/runtime/src/loader/mod.rs @@ -258,6 +258,7 @@ impl Loader { I: IntoIterator, I::IntoIter: DoubleEndedIterator, { + let _timer = VM_TIMER.timer_with_label("Loader::check_dependencies_and_charge_gas"); match self { Self::V1(loader) => loader.check_dependencies_and_charge_gas( module_store, @@ -526,7 +527,7 @@ impl LoaderV1 { data_store: &mut TransactionDataCache, module_store: &LegacyModuleStorageAdapter, ) -> VMResult> { - let _timer = VM_TIMER.timer_with_label("Loader::deserialize_and_verify_script"); + let _timer = VM_TIMER.timer_with_label("LoaderV1::deserialize_and_verify_script"); let script = data_store.load_compiled_script_to_cache(script, hash_value)?; @@ -847,8 +848,6 @@ impl LoaderV1 { I: IntoIterator, I::IntoIter: DoubleEndedIterator, { - let _timer = VM_TIMER.timer_with_label("Loader::check_dependencies_and_charge_gas"); - // Initialize the work list (stack) and the map of visited modules. // // TODO: Determine the reserved capacity based on the max number of dependencies allowed. @@ -918,7 +917,7 @@ impl LoaderV1 { return Ok(cached); } - let _timer = VM_TIMER.timer_with_label("Loader::load_module [cache miss]"); + let _timer = VM_TIMER.timer_with_label("LoaderV1::load_module [cache miss]"); // otherwise, load the transitive closure of the target module let module_ref = self.load_and_verify_module_and_dependencies_and_friends( @@ -962,7 +961,7 @@ impl LoaderV1 { // Verify the module if it hasn't been verified before. if VERIFIED_MODULES.lock().get(&hash_value).is_none() { let _timer = VM_TIMER - .timer_with_label("Loader::load_and_verify_module [verification cache miss]"); + .timer_with_label("LoaderV1::load_and_verify_module [verification cache miss]"); move_bytecode_verifier::verify_module_with_config( &self.vm_config.verifier_config, diff --git a/third_party/move/move-vm/runtime/src/storage/environment.rs b/third_party/move/move-vm/runtime/src/storage/environment.rs index cf51100d91da8..5f53db11161e9 100644 --- a/third_party/move/move-vm/runtime/src/storage/environment.rs +++ b/third_party/move/move-vm/runtime/src/storage/environment.rs @@ -25,6 +25,7 @@ use move_core_types::{ identifier::{IdentStr, Identifier}, vm_status::{sub_status::unknown_invariant_violation::EPARANOID_FAILURE, StatusCode}, }; +use move_vm_metrics::{Timer, VM_TIMER}; #[cfg(any(test, feature = "testing"))] use move_vm_types::loaded_data::runtime_types::{StructIdentifier, StructNameIndex}; use std::sync::Arc; @@ -152,6 +153,10 @@ impl RuntimeEnvironment { module_hash: &[u8; 32], ) -> VMResult { if !VERIFIED_MODULES_V2.contains(module_hash) { + let _timer = VM_TIMER.timer_with_label( + "LoaderV2::build_locally_verified_module [verification cache miss]", + ); + // For regular execution, we cache already verified modules. Note that this even caches // verification for the published modules. This should be ok because as long as the // hash is the same, the deployed bytecode and any dependencies are the same, and so diff --git a/third_party/move/move-vm/runtime/src/storage/module_storage.rs b/third_party/move/move-vm/runtime/src/storage/module_storage.rs index 714871a70cc77..da64fc6dbd001 100644 --- a/third_party/move/move-vm/runtime/src/storage/module_storage.rs +++ b/third_party/move/move-vm/runtime/src/storage/module_storage.rs @@ -10,6 +10,7 @@ use move_core_types::{ account_address::AccountAddress, identifier::IdentStr, language_storage::ModuleId, metadata::Metadata, }; +use move_vm_metrics::{Timer, VM_TIMER}; use move_vm_types::{ code::{ModuleCache, ModuleCode, ModuleCodeBuilder, WithBytes, WithHash, WithSize}, module_cyclic_dependency_error, module_linker_error, @@ -191,6 +192,8 @@ where return Ok(Some(module.code().verified().clone())); } + let _timer = VM_TIMER.timer_with_label("ModuleStorage::fetch_verified_module [cache miss]"); + let mut visited = HashSet::new(); visited.insert(id.clone()); Ok(Some(visit_dependencies_and_verify( diff --git a/types/Cargo.toml b/types/Cargo.toml index 088b34699ac06..26e8db6d58771 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -94,7 +94,7 @@ url = { workspace = true } [features] default = [] -testing = [] +testing = ["aptos-crypto/fuzzing"] fuzzing = ["proptest", "proptest-derive", "aptos-crypto/fuzzing", "move-core-types/fuzzing", "arbitrary"] [[bench]] diff --git a/types/src/block_executor/execution_state.rs b/types/src/block_executor/execution_state.rs deleted file mode 100644 index a06aa8391cab2..0000000000000 --- a/types/src/block_executor/execution_state.rs +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::transaction::Version; -use aptos_crypto::HashValue; - -/// Specifies the kind of transactions for the block executor. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum TransactionSliceMetadata { - /// Block execution. Specifies the parent (executed) block, and the child (to be executed) - /// block. - Block { parent: HashValue, child: HashValue }, - /// Chunk execution, e.g., state sync or replay. Specifies the start and the end versions of - /// transaction slice. - Chunk { begin: Version, end: Version }, - /// The origin of transactions is not known, e.g., running a test. - Unknown, -} - -impl TransactionSliceMetadata { - pub fn unknown() -> Self { - Self::Unknown - } - - pub fn block(parent: HashValue, child: HashValue) -> Self { - Self::Block { parent, child } - } - - #[cfg(any(test, feature = "testing"))] - pub fn block_from_u64(parent: u64, child: u64) -> Self { - Self::Block { - parent: HashValue::from_u64(parent), - child: HashValue::from_u64(child), - } - } - - pub fn chunk(begin: Version, end: Version) -> Self { - Self::Chunk { begin, end } - } - - /// Returns the hash of the block where to append the state checkpoint (i.e., the current hash - /// of [TransactionSliceMetadata::Block]). For other variants, returns [None]. - pub fn append_state_checkpoint_to_block(&self) -> Option { - use TransactionSliceMetadata::*; - - match self { - Unknown => None, - Block { child, .. } => Some(*child), - Chunk { .. } => None, - } - } - - /// Returns true if transaction slice immediately follows the previous one. That is, if: - /// 1. Both are [TransactionSliceMetadata::Block] and the previous child is equal to the - /// current parent. - /// 2. Both are [TransactionSliceMetadata::Chunk] and the previous end version is equal to - /// the current start version. - pub fn is_immediately_after(&self, previous: &TransactionSliceMetadata) -> bool { - use TransactionSliceMetadata::*; - - match (previous, self) { - (Unknown, Unknown) - | (Unknown, Block { .. }) - | (Unknown, Chunk { .. }) - | (Block { .. }, Unknown) - | (Block { .. }, Chunk { .. }) - | (Chunk { .. }, Unknown) - | (Chunk { .. }, Block { .. }) => false, - (Block { child, .. }, Block { parent, .. }) => parent == child, - (Chunk { end, .. }, Chunk { begin, .. }) => begin == end, - } - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn test_append_state_checkpoint_to_block() { - assert!(TransactionSliceMetadata::unknown() - .append_state_checkpoint_to_block() - .is_none()); - assert!(TransactionSliceMetadata::chunk(1, 2) - .append_state_checkpoint_to_block() - .is_none()); - - let parent = HashValue::from_u64(2); - let child = HashValue::from_u64(3); - let execution_state = TransactionSliceMetadata::block(parent, child); - assert_eq!( - execution_state.append_state_checkpoint_to_block(), - Some(child) - ); - } - - #[test] - fn test_is_immediately_after() { - let fst = TransactionSliceMetadata::block(HashValue::from_u64(2), HashValue::from_u64(3)); - let snd = TransactionSliceMetadata::block(HashValue::from_u64(3), HashValue::from_u64(4)); - assert!(snd.is_immediately_after(&fst)); - - let fst = TransactionSliceMetadata::block(HashValue::from_u64(2), HashValue::from_u64(3)); - let snd = TransactionSliceMetadata::block(HashValue::from_u64(4), HashValue::from_u64(5)); - assert!(!snd.is_immediately_after(&fst)); - } -} diff --git a/types/src/block_executor/mod.rs b/types/src/block_executor/mod.rs index fb0081dacd7ca..a75beececb574 100644 --- a/types/src/block_executor/mod.rs +++ b/types/src/block_executor/mod.rs @@ -3,5 +3,5 @@ // SPDX-License-Identifier: Apache-2.0 pub mod config; -pub mod execution_state; pub mod partitioner; +pub mod transaction_slice_metadata; diff --git a/types/src/block_executor/transaction_slice_metadata.rs b/types/src/block_executor/transaction_slice_metadata.rs new file mode 100644 index 0000000000000..8df707552253f --- /dev/null +++ b/types/src/block_executor/transaction_slice_metadata.rs @@ -0,0 +1,169 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::transaction::Version; +use aptos_crypto::HashValue; + +/// Specifies the kind of transactions for the block executor. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum TransactionSliceMetadata { + /// Block execution. Specifies the parent (executed) block, and the child (to be executed) + /// block. + Block { parent: HashValue, child: HashValue }, + /// Chunk execution, e.g., state sync or replay. Specifies the start (inclusive) and the end + /// (exclusive) versions of a transaction slice. + Chunk { begin: Version, end: Version }, + /// The origin of transactions is not known, e.g., running a test. + Unknown, +} + +impl TransactionSliceMetadata { + pub fn unknown() -> Self { + Self::Unknown + } + + pub fn block(parent: HashValue, child: HashValue) -> Self { + Self::Block { parent, child } + } + + #[cfg(any(test, feature = "testing"))] + pub fn block_from_u64(parent: u64, child: u64) -> Self { + Self::Block { + parent: HashValue::from_u64(parent), + child: HashValue::from_u64(child), + } + } + + pub fn chunk(begin: Version, end: Version) -> Self { + debug_assert!( + begin < end, + "Chunk must have non-negative size, but it has: {}-{}", + begin, + end + ); + Self::Chunk { begin, end } + } + + /// Returns the hash of the block where to append the state checkpoint (i.e., the current hash + /// of [TransactionSliceMetadata::Block]). For other variants, returns [None]. + pub fn append_state_checkpoint_to_block(&self) -> Option { + use TransactionSliceMetadata::*; + + match self { + Unknown => None, + Block { child, .. } => Some(*child), + Chunk { .. } => None, + } + } + + /// Returns true if transaction slice immediately follows the previous one. That is, if: + /// 1. Both are [TransactionSliceMetadata::Block] and the previous child is equal to the + /// current parent. + /// 2. Both are [TransactionSliceMetadata::Chunk] and the previous end version is equal to + /// the current start version. + pub fn is_immediately_after(&self, previous: &TransactionSliceMetadata) -> bool { + use TransactionSliceMetadata::*; + + match (previous, self) { + (Unknown, Unknown) + | (Unknown, Block { .. }) + | (Unknown, Chunk { .. }) + | (Block { .. }, Unknown) + | (Block { .. }, Chunk { .. }) + | (Chunk { .. }, Unknown) + | (Chunk { .. }, Block { .. }) => false, + (Block { child, .. }, Block { parent, .. }) => parent == child, + (Chunk { end, .. }, Chunk { begin, .. }) => begin == end, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + use claims::assert_none; + + #[test] + fn test_append_state_checkpoint_to_block() { + assert_none!(TransactionSliceMetadata::unknown().append_state_checkpoint_to_block()); + assert_none!(TransactionSliceMetadata::chunk(1, 2).append_state_checkpoint_to_block()); + + let metadata = TransactionSliceMetadata::block_from_u64(2, 3); + assert_eq!( + metadata.append_state_checkpoint_to_block(), + Some(HashValue::from_u64(3)) + ); + } + + #[test] + fn test_is_immediately_after() { + let is_immediately_after = [ + ( + TransactionSliceMetadata::block_from_u64(2, 3), + TransactionSliceMetadata::block_from_u64(3, 4), + ), + ( + TransactionSliceMetadata::chunk(0, 1), + TransactionSliceMetadata::chunk(1, 2), + ), + ]; + + for (fst, snd) in is_immediately_after { + assert!(snd.is_immediately_after(&fst)); + } + } + + #[test] + fn test_is_not_immediately_after() { + let is_not_immediately_after = [ + ( + TransactionSliceMetadata::unknown(), + TransactionSliceMetadata::unknown(), + ), + ( + TransactionSliceMetadata::unknown(), + TransactionSliceMetadata::block_from_u64(3, 4), + ), + ( + TransactionSliceMetadata::unknown(), + TransactionSliceMetadata::chunk(3, 4), + ), + ( + TransactionSliceMetadata::block_from_u64(0, 1), + TransactionSliceMetadata::unknown(), + ), + ( + TransactionSliceMetadata::block_from_u64(1, 2), + TransactionSliceMetadata::block_from_u64(0, 1), + ), + ( + TransactionSliceMetadata::block_from_u64(1, 2), + TransactionSliceMetadata::block_from_u64(1, 2), + ), + ( + TransactionSliceMetadata::block_from_u64(0, 1), + TransactionSliceMetadata::chunk(2, 3), + ), + ( + TransactionSliceMetadata::chunk(0, 1), + TransactionSliceMetadata::unknown(), + ), + ( + TransactionSliceMetadata::chunk(0, 1), + TransactionSliceMetadata::block_from_u64(1, 2), + ), + ( + TransactionSliceMetadata::chunk(1, 2), + TransactionSliceMetadata::chunk(0, 1), + ), + ( + TransactionSliceMetadata::chunk(1, 2), + TransactionSliceMetadata::chunk(1, 2), + ), + ]; + + for (fst, snd) in is_not_immediately_after { + assert!(!snd.is_immediately_after(&fst)); + } + } +} diff --git a/types/src/transaction/webauthn.rs b/types/src/transaction/webauthn.rs index 84d76de586d19..cebdd2cec6262 100644 --- a/types/src/transaction/webauthn.rs +++ b/types/src/transaction/webauthn.rs @@ -57,7 +57,7 @@ pub enum AssertionSignature { /// Custom arbitrary implementation for fuzzing /// as the `secp256r1_ecdsa::Signature` type is an external dependency /// p256::ecdsa::Signature -#[cfg(any(test, feature = "fuzzing"))] +#[cfg(feature = "fuzzing")] impl<'a> arbitrary::Arbitrary<'a> for AssertionSignature { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { // Generate a fixed-length byte array for the signature From a734d235af377347196f25d90291df51a23915b5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 20:06:00 +0000 Subject: [PATCH 07/16] [loader-v2] Addressing TODOs (#15316) (#15342) - Switching from undefined to script location - Keeping error remapping because the status code exists on-chain. It is probably fine t keep it as is. - Removed useless TODO for alerts on concurrent manager uses. - Changed errors.rs TODO into a note, as it is not a P0/P1/P2 to fix. (cherry picked from commit dbdb613b467aa67fb620d8416ec8b3c19db46271) Co-authored-by: George Mitenkov --- .../block-executor/src/code_cache_global_manager.rs | 1 - .../src/tests/bad_storage_tests.rs | 3 +-- third_party/move/move-vm/runtime/src/loader/mod.rs | 3 +-- .../move/move-vm/runtime/src/storage/loader.rs | 13 +++++-------- .../entry_points/script_too_few_type_args_inner.exp | 2 +- .../script_too_few_type_args_inner.v2_exp | 2 +- .../script_too_many_type_args_inner.exp | 2 +- .../script_too_many_type_args_inner.v2_exp | 2 +- third_party/move/move-vm/types/src/code/errors.rs | 6 +++--- 9 files changed, 14 insertions(+), 20 deletions(-) diff --git a/aptos-move/block-executor/src/code_cache_global_manager.rs b/aptos-move/block-executor/src/code_cache_global_manager.rs index 5daaf4c0b7e90..f90ada6ba1994 100644 --- a/aptos-move/block-executor/src/code_cache_global_manager.rs +++ b/aptos-move/block-executor/src/code_cache_global_manager.rs @@ -173,7 +173,6 @@ impl AptosModuleCacheManager { AptosModuleCacheManagerGuard::Guard { guard } }, None => { - // TODO(loader_v2): Should we return an error here instead? alert_or_println!("Locking module cache manager failed, fallback to empty caches"); // If this is true, we failed to acquire a lock, and so default storage environment diff --git a/third_party/move/move-vm/integration-tests/src/tests/bad_storage_tests.rs b/third_party/move/move-vm/integration-tests/src/tests/bad_storage_tests.rs index cbc19460eca72..922d80ef4775e 100644 --- a/third_party/move/move-vm/integration-tests/src/tests/bad_storage_tests.rs +++ b/third_party/move/move-vm/integration-tests/src/tests/bad_storage_tests.rs @@ -792,8 +792,7 @@ fn test_storage_returns_bogus_error_when_loading_resource() { .unwrap_err(); if *error_code == StatusCode::UNKNOWN_VERIFICATION_ERROR { - // MoveVM maps `UNKNOWN_VERIFICATION_ERROR` to `VERIFICATION_ERROR` in - // `maybe_core_dump` function in interpreter.rs. + // MoveVM maps `UNKNOWN_VERIFICATION_ERROR` to `VERIFICATION_ERROR`. assert_eq!(err.major_status(), StatusCode::VERIFICATION_ERROR); } else { assert_eq!(err.major_status(), *error_code); diff --git a/third_party/move/move-vm/runtime/src/loader/mod.rs b/third_party/move/move-vm/runtime/src/loader/mod.rs index 4b74cc881dac6..1777fd5ac9b9b 100644 --- a/third_party/move/move-vm/runtime/src/loader/mod.rs +++ b/third_party/move/move-vm/runtime/src/loader/mod.rs @@ -1303,8 +1303,7 @@ impl<'a> Resolver<'a> { function_name, ) .map_err(|_| { - // TODO(loader_v2): - // Loader V1 implementation uses this error, but it should be a linker error. + // Note: legacy loader implementation used this error, so we need to remap. PartialVMError::new(StatusCode::FUNCTION_RESOLUTION_FAILURE).with_message( format!( "Module or function do not exist for {}::{}::{}", diff --git a/third_party/move/move-vm/runtime/src/storage/loader.rs b/third_party/move/move-vm/runtime/src/storage/loader.rs index 3c484c7f74549..539a439c0c4f5 100644 --- a/third_party/move/move-vm/runtime/src/storage/loader.rs +++ b/third_party/move/move-vm/runtime/src/storage/loader.rs @@ -139,14 +139,11 @@ impl LoaderV2 { .iter() .map(|ty_tag| self.load_ty(code_storage, ty_tag)) .collect::>>() - // TODO(loader_v2): - // Loader V1 implementation returns undefined here, causing some tests to fail. We - // should probably map this to script. - .map_err(|e| e.finish(Location::Undefined))?; + .map_err(|err| err.finish(Location::Script))?; let main = script.entry_point(); Type::verify_ty_arg_abilities(main.ty_param_abilities(), &ty_args) - .map_err(|e| e.finish(Location::Script))?; + .map_err(|err| err.finish(Location::Script))?; Ok(LoadedFunction { owner: LoadedFunctionOwner::Script(script), @@ -205,7 +202,7 @@ impl LoaderV2 { ) -> PartialVMResult> { let module = self .load_module(module_storage, address, module_name) - .map_err(|e| e.to_partial())?; + .map_err(|err| err.to_partial())?; Ok(module .struct_map .get(struct_name) @@ -239,9 +236,9 @@ impl LoaderV2 { st.module.as_ident_str(), st.name.as_ident_str(), ) - .map_err(|e| e.finish(Location::Undefined)) + .map_err(|err| err.finish(Location::Undefined)) }) - .map_err(|e| e.to_partial()) + .map_err(|err| err.to_partial()) } } diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.exp index 8bfde526b7e76..1ee2d970eb9f3 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.exp +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.exp @@ -4,7 +4,7 @@ task 1 'run'. lines 6-10: Error: Script execution failed with VMError: { major_status: NUMBER_OF_TYPE_ARGUMENTS_MISMATCH, sub_status: None, - location: undefined, + location: script, indices: [], offsets: [], } diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.v2_exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.v2_exp index 8bfde526b7e76..1ee2d970eb9f3 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.v2_exp +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_few_type_args_inner.v2_exp @@ -4,7 +4,7 @@ task 1 'run'. lines 6-10: Error: Script execution failed with VMError: { major_status: NUMBER_OF_TYPE_ARGUMENTS_MISMATCH, sub_status: None, - location: undefined, + location: script, indices: [], offsets: [], } diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.exp index 8bfde526b7e76..1ee2d970eb9f3 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.exp +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.exp @@ -4,7 +4,7 @@ task 1 'run'. lines 6-10: Error: Script execution failed with VMError: { major_status: NUMBER_OF_TYPE_ARGUMENTS_MISMATCH, sub_status: None, - location: undefined, + location: script, indices: [], offsets: [], } diff --git a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.v2_exp b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.v2_exp index 8bfde526b7e76..1ee2d970eb9f3 100644 --- a/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.v2_exp +++ b/third_party/move/move-vm/transactional-tests/tests/entry_points/script_too_many_type_args_inner.v2_exp @@ -4,7 +4,7 @@ task 1 'run'. lines 6-10: Error: Script execution failed with VMError: { major_status: NUMBER_OF_TYPE_ARGUMENTS_MISMATCH, sub_status: None, - location: undefined, + location: script, indices: [], offsets: [], } diff --git a/third_party/move/move-vm/types/src/code/errors.rs b/third_party/move/move-vm/types/src/code/errors.rs index c0ad3879111f9..6cd0ae508b4e9 100644 --- a/third_party/move/move-vm/types/src/code/errors.rs +++ b/third_party/move/move-vm/types/src/code/errors.rs @@ -26,9 +26,9 @@ macro_rules! module_storage_error { }; } -// TODO(loader_v2): -// The error message is formatted in the same way as V1, to ensure that replay and tests work in -// the same way, but ideally we should use proper formatting here. +// Note: +// The error message is formatted in the same way as by the legacy loader implementation, to +// ensure that replay and tests work in the same way. #[macro_export] macro_rules! module_linker_error { ($addr:expr, $name:expr) => { From 327445f70a3b9474f13a792e8ada9b85809dec86 Mon Sep 17 00:00:00 2001 From: Alden Hu Date: Fri, 22 Nov 2024 18:47:20 +0000 Subject: [PATCH 08/16] [cp 1.24] Move payload_manager.notify_commit to after commit (#15362) --- consensus/src/pipeline/pipeline_builder.rs | 13 ++--- consensus/src/state_computer.rs | 47 ++++++++++++------- .../src/vm_test_harness.rs | 2 +- 3 files changed, 37 insertions(+), 25 deletions(-) diff --git a/consensus/src/pipeline/pipeline_builder.rs b/consensus/src/pipeline/pipeline_builder.rs index abd3884d8c22b..07cbf4673b49a 100644 --- a/consensus/src/pipeline/pipeline_builder.rs +++ b/consensus/src/pipeline/pipeline_builder.rs @@ -325,7 +325,6 @@ impl PipelineBuilder { pre_commit_fut.clone(), parent.post_pre_commit_fut.clone(), self.state_sync_notifier.clone(), - self.payload_manager.clone(), block.clone(), ), &mut abort_handles, @@ -335,6 +334,7 @@ impl PipelineBuilder { pre_commit_fut.clone(), commit_ledger_fut.clone(), parent.post_commit_fut.clone(), + self.payload_manager.clone(), block_store_callback, block.clone(), ), @@ -618,15 +618,12 @@ impl PipelineBuilder { pre_commit: TaskFuture, parent_post_pre_commit: TaskFuture, state_sync_notifier: Arc, - payload_manager: Arc, block: Arc, ) -> TaskResult { let compute_result = pre_commit.await?; parent_post_pre_commit.await?; let _tracker = Tracker::new("post_pre_commit", &block); - let payload = block.payload().cloned(); - let timestamp = block.timestamp_usecs(); let _timer = counters::OP_COUNTERS.timer("pre_commit_notify"); let txns = compute_result.transactions_to_commit().to_vec(); @@ -640,8 +637,6 @@ impl PipelineBuilder { error!(error = ?e, "Failed to notify state synchronizer"); } - let payload_vec = payload.into_iter().collect(); - payload_manager.notify_commit(timestamp, payload_vec); Ok(()) } @@ -684,6 +679,7 @@ impl PipelineBuilder { pre_commit_fut: TaskFuture, commit_ledger_fut: TaskFuture, parent_post_commit: TaskFuture, + payload_manager: Arc, block_store_callback: Box, block: Arc, ) -> TaskResult { @@ -695,6 +691,11 @@ impl PipelineBuilder { update_counters_for_block(&block); update_counters_for_compute_result(&compute_result); + let payload = block.payload().cloned(); + let timestamp = block.timestamp_usecs(); + let payload_vec = payload.into_iter().collect(); + payload_manager.notify_commit(timestamp, payload_vec); + if let Some(ledger_info_with_sigs) = maybe_ledger_info_with_sigs { block_store_callback(ledger_info_with_sigs); } diff --git a/consensus/src/state_computer.rs b/consensus/src/state_computer.rs index 5db63850cd6d6..498be4e87ea9a 100644 --- a/consensus/src/state_computer.rs +++ b/consensus/src/state_computer.rs @@ -131,15 +131,9 @@ impl ExecutionProxy { tx } - fn pre_commit_hook( - &self, - block: &Block, - payload_manager: Arc, - ) -> PreCommitHook { + fn pre_commit_hook(&self) -> PreCommitHook { let mut pre_commit_notifier = self.pre_commit_notifier.clone(); let state_sync_notifier = self.state_sync_notifier.clone(); - let payload = block.payload().cloned(); - let timestamp = block.timestamp_usecs(); Box::new(move |state_compute_result: &StateComputeResult| { let state_compute_result = state_compute_result.clone(); Box::pin(async move { @@ -158,9 +152,6 @@ impl ExecutionProxy { ) { error!(error = ?e, "Failed to notify state synchronizer"); } - - let payload_vec = payload.into_iter().collect(); - payload_manager.notify_commit(timestamp, payload_vec); })) .await .expect("Failed to send pre-commit notification"); @@ -168,6 +159,31 @@ impl ExecutionProxy { }) } + fn commit_hook( + &self, + blocks: &[Arc], + callback: StateComputerCommitCallBackType, + finality_proof: LedgerInfoWithSignatures, + ) -> NotificationType { + let payload_manager = self + .state + .read() + .as_ref() + .expect("must be set within an epoch") + .payload_manager + .clone(); + let blocks = blocks.to_vec(); + Box::pin(async move { + for block in blocks.iter() { + let payload = block.payload().cloned(); + let payload_vec = payload.into_iter().collect(); + let timestamp = block.timestamp_usecs(); + payload_manager.notify_commit(timestamp, payload_vec); + } + callback(&blocks, finality_proof); + }) + } + pub fn pipeline_builder(&self, commit_signer: Arc) -> PipelineBuilder { let MutableState { validators, @@ -236,7 +252,7 @@ impl StateComputer for ExecutionProxy { let txn_notifier = self.txn_notifier.clone(); let transaction_generator = BlockPreparer::new( - payload_manager.clone(), + payload_manager, self.transaction_filter.clone(), transaction_deduper.clone(), transaction_shuffler.clone(), @@ -260,7 +276,7 @@ impl StateComputer for ExecutionProxy { parent_block_id, transaction_generator, block_executor_onchain_config, - self.pre_commit_hook(block, payload_manager), + self.pre_commit_hook(), lifetime_guard, ) .await; @@ -343,14 +359,9 @@ impl StateComputer for ExecutionProxy { ) .expect("spawn_blocking failed"); - let blocks = blocks.to_vec(); - let callback_fut = Box::pin(async move { - callback(&blocks, finality_proof); - }); - self.commit_notifier .clone() - .send(callback_fut) + .send(self.commit_hook(blocks, callback, finality_proof)) .await .expect("Failed to send commit notification"); diff --git a/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs b/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs index 00730088b70a6..0cf1f792eb255 100644 --- a/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs +++ b/third_party/move/testing-infra/transactional-test-runner/src/vm_test_harness.rs @@ -302,7 +302,7 @@ impl<'a> MoveTestAdapter<'a> for SimpleVMTestAdapter<'a> { Compatibility::new( !extra_args.skip_check_struct_layout, !extra_args.skip_check_friend_linking, - false + false, ) }; if vm.vm_config().use_loader_v2 { From 94976266c0e4edd1a31a3783be4c4184f8892ff5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 23 Nov 2024 02:48:21 +0000 Subject: [PATCH 09/16] [consensus] sync improvements to help slow nodes sync better (#15364) (#15377) * [qs] grace period before GC committed batches * [consensus] trigger sync based on remote LI timestamp (cherry picked from commit d6720851a312e5af6e33a73d109e181a4108594e) Co-authored-by: Balaji Arun --- consensus/src/quorum_store/batch_store.rs | 11 +++++++++-- consensus/src/quorum_store/quorum_store_builder.rs | 1 + consensus/src/quorum_store/tests/batch_store_test.rs | 1 + .../forge-cli/src/suites/realistic_environment.rs | 6 +++--- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/consensus/src/quorum_store/batch_store.rs b/consensus/src/quorum_store/batch_store.rs index f8d32b23137ff..74720737dd278 100644 --- a/consensus/src/quorum_store/batch_store.rs +++ b/consensus/src/quorum_store/batch_store.rs @@ -117,6 +117,7 @@ pub struct BatchStore { batch_quota: usize, validator_signer: ValidatorSigner, persist_subscribers: DashMap>>, + expiration_buffer_usecs: u64, } impl BatchStore { @@ -128,6 +129,7 @@ impl BatchStore { db_quota: usize, batch_quota: usize, validator_signer: ValidatorSigner, + expiration_buffer_usecs: u64, ) -> Self { let db_clone = db.clone(); let batch_store = Self { @@ -142,6 +144,7 @@ impl BatchStore { batch_quota, validator_signer, persist_subscribers: DashMap::new(), + expiration_buffer_usecs, }; let db_content = db_clone .get_all_batches() @@ -283,7 +286,11 @@ impl BatchStore { // pub(crate) for testing #[allow(clippy::unwrap_used)] pub(crate) fn clear_expired_payload(&self, certified_time: u64) -> Vec { - let expired_digests = self.expirations.lock().unwrap().expire(certified_time); + // To help slow nodes catch up via execution without going to state sync we keep the blocks for 60 extra seconds + // after the expiration time. This will help remote peers fetch batches that just expired but are within their + // execution window. + let expiration_time = certified_time.saturating_sub(self.expiration_buffer_usecs); + let expired_digests = self.expirations.lock().unwrap().expire(expiration_time); let mut ret = Vec::new(); for h in expired_digests { let removed_value = match self.db_cache.entry(h) { @@ -291,7 +298,7 @@ impl BatchStore { // We need to check up-to-date expiration again because receiving the same // digest with a higher expiration would update the persisted value and // effectively extend the expiration. - if entry.get().expiration() <= certified_time { + if entry.get().expiration() <= expiration_time { self.persist_subscribers.remove(entry.get().digest()); Some(entry.remove()) } else { diff --git a/consensus/src/quorum_store/quorum_store_builder.rs b/consensus/src/quorum_store/quorum_store_builder.rs index f6c9963f671ae..50302d9f05f4d 100644 --- a/consensus/src/quorum_store/quorum_store_builder.rs +++ b/consensus/src/quorum_store/quorum_store_builder.rs @@ -260,6 +260,7 @@ impl InnerBuilder { self.config.db_quota, self.config.batch_quota, signer, + Duration::from_secs(60).as_micros() as u64, )); self.batch_store = Some(batch_store.clone()); let batch_reader = Arc::new(BatchReaderImpl::new(batch_store.clone(), batch_requester)); diff --git a/consensus/src/quorum_store/tests/batch_store_test.rs b/consensus/src/quorum_store/tests/batch_store_test.rs index fed469c4df93f..196255f69e50a 100644 --- a/consensus/src/quorum_store/tests/batch_store_test.rs +++ b/consensus/src/quorum_store/tests/batch_store_test.rs @@ -36,6 +36,7 @@ pub fn batch_store_for_test(memory_quota: usize) -> Arc { 2001, // db quota 2001, // batch quota signers[0].clone(), + 0, )) } diff --git a/testsuite/forge-cli/src/suites/realistic_environment.rs b/testsuite/forge-cli/src/suites/realistic_environment.rs index ffcf4caf6db67..28a1e6e20e2b8 100644 --- a/testsuite/forge-cli/src/suites/realistic_environment.rs +++ b/testsuite/forge-cli/src/suites/realistic_environment.rs @@ -303,9 +303,9 @@ pub(crate) fn realistic_env_max_load_test( .add_system_metrics_threshold(SystemMetricsThreshold::new( // Check that we don't use more than 18 CPU cores for 15% of the time. MetricsThreshold::new(25.0, 15), - // Memory starts around 7GB, and grows around 1.4GB/hr in this test. + // Memory starts around 8GB, and grows around 1.4GB/hr in this test. // Check that we don't use more than final expected memory for more than 20% of the time. - MetricsThreshold::new_gb(7.0 + 1.4 * (duration_secs as f64 / 3600.0), 20), + MetricsThreshold::new_gb(8.0 + 1.4 * (duration_secs as f64 / 3600.0), 20), )) .add_no_restarts() .add_wait_for_catchup_s( @@ -316,7 +316,7 @@ pub(crate) fn realistic_env_max_load_test( .add_latency_threshold(4.5, LatencyType::P70) .add_chain_progress(StateProgressThreshold { max_non_epoch_no_progress_secs: 15.0, - max_epoch_no_progress_secs: 15.0, + max_epoch_no_progress_secs: 16.0, max_non_epoch_round_gap: 4, max_epoch_round_gap: 4, }); From f436adbe4384d6c5fd296addbb7f52d4be77231b Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Mon, 25 Nov 2024 16:58:19 -0500 Subject: [PATCH 10/16] [cp] Temporarily loosen backpressures, until module loading improvement speeds up blocks --- config/src/config/consensus_config.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/src/config/consensus_config.rs b/config/src/config/consensus_config.rs index 800999c3ec5e0..5f61cabb35941 100644 --- a/config/src/config/consensus_config.rs +++ b/config/src/config/consensus_config.rs @@ -196,10 +196,10 @@ impl Default for ConsensusConfig { min_max_txns_in_block_after_filtering_from_backpressure: MIN_BLOCK_TXNS_AFTER_FILTERING, execution_backpressure: Some(ExecutionBackpressureConfig { num_blocks_to_look_at: 20, - min_blocks_to_activate: 4, + min_blocks_to_activate: 10, percentile: 0.5, - target_block_time_ms: 200, - min_block_time_ms_to_activate: 100, + target_block_time_ms: 350, + min_block_time_ms_to_activate: 200, // allow at least two spreading group from reordering in a single block, to utilize paralellism min_calibrated_txns_per_block: 8, }), From 010570d3b7aa20889fb5ad0e5b23800aa33f5634 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Mon, 25 Nov 2024 20:33:27 -0500 Subject: [PATCH 11/16] Fix units in timed feature flags (#15391) (cherry picked from commit 4d4c200f854db1c223714e49a531b8606e3b73f5) --- .../aptos-vm-environment/src/environment.rs | 6 +- crates/aptos/src/node/mod.rs | 2 +- types/src/on_chain_config/mod.rs | 4 +- types/src/on_chain_config/timed_features.rs | 116 +++++++++++++++--- 4 files changed, 106 insertions(+), 22 deletions(-) diff --git a/aptos-move/aptos-vm-environment/src/environment.rs b/aptos-move/aptos-vm-environment/src/environment.rs index debdd654c92ac..0d3474ab64e96 100644 --- a/aptos-move/aptos-vm-environment/src/environment.rs +++ b/aptos-move/aptos-vm-environment/src/environment.rs @@ -181,12 +181,12 @@ impl Environment { // If no chain ID is in storage, we assume we are in a testing environment. let chain_id = fetch_config_and_update_hash::(&mut sha3_256, state_view) .unwrap_or_else(ChainId::test); - let timestamp = + let timestamp_micros = fetch_config_and_update_hash::(&mut sha3_256, state_view) - .map(|config| config.last_reconfiguration_time()) + .map(|config| config.last_reconfiguration_time_micros()) .unwrap_or(0); - let mut timed_features_builder = TimedFeaturesBuilder::new(chain_id, timestamp); + let mut timed_features_builder = TimedFeaturesBuilder::new(chain_id, timestamp_micros); if let Some(profile) = get_timed_feature_override() { // We need to ensure the override is taken into account for the hash. let profile_bytes = bcs::to_bytes(&profile) diff --git a/crates/aptos/src/node/mod.rs b/crates/aptos/src/node/mod.rs index c9fe8c9a1bacf..e062e721cc94a 100644 --- a/crates/aptos/src/node/mod.rs +++ b/crates/aptos/src/node/mod.rs @@ -1443,7 +1443,7 @@ async fn get_epoch_info(client: &Client) -> CliTypedResult { let epoch_interval = block_resource.epoch_interval(); let epoch_interval_secs = epoch_interval / SECS_TO_MICROSECS; - let last_reconfig = reconfig_resource.last_reconfiguration_time(); + let last_reconfig = reconfig_resource.last_reconfiguration_time_micros(); Ok(EpochInfo { epoch: reconfig_resource.epoch(), epoch_interval_secs, diff --git a/types/src/on_chain_config/mod.rs b/types/src/on_chain_config/mod.rs index 03b5c5f2a409a..4a1bd1d9c023f 100644 --- a/types/src/on_chain_config/mod.rs +++ b/types/src/on_chain_config/mod.rs @@ -238,6 +238,7 @@ pub fn struct_tag_for_config(config_id: ConfigID) -> StructTag { #[derive(Debug, Deserialize, Serialize)] pub struct ConfigurationResource { epoch: u64, + /// Unix epoch timestamp (in microseconds) of the last reconfiguration time. last_reconfiguration_time: u64, events: EventHandle, } @@ -247,7 +248,8 @@ impl ConfigurationResource { self.epoch } - pub fn last_reconfiguration_time(&self) -> u64 { + /// Return the last Unix epoch timestamp (in microseconds) of the last reconfiguration time. + pub fn last_reconfiguration_time_micros(&self) -> u64 { self.last_reconfiguration_time } diff --git a/types/src/on_chain_config/timed_features.rs b/types/src/on_chain_config/timed_features.rs index ea7cafa68a7b9..aa590a7026db8 100644 --- a/types/src/on_chain_config/timed_features.rs +++ b/types/src/on_chain_config/timed_features.rs @@ -6,10 +6,6 @@ use serde::Serialize; use strum::{EnumCount, IntoEnumIterator}; use strum_macros::{EnumCount as EnumCountMacro, EnumIter}; -// A placeholder that can be used to represent activation times that have not been determined. -const NOT_YET_SPECIFIED: u64 = END_OF_TIME; /* Thursday, December 31, 2099 11:59:59 PM */ - -pub const END_OF_TIME: u64 = 4102444799000; /* Thursday, December 31, 2099 11:59:59 PM */ #[derive(Debug, EnumCountMacro, EnumIter, Clone, Copy, Eq, PartialEq)] pub enum TimedFeatureFlag { DisableInvariantViolationCheckInSwapLoc, @@ -23,7 +19,8 @@ pub enum TimedFeatureFlag { enum TimedFeaturesImpl { OnNamedChain { named_chain: NamedChain, - timestamp: u64, + // Unix Epoch timestamp in microseconds. + timestamp_micros: u64, }, EnableAll, } @@ -44,7 +41,6 @@ impl TimedFeatureOverride { Replay => match flag { LimitTypeTagSize => true, ModuleComplexityCheck => true, - EntryCompatibility => true, // Add overrides for replay here. _ => return None, }, @@ -57,19 +53,22 @@ impl TimedFeatureOverride { } impl TimedFeatureFlag { - pub const fn activation_time_on(&self, chain_id: &NamedChain) -> u64 { + /// Returns the activation time of the feature on the given chain. + /// The time is specified as a Unix Epoch timestamp in microseconds. + pub const fn activation_time_micros_on(&self, chain_id: &NamedChain) -> u64 { use NamedChain::*; use TimedFeatureFlag::*; match (self, chain_id) { - (DisableInvariantViolationCheckInSwapLoc, TESTNET) => NOT_YET_SPECIFIED, - (DisableInvariantViolationCheckInSwapLoc, MAINNET) => NOT_YET_SPECIFIED, + // Enabled from the beginning of time. + (DisableInvariantViolationCheckInSwapLoc, TESTNET) => 0, + (DisableInvariantViolationCheckInSwapLoc, MAINNET) => 0, - (ModuleComplexityCheck, TESTNET) => 1719356400000, /* Tuesday, June 21, 2024 16:00:00 AM GMT-07:00 */ - (ModuleComplexityCheck, MAINNET) => 1720033200000, /* Wednesday, July 3, 2024 12:00:00 AM GMT-07:00 */ + (ModuleComplexityCheck, TESTNET) => 1_719_356_400_000_000, /* Tuesday, June 21, 2024 16:00:00 AM GMT-07:00 */ + (ModuleComplexityCheck, MAINNET) => 1_720_033_200_000_000, /* Wednesday, July 3, 2024 12:00:00 AM GMT-07:00 */ - (EntryCompatibility, TESTNET) => 1730923200000, /* Wednesday, Nov 6, 2024 12:00:00 AM GMT-07:00 */ - (EntryCompatibility, MAINNET) => 1731441600000, /* Tuesday, Nov 12, 2024 12:00:00 AM GMT-07:00 */ + (EntryCompatibility, TESTNET) => 1_730_923_200_000_000, /* Wednesday, Nov 6, 2024 12:00:00 AM GMT-07:00 */ + (EntryCompatibility, MAINNET) => 1_731_441_600_000_000, /* Tuesday, Nov 12, 2024 12:00:00 AM GMT-07:00 */ // If unspecified, a timed feature is considered enabled from the very beginning of time. _ => 0, @@ -84,11 +83,12 @@ pub struct TimedFeaturesBuilder { } impl TimedFeaturesBuilder { - pub fn new(chain_id: ChainId, timestamp: u64) -> Self { + /// `timestamp_micros` is a Unix Epoch timestamp in microseconds. + pub fn new(chain_id: ChainId, timestamp_micros: u64) -> Self { let inner = match NamedChain::from_chain_id(&chain_id) { Ok(named_chain) => TimedFeaturesImpl::OnNamedChain { named_chain, - timestamp, + timestamp_micros, }, Err(_) => TimedFeaturesImpl::EnableAll, // Unknown chain => enable all features by default. }; @@ -125,8 +125,8 @@ impl TimedFeaturesBuilder { match &self.inner { OnNamedChain { named_chain, - timestamp, - } => *timestamp >= flag.activation_time_on(named_chain), + timestamp_micros, + } => *timestamp_micros >= flag.activation_time_micros_on(named_chain), EnableAll => true, } } @@ -161,4 +161,86 @@ mod test { let testing = assert_ok!(bcs::to_bytes(&TimedFeatureOverride::Testing)); assert_ne!(replay, testing); } + + #[test] + fn test_timed_features_activation() { + use TimedFeatureFlag::*; + // Monday, Jan 01, 2024 12:00:00.000 AM GMT + let jan_1_2024_micros: u64 = 1_704_067_200_000_000; + // Friday, November 15, 2024 12:00:00 AM GMT + let nov_15_2024_micros: u64 = 1_731_628_800_000_000; + + // Check testnet on Jan 1, 2024. + let testnet_jan_1_2024 = TimedFeaturesBuilder::new(ChainId::testnet(), jan_1_2024_micros); + assert!( + testnet_jan_1_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), + "DisableInvariantViolationCheckInSwapLoc should always be enabled" + ); + assert!( + testnet_jan_1_2024.is_enabled(LimitTypeTagSize), + "LimitTypeTagSize should always be enabled" + ); + assert!( + !testnet_jan_1_2024.is_enabled(ModuleComplexityCheck), + "ModuleComplexityCheck should be disabled on Jan 1, 2024 on testnet" + ); + assert!( + !testnet_jan_1_2024.is_enabled(EntryCompatibility), + "EntryCompatibility should be disabled on Jan 1, 2024 on testnet" + ); + // Check testnet on Nov 15, 2024. + let testnet_nov_15_2024 = TimedFeaturesBuilder::new(ChainId::testnet(), nov_15_2024_micros); + assert!( + testnet_nov_15_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), + "DisableInvariantViolationCheckInSwapLoc should always be enabled" + ); + assert!( + testnet_nov_15_2024.is_enabled(LimitTypeTagSize), + "LimitTypeTagSize should always be enabled" + ); + assert!( + testnet_nov_15_2024.is_enabled(ModuleComplexityCheck), + "ModuleComplexityCheck should be enabled on Nov 15, 2024 on testnet" + ); + assert!( + testnet_nov_15_2024.is_enabled(EntryCompatibility), + "EntryCompatibility should be enabled on Nov 15, 2024 on testnet" + ); + // Check mainnet on Jan 1, 2024. + let mainnet_jan_1_2024 = TimedFeaturesBuilder::new(ChainId::mainnet(), jan_1_2024_micros); + assert!( + mainnet_jan_1_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), + "DisableInvariantViolationCheckInSwapLoc should always be enabled" + ); + assert!( + mainnet_jan_1_2024.is_enabled(LimitTypeTagSize), + "LimitTypeTagSize should always be enabled" + ); + assert!( + !mainnet_jan_1_2024.is_enabled(ModuleComplexityCheck), + "ModuleComplexityCheck should be disabled on Jan 1, 2024 on mainnet" + ); + assert!( + !mainnet_jan_1_2024.is_enabled(EntryCompatibility), + "EntryCompatibility should be disabled on Jan 1, 2024 on mainnet" + ); + // Check mainnet on Nov 15, 2024. + let mainnet_nov_15_2024 = TimedFeaturesBuilder::new(ChainId::mainnet(), nov_15_2024_micros); + assert!( + mainnet_nov_15_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), + "DisableInvariantViolationCheckInSwapLoc should always be enabled" + ); + assert!( + mainnet_nov_15_2024.is_enabled(LimitTypeTagSize), + "LimitTypeTagSize should always be enabled" + ); + assert!( + mainnet_nov_15_2024.is_enabled(ModuleComplexityCheck), + "ModuleComplexityCheck should be enabled on Nov 15, 2024 on mainnet" + ); + assert!( + mainnet_nov_15_2024.is_enabled(EntryCompatibility), + "EntryCompatibility should be enabled on Nov 15, 2024 on mainnet" + ); + } } From fe13df0891e92481a261c0c34e286f65097cb926 Mon Sep 17 00:00:00 2001 From: Aleks Zi <137826094+ziaptos@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:46:58 -0500 Subject: [PATCH 12/16] followup to a TODO for a constant (cherry picked from commit 14cd388e7f82bc4e6505c174d071b44a38b04382) --- api/types/src/move_types.rs | 77 +++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/api/types/src/move_types.rs b/api/types/src/move_types.rs index 885b01e39b3cd..c6a3d4942ad86 100644 --- a/api/types/src/move_types.rs +++ b/api/types/src/move_types.rs @@ -521,11 +521,9 @@ pub enum MoveType { Unparsable(String), } -/// Maximum number of recursive types -/// Currently, this is allowed up to the serde limit of 16 -/// -/// TODO: Should this number be re-evaluated -pub const MAX_RECURSIVE_TYPES_ALLOWED: u8 = 16; +/// Maximum number of recursive types - Same as (non-public) +/// move_core_types::safe_serialize::MAX_TYPE_TAG_NESTING +pub const MAX_RECURSIVE_TYPES_ALLOWED: u8 = 8; impl VerifyInputWithRecursion for MoveType { fn verify(&self, recursion_count: u8) -> anyhow::Result<()> { @@ -1262,30 +1260,40 @@ mod tests { fn test_serialize_move_resource() { use AnnotatedMoveValue::*; - let res = MoveResource::try_from(annotated_move_struct("Values", vec![ - (identifier("field_u8"), U8(7)), - (identifier("field_u64"), U64(7)), - (identifier("field_u128"), U128(7)), - (identifier("field_bool"), Bool(true)), - (identifier("field_address"), Address(address("0xdd"))), - ( - identifier("field_vector"), - Vector(TypeTag::U128, vec![U128(128)]), - ), - (identifier("field_bytes"), Bytes(vec![9, 9])), - ( - identifier("field_struct"), - Struct(annotated_move_struct("Nested", vec![( - identifier("nested_vector"), - Vector(TypeTag::Struct(Box::new(type_struct("Host"))), vec![ - Struct(annotated_move_struct("String", vec![ - (identifier("address1"), Address(address("0x0"))), - (identifier("address2"), Address(address("0x123"))), - ])), - ]), - )])), - ), - ])) + let res = MoveResource::try_from(annotated_move_struct( + "Values", + vec![ + (identifier("field_u8"), U8(7)), + (identifier("field_u64"), U64(7)), + (identifier("field_u128"), U128(7)), + (identifier("field_bool"), Bool(true)), + (identifier("field_address"), Address(address("0xdd"))), + ( + identifier("field_vector"), + Vector(TypeTag::U128, vec![U128(128)]), + ), + (identifier("field_bytes"), Bytes(vec![9, 9])), + ( + identifier("field_struct"), + Struct(annotated_move_struct( + "Nested", + vec![( + identifier("nested_vector"), + Vector( + TypeTag::Struct(Box::new(type_struct("Host"))), + vec![Struct(annotated_move_struct( + "String", + vec![ + (identifier("address1"), Address(address("0x0"))), + (identifier("address2"), Address(address("0x123"))), + ], + ))], + ), + )], + )), + ), + ], + )) .unwrap(); let value = to_value(&res).unwrap(); assert_json( @@ -1310,10 +1318,13 @@ mod tests { #[test] fn test_serialize_move_resource_with_address_0x0() { - let res = MoveResource::try_from(annotated_move_struct("Values", vec![( - identifier("address_0x0"), - AnnotatedMoveValue::Address(address("0x0")), - )])) + let res = MoveResource::try_from(annotated_move_struct( + "Values", + vec![( + identifier("address_0x0"), + AnnotatedMoveValue::Address(address("0x0")), + )], + )) .unwrap(); let value = to_value(&res).unwrap(); assert_json( From da3b3a162d4a4803b5673abca23f1971618aeeae Mon Sep 17 00:00:00 2001 From: Aleks Zi <137826094+ziaptos@users.noreply.github.com> Date: Mon, 2 Dec 2024 12:53:27 -0500 Subject: [PATCH 13/16] followup to a TODO for a constant (cherry picked from commit c522181292a58b51a3fc41f21c7bb6b5c401ebd6) --- api/types/src/move_types.rs | 69 +++++++++++++++---------------------- 1 file changed, 28 insertions(+), 41 deletions(-) diff --git a/api/types/src/move_types.rs b/api/types/src/move_types.rs index c6a3d4942ad86..3b0efb62b9bd6 100644 --- a/api/types/src/move_types.rs +++ b/api/types/src/move_types.rs @@ -1260,40 +1260,30 @@ mod tests { fn test_serialize_move_resource() { use AnnotatedMoveValue::*; - let res = MoveResource::try_from(annotated_move_struct( - "Values", - vec![ - (identifier("field_u8"), U8(7)), - (identifier("field_u64"), U64(7)), - (identifier("field_u128"), U128(7)), - (identifier("field_bool"), Bool(true)), - (identifier("field_address"), Address(address("0xdd"))), - ( - identifier("field_vector"), - Vector(TypeTag::U128, vec![U128(128)]), - ), - (identifier("field_bytes"), Bytes(vec![9, 9])), - ( - identifier("field_struct"), - Struct(annotated_move_struct( - "Nested", - vec![( - identifier("nested_vector"), - Vector( - TypeTag::Struct(Box::new(type_struct("Host"))), - vec![Struct(annotated_move_struct( - "String", - vec![ - (identifier("address1"), Address(address("0x0"))), - (identifier("address2"), Address(address("0x123"))), - ], - ))], - ), - )], - )), - ), - ], - )) + let res = MoveResource::try_from(annotated_move_struct("Values", vec![ + (identifier("field_u8"), U8(7)), + (identifier("field_u64"), U64(7)), + (identifier("field_u128"), U128(7)), + (identifier("field_bool"), Bool(true)), + (identifier("field_address"), Address(address("0xdd"))), + ( + identifier("field_vector"), + Vector(TypeTag::U128, vec![U128(128)]), + ), + (identifier("field_bytes"), Bytes(vec![9, 9])), + ( + identifier("field_struct"), + Struct(annotated_move_struct("Nested", vec![( + identifier("nested_vector"), + Vector(TypeTag::Struct(Box::new(type_struct("Host"))), vec![ + Struct(annotated_move_struct("String", vec![ + (identifier("address1"), Address(address("0x0"))), + (identifier("address2"), Address(address("0x123"))), + ])), + ]), + )])), + ), + ])) .unwrap(); let value = to_value(&res).unwrap(); assert_json( @@ -1318,13 +1308,10 @@ mod tests { #[test] fn test_serialize_move_resource_with_address_0x0() { - let res = MoveResource::try_from(annotated_move_struct( - "Values", - vec![( - identifier("address_0x0"), - AnnotatedMoveValue::Address(address("0x0")), - )], - )) + let res = MoveResource::try_from(annotated_move_struct("Values", vec![( + identifier("address_0x0"), + AnnotatedMoveValue::Address(address("0x0")), + )])) .unwrap(); let value = to_value(&res).unwrap(); assert_json( From 8dfd7b955a7a2f1b2fe46de96d3a06164137aa9a Mon Sep 17 00:00:00 2001 From: Aleks Zi <137826094+ziaptos@users.noreply.github.com> Date: Mon, 2 Dec 2024 15:43:12 -0500 Subject: [PATCH 14/16] allowing larger constant for legacy tests (cherry picked from commit 629850d4966932c4bd2c0740e70487a119ea8d2e) --- api/types/src/move_types.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/types/src/move_types.rs b/api/types/src/move_types.rs index 3b0efb62b9bd6..45a1c0111e118 100644 --- a/api/types/src/move_types.rs +++ b/api/types/src/move_types.rs @@ -523,7 +523,12 @@ pub enum MoveType { /// Maximum number of recursive types - Same as (non-public) /// move_core_types::safe_serialize::MAX_TYPE_TAG_NESTING -pub const MAX_RECURSIVE_TYPES_ALLOWED: u8 = 8; +/// We keep 16 for legacy tests +pub const MAX_RECURSIVE_TYPES_ALLOWED: u8 = if cfg!(test) { + 16 +} else { + 8 // = move_core_types::safe_serialize::MAX_TYPE_TAG_NESTING +}; impl VerifyInputWithRecursion for MoveType { fn verify(&self, recursion_count: u8) -> anyhow::Result<()> { From 5279eaf03dd910ad753a68c134b6d0e6cbce3f11 Mon Sep 17 00:00:00 2001 From: Aleks Zi <137826094+ziaptos@users.noreply.github.com> Date: Mon, 2 Dec 2024 16:15:43 -0500 Subject: [PATCH 15/16] separating constants (cherry picked from commit 2dd6b77bc9428ad0b76625b2d0b1987560fbb5c4) --- api/src/transactions.rs | 7 ++++--- api/types/src/move_types.rs | 7 +------ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/api/src/transactions.rs b/api/src/transactions.rs index 56495de0ad2c6..24e4a1c26c87a 100644 --- a/api/src/transactions.rs +++ b/api/src/transactions.rs @@ -25,8 +25,7 @@ use aptos_api_types::{ AsConverter, EncodeSubmissionRequest, GasEstimation, GasEstimationBcs, HashValue, HexEncodedBytes, LedgerInfo, MoveType, PendingTransaction, SubmitTransactionRequest, Transaction, TransactionData, TransactionOnChainData, TransactionsBatchSingleSubmissionFailure, - TransactionsBatchSubmissionResult, UserTransaction, VerifyInput, VerifyInputWithRecursion, - MAX_RECURSIVE_TYPES_ALLOWED, U64, + TransactionsBatchSubmissionResult, UserTransaction, VerifyInput, VerifyInputWithRecursion, U64, }; use aptos_crypto::{hash::CryptoHash, signing_message}; use aptos_types::{ @@ -1041,10 +1040,12 @@ impl TransactionsApi { ledger_info: &LedgerInfo, data: SubmitTransactionPost, ) -> Result { + pub const MAX_SIGNED_TRANSACTION_DEPTH: usize = 16; + match data { SubmitTransactionPost::Bcs(data) => { let signed_transaction: SignedTransaction = - bcs::from_bytes_with_limit(&data.0, MAX_RECURSIVE_TYPES_ALLOWED as usize) + bcs::from_bytes_with_limit(&data.0, MAX_SIGNED_TRANSACTION_DEPTH) .context("Failed to deserialize input into SignedTransaction") .map_err(|err| { SubmitTransactionError::bad_request_with_code( diff --git a/api/types/src/move_types.rs b/api/types/src/move_types.rs index 45a1c0111e118..3b0efb62b9bd6 100644 --- a/api/types/src/move_types.rs +++ b/api/types/src/move_types.rs @@ -523,12 +523,7 @@ pub enum MoveType { /// Maximum number of recursive types - Same as (non-public) /// move_core_types::safe_serialize::MAX_TYPE_TAG_NESTING -/// We keep 16 for legacy tests -pub const MAX_RECURSIVE_TYPES_ALLOWED: u8 = if cfg!(test) { - 16 -} else { - 8 // = move_core_types::safe_serialize::MAX_TYPE_TAG_NESTING -}; +pub const MAX_RECURSIVE_TYPES_ALLOWED: u8 = 8; impl VerifyInputWithRecursion for MoveType { fn verify(&self, recursion_count: u8) -> anyhow::Result<()> { From 3527aa2e299553b759c515d9843586bad48c802c Mon Sep 17 00:00:00 2001 From: Josh Lind Date: Mon, 2 Dec 2024 19:27:19 -0500 Subject: [PATCH 16/16] [Release] Update release.yaml for v1.24.0 framework release. --- .../aptos-release-builder/data/release.yaml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/aptos-move/aptos-release-builder/data/release.yaml b/aptos-move/aptos-release-builder/data/release.yaml index a12d498463731..1b3bf8f9818c7 100644 --- a/aptos-move/aptos-release-builder/data/release.yaml +++ b/aptos-move/aptos-release-builder/data/release.yaml @@ -1,19 +1,16 @@ --- -remote_endpoint: https://fullnode.mainnet.aptoslabs.com -name: "TBD" +remote_endpoint: ~ +name: "v1.24.0" proposals: - name: proposal_1_upgrade_framework metadata: - title: "Multi-step proposal to upgrade mainnet framework, version TBD" - description: "This includes changes in (TBA: URL to changes)" + title: "Multi-step proposal to upgrade mainnet framework, version v1.24.0" + description: "This includes changes in https://github.com/aptos-labs/aptos-core/releases/tag/aptos-node-v1.24.0-rc" execution_mode: MultiStep update_sequence: - Gas: - new: current + old: https://raw.githubusercontent.com/aptos-labs/aptos-networks/main/gas/v1.23.1-rc.json + new: https://raw.githubusercontent.com/aptos-labs/aptos-networks/main/gas/v1.24.0.json - Framework: - bytecode_version: 6 + bytecode_version: 7 git_hash: ~ - - FeatureFlag: - enabled: - - allow_serialized_script_args -