From 84b67ea3a22edce1cc86c6888f973159fe8b1ee8 Mon Sep 17 00:00:00 2001 From: Igor Date: Fri, 1 Nov 2024 10:00:41 -0700 Subject: [PATCH] new stuff --- Cargo.lock | 2 + aptos-move/aptos-aggregator/src/resolver.rs | 1 - aptos-move/e2e-tests/src/executor.rs | 8 +- .../aptos-framework/doc/fungible_asset.md | 34 +- .../sources/fungible_asset.move | 34 +- execution/executor-benchmark/Cargo.toml | 2 + execution/executor-benchmark/src/db_access.rs | 23 +- execution/executor-benchmark/src/lib.rs | 235 ++++-- .../src/native/native_config.rs | 2 +- .../src/native/native_transaction.rs | 24 +- .../src/native/native_vm.rs | 544 ++++++++++--- .../parallel_uncoordinated_block_executor.rs | 713 ++++++++++-------- testsuite/single_node_performance.py | 100 +-- types/src/account_config/events/coin.rs | 113 +++ types/src/account_config/events/deposit.rs | 28 - .../account_config/events/fungible_asset.rs | 36 + types/src/account_config/events/mod.rs | 8 +- types/src/account_config/events/withdraw.rs | 48 -- .../src/account_config/resources/coin_info.rs | 14 +- .../account_config/resources/coin_store.rs | 8 + .../resources/fungible_asset_metadata.rs | 6 +- .../resources/fungible_store.rs | 32 +- types/src/account_config/resources/mod.rs | 2 + .../src/account_config/resources/type_info.rs | 52 ++ types/src/event.rs | 1 - types/src/lib.rs | 1 - types/src/move_event_v2.rs | 15 - types/src/move_utils/mod.rs | 1 + types/src/move_utils/move_event_v1.rs | 19 + types/src/utility_coin.rs | 9 + 30 files changed, 1354 insertions(+), 761 deletions(-) create mode 100644 types/src/account_config/events/coin.rs delete mode 100644 types/src/account_config/events/deposit.rs create mode 100644 types/src/account_config/events/fungible_asset.rs delete mode 100644 types/src/account_config/events/withdraw.rs create mode 100644 types/src/account_config/resources/type_info.rs delete mode 100644 types/src/move_event_v2.rs create mode 100644 types/src/move_utils/move_event_v1.rs diff --git a/Cargo.lock b/Cargo.lock index 15eb69c30f7e12..4afec53542c83c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1490,6 +1490,7 @@ name = "aptos-executor-benchmark" version = "0.1.0" dependencies = [ "anyhow", + "aptos-aggregator", "aptos-block-executor", "aptos-block-partitioner", "aptos-config", @@ -1528,6 +1529,7 @@ dependencies = [ "itertools 0.13.0", "jemallocator", "move-core-types", + "move-vm-types", "num_cpus", "once_cell", "rand 0.7.3", diff --git a/aptos-move/aptos-aggregator/src/resolver.rs b/aptos-move/aptos-aggregator/src/resolver.rs index 0f522753392a1f..200633129734cd 100644 --- a/aptos-move/aptos-aggregator/src/resolver.rs +++ b/aptos-move/aptos-aggregator/src/resolver.rs @@ -86,7 +86,6 @@ pub trait TAggregatorV1View { PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR) .with_message("Cannot convert delta for deleted aggregator".to_string()) })?; - delta_op .apply_to(base) .map_err(|e| match &e { diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 4c44a7e585c634..b97961dad4efc8 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -24,7 +24,7 @@ use aptos_keygen::KeyGen; use aptos_types::{ account_config::{ new_block_event_key, AccountResource, CoinInfoResource, CoinStoreResource, - ConcurrentSupply, NewBlockEvent, ObjectGroupResource, CORE_CODE_ADDRESS, + ConcurrentSupplyResource, NewBlockEvent, ObjectGroupResource, CORE_CODE_ADDRESS, }, block_executor::config::{ BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig, @@ -438,10 +438,10 @@ impl FakeExecutor { let mut fa_resource_group = self .read_resource_group::(&AccountAddress::TEN) .expect("resource group must exist in data store"); - let mut supply = bcs::from_bytes::( + let mut supply = bcs::from_bytes::( fa_resource_group .group - .get(&ConcurrentSupply::struct_tag()) + .get(&ConcurrentSupplyResource::struct_tag()) .unwrap(), ) .unwrap(); @@ -451,7 +451,7 @@ impl FakeExecutor { fa_resource_group .group .insert( - ConcurrentSupply::struct_tag(), + ConcurrentSupplyResource::struct_tag(), bcs::to_bytes(&supply).unwrap(), ) .unwrap(); diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index a7fd696d9d8fe8..17ee3056667dad 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -3468,25 +3468,23 @@ Decrease the supply of a fungible asset by burning. }; let metadata_address = object::object_address(metadata); - if (amount == 0) { - if (exists<ConcurrentSupply>(metadata_address)) { - let supply = borrow_global_mut<ConcurrentSupply>(metadata_address); + if (exists<ConcurrentSupply>(metadata_address)) { + let supply = borrow_global_mut<ConcurrentSupply>(metadata_address); - assert!( - aggregator_v2::try_sub(&mut supply.current, (amount as u128)), - error::out_of_range(ESUPPLY_UNDERFLOW) - ); - } else if (exists<Supply>(metadata_address)) { - assert!(exists<Supply>(metadata_address), error::not_found(ESUPPLY_NOT_FOUND)); - let supply = borrow_global_mut<Supply>(metadata_address); - assert!( - supply.current >= (amount as u128), - error::invalid_state(ESUPPLY_UNDERFLOW) - ); - supply.current = supply.current - (amount as u128); - } else { - assert!(false, error::not_found(ESUPPLY_NOT_FOUND)); - } + assert!( + aggregator_v2::try_sub(&mut supply.current, (amount as u128)), + error::out_of_range(ESUPPLY_UNDERFLOW) + ); + } else if (exists<Supply>(metadata_address)) { + assert!(exists<Supply>(metadata_address), error::not_found(ESUPPLY_NOT_FOUND)); + let supply = borrow_global_mut<Supply>(metadata_address); + assert!( + supply.current >= (amount as u128), + error::invalid_state(ESUPPLY_UNDERFLOW) + ); + supply.current = supply.current - (amount as u128); + } else { + assert!(false, error::not_found(ESUPPLY_NOT_FOUND)); } } diff --git a/aptos-move/framework/aptos-framework/sources/fungible_asset.move b/aptos-move/framework/aptos-framework/sources/fungible_asset.move index 7e3791c5cea91c..50a77348c630c8 100644 --- a/aptos-move/framework/aptos-framework/sources/fungible_asset.move +++ b/aptos-move/framework/aptos-framework/sources/fungible_asset.move @@ -1098,25 +1098,23 @@ module aptos_framework::fungible_asset { }; let metadata_address = object::object_address(metadata); - if (amount == 0) { - if (exists(metadata_address)) { - let supply = borrow_global_mut(metadata_address); + if (exists(metadata_address)) { + let supply = borrow_global_mut(metadata_address); - assert!( - aggregator_v2::try_sub(&mut supply.current, (amount as u128)), - error::out_of_range(ESUPPLY_UNDERFLOW) - ); - } else if (exists(metadata_address)) { - assert!(exists(metadata_address), error::not_found(ESUPPLY_NOT_FOUND)); - let supply = borrow_global_mut(metadata_address); - assert!( - supply.current >= (amount as u128), - error::invalid_state(ESUPPLY_UNDERFLOW) - ); - supply.current = supply.current - (amount as u128); - } else { - assert!(false, error::not_found(ESUPPLY_NOT_FOUND)); - } + assert!( + aggregator_v2::try_sub(&mut supply.current, (amount as u128)), + error::out_of_range(ESUPPLY_UNDERFLOW) + ); + } else if (exists(metadata_address)) { + assert!(exists(metadata_address), error::not_found(ESUPPLY_NOT_FOUND)); + let supply = borrow_global_mut(metadata_address); + assert!( + supply.current >= (amount as u128), + error::invalid_state(ESUPPLY_UNDERFLOW) + ); + supply.current = supply.current - (amount as u128); + } else { + assert!(false, error::not_found(ESUPPLY_NOT_FOUND)); } } diff --git a/execution/executor-benchmark/Cargo.toml b/execution/executor-benchmark/Cargo.toml index 311bc271bc494a..11083a7c5430bd 100644 --- a/execution/executor-benchmark/Cargo.toml +++ b/execution/executor-benchmark/Cargo.toml @@ -14,6 +14,7 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } +aptos-aggregator = { workspace = true } aptos-block-executor = { workspace = true } aptos-block-partitioner = { workspace = true } aptos-config = { workspace = true } @@ -49,6 +50,7 @@ derivative = { workspace = true } indicatif = { workspace = true } itertools = { workspace = true } move-core-types = { workspace = true } +move-vm-types = { workspace = true } num_cpus = { workspace = true } once_cell = { workspace = true } rand = { workspace = true } diff --git a/execution/executor-benchmark/src/db_access.rs b/execution/executor-benchmark/src/db_access.rs index 854b6f338b2071..5a475bcfc0509c 100644 --- a/execution/executor-benchmark/src/db_access.rs +++ b/execution/executor-benchmark/src/db_access.rs @@ -5,12 +5,13 @@ use anyhow::Result; use aptos_types::{ account_address::AccountAddress, account_config::{ - AccountResource, CoinStoreResource, FungibleStoreResource, ObjectGroupResource, + AccountResource, CoinInfoResource, CoinStoreResource, ConcurrentSupplyResource, + FungibleStoreResource, ObjectCoreResource, ObjectGroupResource, }, event::{EventHandle, EventKey}, state_store::{state_key::StateKey, StateView}, write_set::TOTAL_SUPPLY_STATE_KEY, - AptosCoinType, + AptosCoinType, CoinType, }; use move_core_types::{ identifier::Identifier, @@ -24,7 +25,13 @@ pub struct CommonStructTags { pub account: StructTag, pub apt_coin_store: StructTag, pub object_group: StructTag, + pub object_core: StructTag, pub fungible_store: StructTag, + pub concurrent_supply: StructTag, + + pub apt_coin_type_name: String, + + pub apt_coin_info_resource: StateKey, } impl CommonStructTags { @@ -33,7 +40,15 @@ impl CommonStructTags { account: AccountResource::struct_tag(), apt_coin_store: CoinStoreResource::::struct_tag(), object_group: ObjectGroupResource::struct_tag(), + object_core: ObjectCoreResource::struct_tag(), fungible_store: FungibleStoreResource::struct_tag(), + concurrent_supply: ConcurrentSupplyResource::struct_tag(), + + apt_coin_type_name: "0x1::aptos_coin::AptosCoin".to_string(), + apt_coin_info_resource: StateKey::resource_typed::>( + &AptosCoinType::coin_info_address(), + ) + .unwrap(), } } } @@ -149,4 +164,8 @@ impl DbAccessUtil { EventHandle::new(EventKey::new(2, address), 0), ) } + + pub fn new_object_core(address: AccountAddress, owner: AccountAddress) -> ObjectCoreResource { + ObjectCoreResource::new(owner, false, EventHandle::new(EventKey::new(1, address), 0)) + } } diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index 6f6aeb0bd35f9f..cbaada4ec8246d 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -792,99 +792,222 @@ mod tests { use aptos_temppath::TempPath; use aptos_transaction_generator_lib::{args::TransactionTypeArg, WorkflowProgress}; use aptos_types::{ + access_path::Path, + account_address::AccountAddress, on_chain_config::{FeatureFlag, Features}, - transaction::Transaction, + state_store::state_key::inner::StateKeyInner, + transaction::{Transaction, TransactionPayload}, }; use aptos_vm::{aptos_vm::AptosVMBlockExecutor, AptosVM, VMBlockExecutor}; + use itertools::Itertools; + use move_core_types::language_storage::StructTag; use rand::thread_rng; - use std::fs; + use std::{ + collections::{BTreeMap, HashMap}, + fs, + }; + + #[test] + fn test_compare_vm_and_vm_uncoordinated() { + test_compare_prod_and_another_all_types::(true); + } #[test] fn test_compare_vm_and_native() { + test_compare_prod_and_another_all_types::(false); + } + + #[test] + fn test_compare_vm_and_native_parallel_uncoordinated() { + test_compare_prod_and_another_all_types::< + NativeParallelUncoordinatedBlockExecutor, + >(false); + } + + fn test_compare_prod_and_another_all_types(values_match: bool) { + let mut non_fa_features = Features::default(); + non_fa_features.disable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); + non_fa_features.disable(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); + // non_fa_features.disable(FeatureFlag::MODULE_EVENT_MIGRATION); + // non_fa_features.disable(FeatureFlag::COIN_TO_FUNGIBLE_ASSET_MIGRATION); + + test_compare_prod_and_another::(values_match, non_fa_features.clone(), |address| { + aptos_stdlib::aptos_account_transfer(address, 1000) + }); + + test_compare_prod_and_another::( + values_match, + non_fa_features, + aptos_stdlib::aptos_account_create_account, + ); + + let mut fa_features = Features::default(); + fa_features.enable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); + fa_features.enable(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); + fa_features.disable(FeatureFlag::CONCURRENT_FUNGIBLE_BALANCE); + + test_compare_prod_and_another::(values_match, fa_features.clone(), |address| { + aptos_stdlib::aptos_account_fungible_transfer_only(address, 1000) + }); + + test_compare_prod_and_another::(values_match, fa_features.clone(), |address| { + aptos_stdlib::aptos_account_transfer(address, 1000) + }); + + test_compare_prod_and_another::( + values_match, + fa_features, + aptos_stdlib::aptos_account_create_account, + ); + } + + fn test_compare_prod_and_another( + values_match: bool, + features: Features, + txn_payload_f: impl Fn(AccountAddress) -> TransactionPayload, + ) { aptos_logger::Logger::new().init(); let db_dir = TempPath::new(); fs::create_dir_all(db_dir.as_ref()).unwrap(); - let mut init_features = Features::default(); - init_features.enable(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); - init_features.enable(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); - - bootstrap_with_genesis(&db_dir, false, init_features.clone()); + bootstrap_with_genesis(&db_dir, false, features.clone()); let (mut config, genesis_key) = - aptos_genesis::test_utils::test_config_with_custom_features(init_features); + aptos_genesis::test_utils::test_config_with_custom_features(features); config.storage.dir = db_dir.as_ref().to_path_buf(); config.storage.storage_pruner_config = NO_OP_STORAGE_PRUNER_CONFIG; config.storage.rocksdb_configs.enable_storage_sharding = false; - let txn = { + let (txn, vm_result) = { let (vm_db, vm_executor) = init_db_and_executor::(&config); let root_account = TransactionGenerator::read_root_account(genesis_key, &vm_db); let dst = LocalAccount::generate(&mut thread_rng()); - let num_coins = 1000; let txn_factory = TransactionGenerator::create_transaction_factory(); - let txn = Transaction::UserTransaction(root_account.sign_with_transaction_builder( - txn_factory.payload(aptos_stdlib::aptos_account_fungible_transfer_only( - dst.address(), - num_coins, - )), - )); + let txn = + Transaction::UserTransaction(root_account.sign_with_transaction_builder( + txn_factory.payload(txn_payload_f(dst.address())), + )); + let parent_block_id = vm_executor.committed_block_id(); + let block_id = HashValue::random(); vm_executor .execute_and_state_checkpoint( - (HashValue::zero(), vec![txn.clone()]).into(), - vm_executor.committed_block_id(), + (block_id, vec![txn.clone()]).into(), + parent_block_id, BENCHMARKS_BLOCK_EXECUTOR_ONCHAIN_CONFIG, ) .unwrap(); - txn + let result = vm_executor + .ledger_update(block_id, parent_block_id) + .unwrap() + .execution_output; + result.check_aborts_discards_retries(false, false, false); + (txn, result) }; - let (_native_db, native_executor) = init_db_and_executor::(&config); - native_executor + let (_other_db, other_executor) = init_db_and_executor::(&config); + let parent_block_id = other_executor.committed_block_id(); + let block_id = HashValue::random(); + other_executor .execute_and_state_checkpoint( - (HashValue::zero(), vec![txn]).into(), - native_executor.committed_block_id(), + (block_id, vec![txn]).into(), + parent_block_id, BENCHMARKS_BLOCK_EXECUTOR_ONCHAIN_CONFIG, ) .unwrap(); + let other_result = other_executor + .ledger_update(block_id, parent_block_id) + .unwrap() + .execution_output; + other_result.check_aborts_discards_retries(false, false, false); + + let vm_to_commit = &vm_result.to_commit; + let other_to_commit = &other_result.to_commit; - // let ( - // vm_txns, - // _vm_state_updates_vec, - // _vm_state_checkpoint_hashes, - // _vm_state_updates_before_last_checkpoint, - // _vm_sharded_state_cache, - // _vm_block_end_info, - // ) = vm_result.into_inner(); - // let (vm_statuses_for_input_txns, - // vm_to_commit, - // vm_to_discard, - // vm_to_retry, - // ) = vm_txns.into_inner(); - - // let ( - // native_txns, - // _native_state_updates_vec, - // _native_state_checkpoint_hashes, - // _native_state_updates_before_last_checkpoint, - // _native_sharded_state_cache, - // _native_block_end_info, - // ) = native_result.into_inner(); - // let (native_statuses_for_input_txns, - // native_to_commit, - // native_to_discard, - // native_to_retry, - // ) = native_txns.into_inner(); - - // println!("{:?}", vm_to_commit.parsed_outputs()); - // assert_eq!(vm_statuses_for_input_txns, native_statuses_for_input_txns); - // assert_eq!(vm_to_commit, native_to_commit); - // assert_eq!(vm_to_discard, native_to_discard); - // assert_eq!(vm_to_retry, native_to_retry); + assert_eq!(2, vm_to_commit.transaction_outputs().len()); + let vm_txn_output = &vm_to_commit.transaction_outputs()[0]; + let vm_cp_txn_output = &vm_to_commit.transaction_outputs()[1]; + + assert_eq!(2, other_to_commit.transaction_outputs().len()); + let other_txn_output = &other_to_commit.transaction_outputs()[0]; + let other_cp_txn_output = &other_to_commit.transaction_outputs()[1]; + + assert_eq!(vm_cp_txn_output, other_cp_txn_output); + + let vm_event_types = vm_txn_output + .events() + .iter() + .map(|event| event.type_tag().clone()) + .sorted() + .collect::>(); + let other_event_types = other_txn_output + .events() + .iter() + .map(|event| event.type_tag().clone()) + .sorted() + .collect::>(); + assert_eq!(vm_event_types, other_event_types); + + if values_match { + for (event1, event2) in vm_txn_output + .events() + .iter() + .zip_eq(other_txn_output.events().iter()) + { + assert_eq!(event1, event2); + } + } + + let vm_writes = vm_txn_output + .write_set() + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(); + let other_writes = other_txn_output + .write_set() + .iter() + .map(|(k, v)| (k.clone(), v.clone())) + .collect::>(); + for (key, value) in vm_writes.iter() { + if let StateKeyInner::AccessPath(apath) = key.inner() { + if let Path::ResourceGroup(_) = apath.get_path() { + let vm_resources = + bcs::from_bytes::>>(value.bytes().unwrap()) + .unwrap(); + let other_resources = + other_writes + .get(key) + .map_or_else(BTreeMap::new, |other_value| { + bcs::from_bytes::>>( + other_value.bytes().unwrap(), + ) + .unwrap() + }); + + assert_eq!( + vm_resources.keys().collect::>(), + other_resources.keys().collect::>() + ); + if values_match { + assert_eq!(vm_resources, other_resources); + } + } + } + + assert!(other_writes.contains_key(key), "missing: {:?}", key); + if values_match { + let other_value = other_writes.get(key).unwrap(); + assert_eq!(value, other_value, "different value for key: {:?}", key); + } + } + assert_eq!(vm_writes.len(), other_writes.len()); + + if values_match { + assert_eq!(vm_txn_output, other_txn_output); + } } fn test_generic_benchmark( diff --git a/execution/executor-benchmark/src/native/native_config.rs b/execution/executor-benchmark/src/native/native_config.rs index b770cf0f7d1198..ce552b67ef5e4c 100644 --- a/execution/executor-benchmark/src/native/native_config.rs +++ b/execution/executor-benchmark/src/native/native_config.rs @@ -28,7 +28,7 @@ impl NativeConfig { pub fn get_concurrency_level() -> usize { match NATIVE_EXECUTOR_CONCURRENCY_LEVEL.get() { Some(concurrency_level) => *concurrency_level, - None => 32, + None => 1, } } } diff --git a/execution/executor-benchmark/src/native/native_transaction.rs b/execution/executor-benchmark/src/native/native_transaction.rs index bea3a9c71c17f9..a93f7465503b7b 100644 --- a/execution/executor-benchmark/src/native/native_transaction.rs +++ b/execution/executor-benchmark/src/native/native_transaction.rs @@ -23,16 +23,16 @@ pub enum NativeTransaction { sequence_number: u64, recipient: AccountAddress, amount: u64, - fail_on_account_existing: bool, - fail_on_account_missing: bool, + fail_on_recipient_account_existing: bool, + fail_on_recipient_account_missing: bool, }, BatchTransfer { sender: AccountAddress, sequence_number: u64, recipients: Vec, amounts: Vec, - fail_on_account_existing: bool, - fail_on_account_missing: bool, + fail_on_recipient_account_existing: bool, + fail_on_recipient_account_missing: bool, }, } @@ -60,16 +60,16 @@ impl NativeTransaction { sequence_number: user_txn.sequence_number(), recipient: bcs::from_bytes(&f.args()[0]).unwrap(), amount: bcs::from_bytes(&f.args()[1]).unwrap(), - fail_on_account_existing: false, - fail_on_account_missing: true, + fail_on_recipient_account_existing: false, + fail_on_recipient_account_missing: true, }, (AccountAddress::ONE, "aptos_account", "transfer") => Self::Transfer { sender: user_txn.sender(), sequence_number: user_txn.sequence_number(), recipient: bcs::from_bytes(&f.args()[0]).unwrap(), amount: bcs::from_bytes(&f.args()[1]).unwrap(), - fail_on_account_existing: false, - fail_on_account_missing: false, + fail_on_recipient_account_existing: false, + fail_on_recipient_account_missing: false, }, (AccountAddress::ONE, "aptos_account", "create_account") => { Self::Transfer { @@ -77,8 +77,8 @@ impl NativeTransaction { sequence_number: user_txn.sequence_number(), recipient: bcs::from_bytes(&f.args()[0]).unwrap(), amount: 0, - fail_on_account_existing: true, - fail_on_account_missing: false, + fail_on_recipient_account_existing: true, + fail_on_recipient_account_missing: false, } }, (AccountAddress::ONE, "aptos_account", "batch_transfer") => { @@ -87,8 +87,8 @@ impl NativeTransaction { sequence_number: user_txn.sequence_number(), recipients: bcs::from_bytes(&f.args()[0]).unwrap(), amounts: bcs::from_bytes(&f.args()[1]).unwrap(), - fail_on_account_existing: false, - fail_on_account_missing: true, + fail_on_recipient_account_existing: false, + fail_on_recipient_account_missing: true, } }, (_, "simple", "nop") => Self::Nop { diff --git a/execution/executor-benchmark/src/native/native_vm.rs b/execution/executor-benchmark/src/native/native_vm.rs index 1b9830c4689afe..7264af09085099 100644 --- a/execution/executor-benchmark/src/native/native_vm.rs +++ b/execution/executor-benchmark/src/native/native_vm.rs @@ -9,6 +9,12 @@ use crate::{ native_transaction::NativeTransaction, }, }; +use aptos_aggregator::{ + bounded_math::SignedU128, + delayed_change::{DelayedApplyChange, DelayedChange}, + delta_change_set::{DeltaOp, DeltaWithMax}, + delta_math::DeltaHistory, +}; use aptos_block_executor::{ code_cache_global::ImmutableModuleCache, errors::BlockExecutionError, @@ -20,7 +26,9 @@ use aptos_mvhashmap::types::TxnIndex; use aptos_types::{ account_address::AccountAddress, account_config::{ - primary_apt_store, AccountResource, DepositFAEvent, FungibleStoreResource, WithdrawFAEvent, + primary_apt_store, AccountResource, CoinDeposit, CoinInfoResource, CoinRegister, + CoinStoreResource, CoinWithdraw, ConcurrentSupplyResource, DepositFAEvent, + FungibleStoreResource, TypeInfoResource, WithdrawFAEvent, }, block_executor::config::{ BlockExecutorConfig, BlockExecutorConfigFromOnchain, BlockExecutorLocalConfig, @@ -37,26 +45,29 @@ use aptos_types::{ TransactionAuxiliaryData, TransactionOutput, TransactionStatus, WriteSetPayload, }, write_set::WriteOp, + AptosCoinType, }; use aptos_vm::{block_executor::AptosTransactionOutput, VMBlockExecutor}; use aptos_vm_environment::environment::AptosEnvironment; use aptos_vm_types::{ - abstract_write_op::{AbstractResourceWriteOp, GroupWrite}, + abstract_write_op::{ + AbstractResourceWriteOp, GroupWrite, ResourceGroupInPlaceDelayedFieldChangeOp, + }, change_set::VMChangeSet, module_write_set::ModuleWriteSet, output::VMOutput, - resolver::{ExecutorView, ResourceGroupSize, ResourceGroupView}, - resource_group_adapter::group_tagged_resource_size, + resolver::{ExecutorView, ResourceGroupView}, + resource_group_adapter::group_size_as_sum, }; use bytes::Bytes; use move_core_types::{ language_storage::StructTag, - move_resource::MoveStructType, - value::MoveTypeLayout, + value::{IdentifierMappingKind, MoveStructLayout, MoveTypeLayout}, vm_status::{StatusCode, VMStatus}, }; +use move_vm_types::delayed_values::delayed_field_id::DelayedFieldID; use serde::{de::DeserializeOwned, Serialize}; -use std::{collections::BTreeMap, fmt::Debug, sync::Arc}; +use std::{collections::BTreeMap, fmt::Debug, sync::Arc, u128}; pub struct NativeVMBlockExecutor; @@ -80,7 +91,7 @@ impl VMBlockExecutor for NativeVMBlockExecutor { Self::execute_block_impl(transactions, state_view, BlockExecutorConfig { local: BlockExecutorLocalConfig { concurrency_level: NativeConfig::get_concurrency_level(), - allow_fallback: true, + allow_fallback: false, discard_failed_blocks: false, }, onchain: onchain_config, @@ -146,10 +157,19 @@ impl ExecutorTask for NativeVMExecutorTask { type Txn = SignatureVerifiedTransaction; fn init(env: Self::Environment, _state_view: &impl StateView) -> Self { + let fa_migration_complete = env + .features() + .is_enabled(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); + let new_accounts_default_to_fa = env + .features() + .is_enabled(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); + assert_eq!( + fa_migration_complete, new_accounts_default_to_fa, + "native code only works with both flags either enabled or disabled" + ); + Self { - fa_migration_complete: env - .features() - .is_enabled(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE), + fa_migration_complete, db_util: DbAccessUtil::new(), } } @@ -164,12 +184,11 @@ impl ExecutorTask for NativeVMExecutorTask { _txn_idx: TxnIndex, ) -> ExecutionStatus { let gas_units = 4; - let gas = gas_units * 100; match self.execute_transaction_impl( executor_with_group_view, txn, - gas, + gas_units, self.fa_migration_complete, ) { Ok(change_set) => ExecutionStatus::Success(AptosTransactionOutput::new(VMOutput::new( @@ -201,14 +220,26 @@ impl NativeVMExecutorTask { &self, view: &(impl ExecutorView + ResourceGroupView), txn: &SignatureVerifiedTransaction, - gas: u64, + gas_units: u64, fa_migration_complete: bool, ) -> Result { + let gas = gas_units * 100; + let mut resource_write_set = BTreeMap::new(); let mut events = Vec::new(); - let delayed_field_change_set = BTreeMap::new(); + let mut delayed_field_change_set = BTreeMap::new(); let aggregator_v1_write_set = BTreeMap::new(); - let aggregator_v1_delta_set = BTreeMap::new(); + let mut aggregator_v1_delta_set = BTreeMap::new(); + + self.reduce_apt_supply( + fa_migration_complete, + gas, + view, + &mut resource_write_set, + &mut delayed_field_change_set, + &mut aggregator_v1_delta_set, + ) + .unwrap(); match NativeTransaction::parse(txn) { NativeTransaction::Nop { @@ -221,7 +252,8 @@ impl NativeVMExecutorTask { view, &mut resource_write_set, )?; - self.withdraw_fa_apt_from_signer( + self.withdraw_apt( + fa_migration_complete, sender, 0, view, @@ -250,34 +282,33 @@ impl NativeVMExecutorTask { &mut resource_write_set, &mut events, )?; - self.deposit_fa_apt( - recipient, - amount, - view, - gas, - &mut resource_write_set, - &mut events, - )?; + if amount > 0 { + self.deposit_fa_apt( + recipient, + amount, + view, + &mut resource_write_set, + &mut events, + )?; + } }, NativeTransaction::Transfer { sender, sequence_number, recipient, amount, - fail_on_account_existing, - fail_on_account_missing, + fail_on_recipient_account_existing: fail_on_account_existing, + fail_on_recipient_account_missing: fail_on_account_missing, } => { - if !fa_migration_complete { - panic!("!fa_migration_complete"); - // return Err(()); - } self.check_and_set_sequence_number( sender, sequence_number, view, &mut resource_write_set, )?; - self.withdraw_fa_apt_from_signer( + + self.withdraw_apt( + fa_migration_complete, sender, amount, view, @@ -286,14 +317,16 @@ impl NativeVMExecutorTask { &mut events, )?; - if !self.deposit_fa_apt( + let exists = self.deposit_apt( + fa_migration_complete, recipient, amount, view, - gas, &mut resource_write_set, &mut events, - )? { + )?; + + if !exists || fail_on_account_existing { self.check_or_create_account( recipient, fail_on_account_existing, @@ -308,6 +341,11 @@ impl NativeVMExecutorTask { }, }; + events.push(( + FeeStatement::new(gas_units, gas_units, 0, 0, 0).create_event_v2(), + None, + )); + Ok(VMChangeSet::new( resource_write_set, events, @@ -335,7 +373,16 @@ impl NativeVMExecutorTask { resource_tag: &StructTag, view: &(impl ExecutorView + ResourceGroupView), ) -> Result, ()> { - view.get_resource_from_group(group_key, resource_tag, None) + Self::get_value_from_group_with_layout(group_key, resource_tag, view, None) + } + + pub fn get_value_from_group_with_layout( + group_key: &StateKey, + resource_tag: &StructTag, + view: &(impl ExecutorView + ResourceGroupView), + maybe_layout: Option<&MoveTypeLayout>, + ) -> Result, ()> { + view.get_resource_from_group(group_key, resource_tag, maybe_layout) .map_err(hide_error)? .map(|value| bcs::from_bytes::(&value)) .transpose() @@ -416,6 +463,133 @@ impl NativeVMExecutorTask { Ok(()) } + fn reduce_apt_supply( + &self, + fa_migration_complete: bool, + gas: u64, + view: &(impl ExecutorView + ResourceGroupView), + resource_write_set: &mut BTreeMap, + delayed_field_change_set: &mut BTreeMap>, + aggregator_v1_delta_set: &mut BTreeMap, + ) -> Result<(), ()> { + if fa_migration_complete { + self.reduce_fa_apt_supply(gas, view, resource_write_set, delayed_field_change_set) + } else { + self.reduce_coin_apt_supply(gas, view, aggregator_v1_delta_set) + } + } + + fn reduce_fa_apt_supply( + &self, + gas: u64, + view: &(impl ExecutorView + ResourceGroupView), + resource_write_set: &mut BTreeMap, + delayed_field_change_set: &mut BTreeMap>, + ) -> Result<(), ()> { + let apt_metadata_object_state_key = self + .db_util + .new_state_key_object_resource_group(&AccountAddress::TEN); + + let concurrent_supply_rg_tag = &self.db_util.common.concurrent_supply; + + let concurrent_supply_layout = MoveTypeLayout::Struct(MoveStructLayout::new(vec![ + MoveTypeLayout::Native( + IdentifierMappingKind::Aggregator, + Box::new(MoveTypeLayout::U128), + ), + MoveTypeLayout::U128, + ])); + + let supply = Self::get_value_from_group_with_layout::( + &apt_metadata_object_state_key, + concurrent_supply_rg_tag, + view, + Some(&concurrent_supply_layout), + )? + .unwrap(); + + let delayed_id = DelayedFieldID::from(*supply.current.get() as u64); + view.validate_delayed_field_id(&delayed_id).unwrap(); + delayed_field_change_set.insert( + delayed_id, + DelayedChange::Apply(DelayedApplyChange::AggregatorDelta { + delta: DeltaWithMax::new(SignedU128::Negative(gas as u128), u128::MAX), + }), + ); + let materialized_size = view + .get_resource_state_value_size(&apt_metadata_object_state_key) + .map_err(hide_error)? + .unwrap(); + let metadata = view + .get_resource_state_value_metadata(&apt_metadata_object_state_key) + .map_err(hide_error)? + .unwrap(); + resource_write_set.insert( + apt_metadata_object_state_key, + AbstractResourceWriteOp::ResourceGroupInPlaceDelayedFieldChange( + ResourceGroupInPlaceDelayedFieldChangeOp { + materialized_size, + metadata, + }, + ), + ); + Ok(()) + } + + fn reduce_coin_apt_supply( + &self, + gas: u64, + view: &(impl ExecutorView + ResourceGroupView), + aggregator_v1_delta_set: &mut BTreeMap, + ) -> Result<(), ()> { + let (sender_coin_store, _metadata) = Self::get_value::>( + &self.db_util.common.apt_coin_info_resource, + view, + )? + .ok_or(())?; + + let delta_op = DeltaOp::new(SignedU128::Negative(gas as u128), u128::MAX, DeltaHistory { + max_achieved_positive_delta: 0, + min_achieved_negative_delta: gas as u128, + min_overflow_positive_delta: None, + max_underflow_negative_delta: None, + }); + aggregator_v1_delta_set.insert(sender_coin_store.supply_aggregator_state_key(), delta_op); + Ok(()) + } + + fn withdraw_apt( + &self, + fa_migration_complete: bool, + sender: AccountAddress, + amount: u64, + view: &(impl ExecutorView + ResourceGroupView), + gas: u64, + resource_write_set: &mut BTreeMap, + events: &mut Vec<(ContractEvent, Option)>, + ) -> Result<(), ()> { + if fa_migration_complete { + self.withdraw_fa_apt_from_signer( + sender, + amount, + view, + gas, + resource_write_set, + events, + )?; + } else { + self.withdraw_coin_apt_from_signer( + sender, + amount, + view, + gas, + resource_write_set, + events, + )?; + } + Ok(()) + } + fn withdraw_fa_apt_from_signer( &self, sender_address: AccountAddress, @@ -429,11 +603,11 @@ impl NativeVMExecutorTask { let sender_fa_store_object_key = self .db_util .new_state_key_object_resource_group(&sender_store_address); - let fungible_store_rg_tag = FungibleStoreResource::struct_tag(); + let fungible_store_rg_tag = &self.db_util.common.fungible_store; match Self::get_value_from_group::( &sender_fa_store_object_key, - &fungible_store_rg_tag, + fungible_store_rg_tag, view, )? { Some(mut fa_store) => { @@ -442,7 +616,7 @@ impl NativeVMExecutorTask { let fa_store_write = Self::create_single_resource_in_group_modification( &fa_store, &sender_fa_store_object_key, - fungible_store_rg_tag, + fungible_store_rg_tag.clone(), view, )?; resource_write_set.insert(sender_fa_store_object_key, fa_store_write); @@ -474,12 +648,103 @@ impl NativeVMExecutorTask { } } + fn withdraw_coin_apt_from_signer( + &self, + sender_address: AccountAddress, + transfer_amount: u64, + view: &(impl ExecutorView + ResourceGroupView), + gas: u64, + resource_write_set: &mut BTreeMap, + events: &mut Vec<(ContractEvent, Option)>, + ) -> Result<(), ()> { + let sender_coin_store_key = self.db_util.new_state_key_aptos_coin(&sender_address); + + let sender_coin_store_opt = + Self::get_value::>(&sender_coin_store_key, view)?; + + let (mut sender_coin_store, metadata) = match sender_coin_store_opt { + None => { + return self.withdraw_fa_apt_from_signer( + sender_address, + transfer_amount, + view, + gas, + resource_write_set, + events, + ) + }, + Some((sender_coin_store, metadata)) => (sender_coin_store, metadata), + }; + + sender_coin_store.set_coin(sender_coin_store.coin() - transfer_amount - gas); + + // first need to create events, to update the handle, and then serialize sender_coin_store + if transfer_amount > 0 { + // events.push(( + // WithdrawEvent { + // amount: transfer_amount, + // } + // .create_event_v1(sender_coin_store.withdraw_events_mut()), + // None, + // )); + events.push(( + CoinWithdraw { + coin_type: self.db_util.common.apt_coin_type_name.clone(), + account: sender_address, + amount: transfer_amount, + } + .create_event_v2(), + None, + )); + } + // coin doesn't emit WithdrawEvent for gas. + + resource_write_set.insert( + sender_coin_store_key, + AbstractResourceWriteOp::Write(WriteOp::Modification { + data: Bytes::from(bcs::to_bytes(&sender_coin_store).map_err(hide_error)?), + metadata, + }), + ); + + Ok(()) + } + + /// Returns bool whether FungibleStore existed. + fn deposit_apt( + &self, + fa_migration_complete: bool, + recipient_address: AccountAddress, + transfer_amount: u64, + view: &(impl ExecutorView + ResourceGroupView), + resource_write_set: &mut BTreeMap, + events: &mut Vec<(ContractEvent, Option)>, + ) -> Result { + if fa_migration_complete { + self.deposit_fa_apt( + recipient_address, + transfer_amount, + view, + resource_write_set, + events, + ) + } else { + self.deposit_coin_apt( + recipient_address, + transfer_amount, + view, + resource_write_set, + events, + ) + } + } + + /// Returns bool whether FungibleStore existed. fn deposit_fa_apt( &self, recipient_address: AccountAddress, transfer_amount: u64, view: &(impl ExecutorView + ResourceGroupView), - gas: u64, resource_write_set: &mut BTreeMap, events: &mut Vec<(ContractEvent, Option)>, ) -> Result { @@ -487,55 +752,130 @@ impl NativeVMExecutorTask { let recipient_fa_store_object_key = self .db_util .new_state_key_object_resource_group(&recipient_store_address); - let fungible_store_rg_tag = FungibleStoreResource::struct_tag(); - - match Self::get_value_from_group::( - &recipient_fa_store_object_key, - &fungible_store_rg_tag, - view, - )? { - Some(mut fa_store) => { - fa_store.balance += transfer_amount + gas; - let fa_store_write = Self::create_single_resource_in_group_modification( - &fa_store, - &recipient_fa_store_object_key, - fungible_store_rg_tag, - view, - )?; - resource_write_set.insert(recipient_fa_store_object_key, fa_store_write); - - events.push(( - DepositFAEvent { - store: recipient_store_address, - amount: transfer_amount, - } - .create_event_v2(), - None, - )); - Ok(true) - }, - None => { - let receipeint_fa_store = - FungibleStoreResource::new(AccountAddress::TEN, transfer_amount, false); - let fa_store_write = Self::create_single_resource_in_group_creation( - &receipeint_fa_store, - &recipient_fa_store_object_key, - fungible_store_rg_tag, - view, - )?; - resource_write_set.insert(recipient_fa_store_object_key, fa_store_write); + let fungible_store_rg_tag = &self.db_util.common.fungible_store; + + let (mut fa_store, rest_to_create, existed) = + match Self::get_value_from_group::( + &recipient_fa_store_object_key, + fungible_store_rg_tag, + view, + )? { + Some(fa_store) => (fa_store, None, true), + None => ( + FungibleStoreResource::new(AccountAddress::TEN, 0, false), + Some(BTreeMap::from([( + self.db_util.common.object_core.clone(), + bcs::to_bytes(&DbAccessUtil::new_object_core( + recipient_store_address, + recipient_address, + )) + .map_err(hide_error)?, + )])), + false, + ), + }; + + fa_store.balance += transfer_amount; + + let fa_store_write = if existed { + Self::create_single_resource_in_group_modification( + &fa_store, + &recipient_fa_store_object_key, + fungible_store_rg_tag.clone(), + view, + )? + } else { + let mut rg = rest_to_create.unwrap(); + rg.insert( + fungible_store_rg_tag.clone(), + bcs::to_bytes(&fa_store).map_err(hide_error)?, + ); + Self::create_resource_in_group_creation(&recipient_fa_store_object_key, rg, view)? + }; + resource_write_set.insert(recipient_fa_store_object_key, fa_store_write); + + if transfer_amount > 0 { + let event = DepositFAEvent { + store: recipient_store_address, + amount: transfer_amount, + }; + events.push((event.create_event_v2(), None)); + } + Ok(existed) + } - events.push(( - DepositFAEvent { - store: recipient_store_address, - amount: transfer_amount, - } - .create_event_v2(), - None, - )); - Ok(false) - }, + fn deposit_coin_apt( + &self, + recipient_address: AccountAddress, + transfer_amount: u64, + view: &(impl ExecutorView + ResourceGroupView), + resource_write_set: &mut BTreeMap, + events: &mut Vec<(ContractEvent, Option)>, + ) -> Result { + let recipient_coin_store_key = self.db_util.new_state_key_aptos_coin(&recipient_address); + let (mut recipient_coin_store, recipient_coin_store_metadata, existed) = + match Self::get_value::>( + &recipient_coin_store_key, + view, + )? { + Some((recipient_coin_store, metadata)) => { + (recipient_coin_store, Some(metadata), true) + }, + None => { + events.push(( + CoinRegister { + account: AccountAddress::ONE, + type_info: TypeInfoResource::new::() + .map_err(hide_error)?, + } + .create_event_v2(), + None, + )); + ( + DbAccessUtil::new_apt_coin_store(0, recipient_address), + None, + false, + ) + }, + }; + + recipient_coin_store.set_coin(recipient_coin_store.coin() + transfer_amount); + + // first need to create events, to update the handle, and then serialize sender_coin_store + if transfer_amount > 0 { + // events.push(( + // DepositEvent { + // amount: transfer_amount, + // } + // .create_event_v1(recipient_coin_store.deposit_events_mut()), + // None, + // )); + events.push(( + CoinDeposit { + coin_type: self.db_util.common.apt_coin_type_name.clone(), + account: recipient_address, + amount: transfer_amount, + } + .create_event_v2(), + None, + )) } + let write_op = if existed { + WriteOp::Modification { + data: Bytes::from(bcs::to_bytes(&recipient_coin_store).map_err(hide_error)?), + metadata: recipient_coin_store_metadata.unwrap(), + } + } else { + WriteOp::legacy_creation(Bytes::from( + bcs::to_bytes(&recipient_coin_store).map_err(hide_error)?, + )) + }; + resource_write_set.insert( + recipient_coin_store_key, + AbstractResourceWriteOp::Write(write_op), + ); + + Ok(existed) } fn create_single_resource_in_group_modification( @@ -565,23 +905,33 @@ impl NativeVMExecutorTask { Ok(group_write) } - fn create_single_resource_in_group_creation( - value: &T, + fn create_resource_in_group_creation( group_key: &StateKey, - resource_tag: StructTag, + resources: BTreeMap>, view: &(impl ExecutorView + ResourceGroupView), ) -> Result { let size = view.resource_group_size(group_key).map_err(hide_error)?; assert_eq!(size.get(), 0); - let value_bytes = Bytes::from(bcs::to_bytes(value).map_err(hide_error)?); - let new_size = ResourceGroupSize::Combined { - num_tagged_resources: 1, - all_tagged_resources_size: group_tagged_resource_size(&resource_tag, value_bytes.len()) - .map_err(hide_error)?, - }; + let inner_ops = resources + .into_iter() + .map(|(resource_tag, value)| -> Result<_, ()> { + Ok(( + resource_tag, + (WriteOp::legacy_creation(Bytes::from(value)), None), + )) + }) + .collect::, ()>>()?; + + let new_size = group_size_as_sum( + inner_ops + .iter() + .map(|(resource_tag, (value, _layout))| (resource_tag, value.size())), + ) + .map_err(hide_error)?; + let group_write = AbstractResourceWriteOp::WriteResourceGroup(GroupWrite::new( WriteOp::legacy_creation(Bytes::new()), - BTreeMap::from([(resource_tag, (WriteOp::legacy_creation(value_bytes), None))]), + inner_ops, new_size, size.get(), )); diff --git a/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs b/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs index 8b9f3096eb169a..a46277aa46436a 100644 --- a/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs +++ b/execution/executor-benchmark/src/native/parallel_uncoordinated_block_executor.rs @@ -11,12 +11,12 @@ use aptos_block_executor::counters::BLOCK_EXECUTOR_INNER_EXECUTE_BLOCK; use aptos_types::{ account_address::AccountAddress, account_config::{ - deposit::DepositEvent, primary_apt_store, withdraw::WithdrawEvent, AccountResource, - DepositFAEvent, FungibleStoreResource, WithdrawFAEvent, + primary_apt_store, AccountResource, CoinDeposit, CoinInfoResource, CoinRegister, + CoinStoreResource, CoinWithdraw, ConcurrentSupplyResource, DepositFAEvent, + FungibleStoreResource, TypeInfoResource, WithdrawFAEvent, }, block_executor::config::BlockExecutorConfigFromOnchain, contract_event::ContractEvent, - event::EventKey, fee_statement::FeeStatement, move_utils::move_event_v2::MoveEventV2Type, on_chain_config::{FeatureFlag, Features, OnChainConfig}, @@ -27,14 +27,11 @@ use aptos_types::{ }, vm_status::{AbortLocation, StatusCode, VMStatus}, write_set::{WriteOp, WriteSetMut}, + AptosCoinType, }; use aptos_vm::VMBlockExecutor; use dashmap::DashMap; -use move_core_types::{ - ident_str, - language_storage::{ModuleId, TypeTag}, - move_resource::MoveStructType, -}; +use move_core_types::{ident_str, language_storage::ModuleId}; use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}; use std::collections::{BTreeMap, HashMap}; @@ -155,24 +152,12 @@ macro_rules! merge_output { }; } -#[macro_export] -macro_rules! merge_output_in_partial { - ($output:ident, $new_output:expr) => { - match $new_output { - Ok(new_output) => { - $output.append(new_output); - }, - Err(status) => return Ok(Err(status)), - } - }; -} - pub struct NativeRawTransactionExecutor { db_util: DbAccessUtil, } impl RawTransactionExecutor for NativeRawTransactionExecutor { - type BlockState = (bool, bool); + type BlockState = bool; fn new() -> Self { Self { @@ -180,68 +165,159 @@ impl RawTransactionExecutor for NativeRawTransactionExecutor { } } - fn init_block_state(&self, state_view: &(impl StateView + Sync)) -> Self::BlockState { + fn init_block_state(&self, state_view: &(impl StateView + Sync)) -> bool { let features = Features::fetch_config(&state_view).unwrap_or_default(); let fa_migration_complete = features.is_enabled(FeatureFlag::OPERATIONS_DEFAULT_TO_FA_APT_STORE); let new_accounts_default_to_fa = features.is_enabled(FeatureFlag::NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE); + assert_eq!( + fa_migration_complete, new_accounts_default_to_fa, + "native code only works with both flags either enabled or disabled" + ); - (fa_migration_complete, new_accounts_default_to_fa) + fa_migration_complete } fn execute_transaction( &self, txn: NativeTransaction, state_view: &(impl StateView + Sync), - block_state: &(bool, bool), + block_state: &bool, ) -> Result { - let (fa_migration_complete, new_accounts_default_to_fa) = *block_state; + let fa_migration_complete = *block_state; - match txn { + let gas_unit = 4; // hardcode gas consumed. + let gas = gas_unit * 100; + + let mut output = match txn { NativeTransaction::Nop { sender, sequence_number: _, - } => self.handle_nop(sender, fa_migration_complete, state_view), + } => { + let mut output = self.increment_sequence_number(sender, state_view)?; + + merge_output!( + output, + self.withdraw_apt_from_signer( + fa_migration_complete, + sender, + 0, + state_view, + gas + )? + ); + + output + }, NativeTransaction::FaTransfer { sender, sequence_number: _, recipient, amount, - } => self.handle_fa_transfer(sender, recipient, amount, state_view), + } => { + let mut output = self.increment_sequence_number(sender, state_view)?; + + merge_output!( + output, + self.withdraw_fa_apt_from_signer(sender, amount, state_view, gas)? + ); + + let (deposit_output, _existed) = + self.deposit_fa_apt(recipient, amount, state_view)?; + output.append(deposit_output); + output + }, NativeTransaction::Transfer { sender, sequence_number: _, recipient, amount, - fail_on_account_existing, - fail_on_account_missing, - } => self.handle_account_creation_and_transfer( - sender, - recipient, - amount, - fail_on_account_existing, - fail_on_account_missing, - state_view, - new_accounts_default_to_fa, - ), + fail_on_recipient_account_existing, + fail_on_recipient_account_missing, + } => { + let mut output = self.increment_sequence_number(sender, state_view)?; + merge_output!( + output, + self.withdraw_apt_from_signer( + fa_migration_complete, + sender, + amount, + state_view, + gas + )? + ); + + let (deposit_output, existed) = + self.deposit_apt(fa_migration_complete, recipient, amount, state_view)?; + output.append(deposit_output); + + if !existed || fail_on_recipient_account_existing { + merge_output!( + output, + self.check_or_create_account( + recipient, + fail_on_recipient_account_existing, + fail_on_recipient_account_missing, + state_view, + )? + ); + } + output + }, NativeTransaction::BatchTransfer { sender, sequence_number: _, recipients, amounts, - fail_on_account_existing, - fail_on_account_missing, - } => self.handle_batch_account_creation_and_transfer( - sender, - recipients, - amounts, - fail_on_account_existing, - fail_on_account_missing, - state_view, - new_accounts_default_to_fa, - ), - } + fail_on_recipient_account_existing: fail_on_account_existing, + fail_on_recipient_account_missing: fail_on_account_missing, + } => { + let mut deltas = compute_deltas_for_batch(recipients, amounts, sender); + + let amount_to_sender = -deltas.remove(&sender).unwrap_or(0); + assert!(amount_to_sender >= 0); + + let mut output = self.increment_sequence_number(sender, state_view)?; + merge_output!( + output, + self.withdraw_apt_from_signer( + fa_migration_complete, + sender, + amount_to_sender as u64, + state_view, + gas + )? + ); + + for (recipient_address, transfer_amount) in deltas.into_iter() { + let (deposit_output, existed) = self.deposit_apt( + fa_migration_complete, + recipient_address, + transfer_amount as u64, + state_view, + )?; + output.append(deposit_output); + + if !existed || fail_on_account_existing { + merge_output!( + output, + self.check_or_create_account( + recipient_address, + fail_on_account_existing, + fail_on_account_missing, + state_view, + )? + ); + } + } + output + }, + }; + + output.append(self.reduce_apt_supply(fa_migration_complete, gas, state_view)?); + + output.into_success_output(gas) } } @@ -250,14 +326,10 @@ impl NativeRawTransactionExecutor { &self, sender_address: AccountAddress, state_view: &(impl StateView + Sync), - ) -> Result> { + ) -> Result { let sender_account_key = self.db_util.new_state_key_account(&sender_address); - let mut sender_account = { - let _timer = TIMER - .with_label_values(&["read_sender_account"]) - .start_timer(); - DbAccessUtil::get_account(&sender_account_key, state_view)?.unwrap() - }; + let mut sender_account = + DbAccessUtil::get_account(&sender_account_key, state_view)?.unwrap(); sender_account.sequence_number += 1; @@ -266,7 +338,80 @@ impl NativeRawTransactionExecutor { WriteOp::legacy_modification(bcs::to_bytes(&sender_account)?.into()), )]; let events = vec![]; - Ok(Ok(IncrementalOutput { write_set, events })) + Ok(IncrementalOutput { write_set, events }) + } + + fn reduce_apt_supply( + &self, + fa_migration_complete: bool, + gas: u64, + state_view: &(impl StateView + Sync), + ) -> Result { + if fa_migration_complete { + self.reduce_fa_apt_supply(gas, state_view) + } else { + self.reduce_coin_apt_supply(gas, state_view) + } + } + + fn reduce_fa_apt_supply( + &self, + gas: u64, + state_view: &(impl StateView + Sync), + ) -> Result { + let apt_metadata_object_state_key = self + .db_util + .new_state_key_object_resource_group(&AccountAddress::TEN); + + let concurrent_supply_rg_tag = &self.db_util.common.concurrent_supply; + + let mut apt_metadata_object = + DbAccessUtil::get_resource_group(&apt_metadata_object_state_key, state_view)?.unwrap(); + let mut supply = bcs::from_bytes::( + &apt_metadata_object + .remove(concurrent_supply_rg_tag) + .unwrap(), + )?; + + supply.current.set(supply.current.get() - gas as u128); + + apt_metadata_object.insert(concurrent_supply_rg_tag.clone(), bcs::to_bytes(&supply)?); + + let write_set = vec![( + apt_metadata_object_state_key, + WriteOp::legacy_modification(bcs::to_bytes(&apt_metadata_object)?.into()), + )]; + + Ok(IncrementalOutput { + write_set, + events: Vec::new(), + }) + } + + fn reduce_coin_apt_supply( + &self, + gas: u64, + state_view: &(impl StateView + Sync), + ) -> Result { + let sender_coin_store = DbAccessUtil::get_value::>( + &self.db_util.common.apt_coin_info_resource, + state_view, + )? + .ok_or_else(|| anyhow::anyhow!("no coin info"))?; + + let total_supply_state_key = sender_coin_store.supply_aggregator_state_key(); + let total_supply = DbAccessUtil::get_value::(&total_supply_state_key, state_view)? + .ok_or_else(|| anyhow::anyhow!("no total supply"))?; + + let write_set = vec![( + total_supply_state_key, + WriteOp::legacy_modification(bcs::to_bytes(&(total_supply - gas as u128))?.into()), + )]; + + Ok(IncrementalOutput { + write_set, + events: vec![], + }) } // add total supply via aggregators? @@ -349,62 +494,19 @@ impl NativeRawTransactionExecutor { Ok(Ok(IncrementalOutput { write_set, events })) } - fn deposit_fa_apt( + fn withdraw_apt_from_signer( &self, - recipient_address: AccountAddress, + fa_migration_complete: bool, + sender_address: AccountAddress, transfer_amount: u64, state_view: &(impl StateView + Sync), + gas: u64, ) -> Result> { - let recipient_store_address = primary_apt_store(recipient_address); - let recipient_fa_store_object_key = self - .db_util - .new_state_key_object_resource_group(&recipient_store_address); - let fungible_store_rg_tag = &self.db_util.common.fungible_store; - - let (recipient_fa_store, mut recipient_fa_store_object, recipient_fa_store_existed) = { - let _timer = TIMER - .with_label_values(&["read_recipient_fa_store"]) - .start_timer(); - match DbAccessUtil::get_resource_group(&recipient_fa_store_object_key, state_view)? { - Some(mut recipient_fa_store_object) => { - let mut recipient_fa_store = bcs::from_bytes::( - &recipient_fa_store_object - .remove(fungible_store_rg_tag) - .unwrap(), - )?; - recipient_fa_store.balance += transfer_amount; - (recipient_fa_store, recipient_fa_store_object, true) - }, - None => { - let receipeint_fa_store = - FungibleStoreResource::new(AccountAddress::TEN, transfer_amount, false); - let receipeint_fa_store_object = BTreeMap::new(); - (receipeint_fa_store, receipeint_fa_store_object, false) - }, - } - }; - - recipient_fa_store_object.insert( - fungible_store_rg_tag.clone(), - bcs::to_bytes(&recipient_fa_store)?, - ); - - let write_set = vec![( - recipient_fa_store_object_key, - if recipient_fa_store_existed { - WriteOp::legacy_modification(bcs::to_bytes(&recipient_fa_store_object)?.into()) - } else { - WriteOp::legacy_creation(bcs::to_bytes(&recipient_fa_store_object)?.into()) - }, - )]; - - let event = DepositFAEvent { - store: recipient_store_address, - amount: transfer_amount, - }; - - let events = vec![event.create_event_v2()]; - Ok(Ok(IncrementalOutput { write_set, events })) + if fa_migration_complete { + self.withdraw_fa_apt_from_signer(sender_address, transfer_amount, state_view, gas) + } else { + self.withdraw_coin_apt_from_signer(sender_address, transfer_amount, state_view, gas) + } } fn withdraw_coin_apt_from_signer( @@ -435,25 +537,31 @@ impl NativeRawTransactionExecutor { sender_coin_store.set_coin(sender_coin_store.coin() - transfer_amount - gas); + let mut events = Vec::new(); + if transfer_amount != 0 { + events.push( + CoinWithdraw { + coin_type: self.db_util.common.apt_coin_type_name.clone(), + account: sender_address, + amount: transfer_amount, + } + .create_event_v2(), + ); + // Coin doesn't emit Withdraw event for gas + } + let write_set = vec![( sender_coin_store_key, WriteOp::legacy_modification(bcs::to_bytes(&sender_coin_store)?.into()), )]; - // TODO(grao): Some values are fake, because I'm lazy. - let events = vec![ContractEvent::new_v1( - EventKey::new(0, sender_address), - 0, - TypeTag::Struct(Box::new(WithdrawEvent::struct_tag())), - sender_address.to_vec(), - )]; Ok(Ok(IncrementalOutput { write_set, events })) } fn create_non_existing_account( recipient_address: AccountAddress, recipient_account_key: StateKey, - ) -> Result> { + ) -> Result { let mut output = IncrementalOutput::new(); let recipient_account = DbAccessUtil::new_account_resource(recipient_address); @@ -462,255 +570,186 @@ impl NativeRawTransactionExecutor { WriteOp::legacy_creation(bcs::to_bytes(&recipient_account)?.into()), )); - Ok(Ok(output)) + Ok(output) } - fn deposit_coin_apt( + fn deposit_apt( &self, + fa_migration_complete: bool, recipient_address: AccountAddress, transfer_amount: u64, - fail_on_existing: bool, - fail_on_missing: bool, state_view: &(impl StateView + Sync), - new_accounts_default_to_fa: bool, - ) -> Result> { - let recipient_account_key = self.db_util.new_state_key_account(&recipient_address); - let recipient_coin_store_key = self.db_util.new_state_key_aptos_coin(&recipient_address); - - let recipient_account = { - let _timer = TIMER.with_label_values(&["read_new_account"]).start_timer(); - DbAccessUtil::get_account(&recipient_account_key, state_view)? - }; - - let mut output = IncrementalOutput::new(); - if recipient_account.is_some() { - if fail_on_existing { - return Ok(Err(TransactionStatus::Keep(ExecutionStatus::MoveAbort { - location: AbortLocation::Module(ModuleId::new( - AccountAddress::ONE, - ident_str!("account").into(), - )), - code: 7, - info: None, - }))); - } - - let mut recipient_coin_store = { - let _timer = TIMER - .with_label_values(&["read_new_coin_store"]) - .start_timer(); - DbAccessUtil::get_apt_coin_store(&recipient_coin_store_key, state_view)?.unwrap() - }; - - if transfer_amount != 0 { - recipient_coin_store.set_coin(recipient_coin_store.coin() + transfer_amount); - - output.write_set.push(( - recipient_coin_store_key, - WriteOp::legacy_modification(bcs::to_bytes(&recipient_coin_store)?.into()), - )); - } + ) -> Result<(IncrementalOutput, bool)> { + if fa_migration_complete { + self.deposit_fa_apt(recipient_address, transfer_amount, state_view) } else { - if fail_on_missing { - return Ok(Err(TransactionStatus::Keep(ExecutionStatus::MoveAbort { - location: AbortLocation::Module(ModuleId::new( - AccountAddress::ONE, - ident_str!("account").into(), - )), - code: 8, - info: None, - }))); - } - - merge_output_in_partial!( - output, - Self::create_non_existing_account(recipient_address, recipient_account_key)? - ); - - if new_accounts_default_to_fa { - merge_output_in_partial!( - output, - self.deposit_fa_apt(recipient_address, transfer_amount, state_view)? - ); - return Ok(Ok(output)); - } - - { - let _timer = TIMER - .with_label_values(&["read_new_coin_store"]) - .start_timer(); - assert!( - DbAccessUtil::get_apt_coin_store(&recipient_coin_store_key, state_view)? - .is_none() - ); - } - - let recipient_coin_store = - DbAccessUtil::new_apt_coin_store(transfer_amount, recipient_address); - - output.write_set.push(( - recipient_coin_store_key, - WriteOp::legacy_creation(bcs::to_bytes(&recipient_coin_store)?.into()), - )); + self.deposit_coin_apt(recipient_address, transfer_amount, state_view) } - - output.events.push( - ContractEvent::new_v1( - EventKey::new(0, recipient_address), - 0, - TypeTag::Struct(Box::new(DepositEvent::struct_tag())), - recipient_address.to_vec(), - ), // TODO(grao): CoinRegisterEvent - ); - Ok(Ok(output)) } - fn handle_fa_transfer( + fn deposit_fa_apt( &self, - sender_address: AccountAddress, recipient_address: AccountAddress, transfer_amount: u64, state_view: &(impl StateView + Sync), - ) -> Result { - let _timer = TIMER.with_label_values(&["fa_transfer"]).start_timer(); + ) -> Result<(IncrementalOutput, bool)> { + let recipient_store_address = primary_apt_store(recipient_address); + let recipient_fa_store_object_key = self + .db_util + .new_state_key_object_resource_group(&recipient_store_address); + let fungible_store_rg_tag = &self.db_util.common.fungible_store; - let gas = 500; // hardcode gas consumed. + let (mut recipient_fa_store, mut recipient_fa_store_object, recipient_fa_store_existed) = + match DbAccessUtil::get_resource_group(&recipient_fa_store_object_key, state_view)? { + Some(mut recipient_fa_store_object) => { + let recipient_fa_store = bcs::from_bytes::( + &recipient_fa_store_object + .remove(fungible_store_rg_tag) + .unwrap(), + )?; + (recipient_fa_store, recipient_fa_store_object, true) + }, + None => { + let receipeint_fa_store = + FungibleStoreResource::new(AccountAddress::TEN, 0, false); + let receipeint_fa_store_object = BTreeMap::from([( + self.db_util.common.object_core.clone(), + bcs::to_bytes(&DbAccessUtil::new_object_core( + recipient_store_address, + recipient_address, + ))?, + )]); + (receipeint_fa_store, receipeint_fa_store_object, false) + }, + }; - let mut output = IncrementalOutput::new(); + recipient_fa_store.balance += transfer_amount; - merge_output!( - output, - self.increment_sequence_number(sender_address, state_view)? - ); - merge_output!( - output, - self.withdraw_fa_apt_from_signer(sender_address, transfer_amount, state_view, gas)? + recipient_fa_store_object.insert( + fungible_store_rg_tag.clone(), + bcs::to_bytes(&recipient_fa_store)?, ); - merge_output!( - output, - self.deposit_fa_apt(recipient_address, transfer_amount, state_view,)? - ); + let write_set = vec![( + recipient_fa_store_object_key, + if recipient_fa_store_existed { + WriteOp::legacy_modification(bcs::to_bytes(&recipient_fa_store_object)?.into()) + } else { + WriteOp::legacy_creation(bcs::to_bytes(&recipient_fa_store_object)?.into()) + }, + )]; - output.into_success_output(gas) + let mut events = Vec::new(); + if transfer_amount != 0 { + events.push( + DepositFAEvent { + store: recipient_store_address, + amount: transfer_amount, + } + .create_event_v2(), + ) + } + + Ok(( + IncrementalOutput { write_set, events }, + recipient_fa_store_existed, + )) } - fn handle_account_creation_and_transfer( + fn deposit_coin_apt( &self, - sender_address: AccountAddress, recipient_address: AccountAddress, transfer_amount: u64, - fail_on_existing: bool, - fail_on_missing: bool, - state_view: &(impl StateView + Sync), - new_accounts_default_to_fa: bool, - ) -> Result { - let _timer = TIMER.with_label_values(&["account_creation"]).start_timer(); - - let gas = 500; // hardcode gas consumed. - - let mut output = IncrementalOutput::new(); - merge_output!( - output, - self.increment_sequence_number(sender_address, state_view)? - ); - merge_output!( - output, - self.withdraw_coin_apt_from_signer(sender_address, transfer_amount, state_view, gas)? - ); - merge_output!( - output, - self.deposit_coin_apt( - recipient_address, - transfer_amount, - fail_on_existing, - fail_on_missing, - state_view, - new_accounts_default_to_fa, - )? - ); - - output.into_success_output(gas) - } - - fn handle_batch_account_creation_and_transfer( - &self, - sender_address: AccountAddress, - recipient_addresses: Vec, - transfer_amounts: Vec, - fail_on_existing: bool, - fail_on_missing: bool, state_view: &(impl StateView + Sync), - new_accounts_default_to_fa: bool, - ) -> Result { - let gas = 5000; // hardcode gas consumed. + ) -> Result<(IncrementalOutput, bool)> { + let recipient_coin_store_key = self.db_util.new_state_key_aptos_coin(&recipient_address); - let mut deltas = - compute_deltas_for_batch(recipient_addresses, transfer_amounts, sender_address); + let mut events = Vec::new(); + let (mut recipient_coin_store, recipient_coin_store_existed) = + match DbAccessUtil::get_apt_coin_store(&recipient_coin_store_key, state_view)? { + Some(recipient_coin_store) => (recipient_coin_store, true), + None => { + events.push( + CoinRegister { + account: AccountAddress::ONE, + type_info: TypeInfoResource::new::()?, + } + .create_event_v2(), + ); + ( + DbAccessUtil::new_apt_coin_store(0, recipient_address), + false, + ) + }, + }; - let amount_to_sender = -deltas.remove(&sender_address).unwrap_or(0); - assert!(amount_to_sender >= 0); + recipient_coin_store.set_coin(recipient_coin_store.coin() + transfer_amount); - let mut output = IncrementalOutput::new(); - merge_output!( - output, - self.increment_sequence_number(sender_address, state_view)? - ); - merge_output!( - output, - self.withdraw_coin_apt_from_signer( - sender_address, - amount_to_sender as u64, - state_view, - gas - )? - ); - - for (recipient_address, transfer_amount) in deltas.into_iter() { - merge_output!( - output, - self.deposit_coin_apt( - recipient_address, - transfer_amount as u64, - fail_on_existing, - fail_on_missing, - state_view, - new_accounts_default_to_fa, - )? + // first need to create events, to update the handle, and then serialize sender_coin_store + if transfer_amount != 0 { + events.push( + CoinDeposit { + coin_type: self.db_util.common.apt_coin_type_name.clone(), + account: recipient_address, + amount: transfer_amount, + } + .create_event_v2(), ); } - output.into_success_output(gas) + let write_set = vec![( + recipient_coin_store_key, + if recipient_coin_store_existed { + WriteOp::legacy_modification(bcs::to_bytes(&recipient_coin_store)?.into()) + } else { + WriteOp::legacy_creation(bcs::to_bytes(&recipient_coin_store)?.into()) + }, + )]; + + Ok(( + IncrementalOutput { write_set, events }, + recipient_coin_store_existed, + )) } - fn handle_nop( + fn check_or_create_account( &self, - sender_address: AccountAddress, - fa_migration_complete: bool, + address: AccountAddress, + fail_on_account_existing: bool, + fail_on_account_missing: bool, state_view: &(impl StateView + Sync), - ) -> Result { - let _timer = TIMER.with_label_values(&["nop"]).start_timer(); - - let gas = 4; // hardcode gas consumed. - - let mut output = IncrementalOutput::new(); - - merge_output!( - output, - self.increment_sequence_number(sender_address, state_view)? - ); - if fa_migration_complete { - merge_output!( - output, - self.withdraw_fa_apt_from_signer(sender_address, 0, state_view, gas)? - ); - } else { - merge_output!( - output, - self.withdraw_coin_apt_from_signer(sender_address, 0, state_view, gas)? - ); + ) -> Result> { + let account_key = self.db_util.new_state_key_account(&address); + match DbAccessUtil::get_account(&account_key, state_view)? { + Some(_) => { + if fail_on_account_existing { + return Ok(Err(TransactionStatus::Keep(ExecutionStatus::MoveAbort { + location: AbortLocation::Module(ModuleId::new( + AccountAddress::ONE, + ident_str!("account").into(), + )), + code: 7, + info: None, + }))); + } + }, + None => { + if fail_on_account_missing { + return Ok(Err(TransactionStatus::Keep(ExecutionStatus::MoveAbort { + location: AbortLocation::Module(ModuleId::new( + AccountAddress::ONE, + ident_str!("account").into(), + )), + code: 7, + info: None, + }))); + } else { + return Ok(Ok(Self::create_non_existing_account(address, account_key)?)); + } + }, } - output.into_success_output(gas) + + Ok(Ok(IncrementalOutput::new())) } } @@ -739,6 +778,8 @@ fn compute_deltas_for_batch( enum CachedResource { Account(AccountResource), FungibleStore(FungibleStoreResource), + #[allow(dead_code)] + AptCoinStore(CoinStoreResource), } pub struct NativeValueCacheRawTransactionExecutor { @@ -790,8 +831,8 @@ impl RawTransactionExecutor for NativeValueCacheRawTransactionExecutor { sequence_number, recipient, amount, - fail_on_account_existing, - fail_on_account_missing, + fail_on_recipient_account_existing: fail_on_account_existing, + fail_on_recipient_account_missing: fail_on_account_missing, } => { self.update_sequence_number(sender, state_view, sequence_number); self.update_fa_balance(sender, state_view, 0, gas + amount, true); @@ -846,7 +887,9 @@ impl NativeValueCacheRawTransactionExecutor { .value_mut() { CachedResource::Account(account) => account.sequence_number = sequence_number, - CachedResource::FungibleStore(_) => panic!("wrong type"), + CachedResource::FungibleStore(_) | CachedResource::AptCoinStore(_) => { + panic!("wrong type") + }, }; } @@ -913,7 +956,7 @@ impl NativeValueCacheRawTransactionExecutor { fungible_store_resource.balance += increment; fungible_store_resource.balance -= decrement; }, - CachedResource::Account(_) => panic!("wrong type"), + CachedResource::Account(_) | CachedResource::AptCoinStore(_) => panic!("wrong type"), }; exists } diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 265ba75cbab1e2..13b3e33c6231f4 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -103,8 +103,10 @@ class Flow(Flag): if os.environ.get("DISABLE_FA_APT"): FEATURE_FLAGS = "" + FA_MIGRATION_COMPLETE = False else: FEATURE_FLAGS = "--enable-feature NEW_ACCOUNTS_DEFAULT_TO_FA_APT_STORE --enable-feature OPERATIONS_DEFAULT_TO_FA_APT_STORE" + FA_MIGRATION_COMPLETE = True if os.environ.get("ENABLE_PRUNER"): DB_PRUNER_FLAGS = "--enable-state-pruner --enable-ledger-pruner --enable-epoch-snapshot-pruner --ledger-pruning-batch-size 10000 --state-prune-window 3000000 --epoch-snapshot-prune-window 3000000 --ledger-prune-window 3000000" @@ -303,87 +305,25 @@ class RunGroupConfig: RunGroupConfig(expected_tps=6800, key=RunGroupKey("token-v2-ambassador-mint"), included_in=Flow.MAINNET_LARGE_DB), # RunGroupConfig(expected_tps=17000 if NUM_ACCOUNTS < 5000000 else 28000, key=RunGroupKey("coin_transfer_connected_components", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--connected-tx-grps 5000", transaction_type_override=""), included_in=Flow.MAINNET | Flow.MAINNET_LARGE_DB, waived=True), # RunGroupConfig(expected_tps=27000 if NUM_ACCOUNTS < 5000000 else 23000, key=RunGroupKey("coin_transfer_hotspot", executor_type="sharded"), key_extra=RunGroupKeyExtra(sharding_traffic_flags="--hotspot-probability 0.8", transaction_type_override=""), included_in=Flow.MAINNET | Flow.MAINNET_LARGE_DB, waived=True), - - RunGroupConfig(expected_tps=10000, key=RunGroupKey("apt_fa_transfer_sequential_by_stages"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - sig_verify_num_threads_override=1, - execution_num_threads_override=1, - split_stages_override=True, - single_block_dst_working_set=True, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=10000, key=RunGroupKey("apt_fa_transfer_sequential_by_stages", executor_type="NativeVM"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - sig_verify_num_threads_override=1, - execution_num_threads_override=1, - split_stages_override=True, - single_block_dst_working_set=True, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=10000, key=RunGroupKey("apt_fa_transfer_sequential_by_stages", executor_type="AptosVMSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - sig_verify_num_threads_override=1, - execution_num_threads_override=1, - split_stages_override=True, - single_block_dst_working_set=True, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=10000, key=RunGroupKey("apt_fa_transfer_sequential_by_stages", executor_type="NativeSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - sig_verify_num_threads_override=1, - execution_num_threads_override=1, - split_stages_override=True, - single_block_dst_working_set=True, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=10000, key=RunGroupKey("apt_fa_transfer_sequential_by_stages", executor_type="NativeNoStorageSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - sig_verify_num_threads_override=1, - execution_num_threads_override=1, - split_stages_override=True, - single_block_dst_working_set=True, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=10000, key=RunGroupKey("apt_fa_transfer_sequential_by_stages", executor_type="NativeValueCacheSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - sig_verify_num_threads_override=1, - execution_num_threads_override=1, - split_stages_override=True, - single_block_dst_working_set=True, - ), included_in=Flow.EXECUTORS), - - RunGroupConfig(expected_tps=30000, key=RunGroupKey("apt_fa_transfer_by_stages"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - split_stages_override=True, - single_block_dst_working_set=True, - sig_verify_num_threads_override=NUMBER_OF_EXECUTION_THREADS, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=30000, key=RunGroupKey("apt_fa_transfer_by_stages", executor_type="NativeVM"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - split_stages_override=True, - single_block_dst_working_set=True, - sig_verify_num_threads_override=NUMBER_OF_EXECUTION_THREADS, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=30000, key=RunGroupKey("apt_fa_transfer_by_stages", executor_type="AptosVMSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - split_stages_override=True, - single_block_dst_working_set=True, - sig_verify_num_threads_override=NUMBER_OF_EXECUTION_THREADS, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=30000, key=RunGroupKey("apt_fa_transfer_by_stages", executor_type="NativeSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - split_stages_override=True, - single_block_dst_working_set=True, - sig_verify_num_threads_override=NUMBER_OF_EXECUTION_THREADS, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=30000, key=RunGroupKey("apt_fa_transfer_by_stages", executor_type="NativeNoStorageSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - split_stages_override=True, - single_block_dst_working_set=True, - sig_verify_num_threads_override=NUMBER_OF_EXECUTION_THREADS, - ), included_in=Flow.EXECUTORS), - RunGroupConfig(expected_tps=30000, key=RunGroupKey("apt_fa_transfer_by_stages", executor_type="NativeValueCacheSpeculative"), key_extra=RunGroupKeyExtra( - transaction_type_override="apt-fa-transfer", - split_stages_override=True, - single_block_dst_working_set=True, - sig_verify_num_threads_override=NUMBER_OF_EXECUTION_THREADS, - ), included_in=Flow.EXECUTORS), +] + [ + RunGroupConfig( + expected_tps=10000 if sequential else 30000, + key=RunGroupKey("{}_{}_by_stages".format(transaction_type, "sequential" if sequential else "parallel")), + key_extra=RunGroupKeyExtra( + transaction_type_override=transaction_type, + sig_verify_num_threads_override=1 if sequential else NUMBER_OF_EXECUTION_THREADS, + execution_num_threads_override=1 if sequential else None, + split_stages_override=True, + single_block_dst_working_set=True, + ), + included_in=Flow.EXECUTORS + ) + for (transaction_type, requires_fa) in [("no-op", False), ("coin-transfer", False), ("no-op", True), ("apt-fa-transfer", True)] + if FA_MIGRATION_COMPLETE == requires_fa + for sequential in [True, False] + for executor_type in ["VM", "NativeVM", "AptosVMSpeculative", "NativeSpeculative", "NativeValueCacheSpeculative", "NativeNoStorageSpeculative"] ] + # fmt: on # Run the single node with performance optimizations enabled diff --git a/types/src/account_config/events/coin.rs b/types/src/account_config/events/coin.rs new file mode 100644 index 00000000000000..1a0cf5844e7e53 --- /dev/null +++ b/types/src/account_config/events/coin.rs @@ -0,0 +1,113 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{ + account_config::TypeInfoResource, + move_utils::{move_event_v1::MoveEventV1Type, move_event_v2::MoveEventV2Type}, +}; +use anyhow::Result; +use move_core_types::{ + account_address::AccountAddress, ident_str, identifier::IdentStr, move_resource::MoveStructType, +}; +use serde::{Deserialize, Serialize}; + +/// Struct that represents a SentPaymentEvent. +#[derive(Debug, Serialize, Deserialize)] +pub struct WithdrawEvent { + pub amount: u64, +} + +impl WithdrawEvent { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + /// Get the amount sent or received + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for WithdrawEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("WithdrawEvent"); +} + +impl MoveEventV1Type for WithdrawEvent {} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CoinWithdraw { + pub coin_type: String, + pub account: AccountAddress, + pub amount: u64, +} + +impl CoinWithdraw { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } +} + +impl MoveStructType for CoinWithdraw { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinWithdraw"); +} + +impl MoveEventV2Type for CoinWithdraw {} + +/// Struct that represents a DepositPaymentEvent. +#[derive(Debug, Serialize, Deserialize)] +pub struct DepositEvent { + pub amount: u64, +} + +impl DepositEvent { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } + + /// Get the amount sent or received + pub fn amount(&self) -> u64 { + self.amount + } +} + +impl MoveStructType for DepositEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("DepositEvent"); +} + +impl MoveEventV1Type for DepositEvent {} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CoinDeposit { + pub coin_type: String, + pub account: AccountAddress, + pub amount: u64, +} + +impl CoinDeposit { + pub fn try_from_bytes(bytes: &[u8]) -> Result { + bcs::from_bytes(bytes).map_err(Into::into) + } +} + +impl MoveStructType for CoinDeposit { + const MODULE_NAME: &'static IdentStr = ident_str!("coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinDeposit"); +} + +impl MoveEventV2Type for CoinDeposit {} + +#[derive(Debug, Serialize, Deserialize)] +pub struct CoinRegister { + pub account: AccountAddress, + pub type_info: TypeInfoResource, +} + +impl MoveStructType for CoinRegister { + const MODULE_NAME: &'static IdentStr = ident_str!("account"); + const STRUCT_NAME: &'static IdentStr = ident_str!("CoinRegister"); +} + +impl MoveEventV2Type for CoinRegister {} diff --git a/types/src/account_config/events/deposit.rs b/types/src/account_config/events/deposit.rs deleted file mode 100644 index 2c59bc4fc336f1..00000000000000 --- a/types/src/account_config/events/deposit.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::Result; -use move_core_types::{ident_str, identifier::IdentStr, move_resource::MoveStructType}; -use serde::{Deserialize, Serialize}; - -/// Struct that represents a DepositPaymentEvent. -#[derive(Debug, Serialize, Deserialize)] -pub struct DepositEvent { - amount: u64, -} - -impl DepositEvent { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } - - /// Get the amount sent or received - pub fn amount(&self) -> u64 { - self.amount - } -} - -impl MoveStructType for DepositEvent { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("DepositEvent"); -} diff --git a/types/src/account_config/events/fungible_asset.rs b/types/src/account_config/events/fungible_asset.rs new file mode 100644 index 00000000000000..ed003be6d64829 --- /dev/null +++ b/types/src/account_config/events/fungible_asset.rs @@ -0,0 +1,36 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::move_utils::move_event_v2::MoveEventV2Type; +use move_core_types::{ + account_address::AccountAddress, ident_str, identifier::IdentStr, move_resource::MoveStructType, +}; +use serde::{Deserialize, Serialize}; + +/// Struct that represents a Withdraw event. +#[derive(Debug, Serialize, Deserialize)] +pub struct WithdrawFAEvent { + pub store: AccountAddress, + pub amount: u64, +} + +impl MoveEventV2Type for WithdrawFAEvent {} + +impl MoveStructType for WithdrawFAEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("fungible_asset"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Withdraw"); +} + +/// Struct that represents a Deposit event. +#[derive(Debug, Serialize, Deserialize)] +pub struct DepositFAEvent { + pub store: AccountAddress, + pub amount: u64, +} + +impl MoveEventV2Type for DepositFAEvent {} + +impl MoveStructType for DepositFAEvent { + const MODULE_NAME: &'static IdentStr = ident_str!("fungible_asset"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Deposit"); +} diff --git a/types/src/account_config/events/mod.rs b/types/src/account_config/events/mod.rs index 6a224aaae5904f..f2207ec1bbad2f 100644 --- a/types/src/account_config/events/mod.rs +++ b/types/src/account_config/events/mod.rs @@ -2,12 +2,12 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 -pub mod deposit; +pub mod coin; +pub mod fungible_asset; pub mod new_block; pub mod new_epoch; -pub mod withdraw; -pub use deposit::*; +pub use coin::*; +pub use fungible_asset::*; pub use new_block::*; pub use new_epoch::*; -pub use withdraw::*; diff --git a/types/src/account_config/events/withdraw.rs b/types/src/account_config/events/withdraw.rs deleted file mode 100644 index da27bb19e7c028..00000000000000 --- a/types/src/account_config/events/withdraw.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use anyhow::Result; -use move_core_types::{ - account_address::AccountAddress, ident_str, identifier::IdentStr, move_resource::MoveStructType, -}; -use serde::{Deserialize, Serialize}; - -/// Struct that represents a SentPaymentEvent. -#[derive(Debug, Serialize, Deserialize)] -pub struct WithdrawEvent { - amount: u64, -} - -impl WithdrawEvent { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } - - /// Get the amount sent or received - pub fn amount(&self) -> u64 { - self.amount - } -} - -impl MoveStructType for WithdrawEvent { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("WithdrawEvent"); -} - -#[derive(Debug, Serialize, Deserialize)] -pub struct CoinWithdraw { - pub coin_type: String, - pub account: AccountAddress, - pub amount: u64, -} - -impl CoinWithdraw { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - bcs::from_bytes(bytes).map_err(Into::into) - } -} - -impl MoveStructType for CoinWithdraw { - const MODULE_NAME: &'static IdentStr = ident_str!("coin"); - const STRUCT_NAME: &'static IdentStr = ident_str!("CoinWithdraw"); -} diff --git a/types/src/account_config/resources/coin_info.rs b/types/src/account_config/resources/coin_info.rs index 4ab8f09f48694b..394ef0eaf3996f 100644 --- a/types/src/account_config/resources/coin_info.rs +++ b/types/src/account_config/resources/coin_info.rs @@ -76,18 +76,20 @@ impl CoinInfoResource { } } - /// Returns a writeset corresponding to the creation of CoinInfo in Move. - /// This can be passed to data store for testing total supply. - pub fn to_writeset(&self, supply: u128) -> anyhow::Result { - let value_state_key = self - .supply + pub fn supply_aggregator_state_key(&self) -> StateKey { + self.supply .as_ref() .unwrap() .aggregator .as_ref() .unwrap() - .state_key(); + .state_key() + } + /// Returns a writeset corresponding to the creation of CoinInfo in Move. + /// This can be passed to data store for testing total supply. + pub fn to_writeset(&self, supply: u128) -> anyhow::Result { + let value_state_key = self.supply_aggregator_state_key(); // We store CoinInfo and aggregatable value separately. let write_set = vec![ ( diff --git a/types/src/account_config/resources/coin_store.rs b/types/src/account_config/resources/coin_store.rs index d319bd79e79fc5..aeb81816f0b483 100644 --- a/types/src/account_config/resources/coin_store.rs +++ b/types/src/account_config/resources/coin_store.rs @@ -85,9 +85,17 @@ impl CoinStoreResource { &self.deposit_events } + pub fn deposit_events_mut(&mut self) -> &mut EventHandle { + &mut self.deposit_events + } + pub fn withdraw_events(&self) -> &EventHandle { &self.withdraw_events } + + pub fn withdraw_events_mut(&mut self) -> &mut EventHandle { + &mut self.withdraw_events + } } impl MoveStructType for CoinStoreResource { diff --git a/types/src/account_config/resources/fungible_asset_metadata.rs b/types/src/account_config/resources/fungible_asset_metadata.rs index e28a929a8ec525..8ec9c90ff2557d 100644 --- a/types/src/account_config/resources/fungible_asset_metadata.rs +++ b/types/src/account_config/resources/fungible_asset_metadata.rs @@ -10,13 +10,13 @@ use move_core_types::{ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] -pub struct ConcurrentSupply { +pub struct ConcurrentSupplyResource { pub current: AggregatorResource, } -impl MoveStructType for ConcurrentSupply { +impl MoveStructType for ConcurrentSupplyResource { const MODULE_NAME: &'static IdentStr = ident_str!("fungible_asset"); const STRUCT_NAME: &'static IdentStr = ident_str!("ConcurrentSupply"); } -impl MoveResource for ConcurrentSupply {} +impl MoveResource for ConcurrentSupplyResource {} diff --git a/types/src/account_config/resources/fungible_store.rs b/types/src/account_config/resources/fungible_store.rs index c0555e8fce4848..e8066ca712c00f 100644 --- a/types/src/account_config/resources/fungible_store.rs +++ b/types/src/account_config/resources/fungible_store.rs @@ -2,9 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use super::aggregator::AggregatorResource; -use crate::{ - account_address::create_derived_object_address, move_utils::move_event_v2::MoveEventV2Type, -}; +use crate::account_address::create_derived_object_address; use move_core_types::{ account_address::AccountAddress, ident_str, @@ -96,31 +94,3 @@ impl MoveStructType for MigrationFlag { } impl MoveResource for MigrationFlag {} - -/// Struct that represents a Withdraw event. -#[derive(Debug, Serialize, Deserialize)] -pub struct WithdrawFAEvent { - pub store: AccountAddress, - pub amount: u64, -} - -impl MoveEventV2Type for WithdrawFAEvent {} - -impl MoveStructType for WithdrawFAEvent { - const MODULE_NAME: &'static IdentStr = ident_str!("fungble_asset"); - const STRUCT_NAME: &'static IdentStr = ident_str!("Withdraw"); -} - -/// Struct that represents a Deposit event. -#[derive(Debug, Serialize, Deserialize)] -pub struct DepositFAEvent { - pub store: AccountAddress, - pub amount: u64, -} - -impl MoveEventV2Type for DepositFAEvent {} - -impl MoveStructType for DepositFAEvent { - const MODULE_NAME: &'static IdentStr = ident_str!("fungble_asset"); - const STRUCT_NAME: &'static IdentStr = ident_str!("Deposit"); -} diff --git a/types/src/account_config/resources/mod.rs b/types/src/account_config/resources/mod.rs index 82bee857de31a8..cbe90b75996390 100644 --- a/types/src/account_config/resources/mod.rs +++ b/types/src/account_config/resources/mod.rs @@ -11,6 +11,7 @@ pub mod core_account; pub mod fungible_asset_metadata; pub mod fungible_store; pub mod object; +pub mod type_info; pub use chain_id::*; pub use challenge::*; @@ -20,3 +21,4 @@ pub use core_account::*; pub use fungible_asset_metadata::*; pub use fungible_store::*; pub use object::*; +pub use type_info::*; diff --git a/types/src/account_config/resources/type_info.rs b/types/src/account_config/resources/type_info.rs new file mode 100644 index 00000000000000..a026f0f4227743 --- /dev/null +++ b/types/src/account_config/resources/type_info.rs @@ -0,0 +1,52 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use itertools::Itertools; +use move_core_types::{ + account_address::AccountAddress, + ident_str, + identifier::IdentStr, + move_resource::{MoveResource, MoveStructType}, +}; +use serde::{Deserialize, Serialize}; + +/// A Rust representation of TypeInfo. +#[derive(Debug, Eq, PartialEq, Serialize, Deserialize)] +pub struct TypeInfoResource { + pub account_address: AccountAddress, + pub module_name: Vec, + pub struct_name: Vec, +} + +impl TypeInfoResource { + pub fn new() -> anyhow::Result { + let struct_tag = T::struct_tag(); + Ok(Self { + account_address: struct_tag.address, + module_name: bcs::to_bytes(&struct_tag.module.to_string())?, + struct_name: bcs::to_bytes( + &if struct_tag.type_args.is_empty() { + struct_tag.name.to_string() + } else { + format!( + "{}<{}>", + struct_tag.name, + struct_tag + .type_args + .iter() + .map(|v| v.to_string()) + .join(", ") + ) + .to_string() + }, + )?, + }) + } +} + +impl MoveStructType for TypeInfoResource { + const MODULE_NAME: &'static IdentStr = ident_str!("type_info"); + const STRUCT_NAME: &'static IdentStr = ident_str!("TypeInfo"); +} + +impl MoveResource for TypeInfoResource {} diff --git a/types/src/event.rs b/types/src/event.rs index ae7956cbf4cd7b..a3a1bd137827d6 100644 --- a/types/src/event.rs +++ b/types/src/event.rs @@ -117,7 +117,6 @@ impl EventHandle { } } - #[cfg(any(test, feature = "fuzzing"))] pub fn count_mut(&mut self) -> &mut u64 { &mut self.count } diff --git a/types/src/lib.rs b/types/src/lib.rs index 95d59f1232060c..9081b6c0f0a4d0 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -25,7 +25,6 @@ pub mod jwks; pub mod ledger_info; pub mod mempool_status; pub mod move_any; -pub mod move_event_v2; pub mod move_fixed_point; pub mod move_utils; pub mod network_address; diff --git a/types/src/move_event_v2.rs b/types/src/move_event_v2.rs deleted file mode 100644 index bd6b2c2cd6de22..00000000000000 --- a/types/src/move_event_v2.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright © Aptos Foundation -// SPDX-License-Identifier: Apache-2.0 - -use crate::contract_event::ContractEvent; -use move_core_types::{language_storage::TypeTag, move_resource::MoveStructType}; -use serde::Serialize; - -pub trait MoveEventV2: MoveStructType + Serialize { - fn create_event_v2(&self) -> ContractEvent { - ContractEvent::new_v2( - TypeTag::Struct(Box::new(Self::struct_tag())), - bcs::to_bytes(self).unwrap(), - ) - } -} diff --git a/types/src/move_utils/mod.rs b/types/src/move_utils/mod.rs index 5160513ecc8e70..762ea7d76535bb 100644 --- a/types/src/move_utils/mod.rs +++ b/types/src/move_utils/mod.rs @@ -40,4 +40,5 @@ impl FromStr for MemberId { } pub mod as_move_value; +pub mod move_event_v1; pub mod move_event_v2; diff --git a/types/src/move_utils/move_event_v1.rs b/types/src/move_utils/move_event_v1.rs new file mode 100644 index 00000000000000..e438f805d997b6 --- /dev/null +++ b/types/src/move_utils/move_event_v1.rs @@ -0,0 +1,19 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{contract_event::ContractEvent, event::EventHandle}; +use move_core_types::{language_storage::TypeTag, move_resource::MoveStructType}; +use serde::Serialize; + +pub trait MoveEventV1Type: MoveStructType + Serialize { + fn create_event_v1(&self, handle: &mut EventHandle) -> ContractEvent { + let sequence_number = handle.count(); + *handle.count_mut() = sequence_number + 1; + ContractEvent::new_v1( + *handle.key(), + sequence_number, + TypeTag::Struct(Box::new(Self::struct_tag())), + bcs::to_bytes(self).unwrap(), + ) + } +} diff --git a/types/src/utility_coin.rs b/types/src/utility_coin.rs index 0074ac9fb74784..625f63e823109b 100644 --- a/types/src/utility_coin.rs +++ b/types/src/utility_coin.rs @@ -4,9 +4,12 @@ use crate::account_address::AccountAddress; use move_core_types::{ ident_str, + identifier::IdentStr, language_storage::{StructTag, TypeTag}, + move_resource::MoveStructType, }; use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; pub trait CoinType { fn type_tag() -> TypeTag; @@ -23,6 +26,7 @@ static APTOS_COIN_TYPE: Lazy = Lazy::new(|| { })) }); +#[derive(Debug, Serialize, Deserialize)] pub struct AptosCoinType; impl CoinType for AptosCoinType { @@ -34,3 +38,8 @@ impl CoinType for AptosCoinType { AccountAddress::ONE } } + +impl MoveStructType for AptosCoinType { + const MODULE_NAME: &'static IdentStr = ident_str!("aptos_coin"); + const STRUCT_NAME: &'static IdentStr = ident_str!("AptosCoin"); +}