From 793563fc9a022994fbc1d1c073e7090fc8091fe1 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Sun, 4 Feb 2024 10:34:28 -0800 Subject: [PATCH 001/328] jwk #1: validator txn for publishing updates (#11853) * jwk types update * update * update * jwk txn and execution * update * fix dummy * update * update * update * update * update * update * remove dummy txns * check voting power than verify signature * fix warnings * update * update QuorumCertifiedUpdate struct --- Cargo.lock | 1 + aptos-move/aptos-vm/Cargo.toml | 5 +- .../aptos-vm/src/system_module_names.rs | 9 ++ .../aptos-vm/src/validator_txns/dummy.rs | 38 ----- aptos-move/aptos-vm/src/validator_txns/jwk.rs | 149 ++++++++++++++++++ aptos-move/aptos-vm/src/validator_txns/mod.rs | 6 +- .../framework/aptos-framework/doc/jwks.md | 45 ++++++ .../aptos-framework/sources/jwks.move | 6 + .../framework/move-stdlib/doc/features.md | 60 +++++++ .../move-stdlib/sources/configs/features.move | 10 ++ aptos-move/vm-genesis/src/lib.rs | 1 + consensus/src/payload_client/mixed.rs | 29 ++-- consensus/src/round_manager_test.rs | 10 +- consensus/src/state_computer_tests.rs | 8 +- .../src/test_utils/mock_payload_manager.rs | 2 +- .../validator-transaction-pool/src/tests.rs | 99 ++++++++---- testsuite/generate-format/src/api.rs | 8 + testsuite/generate-format/src/aptos.rs | 8 + .../generate-format/tests/staged/api.yaml | 48 ++++-- .../generate-format/tests/staged/aptos.yaml | 48 ++++-- .../tests/staged/consensus.yaml | 35 ++-- types/src/dkg/mod.rs | 11 +- types/src/jwks/mod.rs | 23 +-- types/src/proptest_types.rs | 15 +- types/src/validator_txn.rs | 47 +++--- 25 files changed, 549 insertions(+), 172 deletions(-) delete mode 100644 aptos-move/aptos-vm/src/validator_txns/dummy.rs create mode 100644 aptos-move/aptos-vm/src/validator_txns/jwk.rs diff --git a/Cargo.lock b/Cargo.lock index 213d98425012c..a1db8fda31965 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4256,6 +4256,7 @@ version = "0.1.0" dependencies = [ "anyhow", "aptos-aggregator", + "aptos-bitvec", "aptos-block-executor", "aptos-block-partitioner", "aptos-crypto", diff --git a/aptos-move/aptos-vm/Cargo.toml b/aptos-move/aptos-vm/Cargo.toml index 812a312148e4a..79ff63345615d 100644 --- a/aptos-move/aptos-vm/Cargo.toml +++ b/aptos-move/aptos-vm/Cargo.toml @@ -15,6 +15,7 @@ rust-version = { workspace = true } [dependencies] anyhow = { workspace = true } aptos-aggregator = { workspace = true } +aptos-bitvec = { workspace = true } aptos-block-executor = { workspace = true } aptos-block-partitioner = { workspace = true } aptos-crypto = { workspace = true } @@ -65,13 +66,13 @@ tracing = { workspace = true } [dev-dependencies] aptos-aggregator = { workspace = true, features = ["testing"] } aptos-language-e2e-tests = { workspace = true } -aptos-types = { workspace = true } +aptos-types = { workspace = true, features = ["fuzzing"] } claims = { workspace = true } proptest = { workspace = true } rand_core = { workspace = true } [features] default = [] -fuzzing = ["move-core-types/fuzzing", "move-binary-format/fuzzing", "move-vm-types/fuzzing", "aptos-framework/fuzzing"] +fuzzing = ["move-core-types/fuzzing", "move-binary-format/fuzzing", "move-vm-types/fuzzing", "aptos-framework/fuzzing", "aptos-types/fuzzing"] failpoints = ["fail/failpoints", "move-vm-runtime/failpoints"] testing = ["move-unit-test", "aptos-framework/testing"] diff --git a/aptos-move/aptos-vm/src/system_module_names.rs b/aptos-move/aptos-vm/src/system_module_names.rs index 2a85cde828572..e6945a6114c20 100644 --- a/aptos-move/aptos-vm/src/system_module_names.rs +++ b/aptos-move/aptos-vm/src/system_module_names.rs @@ -39,6 +39,15 @@ pub static RECONFIGURATION_WITH_DKG_MODULE: Lazy = Lazy::new(|| { pub const FINISH_WITH_DKG_RESULT: &IdentStr = ident_str!("finish_with_dkg_result"); +pub static JWKS_MODULE: Lazy = Lazy::new(|| { + ModuleId::new( + account_config::CORE_CODE_ADDRESS, + ident_str!("jwks").to_owned(), + ) +}); + +pub const UPSERT_INTO_OBSERVED_JWKS: &IdentStr = ident_str!("upsert_into_observed_jwks"); + pub static MULTISIG_ACCOUNT_MODULE: Lazy = Lazy::new(|| { ModuleId::new( account_config::CORE_CODE_ADDRESS, diff --git a/aptos-move/aptos-vm/src/validator_txns/dummy.rs b/aptos-move/aptos-vm/src/validator_txns/dummy.rs deleted file mode 100644 index 3bc40caa15887..0000000000000 --- a/aptos-move/aptos-vm/src/validator_txns/dummy.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright © Aptos Foundation - -use crate::{ - move_vm_ext::{AptosMoveResolver, SessionId}, - AptosVM, -}; -use aptos_types::{ - transaction::{ExecutionStatus, TransactionStatus}, - validator_txn::DummyValidatorTransaction, -}; -use aptos_vm_logging::log_schema::AdapterLogSchema; -use aptos_vm_types::output::VMOutput; -use move_core_types::vm_status::{AbortLocation, StatusCode, VMStatus}; - -impl AptosVM { - pub(crate) fn process_dummy_validator_txn( - &self, - _resolver: &impl AptosMoveResolver, - _log_context: &AdapterLogSchema, - _session_id: SessionId, - dummy_vtxn: DummyValidatorTransaction, - ) -> anyhow::Result<(VMStatus, VMOutput), VMStatus> { - let DummyValidatorTransaction { valid, .. } = dummy_vtxn; - if valid { - Ok(( - VMStatus::Executed, - VMOutput::empty_with_status(TransactionStatus::Keep(ExecutionStatus::Success)), - )) - } else { - Ok(( - VMStatus::MoveAbort(AbortLocation::Script, 0), - VMOutput::empty_with_status(TransactionStatus::Discard( - StatusCode::INVALID_SIGNATURE, - )), - )) - } - } -} diff --git a/aptos-move/aptos-vm/src/validator_txns/jwk.rs b/aptos-move/aptos-vm/src/validator_txns/jwk.rs new file mode 100644 index 0000000000000..f302e3ee7e2fa --- /dev/null +++ b/aptos-move/aptos-vm/src/validator_txns/jwk.rs @@ -0,0 +1,149 @@ +// Copyright © Aptos Foundation + +use crate::{ + aptos_vm::get_or_vm_startup_failure, + errors::expect_only_successful_execution, + move_vm_ext::{AptosMoveResolver, SessionId}, + system_module_names::{JWKS_MODULE, UPSERT_INTO_OBSERVED_JWKS}, + validator_txns::jwk::{ + ExecutionFailure::{Expected, Unexpected}, + ExpectedFailure::{ + IncorrectVersion, MissingResourceObservedJWKs, MissingResourceValidatorSet, + MultiSigVerificationFailed, NotEnoughVotingPower, + }, + }, + AptosVM, +}; +use aptos_types::{ + fee_statement::FeeStatement, + jwks, + jwks::{Issuer, ObservedJWKs, ProviderJWKs, QuorumCertifiedUpdate}, + move_utils::as_move_value::AsMoveValue, + on_chain_config::{OnChainConfig, ValidatorSet}, + transaction::{ExecutionStatus, TransactionStatus}, + validator_verifier::ValidatorVerifier, +}; +use aptos_vm_logging::log_schema::AdapterLogSchema; +use aptos_vm_types::output::VMOutput; +use move_core_types::{ + account_address::AccountAddress, + value::{serialize_values, MoveValue}, + vm_status::{AbortLocation, StatusCode, VMStatus}, +}; +use move_vm_types::gas::UnmeteredGasMeter; +use std::collections::HashMap; + +enum ExpectedFailure { + // Move equivalent: `errors::invalid_argument(*)` + IncorrectVersion = 0x010103, + MultiSigVerificationFailed = 0x010104, + NotEnoughVotingPower = 0x010105, + + // Move equivalent: `errors::invalid_state(*)` + MissingResourceValidatorSet = 0x30101, + MissingResourceObservedJWKs = 0x30102, +} + +enum ExecutionFailure { + Expected(ExpectedFailure), + Unexpected(VMStatus), +} + +impl AptosVM { + pub(crate) fn process_jwk_update( + &self, + resolver: &impl AptosMoveResolver, + log_context: &AdapterLogSchema, + session_id: SessionId, + update: jwks::QuorumCertifiedUpdate, + ) -> Result<(VMStatus, VMOutput), VMStatus> { + match self.process_jwk_update_inner(resolver, log_context, session_id, update) { + Ok((vm_status, vm_output)) => Ok((vm_status, vm_output)), + Err(Expected(failure)) => { + // Pretend we are inside Move, and expected failures are like Move aborts. + Ok(( + VMStatus::MoveAbort(AbortLocation::Script, failure as u64), + VMOutput::empty_with_status(TransactionStatus::Discard(StatusCode::ABORTED)), + )) + }, + Err(Unexpected(vm_status)) => Err(vm_status), + } + } + + fn process_jwk_update_inner( + &self, + resolver: &impl AptosMoveResolver, + log_context: &AdapterLogSchema, + session_id: SessionId, + update: jwks::QuorumCertifiedUpdate, + ) -> Result<(VMStatus, VMOutput), ExecutionFailure> { + // Load resources. + let validator_set = ValidatorSet::fetch_config(resolver) + .ok_or_else(|| Expected(MissingResourceValidatorSet))?; + let observed_jwks = ObservedJWKs::fetch_config(resolver) + .ok_or_else(|| Expected(MissingResourceObservedJWKs))?; + + let mut jwks_by_issuer: HashMap = + observed_jwks.into_providers_jwks().into(); + let issuer = update.update.issuer.clone(); + let on_chain = jwks_by_issuer + .entry(issuer.clone()) + .or_insert_with(|| ProviderJWKs::new(issuer)); + let verifier = ValidatorVerifier::from(&validator_set); + + let QuorumCertifiedUpdate { + update: observed, + multi_sig, + } = update; + + // Check version. + if on_chain.version + 1 != observed.version { + return Err(Expected(IncorrectVersion)); + } + + let authors = multi_sig.get_signers_addresses(&verifier.get_ordered_account_addresses()); + + // Check voting power. + verifier + .check_voting_power(authors.iter(), true) + .map_err(|_| Expected(NotEnoughVotingPower))?; + + // Verify multi-sig. + verifier + .verify_multi_signatures(&observed, &multi_sig) + .map_err(|_| Expected(MultiSigVerificationFailed))?; + + // All verification passed. Apply the `observed`. + let mut gas_meter = UnmeteredGasMeter; + let mut session = self.new_session(resolver, session_id); + let args = vec![ + MoveValue::Signer(AccountAddress::ONE), + vec![observed].as_move_value(), + ]; + + session + .execute_function_bypass_visibility( + &JWKS_MODULE, + UPSERT_INTO_OBSERVED_JWKS, + vec![], + serialize_values(&args), + &mut gas_meter, + ) + .map_err(|e| { + expect_only_successful_execution(e, UPSERT_INTO_OBSERVED_JWKS.as_str(), log_context) + }) + .map_err(|r| Unexpected(r.unwrap_err()))?; + + let output = crate::aptos_vm::get_transaction_output( + session, + FeeStatement::zero(), + ExecutionStatus::Success, + &get_or_vm_startup_failure(&self.storage_gas_params, log_context) + .map_err(Unexpected)? + .change_set_configs, + ) + .map_err(Unexpected)?; + + Ok((VMStatus::Executed, output)) + } +} diff --git a/aptos-move/aptos-vm/src/validator_txns/mod.rs b/aptos-move/aptos-vm/src/validator_txns/mod.rs index 13de1fda5f9e2..567fc9081c2cd 100644 --- a/aptos-move/aptos-vm/src/validator_txns/mod.rs +++ b/aptos-move/aptos-vm/src/validator_txns/mod.rs @@ -21,12 +21,12 @@ impl AptosVM { ValidatorTransaction::DKGResult(dkg_node) => { self.process_dkg_result(resolver, log_context, session_id, dkg_node) }, - ValidatorTransaction::DummyTopic1(dummy) | ValidatorTransaction::DummyTopic2(dummy) => { - self.process_dummy_validator_txn(resolver, log_context, session_id, dummy) + ValidatorTransaction::ObservedJWKUpdate(jwk_update) => { + self.process_jwk_update(resolver, log_context, session_id, jwk_update) }, } } } mod dkg; -mod dummy; +mod jwk; diff --git a/aptos-move/framework/aptos-framework/doc/jwks.md b/aptos-move/framework/aptos-framework/doc/jwks.md index 778cf010deb63..2166154629728 100644 --- a/aptos-move/framework/aptos-framework/doc/jwks.md +++ b/aptos-move/framework/aptos-framework/doc/jwks.md @@ -620,6 +620,51 @@ This is what applications should consume. + + + + +
const ENATIVE_INCORRECT_VERSION: u64 = 259;
+
+ + + + + + + +
const ENATIVE_MISSING_RESOURCE_OBSERVED_JWKS: u64 = 258;
+
+ + + + + + + +
const ENATIVE_MISSING_RESOURCE_VALIDATOR_SET: u64 = 257;
+
+ + + + + + + +
const ENATIVE_MULTISIG_VERIFICATION_FAILED: u64 = 260;
+
+ + + + + + + +
const ENATIVE_NOT_ENOUGH_VOTING_POWER: u64 = 261;
+
+ + + diff --git a/aptos-move/framework/aptos-framework/sources/jwks.move b/aptos-move/framework/aptos-framework/sources/jwks.move index f405906207288..b87a71c85f4b5 100644 --- a/aptos-move/framework/aptos-framework/sources/jwks.move +++ b/aptos-move/framework/aptos-framework/sources/jwks.move @@ -29,6 +29,12 @@ module aptos_framework::jwks { const EISSUER_NOT_FOUND: u64 = 5; const EJWK_ID_NOT_FOUND: u64 = 6; + const ENATIVE_MISSING_RESOURCE_VALIDATOR_SET: u64 = 0x0101; + const ENATIVE_MISSING_RESOURCE_OBSERVED_JWKS: u64 = 0x0102; + const ENATIVE_INCORRECT_VERSION: u64 = 0x0103; + const ENATIVE_MULTISIG_VERIFICATION_FAILED: u64 = 0x0104; + const ENATIVE_NOT_ENOUGH_VOTING_POWER: u64 = 0x0105; + /// An OIDC provider. struct OIDCProvider has drop, store { /// The utf-8 encoded issuer string. E.g., b"https://www.facebook.com". diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index a56f3f691e13c..87f2ec8117eda 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -88,6 +88,8 @@ return true. - [Function `zkid_feature_enabled`](#0x1_features_zkid_feature_enabled) - [Function `get_zkid_zkless_feature`](#0x1_features_get_zkid_zkless_feature) - [Function `zkid_zkless_feature_enabled`](#0x1_features_zkid_zkless_feature_enabled) +- [Function `get_jwk_consensus_feature`](#0x1_features_get_jwk_consensus_feature) +- [Function `jwk_consensus_enabled`](#0x1_features_jwk_consensus_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `is_enabled`](#0x1_features_is_enabled) - [Function `set`](#0x1_features_set) @@ -369,6 +371,18 @@ Lifetime: transient + + +The JWK consensus feature. + +Lifetime: permanent + + +
const JWK_CONSENSUS: u64 = 49;
+
+ + + @@ -1918,6 +1932,52 @@ Lifetime: transient + + + + +## Function `get_jwk_consensus_feature` + + + +
public fun get_jwk_consensus_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_jwk_consensus_feature(): u64 { JWK_CONSENSUS }
+
+ + + +
+ + + +## Function `jwk_consensus_enabled` + + + +
public fun jwk_consensus_enabled(): bool
+
+ + + +
+Implementation + + +
public fun jwk_consensus_enabled(): bool acquires Features {
+    is_enabled(JWK_CONSENSUS)
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 8db36f003ee42..53189fc2408ed 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -355,6 +355,16 @@ module std::features { is_enabled(ZK_ID_ZKLESS_SIGNATURE) } + /// The JWK consensus feature. + /// + /// Lifetime: permanent + const JWK_CONSENSUS: u64 = 49; + + public fun get_jwk_consensus_feature(): u64 { JWK_CONSENSUS } + + public fun jwk_consensus_enabled(): bool acquires Features { + is_enabled(JWK_CONSENSUS) + } // ============================================================================================ // Feature Flag Implementation diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 17788f6d64cae..de1792bacbd59 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -446,6 +446,7 @@ pub fn default_features() -> Vec { // FeatureFlag::RECONFIGURE_WITH_DKG, //TODO: re-enable once randomness is ready. FeatureFlag::ZK_ID_SIGNATURES, FeatureFlag::ZK_ID_ZKLESS_SIGNATURE, + FeatureFlag::JWK_CONSENSUS, ] } diff --git a/consensus/src/payload_client/mixed.rs b/consensus/src/payload_client/mixed.rs index e2f920c2d8efb..a8b63521d1822 100644 --- a/consensus/src/payload_client/mixed.rs +++ b/consensus/src/payload_client/mixed.rs @@ -11,12 +11,14 @@ use crate::{ use aptos_consensus_types::common::{Payload, PayloadFilter}; use aptos_logger::debug; use aptos_types::{ + dkg::{DKGTranscript, DKGTranscriptMetadata}, on_chain_config::ValidatorTxnConfig, - validator_txn::{DummyValidatorTransaction, ValidatorTransaction}, + validator_txn::ValidatorTransaction, }; use aptos_validator_transaction_pool as vtxn_pool; use fail::fail_point; use futures::future::BoxFuture; +use move_core_types::account_address::AccountAddress; #[cfg(test)] use std::collections::HashSet; use std::{ @@ -49,13 +51,12 @@ impl MixedPayloadClient { /// When enabled in smoke tests, generate 2 random validator transactions, 1 valid, 1 invalid. fn extra_test_only_vtxns(&self) -> Vec { fail_point!("mixed_payload_client::extra_test_only_vtxns", |_| vec![ - ValidatorTransaction::DummyTopic1(DummyValidatorTransaction { - valid: true, - payload: b"P0".to_vec(), - }), - ValidatorTransaction::DummyTopic1(DummyValidatorTransaction { - valid: false, - payload: b"P1".to_vec(), + ValidatorTransaction::DKGResult(DKGTranscript { + metadata: DKGTranscriptMetadata { + epoch: 999, + author: AccountAddress::ZERO, + }, + transcript_bytes: vec![], }), ]); vec![] @@ -127,9 +128,9 @@ impl PayloadClient for MixedPayloadClient { #[tokio::test] async fn mixed_payload_client_should_prioritize_validator_txns() { let all_validator_txns = vec![ - ValidatorTransaction::dummy1(b"1".to_vec()), - ValidatorTransaction::dummy1(b"22".to_vec()), - ValidatorTransaction::dummy1(b"333".to_vec()), + ValidatorTransaction::dummy(b"1".to_vec()), + ValidatorTransaction::dummy(b"22".to_vec()), + ValidatorTransaction::dummy(b"333".to_vec()), ]; let all_user_txns = crate::test_utils::create_vec_signed_transactions(10); @@ -232,9 +233,9 @@ async fn mixed_payload_client_should_prioritize_validator_txns() { #[tokio::test] async fn mixed_payload_client_should_respect_validator_txn_feature_flag() { let all_validator_txns = vec![ - ValidatorTransaction::dummy1(b"1".to_vec()), - ValidatorTransaction::dummy1(b"22".to_vec()), - ValidatorTransaction::dummy1(b"333".to_vec()), + ValidatorTransaction::dummy(b"1".to_vec()), + ValidatorTransaction::dummy(b"22".to_vec()), + ValidatorTransaction::dummy(b"333".to_vec()), ]; let all_user_txns = crate::test_utils::create_vec_signed_transactions(10); diff --git a/consensus/src/round_manager_test.rs b/consensus/src/round_manager_test.rs index 8efe90991bedf..b2f22568f5587 100644 --- a/consensus/src/round_manager_test.rs +++ b/consensus/src/round_manager_test.rs @@ -2008,7 +2008,7 @@ fn no_vote_on_proposal_ext_when_feature_disabled() { let genesis_qc = certificate_for_genesis(); let invalid_block = Block::new_proposal_ext( - vec![ValidatorTransaction::dummy1(vec![0xFF]); 5], + vec![ValidatorTransaction::dummy(vec![0xFF]); 5], Payload::empty(false), 1, 1, @@ -2093,7 +2093,7 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { .unwrap(); let block_too_many_vtxns = Block::new_proposal_ext( - vec![ValidatorTransaction::dummy1(vec![0xFF; 20]); 6], + vec![ValidatorTransaction::dummy(vec![0xFF; 20]); 6], Payload::DirectMempool(create_vec_signed_transactions(4)), 1, 1, @@ -2104,7 +2104,7 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { .unwrap(); let block_too_large = Block::new_proposal_ext( - vec![ValidatorTransaction::dummy1(vec![0xFF; 200]); 1], // total_bytes >= 200 * 1 = 200 + vec![ValidatorTransaction::dummy(vec![0xFF; 200]); 1], // total_bytes >= 200 * 1 = 200 Payload::DirectMempool(create_vec_signed_transactions(9)), // = total_bytes >= 69 * 9 = 621 1, 1, @@ -2115,7 +2115,7 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { .unwrap(); let block_vtxns_too_large = Block::new_proposal_ext( - vec![ValidatorTransaction::dummy1(vec![0xFF; 200]); 5], // total_bytes >= 200 * 5 = 1000 + vec![ValidatorTransaction::dummy(vec![0xFF; 200]); 5], // total_bytes >= 200 * 5 = 1000 Payload::empty(false), 1, 1, @@ -2126,7 +2126,7 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { .unwrap(); let valid_block = Block::new_proposal_ext( - vec![ValidatorTransaction::dummy1(vec![0xFF; 60]); 5], // total_bytes >= 60 * 5 = 300 + vec![ValidatorTransaction::dummy(vec![0xFF; 20]); 5], // total_bytes >= 60 * 5 = 300 Payload::DirectMempool(create_vec_signed_transactions(5)), // total_bytes >= 69 * 5 = 345 1, 1, diff --git a/consensus/src/state_computer_tests.rs b/consensus/src/state_computer_tests.rs index 3048de436aeb1..99ac2b25b6277 100644 --- a/consensus/src/state_computer_tests.rs +++ b/consensus/src/state_computer_tests.rs @@ -145,8 +145,8 @@ async fn schedule_compute_should_discover_validator_txns() { TransactionFilter::new(Filter::empty()), ); - let validator_txn_0 = ValidatorTransaction::dummy1(vec![0xFF; 99]); - let validator_txn_1 = ValidatorTransaction::dummy1(vec![0xFF; 999]); + let validator_txn_0 = ValidatorTransaction::dummy(vec![0xFF; 99]); + let validator_txn_1 = ValidatorTransaction::dummy(vec![0xFF; 999]); let block = Block::new_for_testing( HashValue::zero(), @@ -198,8 +198,8 @@ async fn commit_should_discover_validator_txns() { TransactionFilter::new(Filter::empty()), ); - let validator_txn_0 = ValidatorTransaction::dummy1(vec![0xFF; 99]); - let validator_txn_1 = ValidatorTransaction::dummy1(vec![0xFF; 999]); + let validator_txn_0 = ValidatorTransaction::dummy(vec![0xFF; 99]); + let validator_txn_1 = ValidatorTransaction::dummy(vec![0xFF; 999]); let block = Block::new_for_testing( HashValue::zero(), diff --git a/consensus/src/test_utils/mock_payload_manager.rs b/consensus/src/test_utils/mock_payload_manager.rs index cfbb1b35a1772..581f114d12520 100644 --- a/consensus/src/test_utils/mock_payload_manager.rs +++ b/consensus/src/test_utils/mock_payload_manager.rs @@ -68,7 +68,7 @@ impl PayloadClient for MockPayloadManager { ) -> Result<(Vec, Payload), QuorumStoreError> { // generate 1k txn is too slow with coverage instrumentation Ok(( - vec![ValidatorTransaction::dummy1(vec![0xFF; 1024])], + vec![ValidatorTransaction::dummy(vec![0xFF; 1024])], random_payload(10), )) } diff --git a/crates/validator-transaction-pool/src/tests.rs b/crates/validator-transaction-pool/src/tests.rs index 58e01d70de0e2..bcf0414ee9788 100644 --- a/crates/validator-transaction-pool/src/tests.rs +++ b/crates/validator-transaction-pool/src/tests.rs @@ -3,9 +3,10 @@ use crate::{TransactionFilter, VTxnPoolState}; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; use aptos_crypto::hash::CryptoHash; -use aptos_types::validator_txn::{ - Topic::{DUMMY1, DUMMY2}, - ValidatorTransaction, +use aptos_types::{ + dkg::DKGTranscript, + jwks::{dummy_issuer, QuorumCertifiedUpdate}, + validator_txn::{Topic, ValidatorTransaction}, }; use futures_util::StreamExt; use std::{ @@ -19,12 +20,20 @@ use tokio::time::timeout; #[test] fn txn_pull_order_should_be_fifo_except_in_topic_overwriting() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(b"txn0".to_vec()); - let txn_1 = ValidatorTransaction::dummy1(b"txn1".to_vec()); - let txn_2 = ValidatorTransaction::dummy2(b"txn2".to_vec()); - let _guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let _guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), None); - let _guard_2 = pool.put(DUMMY2, Arc::new(txn_2.clone()), None); // txn_0 is replaced. + let txn_0 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let txn_1 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); + let txn_2 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let _guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let _guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), None); + let _guard_2 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_2.clone()), + None, + ); // txn_0 is replaced. let pulled = pool.pull( Instant::now().add(Duration::from_secs(10)), 99, @@ -37,10 +46,14 @@ fn txn_pull_order_should_be_fifo_except_in_topic_overwriting() { #[test] fn delete_by_seq_num() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(b"txn0".to_vec()); - let txn_1 = ValidatorTransaction::dummy1(b"txn1".to_vec()); - let guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let _guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), None); + let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); + let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let _guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), None); drop(guard_0); let pulled = pool.pull( Instant::now().add(Duration::from_secs(10)), @@ -54,10 +67,14 @@ fn delete_by_seq_num() { #[test] fn txn_should_be_dropped_if_guard_is_dropped() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(b"txn0".to_vec()); - let txn_1 = ValidatorTransaction::dummy1(b"txn1".to_vec()); - let guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), None); + let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); + let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), None); drop(guard_0); drop(guard_1); let pulled = pool.pull( @@ -72,11 +89,15 @@ fn txn_should_be_dropped_if_guard_is_dropped() { #[tokio::test] async fn per_txn_pull_notification() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(b"txn0".to_vec()); - let txn_1 = ValidatorTransaction::dummy1(b"txn1".to_vec()); + let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); + let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); let (tx, mut rx) = aptos_channel::new(QueueStyle::KLAST, 1, None); - let _guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let _guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), Some(tx)); + let _guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let _guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), Some(tx)); let notification_received = timeout(Duration::from_millis(100), rx.select_next_some()).await; assert!(notification_received.is_err()); let pulled = pool.pull( @@ -93,10 +114,14 @@ async fn per_txn_pull_notification() { #[test] fn pull_item_limit_should_be_respected() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(b"txn0".to_vec()); - let txn_1 = ValidatorTransaction::dummy1(b"txn1".to_vec()); - let guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let _guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), None); + let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); + let txn_1 = ValidatorTransaction::DKGResult(DKGTranscript::dummy()); + let guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let _guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), None); let pulled = pool.pull( Instant::now().add(Duration::from_secs(10)), 1, @@ -117,10 +142,14 @@ fn pull_item_limit_should_be_respected() { #[test] fn pull_size_limit_should_be_respected() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(vec![0xFF; 100]); - let txn_1 = ValidatorTransaction::dummy1(vec![0xFF; 100]); - let guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let _guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), None); + let txn_0 = ValidatorTransaction::dummy(vec![0xFF; 100]); + let txn_1 = ValidatorTransaction::dummy(vec![0xFF; 100]); + let guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let _guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), None); let pulled = pool.pull( Instant::now().add(Duration::from_secs(10)), 99, @@ -141,10 +170,14 @@ fn pull_size_limit_should_be_respected() { #[test] fn pull_filter_should_be_respected() { let pool = VTxnPoolState::default(); - let txn_0 = ValidatorTransaction::dummy2(vec![0xFF; 100]); - let txn_1 = ValidatorTransaction::dummy1(vec![0xFF; 100]); - let _guard_0 = pool.put(DUMMY2, Arc::new(txn_0.clone()), None); - let _guard_1 = pool.put(DUMMY1, Arc::new(txn_1.clone()), None); + let txn_0 = ValidatorTransaction::ObservedJWKUpdate(QuorumCertifiedUpdate::dummy()); + let txn_1 = ValidatorTransaction::dummy(vec![0xFF; 100]); + let _guard_0 = pool.put( + Topic::JWK_CONSENSUS(dummy_issuer()), + Arc::new(txn_0.clone()), + None, + ); + let _guard_1 = pool.put(Topic::DKG, Arc::new(txn_1.clone()), None); let pulled = pool.pull( Instant::now().add(Duration::from_secs(10)), 99, diff --git a/testsuite/generate-format/src/api.rs b/testsuite/generate-format/src/api.rs index 3a6e09a0f3e46..de5a573d417dd 100644 --- a/testsuite/generate-format/src/api.rs +++ b/testsuite/generate-format/src/api.rs @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_crypto::{ + bls12381, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, hash::{CryptoHasher as _, TestOnlyHasher}, multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature}, @@ -72,6 +73,13 @@ fn trace_crypto_values(tracer: &mut Tracer, samples: &mut Samples) -> Result<()> tracer.trace_value(samples, &secp256r1_ecdsa_public_key)?; tracer.trace_value(samples, &secp256r1_ecdsa_signature)?; + let bls12381_private_key = bls12381::PrivateKey::generate(&mut rng); + let bls12381_public_key = bls12381::PublicKey::from(&bls12381_private_key); + let bls12381_signature = bls12381_private_key.sign(&message).unwrap(); + tracer.trace_value(samples, &bls12381_private_key)?; + tracer.trace_value(samples, &bls12381_public_key)?; + tracer.trace_value(samples, &bls12381_signature)?; + Ok(()) } diff --git a/testsuite/generate-format/src/aptos.rs b/testsuite/generate-format/src/aptos.rs index 74c5573c8bc31..9619c96ca9a90 100644 --- a/testsuite/generate-format/src/aptos.rs +++ b/testsuite/generate-format/src/aptos.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_crypto::{ + bls12381, ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, hash::{CryptoHasher as _, TestOnlyHasher}, multi_ed25519::{MultiEd25519PublicKey, MultiEd25519Signature}, @@ -69,6 +70,13 @@ fn trace_crypto_values(tracer: &mut Tracer, samples: &mut Samples) -> Result<()> tracer.trace_value(samples, &secp256r1_ecdsa_public_key)?; tracer.trace_value(samples, &secp256r1_ecdsa_signature)?; + let bls12381_private_key = bls12381::PrivateKey::generate(&mut rng); + let bls12381_public_key = bls12381::PublicKey::from(&bls12381_private_key); + let bls12381_signature = bls12381_private_key.sign(&message).unwrap(); + tracer.trace_value(samples, &bls12381_private_key)?; + tracer.trace_value(samples, &bls12381_public_key)?; + tracer.trace_value(samples, &bls12381_signature)?; + Ok(()) } diff --git a/testsuite/generate-format/tests/staged/api.yaml b/testsuite/generate-format/tests/staged/api.yaml index 2ac72adbaa8ba..063d1bdaafc7b 100644 --- a/testsuite/generate-format/tests/staged/api.yaml +++ b/testsuite/generate-format/tests/staged/api.yaml @@ -47,6 +47,17 @@ AccountAuthenticator: STRUCT: - authenticator: TYPENAME: MultiKeyAuthenticator +AggregateSignature: + STRUCT: + - validator_bitmask: + TYPENAME: BitVec + - sig: + OPTION: + TYPENAME: Signature +Any: + STRUCT: + - type_name: STR + - data: BYTES AnyPublicKey: ENUM: 0: @@ -191,10 +202,6 @@ DKGTranscriptMetadata: DepositEvent: STRUCT: - amount: U64 -DummyValidatorTransaction: - STRUCT: - - valid: BOOL - - payload: BYTES Ed25519PublicKey: NEWTYPESTRUCT: BYTES Ed25519Signature: @@ -291,6 +298,10 @@ IdCommitment: SIZE: 32 Identifier: NEWTYPESTRUCT: STR +JWKMoveStruct: + STRUCT: + - variant: + TYPENAME: Any Module: STRUCT: - code: BYTES @@ -373,6 +384,23 @@ Pepper: TUPLEARRAY: CONTENT: U8 SIZE: 31 +PrivateKey: + NEWTYPESTRUCT: BYTES +ProviderJWKs: + STRUCT: + - issuer: BYTES + - version: U64 + - jwks: + SEQ: + TYPENAME: JWKMoveStruct +PublicKey: + NEWTYPESTRUCT: BYTES +QuorumCertifiedUpdate: + STRUCT: + - update: + TYPENAME: ProviderJWKs + - multi_sig: + TYPENAME: AggregateSignature RandMetadata: STRUCT: - metadata_to_sign: @@ -422,6 +450,8 @@ Secp256r1EcdsaPublicKey: NEWTYPESTRUCT: BYTES Secp256r1EcdsaSignature: NEWTYPESTRUCT: BYTES +Signature: + NEWTYPESTRUCT: BYTES SignedGroth16Zkp: STRUCT: - proof: @@ -684,17 +714,13 @@ TypeTag: ValidatorTransaction: ENUM: 0: - DummyTopic1: - NEWTYPE: - TYPENAME: DummyValidatorTransaction - 1: DKGResult: NEWTYPE: TYPENAME: DKGTranscript - 2: - DummyTopic2: + 1: + ObservedJWKUpdate: NEWTYPE: - TYPENAME: DummyValidatorTransaction + TYPENAME: QuorumCertifiedUpdate WithdrawEvent: STRUCT: - amount: U64 diff --git a/testsuite/generate-format/tests/staged/aptos.yaml b/testsuite/generate-format/tests/staged/aptos.yaml index 7a34c8684e073..65ae950be420f 100644 --- a/testsuite/generate-format/tests/staged/aptos.yaml +++ b/testsuite/generate-format/tests/staged/aptos.yaml @@ -35,6 +35,17 @@ AccountAuthenticator: STRUCT: - authenticator: TYPENAME: MultiKeyAuthenticator +AggregateSignature: + STRUCT: + - validator_bitmask: + TYPENAME: BitVec + - sig: + OPTION: + TYPENAME: Signature +Any: + STRUCT: + - type_name: STR + - data: BYTES AnyPublicKey: ENUM: 0: @@ -168,10 +179,6 @@ DKGTranscriptMetadata: - epoch: U64 - author: TYPENAME: AccountAddress -DummyValidatorTransaction: - STRUCT: - - valid: BOOL - - payload: BYTES Ed25519PublicKey: NEWTYPESTRUCT: BYTES Ed25519Signature: @@ -237,6 +244,10 @@ IdCommitment: SIZE: 32 Identifier: NEWTYPESTRUCT: STR +JWKMoveStruct: + STRUCT: + - variant: + TYPENAME: Any Module: STRUCT: - code: BYTES @@ -305,6 +316,23 @@ Pepper: TUPLEARRAY: CONTENT: U8 SIZE: 31 +PrivateKey: + NEWTYPESTRUCT: BYTES +ProviderJWKs: + STRUCT: + - issuer: BYTES + - version: U64 + - jwks: + SEQ: + TYPENAME: JWKMoveStruct +PublicKey: + NEWTYPESTRUCT: BYTES +QuorumCertifiedUpdate: + STRUCT: + - update: + TYPENAME: ProviderJWKs + - multi_sig: + TYPENAME: AggregateSignature RandMetadata: STRUCT: - metadata_to_sign: @@ -354,6 +382,8 @@ Secp256r1EcdsaPublicKey: NEWTYPESTRUCT: BYTES Secp256r1EcdsaSignature: NEWTYPESTRUCT: BYTES +Signature: + NEWTYPESTRUCT: BYTES SignedGroth16Zkp: STRUCT: - proof: @@ -569,17 +599,13 @@ TypeTag: ValidatorTransaction: ENUM: 0: - DummyTopic1: - NEWTYPE: - TYPENAME: DummyValidatorTransaction - 1: DKGResult: NEWTYPE: TYPENAME: DKGTranscript - 2: - DummyTopic2: + 1: + ObservedJWKUpdate: NEWTYPE: - TYPENAME: DummyValidatorTransaction + TYPENAME: QuorumCertifiedUpdate WriteOp: ENUM: 0: diff --git a/testsuite/generate-format/tests/staged/consensus.yaml b/testsuite/generate-format/tests/staged/consensus.yaml index 6ff285ca8e0bf..3d69260096c87 100644 --- a/testsuite/generate-format/tests/staged/consensus.yaml +++ b/testsuite/generate-format/tests/staged/consensus.yaml @@ -48,6 +48,10 @@ AggregateSignatureWithRounds: TYPENAME: AggregateSignature - rounds: SEQ: U64 +Any: + STRUCT: + - type_name: STR + - data: BYTES AnyPublicKey: ENUM: 0: @@ -420,10 +424,6 @@ DKGTranscriptMetadata: - epoch: U64 - author: TYPENAME: AccountAddress -DummyValidatorTransaction: - STRUCT: - - valid: BOOL - - payload: BYTES Ed25519PublicKey: NEWTYPESTRUCT: BYTES Ed25519Signature: @@ -504,6 +504,10 @@ IdCommitment: SIZE: 32 Identifier: NEWTYPESTRUCT: STR +JWKMoveStruct: + STRUCT: + - variant: + TYPENAME: Any LedgerInfo: STRUCT: - commit_info: @@ -640,6 +644,13 @@ ProposalMsg: TYPENAME: Block - sync_info: TYPENAME: SyncInfo +ProviderJWKs: + STRUCT: + - issuer: BYTES + - version: U64 + - jwks: + SEQ: + TYPENAME: JWKMoveStruct PublicKey: NEWTYPESTRUCT: BYTES QuorumCert: @@ -648,6 +659,12 @@ QuorumCert: TYPENAME: VoteData - signed_ledger_info: TYPENAME: LedgerInfoWithSignatures +QuorumCertifiedUpdate: + STRUCT: + - update: + TYPENAME: ProviderJWKs + - multi_sig: + TYPENAME: AggregateSignature RandGenMessage: STRUCT: - epoch: U64 @@ -962,17 +979,13 @@ ValidatorConsensusInfo: ValidatorTransaction: ENUM: 0: - DummyTopic1: - NEWTYPE: - TYPENAME: DummyValidatorTransaction - 1: DKGResult: NEWTYPE: TYPENAME: DKGTranscript - 2: - DummyTopic2: + 1: + ObservedJWKUpdate: NEWTYPE: - TYPENAME: DummyValidatorTransaction + TYPENAME: QuorumCertifiedUpdate ValidatorVerifier: STRUCT: - validator_infos: diff --git a/types/src/dkg/mod.rs b/types/src/dkg/mod.rs index 9df95eebd8a9c..4ad45711131f2 100644 --- a/types/src/dkg/mod.rs +++ b/types/src/dkg/mod.rs @@ -20,7 +20,6 @@ pub struct DKGTranscriptMetadata { pub author: AccountAddress, } -/// Reflection of Move type `0x1::dkg::DKGStartEvent`. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DKGStartEvent { pub session_metadata: DKGSessionMetadata, @@ -47,6 +46,16 @@ impl DKGTranscript { transcript_bytes, } } + + pub fn dummy() -> Self { + Self { + metadata: DKGTranscriptMetadata { + epoch: 0, + author: AccountAddress::ZERO, + }, + transcript_bytes: vec![], + } + } } // The input of DKG. diff --git a/types/src/jwks/mod.rs b/types/src/jwks/mod.rs index 307502b398fe4..bae7c46633964 100644 --- a/types/src/jwks/mod.rs +++ b/types/src/jwks/mod.rs @@ -1,13 +1,14 @@ // Copyright © Aptos Foundation use self::jwk::JWK; -use crate::{move_utils::as_move_value::AsMoveValue, on_chain_config::OnChainConfig}; +use crate::{ + aggregate_signature::AggregateSignature, move_utils::as_move_value::AsMoveValue, + on_chain_config::OnChainConfig, +}; use anyhow::{bail, Context}; -use aptos_crypto::bls12381; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; use jwk::JWKMoveStruct; use move_core_types::{ - account_address::AccountAddress, ident_str, identifier::IdentStr, move_resource::MoveStructType, @@ -15,7 +16,7 @@ use move_core_types::{ }; use serde::{Deserialize, Serialize}; use std::{ - collections::{BTreeSet, HashMap}, + collections::HashMap, fmt::{Debug, Formatter}, }; @@ -29,6 +30,11 @@ pub fn issuer_from_str(s: &str) -> Issuer { s.as_bytes().to_vec() } +#[cfg(any(test, feature = "fuzzing"))] +pub fn dummy_issuer() -> Issuer { + issuer_from_str("https:://dummy.issuer") +} + /// Move type `0x1::jwks::OIDCProvider` in rust. /// See its doc in Move for more details. #[derive(Default, Serialize, Deserialize)] @@ -59,6 +65,7 @@ impl OnChainConfig for SupportedOIDCProviders { /// See its doc in Move for more details. #[derive(Clone, Default, Eq, PartialEq, Serialize, Deserialize, CryptoHasher, BCSCryptoHash)] pub struct ProviderJWKs { + #[serde(with = "serde_bytes")] pub issuer: Issuer, pub version: u64, pub jwks: Vec, @@ -185,18 +192,16 @@ impl MoveStructType for PatchedJWKs { /// A JWK update in format of `ProviderJWKs` and a multi-signature of it as a quorum certificate. #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, CryptoHasher, BCSCryptoHash)] pub struct QuorumCertifiedUpdate { - pub authors: BTreeSet, pub update: ProviderJWKs, - pub multi_sig: bls12381::Signature, + pub multi_sig: AggregateSignature, } impl QuorumCertifiedUpdate { #[cfg(any(test, feature = "fuzzing"))] pub fn dummy() -> Self { Self { - authors: Default::default(), - update: Default::default(), - multi_sig: bls12381::Signature::dummy_signature(), + update: ProviderJWKs::new(dummy_issuer()), + multi_sig: AggregateSignature::empty(), } } } diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index bdf9101492ec8..2ebde083bfb66 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -15,6 +15,7 @@ use crate::{ block_metadata_ext::BlockMetadataExt, chain_id::ChainId, contract_event::ContractEvent, + dkg::{DKGTranscript, DKGTranscriptMetadata}, epoch_state::EpochState, event::{EventHandle, EventKey}, ledger_info::{generate_ledger_info_with_sig, LedgerInfo, LedgerInfoWithSignatures}, @@ -29,7 +30,7 @@ use crate::{ }, validator_info::ValidatorInfo, validator_signer::ValidatorSigner, - validator_txn::{DummyValidatorTransaction, ValidatorTransaction}, + validator_txn::ValidatorTransaction, validator_verifier::{ValidatorConsensusInfo, ValidatorVerifier}, vm_status::VMStatus, write_set::{WriteOp, WriteSet, WriteSetMut}, @@ -1262,9 +1263,15 @@ impl Arbitrary for ValidatorTransaction { type Strategy = BoxedStrategy; fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { - (any::(), any::>()) - .prop_map(|(valid, payload)| { - ValidatorTransaction::DummyTopic1(DummyValidatorTransaction { valid, payload }) + (any::>()) + .prop_map(|payload| { + ValidatorTransaction::DKGResult(DKGTranscript { + metadata: DKGTranscriptMetadata { + epoch: 0, + author: AccountAddress::ZERO, + }, + transcript_bytes: payload, + }) }) .boxed() } diff --git a/types/src/validator_txn.rs b/types/src/validator_txn.rs index 7960ae0da7867..d99b43a96a1d2 100644 --- a/types/src/validator_txn.rs +++ b/types/src/validator_txn.rs @@ -1,53 +1,50 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +#[cfg(any(test, feature = "fuzzing"))] +use crate::dkg::DKGTranscriptMetadata; use crate::{dkg::DKGTranscript, jwks}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; +#[cfg(any(test, feature = "fuzzing"))] +use move_core_types::account_address::AccountAddress; use serde::{Deserialize, Serialize}; use std::fmt::Debug; #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, CryptoHasher, BCSCryptoHash)] pub enum ValidatorTransaction { - DummyTopic1(DummyValidatorTransaction), DKGResult(DKGTranscript), - DummyTopic2(DummyValidatorTransaction), -} - -#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, CryptoHasher, BCSCryptoHash)] -pub struct DummyValidatorTransaction { - pub valid: bool, - #[serde(with = "serde_bytes")] - pub payload: Vec, + ObservedJWKUpdate(jwks::QuorumCertifiedUpdate), } impl ValidatorTransaction { #[cfg(any(test, feature = "fuzzing"))] - pub fn dummy1(payload: Vec) -> Self { - Self::DummyTopic1(DummyValidatorTransaction { - valid: true, - payload, - }) - } - - #[cfg(any(test, feature = "fuzzing"))] - pub fn dummy2(payload: Vec) -> Self { - Self::DummyTopic2(DummyValidatorTransaction { - valid: true, - payload, + pub fn dummy(payload: Vec) -> Self { + Self::DKGResult(DKGTranscript { + metadata: DKGTranscriptMetadata { + epoch: 999, + author: AccountAddress::ZERO, + }, + transcript_bytes: payload, }) } pub fn size_in_bytes(&self) -> usize { bcs::serialized_size(self).unwrap() } + + pub fn topic(&self) -> Topic { + match self { + ValidatorTransaction::DKGResult(_) => Topic::DKG, + ValidatorTransaction::ObservedJWKUpdate(update) => { + Topic::JWK_CONSENSUS(update.update.issuer.clone()) + }, + } + } } -#[derive(Clone, Eq, Hash, PartialEq)] +#[derive(Clone, Debug, Eq, Hash, PartialEq)] #[allow(non_camel_case_types)] pub enum Topic { DKG, JWK_CONSENSUS(jwks::Issuer), - DUMMY1, - #[cfg(any(test, feature = "fuzzing"))] - DUMMY2, } From 0503b1803a9af7e781f386051e501a921a0e4109 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Sun, 4 Feb 2024 18:34:40 -0800 Subject: [PATCH 002/328] jwk #2: ensure jwk txns are expected in consensus (#11855) * jwk types update * update * update * jwk txn and execution * update * consensus ensure jwk txns are expected * update * fix dummy * update * update * update * update * update * update * remove dummy txns * check voting power than verify signature * fix warnings * debug * debug * debug * debug * debug * debug * debug * finish debug * fmt --- Cargo.lock | 1 + consensus/safety-rules/Cargo.toml | 1 + consensus/safety-rules/src/lib.rs | 2 +- .../safety-rules/src/safety_rules_manager.rs | 14 +++ consensus/src/dag/bootstrap.rs | 9 +- consensus/src/dag/rb_handler.rs | 41 +++++--- consensus/src/dag/tests/integration_tests.rs | 2 - consensus/src/dag/tests/rb_handler_tests.rs | 10 +- consensus/src/epoch_manager.rs | 16 +++- consensus/src/round_manager.rs | 16 +++- consensus/src/round_manager_fuzzing.rs | 3 +- consensus/src/round_manager_test.rs | 95 ++++++++++++++++++- consensus/src/util/mod.rs | 16 ++++ 13 files changed, 203 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1db8fda31965..02613f7484d9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3518,6 +3518,7 @@ dependencies = [ name = "aptos-safety-rules" version = "0.1.0" dependencies = [ + "anyhow", "aptos-config", "aptos-consensus-types", "aptos-crypto", diff --git a/consensus/safety-rules/Cargo.toml b/consensus/safety-rules/Cargo.toml index 0b85516acacf8..cb81702a69fd7 100644 --- a/consensus/safety-rules/Cargo.toml +++ b/consensus/safety-rules/Cargo.toml @@ -13,6 +13,7 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] +anyhow = { workspace = true } aptos-config = { workspace = true } aptos-consensus-types = { workspace = true } aptos-crypto = { workspace = true } diff --git a/consensus/safety-rules/src/lib.rs b/consensus/safety-rules/src/lib.rs index 0cd3f245fd411..4b66b4c489a82 100644 --- a/consensus/safety-rules/src/lib.rs +++ b/consensus/safety-rules/src/lib.rs @@ -14,7 +14,7 @@ mod process; mod remote_service; mod safety_rules; mod safety_rules_2chain; -mod safety_rules_manager; +pub mod safety_rules_manager; mod serializer; mod t_safety_rules; mod thread; diff --git a/consensus/safety-rules/src/safety_rules_manager.rs b/consensus/safety-rules/src/safety_rules_manager.rs index 4537cdfb2d550..c73664be47344 100644 --- a/consensus/safety-rules/src/safety_rules_manager.rs +++ b/consensus/safety-rules/src/safety_rules_manager.rs @@ -11,7 +11,10 @@ use crate::{ thread::ThreadService, SafetyRules, TSafetyRules, }; +use anyhow::anyhow; use aptos_config::config::{InitialSafetyRulesConfig, SafetyRulesConfig, SafetyRulesService}; +use aptos_crypto::bls12381::PrivateKey; +use aptos_global_constants::CONSENSUS_KEY; use aptos_infallible::RwLock; use aptos_secure_storage::{KVStorage, Storage}; use std::{net::SocketAddr, sync::Arc}; @@ -73,6 +76,17 @@ pub fn storage(config: &SafetyRulesConfig) -> PersistentSafetyStorage { } } +pub fn load_consensus_key_from_secure_storage( + config: &SafetyRulesConfig, +) -> anyhow::Result { + let storage: Storage = (&config.backend).into(); + let storage = Box::new(storage); + let response = storage.get::(CONSENSUS_KEY).map_err(|e| { + anyhow!("load_consensus_key_from_secure_storage failed with storage read error: {e}") + })?; + Ok(response.value) +} + enum SafetyRulesWrapper { Local(Arc>), Process(ProcessService), diff --git a/consensus/src/dag/bootstrap.rs b/consensus/src/dag/bootstrap.rs index a84175f215f9a..f671b957c9f05 100644 --- a/consensus/src/dag/bootstrap.rs +++ b/consensus/src/dag/bootstrap.rs @@ -46,7 +46,7 @@ use aptos_logger::{debug, info}; use aptos_reliable_broadcast::{RBNetworkSender, ReliableBroadcast}; use aptos_types::{ epoch_state::EpochState, - on_chain_config::{DagConsensusConfigV1, ValidatorTxnConfig}, + on_chain_config::{DagConsensusConfigV1, FeatureFlag, Features, ValidatorTxnConfig}, validator_signer::ValidatorSigner, }; use async_trait::async_trait; @@ -330,6 +330,7 @@ pub struct DagBootstrapper { quorum_store_enabled: bool, vtxn_config: ValidatorTxnConfig, executor: BoundedExecutor, + features: Features, } impl DagBootstrapper { @@ -352,6 +353,7 @@ impl DagBootstrapper { quorum_store_enabled: bool, vtxn_config: ValidatorTxnConfig, executor: BoundedExecutor, + features: Features, ) -> Self { Self { self_peer, @@ -371,6 +373,7 @@ impl DagBootstrapper { quorum_store_enabled, vtxn_config, executor, + features, } } @@ -557,6 +560,7 @@ impl DagBootstrapper { fetch_requester, self.config.node_payload_config.clone(), self.vtxn_config.clone(), + self.features.clone(), ); let fetch_handler = FetchRequestHandler::new(dag_store.clone(), self.epoch_state.clone()); @@ -647,6 +651,8 @@ pub(super) fn bootstrap_dag_for_test( UnboundedReceiver, ) { let (ordered_nodes_tx, ordered_nodes_rx) = futures_channel::mpsc::unbounded(); + let mut features = Features::default(); + features.enable(FeatureFlag::RECONFIGURE_WITH_DKG); let bootstraper = DagBootstrapper::new( self_peer, DagConsensusConfig::default(), @@ -665,6 +671,7 @@ pub(super) fn bootstrap_dag_for_test( false, ValidatorTxnConfig::default_enabled(), BoundedExecutor::new(2, Handle::current()), + features, ); let (_base_state, handler, fetch_service) = bootstraper.full_bootstrap(); diff --git a/consensus/src/dag/rb_handler.rs b/consensus/src/dag/rb_handler.rs index 25e2d4a35496b..8f8afaa57aaab 100644 --- a/consensus/src/dag/rb_handler.rs +++ b/consensus/src/dag/rb_handler.rs @@ -1,18 +1,21 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::dag::{ - dag_fetcher::TFetchRequester, - dag_network::RpcHandler, - dag_store::Dag, - errors::NodeBroadcastHandleError, - observability::{ - logging::{LogEvent, LogSchema}, - tracing::{observe_node, NodeStage}, +use crate::{ + dag::{ + dag_fetcher::TFetchRequester, + dag_network::RpcHandler, + dag_store::Dag, + errors::NodeBroadcastHandleError, + observability::{ + logging::{LogEvent, LogSchema}, + tracing::{observe_node, NodeStage}, + }, + storage::DAGStorage, + types::{Node, NodeCertificate, Vote}, + NodeId, }, - storage::DAGStorage, - types::{Node, NodeCertificate, Vote}, - NodeId, + util::is_vtxn_expected, }; use anyhow::{bail, ensure}; use aptos_config::config::DagPayloadConfig; @@ -20,8 +23,10 @@ use aptos_consensus_types::common::{Author, Round}; use aptos_infallible::RwLock; use aptos_logger::{debug, error}; use aptos_types::{ - epoch_state::EpochState, on_chain_config::ValidatorTxnConfig, - validator_signer::ValidatorSigner, validator_txn::ValidatorTransaction, + epoch_state::EpochState, + on_chain_config::{Features, ValidatorTxnConfig}, + validator_signer::ValidatorSigner, + validator_txn::ValidatorTransaction, }; use async_trait::async_trait; use std::{collections::BTreeMap, mem, sync::Arc}; @@ -35,6 +40,7 @@ pub(crate) struct NodeBroadcastHandler { fetch_requester: Arc, payload_config: DagPayloadConfig, vtxn_config: ValidatorTxnConfig, + features: Features, } impl NodeBroadcastHandler { @@ -46,6 +52,7 @@ impl NodeBroadcastHandler { fetch_requester: Arc, payload_config: DagPayloadConfig, vtxn_config: ValidatorTxnConfig, + features: Features, ) -> Self { let epoch = epoch_state.epoch; let votes_by_round_peer = read_votes_from_storage(&storage, epoch); @@ -59,6 +66,7 @@ impl NodeBroadcastHandler { fetch_requester, payload_config, vtxn_config, + features, } } @@ -87,6 +95,13 @@ impl NodeBroadcastHandler { fn validate(&self, node: Node) -> anyhow::Result { let num_vtxns = node.validator_txns().len() as u64; ensure!(num_vtxns <= self.vtxn_config.per_block_limit_txn_count()); + for vtxn in node.validator_txns() { + ensure!( + is_vtxn_expected(&self.features, vtxn), + "unexpected validator transaction: {:?}", + vtxn.topic() + ); + } let vtxn_total_bytes = node .validator_txns() .iter() diff --git a/consensus/src/dag/tests/integration_tests.rs b/consensus/src/dag/tests/integration_tests.rs index fc38b61557bbf..725300073db70 100644 --- a/consensus/src/dag/tests/integration_tests.rs +++ b/consensus/src/dag/tests/integration_tests.rs @@ -213,7 +213,6 @@ async fn test_dag_e2e() { let runtime = consensus_runtime(); let mut playground = NetworkPlayground::new(runtime.handle().clone()); let (signers, validators) = random_validator_verifier(num_nodes, None, false); - let (nodes, mut ordered_node_receivers) = bootstrap_nodes(&mut playground, signers, validators); for node in nodes { runtime.spawn(node.start()); @@ -229,7 +228,6 @@ async fn test_dag_e2e() { } let first = all_ordered.first().unwrap(); assert_gt!(first.len(), 0, "must order nodes"); - debug!("Nodes: {:?}", first); for a in all_ordered.iter() { assert_eq!(a.len(), first.len(), "length should match"); assert_eq!(a, first); diff --git a/consensus/src/dag/tests/rb_handler_tests.rs b/consensus/src/dag/tests/rb_handler_tests.rs index d19b3e29fa4de..47e47d5ab421f 100644 --- a/consensus/src/dag/tests/rb_handler_tests.rs +++ b/consensus/src/dag/tests/rb_handler_tests.rs @@ -17,8 +17,10 @@ use crate::dag::{ use aptos_config::config::DagPayloadConfig; use aptos_infallible::RwLock; use aptos_types::{ - aggregate_signature::PartialSignatures, epoch_state::EpochState, - on_chain_config::ValidatorTxnConfig, validator_verifier::random_validator_verifier, + aggregate_signature::PartialSignatures, + epoch_state::EpochState, + on_chain_config::{Features, ValidatorTxnConfig}, + validator_verifier::random_validator_verifier, }; use claims::{assert_ok, assert_ok_eq}; use futures::executor::block_on; @@ -68,6 +70,7 @@ async fn test_node_broadcast_receiver_succeed() { Arc::new(MockFetchRequester {}), DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), + Features::default(), ); let expected_result = Vote::new( @@ -114,6 +117,7 @@ async fn test_node_broadcast_receiver_failure() { Arc::new(MockFetchRequester {}), DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), + Features::default(), ) }) .collect(); @@ -197,6 +201,7 @@ async fn test_node_broadcast_receiver_storage() { Arc::new(MockFetchRequester {}), DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), + Features::default(), ); let sig = rb_receiver.process(node).await.expect("must succeed"); @@ -213,6 +218,7 @@ async fn test_node_broadcast_receiver_storage() { Arc::new(MockFetchRequester {}), DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), + Features::default(), ); assert_ok!(rb_receiver.gc_before_round(2)); assert_eq!(storage.get_votes().unwrap().len(), 0); diff --git a/consensus/src/epoch_manager.rs b/consensus/src/epoch_manager.rs index 29ee8b844e830..6ffd58555c4f4 100644 --- a/consensus/src/epoch_manager.rs +++ b/consensus/src/epoch_manager.rs @@ -823,6 +823,7 @@ impl EpochManager

{ network_sender: NetworkSender, payload_client: Arc, payload_manager: Arc, + features: Features, ) { let epoch = epoch_state.epoch; info!( @@ -930,6 +931,7 @@ impl EpochManager

{ onchain_consensus_config, buffered_proposal_tx, self.config.clone(), + features, ); round_manager.init(last_vote).await; @@ -975,7 +977,7 @@ impl EpochManager

{ let onchain_consensus_config: anyhow::Result = payload.get(); let onchain_execution_config: anyhow::Result = payload.get(); - let features = payload.get::().ok().unwrap_or_default(); + let features = payload.get::(); if let Err(error) = &onchain_consensus_config { error!("Failed to read on-chain consensus config {}", error); @@ -985,11 +987,17 @@ impl EpochManager

{ error!("Failed to read on-chain execution config {}", error); } + if let Err(error) = &features { + error!("Failed to read on-chain features {}", error); + } + self.epoch_state = Some(epoch_state.clone()); let consensus_config = onchain_consensus_config.unwrap_or_default(); let execution_config = onchain_execution_config .unwrap_or_else(|_| OnChainExecutionConfig::default_if_missing()); + let features = features.unwrap_or_default(); + let (network_sender, payload_client, payload_manager) = self .initialize_shared_component( &epoch_state, @@ -1006,6 +1014,7 @@ impl EpochManager

{ network_sender, payload_client, payload_manager, + features, ) .await } else { @@ -1015,6 +1024,7 @@ impl EpochManager

{ network_sender, payload_client, payload_manager, + features, ) .await } @@ -1061,6 +1071,7 @@ impl EpochManager

{ network_sender: NetworkSender, payload_client: Arc, payload_manager: Arc, + features: Features, ) { match self.storage.start() { LivenessStorageData::FullRecoveryData(initial_data) => { @@ -1072,6 +1083,7 @@ impl EpochManager

{ network_sender, payload_client, payload_manager, + features, ) .await }, @@ -1095,6 +1107,7 @@ impl EpochManager

{ network_sender: NetworkSender, payload_client: Arc, payload_manager: Arc, + features: Features, ) { let epoch = epoch_state.epoch; @@ -1147,6 +1160,7 @@ impl EpochManager

{ onchain_consensus_config.quorum_store_enabled(), onchain_consensus_config.effective_validator_txn_config(), self.bounded_executor.clone(), + features, ); let (dag_rpc_tx, dag_rpc_rx) = aptos_channel::new(QueueStyle::FIFO, 10, None); diff --git a/consensus/src/round_manager.rs b/consensus/src/round_manager.rs index 6c83aad53ad8e..b0880f377e0ab 100644 --- a/consensus/src/round_manager.rs +++ b/consensus/src/round_manager.rs @@ -23,6 +23,7 @@ use crate::{ pending_votes::VoteReceptionResult, persistent_liveness_storage::PersistentLivenessStorage, quorum_store::types::BatchMsg, + util::is_vtxn_expected, }; use anyhow::{bail, ensure, Context}; use aptos_channels::aptos_channel; @@ -47,7 +48,7 @@ use aptos_safety_rules::ConsensusState; use aptos_safety_rules::TSafetyRules; use aptos_types::{ epoch_state::EpochState, - on_chain_config::{OnChainConsensusConfig, ValidatorTxnConfig}, + on_chain_config::{Features, OnChainConsensusConfig, ValidatorTxnConfig}, validator_verifier::ValidatorVerifier, PeerId, }; @@ -187,6 +188,7 @@ pub struct RoundManager { vtxn_config: ValidatorTxnConfig, buffered_proposal_tx: aptos_channel::Sender, local_config: ConsensusConfig, + features: Features, } impl RoundManager { @@ -202,6 +204,7 @@ impl RoundManager { onchain_config: OnChainConsensusConfig, buffered_proposal_tx: aptos_channel::Sender, local_config: ConsensusConfig, + features: Features, ) -> Self { // when decoupled execution is false, // the counter is still static. @@ -226,6 +229,7 @@ impl RoundManager { vtxn_config, buffered_proposal_tx, local_config, + features, } } @@ -652,6 +656,16 @@ impl RoundManager { bail!("ProposalExt unexpected while the feature is disabled."); } + if let Some(vtxns) = proposal.validator_txns() { + for vtxn in vtxns { + ensure!( + is_vtxn_expected(&self.features, vtxn), + "unexpected validator txn: {:?}", + vtxn.topic() + ); + } + } + let (num_validator_txns, validator_txns_total_bytes): (usize, usize) = proposal.validator_txns().map_or((0, 0), |txns| { txns.iter().fold((0, 0), |(count_acc, size_acc), txn| { diff --git a/consensus/src/round_manager_fuzzing.rs b/consensus/src/round_manager_fuzzing.rs index 2c720b4439acf..0d8507ec5238c 100644 --- a/consensus/src/round_manager_fuzzing.rs +++ b/consensus/src/round_manager_fuzzing.rs @@ -38,7 +38,7 @@ use aptos_types::{ epoch_change::EpochChangeProof, epoch_state::EpochState, ledger_info::{LedgerInfo, LedgerInfoWithSignatures}, - on_chain_config::{OnChainConsensusConfig, ValidatorSet, ValidatorTxnConfig}, + on_chain_config::{Features, OnChainConsensusConfig, ValidatorSet, ValidatorTxnConfig}, validator_info::ValidatorInfo, validator_signer::ValidatorSigner, validator_verifier::ValidatorVerifier, @@ -209,6 +209,7 @@ fn create_node_for_fuzzing() -> RoundManager { OnChainConsensusConfig::default(), round_manager_tx, ConsensusConfig::default(), + Features::default(), ) } diff --git a/consensus/src/round_manager_test.rs b/consensus/src/round_manager_test.rs index b2f22568f5587..2cc270ce9ada4 100644 --- a/consensus/src/round_manager_test.rs +++ b/consensus/src/round_manager_test.rs @@ -62,9 +62,11 @@ use aptos_safety_rules::{PersistentSafetyStorage, SafetyRulesManager}; use aptos_secure_storage::Storage; use aptos_types::{ epoch_state::EpochState, + jwks::QuorumCertifiedUpdate, ledger_info::LedgerInfo, on_chain_config::{ - ConsensusAlgorithmConfig, ConsensusConfigV1, OnChainConsensusConfig, ValidatorTxnConfig, + ConsensusAlgorithmConfig, ConsensusConfigV1, FeatureFlag, Features, OnChainConsensusConfig, + ValidatorTxnConfig, }, transaction::SignedTransaction, validator_signer::ValidatorSigner, @@ -110,6 +112,7 @@ pub struct NodeSetup { id: usize, onchain_consensus_config: OnChainConsensusConfig, local_consensus_config: ConsensusConfig, + features: Features, } impl NodeSetup { @@ -138,6 +141,7 @@ impl NodeSetup { proposer_indices: Option>, onchain_consensus_config: Option, local_consensus_config: Option, + features: Option, ) -> Vec { let onchain_consensus_config = onchain_consensus_config.unwrap_or_default(); let local_consensus_config = local_consensus_config.unwrap_or_default(); @@ -190,6 +194,7 @@ impl NodeSetup { id, onchain_consensus_config.clone(), local_consensus_config.clone(), + features.clone().unwrap_or_default(), )); } nodes @@ -206,6 +211,7 @@ impl NodeSetup { id: usize, onchain_consensus_config: OnChainConsensusConfig, local_consensus_config: ConsensusConfig, + features: Features, ) -> Self { let _entered_runtime = executor.enter(); let epoch_state = Arc::new(EpochState { @@ -296,6 +302,7 @@ impl NodeSetup { onchain_consensus_config.clone(), round_manager_tx, local_consensus_config.clone(), + features.clone(), ); block_on(round_manager.init(last_vote_sent)); Self { @@ -313,6 +320,7 @@ impl NodeSetup { id, onchain_consensus_config, local_consensus_config, + features, } } @@ -332,6 +340,7 @@ impl NodeSetup { self.id, self.onchain_consensus_config.clone(), self.local_consensus_config.clone(), + self.features, ) } @@ -629,6 +638,7 @@ fn new_round_on_quorum_cert() { None, None, None, + None, ); let node = &mut nodes[0]; let genesis = node.block_store.ordered_root(); @@ -673,6 +683,7 @@ fn vote_on_successful_proposal() { None, None, None, + None, ); let node = &mut nodes[0]; @@ -717,6 +728,7 @@ fn delay_proposal_processing_in_sync_only() { None, None, None, + None, ); let node = &mut nodes[0]; @@ -785,6 +797,7 @@ fn no_vote_on_old_proposal() { None, None, None, + None, ); let node = &mut nodes[0]; let genesis_qc = certificate_for_genesis(); @@ -841,6 +854,7 @@ fn no_vote_on_mismatch_round() { None, None, None, + None, ) .pop() .unwrap(); @@ -897,6 +911,7 @@ fn sync_info_carried_on_timeout_vote() { None, None, None, + None, ); let mut node = nodes.pop().unwrap(); @@ -959,6 +974,7 @@ fn no_vote_on_invalid_proposer() { None, None, None, + None, ); let incorrect_proposer = nodes.pop().unwrap(); let mut node = nodes.pop().unwrap(); @@ -1017,6 +1033,7 @@ fn new_round_on_timeout_certificate() { None, None, None, + None, ) .pop() .unwrap(); @@ -1083,6 +1100,7 @@ fn reject_invalid_failed_authors() { None, None, None, + None, ) .pop() .unwrap(); @@ -1177,6 +1195,7 @@ fn response_on_block_retrieval() { None, None, None, + None, ) .pop() .unwrap(); @@ -1288,6 +1307,7 @@ fn recover_on_restart() { None, None, None, + None, ) .pop() .unwrap(); @@ -1363,6 +1383,7 @@ fn nil_vote_on_timeout() { None, None, None, + None, ); let node = &mut nodes[0]; let genesis = node.block_store.ordered_root(); @@ -1404,6 +1425,7 @@ fn vote_resent_on_timeout() { None, None, None, + None, ); let node = &mut nodes[0]; timed_block_on(&runtime, async { @@ -1443,6 +1465,7 @@ fn sync_on_partial_newer_sync_info() { None, None, None, + None, ); let mut node = nodes.pop().unwrap(); runtime.spawn(playground.start()); @@ -1502,6 +1525,7 @@ fn safety_rules_crash() { None, None, None, + None, ); let mut node = nodes.pop().unwrap(); runtime.spawn(playground.start()); @@ -1565,6 +1589,7 @@ fn echo_timeout() { None, None, None, + None, ); runtime.spawn(playground.start()); timed_block_on(&runtime, async { @@ -1618,6 +1643,7 @@ fn no_next_test() { None, None, None, + None, ); runtime.spawn(playground.start()); @@ -1653,6 +1679,7 @@ fn commit_pipeline_test() { Some(proposers.clone()), None, None, + None, ); runtime.spawn(playground.start()); let behind_node = 6; @@ -1692,6 +1719,7 @@ fn block_retrieval_test() { Some(vec![0, 1]), None, None, + None, ); runtime.spawn(playground.start()); @@ -1760,6 +1788,7 @@ pub fn forking_retrieval_test() { ]), None, None, + None, ); runtime.spawn(playground.start()); @@ -2003,6 +2032,7 @@ fn no_vote_on_proposal_ext_when_feature_disabled() { None, None, None, + None, ); let node = &mut nodes[0]; let genesis_qc = certificate_for_genesis(); @@ -2046,6 +2076,66 @@ fn no_vote_on_proposal_ext_when_feature_disabled() { }); } +#[test] +fn no_vote_on_proposal_with_unexpected_vtxns() { + let vtxns = vec![ValidatorTransaction::ObservedJWKUpdate( + QuorumCertifiedUpdate::dummy(), + )]; + let mut features = Features::default(); + features.disable(FeatureFlag::JWK_CONSENSUS); + assert_process_proposal_result(Some(features.clone()), vtxns.clone(), false); + + features.enable(FeatureFlag::JWK_CONSENSUS); + assert_process_proposal_result(Some(features), vtxns, true); +} + +/// Setup a node with default configs and an optional `Features` override. +/// Create a block, fill it with the given vtxns, and process it with the `RoundManager` from the setup. +/// Assert the processing result. +fn assert_process_proposal_result( + features: Option, + vtxns: Vec, + expected_result: bool, +) { + let runtime = consensus_runtime(); + let mut playground = NetworkPlayground::new(runtime.handle().clone()); + let mut nodes = NodeSetup::create_nodes( + &mut playground, + runtime.handle().clone(), + 1, + None, + Some(OnChainConsensusConfig::default_for_genesis()), + None, + features, + ); + + let node = &mut nodes[0]; + let genesis_qc = certificate_for_genesis(); + let block = Block::new_proposal_ext( + vtxns, + Payload::empty(false), + 1, + 1, + genesis_qc.clone(), + &node.signer, + Vec::new(), + ) + .unwrap(); + + timed_block_on(&runtime, async { + // clear the message queue + node.next_proposal().await; + + assert_eq!( + expected_result, + node.round_manager + .process_proposal(block.clone()) + .await + .is_ok() + ); + }); +} + #[test] /// If receiving txn num/block size limit is exceeded, ProposalExt should be rejected. fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { @@ -2067,6 +2157,8 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { ..Default::default() }; + let mut features = Features::default(); + features.enable(FeatureFlag::RECONFIGURE_WITH_DKG); let mut nodes = NodeSetup::create_nodes( &mut playground, runtime.handle().clone(), @@ -2077,6 +2169,7 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { vtxn: vtxn_config, }), Some(local_config), + Some(features), ); let node = &mut nodes[0]; let genesis_qc = certificate_for_genesis(); diff --git a/consensus/src/util/mod.rs b/consensus/src/util/mod.rs index 9761f85b6b5fa..a99fa1b51b859 100644 --- a/consensus/src/util/mod.rs +++ b/consensus/src/util/mod.rs @@ -2,7 +2,23 @@ // Parts of the project are originally copyright © Meta Platforms, Inc. // SPDX-License-Identifier: Apache-2.0 +use aptos_types::{ + on_chain_config::{FeatureFlag, Features}, + validator_txn::ValidatorTransaction, +}; + pub mod db_tool; #[cfg(any(test, feature = "fuzzing"))] pub mod mock_time_service; pub mod time_service; + +pub fn is_vtxn_expected(features: &Features, vtxn: &ValidatorTransaction) -> bool { + match vtxn { + ValidatorTransaction::DKGResult(_) => { + features.is_enabled(FeatureFlag::RECONFIGURE_WITH_DKG) + }, + ValidatorTransaction::ObservedJWKUpdate(_) => { + features.is_enabled(FeatureFlag::JWK_CONSENSUS) + }, + } +} From dae6f11eee025f8d10cddd2550c1b3d7f505d554 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Sun, 4 Feb 2024 20:05:00 -0800 Subject: [PATCH 003/328] jwk #3: jwk consensus deps, network, and type defs (#11856) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * update --- Cargo.lock | 22 +++ aptos-node/src/network.rs | 2 +- crates/aptos-jwk-consensus/Cargo.toml | 25 +++ crates/aptos-jwk-consensus/src/lib.rs | 38 +--- crates/aptos-jwk-consensus/src/network.rs | 184 ++++++++++++++++++ .../src/network_interface.rs | 34 +++- crates/aptos-jwk-consensus/src/types.rs | 53 +++++ crates/validator-transaction-pool/Cargo.toml | 3 + crates/validator-transaction-pool/src/lib.rs | 12 ++ 9 files changed, 337 insertions(+), 36 deletions(-) create mode 100644 crates/aptos-jwk-consensus/src/network.rs create mode 100644 crates/aptos-jwk-consensus/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index 02613f7484d9d..d1bdd32c4d426 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2496,15 +2496,37 @@ dependencies = [ name = "aptos-jwk-consensus" version = "0.1.0" dependencies = [ + "anyhow", + "aptos-bitvec", + "aptos-bounded-executor", + "aptos-channels", "aptos-config", + "aptos-consensus-types", + "aptos-crypto", + "aptos-enum-conversion-derive", "aptos-event-notifications", + "aptos-global-constants", + "aptos-infallible", + "aptos-logger", + "aptos-metrics-core", "aptos-network", + "aptos-reliable-broadcast", "aptos-runtimes", + "aptos-time-service", "aptos-types", "aptos-validator-transaction-pool", + "async-trait", + "bytes", + "futures", + "futures-channel", "futures-util", + "move-core-types", + "once_cell", + "reqwest", "serde", + "serde_json", "tokio", + "tokio-retry", ] [[package]] diff --git a/aptos-node/src/network.rs b/aptos-node/src/network.rs index 4167e88ffe09f..9c95ec7a30d0c 100644 --- a/aptos-node/src/network.rs +++ b/aptos-node/src/network.rs @@ -10,7 +10,7 @@ use aptos_config::{ use aptos_consensus::network_interface::ConsensusMsg; use aptos_dkg_runtime::DKGMessage; use aptos_event_notifications::EventSubscriptionService; -use aptos_jwk_consensus::JWKConsensusMsg; +use aptos_jwk_consensus::types::JWKConsensusMsg; use aptos_logger::debug; use aptos_mempool::network::MempoolSyncMsg; use aptos_network::{ diff --git a/crates/aptos-jwk-consensus/Cargo.toml b/crates/aptos-jwk-consensus/Cargo.toml index da4d6a204ff20..f77612bbcddfa 100644 --- a/crates/aptos-jwk-consensus/Cargo.toml +++ b/crates/aptos-jwk-consensus/Cargo.toml @@ -13,15 +13,40 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] +anyhow = { workspace = true } +aptos-bitvec = { workspace = true } +aptos-bounded-executor = { workspace = true } +aptos-channels = { workspace = true } aptos-config = { workspace = true } +aptos-consensus-types = { workspace = true } +aptos-crypto = { workspace = true } +aptos-enum-conversion-derive = { workspace = true } aptos-event-notifications = { workspace = true } +aptos-global-constants = { workspace = true } +aptos-infallible = { workspace = true } +aptos-logger = { workspace = true } +aptos-metrics-core = { workspace = true } aptos-network = { workspace = true } +aptos-reliable-broadcast = { workspace = true } aptos-runtimes = { workspace = true } +aptos-time-service = { workspace = true } aptos-types = { workspace = true } aptos-validator-transaction-pool = { workspace = true } +async-trait = { workspace = true } +bytes = { workspace = true } +futures = { workspace = true } +futures-channel = { workspace = true } futures-util = { workspace = true } +move-core-types = { workspace = true } +once_cell = { workspace = true } +reqwest = { workspace = true } serde = { workspace = true } +serde_json = { workspace = true } tokio = { workspace = true } +tokio-retry = { workspace = true } +[dev-dependencies] +aptos-types = { workspace = true, features = ["fuzzing"] } +aptos-validator-transaction-pool = { workspace = true, features = ["fuzzing"] } [features] smoke-test = [] diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index 1b873aeeba873..737b1a1f8a1ca 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -1,18 +1,12 @@ // Copyright © Aptos Foundation -use aptos_config::network_id::{NetworkId, PeerNetworkId}; +use crate::types::JWKConsensusMsg; use aptos_event_notifications::{ DbBackedOnChainConfig, EventNotificationListener, ReconfigNotificationListener, }; -use aptos_network::application::{ - error::Error, - interface::{NetworkClient, NetworkClientInterface, NetworkServiceEvents}, -}; -use aptos_types::PeerId; +use aptos_network::application::interface::{NetworkClient, NetworkServiceEvents}; use aptos_validator_transaction_pool::VTxnPoolState; use futures_util::StreamExt; -use serde::{Deserialize, Serialize}; -use std::time::Duration; use tokio::runtime::Runtime; #[allow(clippy::let_and_return)] @@ -35,30 +29,6 @@ pub fn start_jwk_consensus_runtime( runtime } -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct JWKConsensusMsg {} - -#[derive(Clone)] -pub struct JWKNetworkClient { - network_client: NetworkClient, -} - -impl> JWKNetworkClient { - pub fn new(network_client: NetworkClient) -> Self { - Self { network_client } - } - - pub async fn send_rpc( - &self, - peer: PeerId, - message: JWKConsensusMsg, - rpc_timeout: Duration, - ) -> Result { - let peer_network_id = PeerNetworkId::new(NetworkId::Validator, peer); - self.network_client - .send_to_peer_rpc(message, rpc_timeout, peer_network_id) - .await - } -} - +pub mod network; pub mod network_interface; +pub mod types; diff --git a/crates/aptos-jwk-consensus/src/network.rs b/crates/aptos-jwk-consensus/src/network.rs new file mode 100644 index 0000000000000..ffea47f1f2114 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/network.rs @@ -0,0 +1,184 @@ +// Copyright © Aptos Foundation + +use crate::{ + network_interface::{JWKConsensusNetworkClient, RPC}, + types::JWKConsensusMsg, +}; +use anyhow::bail; +use aptos_channels::{aptos_channel, message_queues::QueueStyle}; +use aptos_config::network_id::NetworkId; +use aptos_consensus_types::common::Author; +#[cfg(test)] +use aptos_infallible::RwLock; +use aptos_logger::warn; +use aptos_network::{ + application::interface::{NetworkClient, NetworkServiceEvents}, + protocols::network::{Event, RpcError}, + ProtocolId, +}; +use aptos_reliable_broadcast::RBNetworkSender; +use aptos_types::account_address::AccountAddress; +use bytes::Bytes; +use futures::Stream; +use futures_channel::oneshot; +use futures_util::{ + stream::{select, select_all, StreamExt}, + SinkExt, +}; +#[cfg(test)] +use std::sync::Arc; +use std::time::Duration; +use tokio::time::timeout; + +pub struct IncomingRpcRequest { + pub msg: JWKConsensusMsg, + pub sender: AccountAddress, + pub response_sender: Box, +} + +pub struct NetworkSender { + author: AccountAddress, + jwk_network_client: JWKConsensusNetworkClient>, + self_sender: aptos_channels::Sender>, +} + +impl NetworkSender { + pub fn new( + author: AccountAddress, + jwk_network_client: JWKConsensusNetworkClient>, + self_sender: aptos_channels::Sender>, + ) -> Self { + Self { + author, + jwk_network_client, + self_sender, + } + } +} + +#[async_trait::async_trait] +impl RBNetworkSender for NetworkSender { + async fn send_rb_rpc( + &self, + receiver: Author, + msg: JWKConsensusMsg, + time_limit: Duration, + ) -> anyhow::Result { + if receiver == self.author { + let (tx, rx) = oneshot::channel(); + let self_msg = Event::RpcRequest(receiver, msg, RPC[0], tx); + self.self_sender.clone().send(self_msg).await?; + if let Ok(Ok(Ok(bytes))) = timeout(time_limit, rx).await { + Ok(RPC[0].from_bytes(&bytes)?) + } else { + bail!("self rpc failed"); + } + } else { + let result = self + .jwk_network_client + .send_rpc(receiver, msg, time_limit) + .await?; + Ok(result) + } + } +} + +pub trait RpcResponseSender: Send + Sync { + fn send(&mut self, response: anyhow::Result); +} + +pub struct RealRpcResponseSender { + pub inner: Option>>, + pub protocol: ProtocolId, +} + +impl RpcResponseSender for RealRpcResponseSender { + fn send(&mut self, response: anyhow::Result) { + let rpc_response = response + .and_then(|msg| self.protocol.to_bytes(&msg).map(Bytes::from)) + .map_err(RpcError::ApplicationError); + if let Some(tx) = self.inner.take() { + let _ = tx.send(rpc_response); + } + } +} + +#[cfg(test)] +pub struct DummyRpcResponseSender { + pub rpc_response_collector: Arc>>>, +} + +#[cfg(test)] +impl DummyRpcResponseSender { + pub fn new(rpc_response_collector: Arc>>>) -> Self { + Self { + rpc_response_collector, + } + } +} + +#[cfg(test)] +impl RpcResponseSender for DummyRpcResponseSender { + fn send(&mut self, response: anyhow::Result) { + self.rpc_response_collector.write().push(response); + } +} + +pub struct NetworkReceivers { + pub rpc_rx: aptos_channel::Receiver, +} + +pub struct NetworkTask { + all_events: Box> + Send + Unpin>, + rpc_tx: aptos_channel::Sender, +} + +impl NetworkTask { + /// Establishes the initial connections with the peers and returns the receivers. + pub fn new( + network_service_events: NetworkServiceEvents, + self_receiver: aptos_channels::Receiver>, + ) -> (NetworkTask, NetworkReceivers) { + let (rpc_tx, rpc_rx) = aptos_channel::new(QueueStyle::FIFO, 10, None); + + let network_and_events = network_service_events.into_network_and_events(); + if (network_and_events.values().len() != 1) + || !network_and_events.contains_key(&NetworkId::Validator) + { + panic!("The network has not been setup correctly for JWK consensus!"); + } + + // Collect all the network events into a single stream + let network_events: Vec<_> = network_and_events.into_values().collect(); + let network_events = select_all(network_events).fuse(); + let all_events = Box::new(select(network_events, self_receiver)); + + (NetworkTask { rpc_tx, all_events }, NetworkReceivers { + rpc_rx, + }) + } + + pub async fn start(mut self) { + while let Some(message) = self.all_events.next().await { + match message { + Event::RpcRequest(peer_id, msg, protocol, response_sender) => { + let req = IncomingRpcRequest { + msg, + sender: peer_id, + response_sender: Box::new(RealRpcResponseSender { + inner: Some(response_sender), + protocol, + }), + }; + + if let Err(e) = self.rpc_tx.push(peer_id, (peer_id, req)) { + warn!(error = ?e, "aptos channel closed"); + }; + }, + _ => { + // Ignore + }, + } + } + } +} diff --git a/crates/aptos-jwk-consensus/src/network_interface.rs b/crates/aptos-jwk-consensus/src/network_interface.rs index 3e29a1bec328c..5fe9ecf56f8df 100644 --- a/crates/aptos-jwk-consensus/src/network_interface.rs +++ b/crates/aptos-jwk-consensus/src/network_interface.rs @@ -1,6 +1,13 @@ // Copyright © Aptos Foundation -use aptos_network::ProtocolId; +use crate::types::JWKConsensusMsg; +use aptos_config::network_id::{NetworkId, PeerNetworkId}; +use aptos_network::{ + application::{error::Error, interface::NetworkClientInterface}, + ProtocolId, +}; +use move_core_types::account_address::AccountAddress as PeerId; +use std::time::Duration; /// Supported protocols in preferred order (from highest priority to lowest). pub const DIRECT_SEND: &[ProtocolId] = &[ @@ -15,3 +22,28 @@ pub const RPC: &[ProtocolId] = &[ ProtocolId::JWKConsensusRpcBcs, ProtocolId::JWKConsensusRpcJson, ]; + +#[derive(Clone)] +pub struct JWKConsensusNetworkClient { + network_client: NetworkClient, +} + +impl> + JWKConsensusNetworkClient +{ + pub fn new(network_client: NetworkClient) -> Self { + Self { network_client } + } + + pub async fn send_rpc( + &self, + peer: PeerId, + message: JWKConsensusMsg, + rpc_timeout: Duration, + ) -> Result { + let peer_network_id = PeerNetworkId::new(NetworkId::Validator, peer); + self.network_client + .send_to_peer_rpc(message, rpc_timeout, peer_network_id) + .await + } +} diff --git a/crates/aptos-jwk-consensus/src/types.rs b/crates/aptos-jwk-consensus/src/types.rs new file mode 100644 index 0000000000000..31223ec4c746f --- /dev/null +++ b/crates/aptos-jwk-consensus/src/types.rs @@ -0,0 +1,53 @@ +// Copyright © Aptos Foundation + +use aptos_crypto::bls12381::Signature; +use aptos_enum_conversion_derive::EnumConversion; +use aptos_reliable_broadcast::RBMessage; +use aptos_types::{ + account_address::AccountAddress, + jwks::{Issuer, ProviderJWKs}, +}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, EnumConversion, Deserialize, Serialize, PartialEq)] +pub enum JWKConsensusMsg { + ObservationRequest(ObservedUpdateRequest), + ObservationResponse(ObservedUpdateResponse), +} + +impl JWKConsensusMsg { + pub fn name(&self) -> &str { + match self { + JWKConsensusMsg::ObservationRequest(_) => "ObservationRequest", + JWKConsensusMsg::ObservationResponse(_) => "ObservationResponse", + } + } + + pub fn epoch(&self) -> u64 { + match self { + JWKConsensusMsg::ObservationRequest(request) => request.epoch, + JWKConsensusMsg::ObservationResponse(response) => response.epoch, + } + } +} + +impl RBMessage for JWKConsensusMsg {} + +#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)] +pub struct ObservedUpdate { + pub author: AccountAddress, + pub observed: ProviderJWKs, + pub signature: Signature, +} + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +pub struct ObservedUpdateRequest { + pub epoch: u64, + pub issuer: Issuer, +} + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)] +pub struct ObservedUpdateResponse { + pub epoch: u64, + pub update: ObservedUpdate, +} diff --git a/crates/validator-transaction-pool/Cargo.toml b/crates/validator-transaction-pool/Cargo.toml index c3eac3de8d54c..c0604b9d34f4b 100644 --- a/crates/validator-transaction-pool/Cargo.toml +++ b/crates/validator-transaction-pool/Cargo.toml @@ -23,3 +23,6 @@ tokio = { workspace = true } [dev-dependencies] aptos-types = { workspace = true, features = ["fuzzing"] } + +[features] +fuzzing = [] diff --git a/crates/validator-transaction-pool/src/lib.rs b/crates/validator-transaction-pool/src/lib.rs index dbe9d3065a17b..5ed1cd10dd56c 100644 --- a/crates/validator-transaction-pool/src/lib.rs +++ b/crates/validator-transaction-pool/src/lib.rs @@ -22,6 +22,10 @@ impl TransactionFilter { } impl TransactionFilter { + pub fn empty() -> Self { + Self::PendingTxnHashSet(HashSet::new()) + } + pub fn should_exclude(&self, txn: &ValidatorTransaction) -> bool { match self { TransactionFilter::PendingTxnHashSet(set) => set.contains(&txn.hash()), @@ -87,6 +91,14 @@ impl VTxnPoolState { .lock() .pull(deadline, max_items, max_bytes, filter) } + + #[cfg(any(test, feature = "fuzzing"))] + pub fn dummy_txn_guard(&self) -> TxnGuard { + TxnGuard { + pool: self.inner.clone(), + seq_num: u64::MAX, + } + } } struct PoolItem { From c2a3453dfa8a7a9425c0dd7bf96cf3e4bb4a47f2 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Mon, 5 Feb 2024 06:33:32 -0800 Subject: [PATCH 004/328] jwk #4: jwk update quorum certification (#11857) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * jwk update quorum certification * update * update * update * update * update * update * update * update * update * update * update --- crates/aptos-jwk-consensus/src/lib.rs | 2 + .../src/observation_aggregation/mod.rs | 97 +++++++++++++ .../src/observation_aggregation/tests.rs | 132 ++++++++++++++++++ .../src/update_certifier.rs | 63 +++++++++ types/src/aggregate_signature.rs | 4 + 5 files changed, 298 insertions(+) create mode 100644 crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs create mode 100644 crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs create mode 100644 crates/aptos-jwk-consensus/src/update_certifier.rs diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index 737b1a1f8a1ca..f2dc5066e54a9 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -31,4 +31,6 @@ pub fn start_jwk_consensus_runtime( pub mod network; pub mod network_interface; +pub mod observation_aggregation; pub mod types; +pub mod update_certifier; diff --git a/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs b/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs new file mode 100644 index 0000000000000..cc8dc22049404 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs @@ -0,0 +1,97 @@ +// Copyright © Aptos Foundation + +use crate::types::{ + JWKConsensusMsg, ObservedUpdate, ObservedUpdateRequest, ObservedUpdateResponse, +}; +use anyhow::{anyhow, ensure}; +use aptos_consensus_types::common::Author; +use aptos_infallible::Mutex; +use aptos_reliable_broadcast::BroadcastStatus; +use aptos_types::{ + aggregate_signature::PartialSignatures, + epoch_state::EpochState, + jwks::{ProviderJWKs, QuorumCertifiedUpdate}, +}; +use move_core_types::account_address::AccountAddress; +use std::{collections::BTreeSet, sync::Arc}; + +/// The aggregation state of reliable broadcast where a validator broadcast JWK observation requests +/// and produce quorum-certified JWK updates. +pub struct ObservationAggregationState { + epoch_state: Arc, + local_view: ProviderJWKs, + inner_state: Mutex, +} + +impl ObservationAggregationState { + pub fn new(epoch_state: Arc, local_view: ProviderJWKs) -> Self { + Self { + epoch_state, + local_view, + inner_state: Mutex::new(PartialSignatures::empty()), + } + } +} + +impl BroadcastStatus for Arc { + type Aggregated = QuorumCertifiedUpdate; + type Message = ObservedUpdateRequest; + type Response = ObservedUpdateResponse; + + fn add( + &self, + sender: Author, + response: Self::Response, + ) -> anyhow::Result> { + let ObservedUpdateResponse { epoch, update } = response; + let ObservedUpdate { + author, + observed: peer_view, + signature, + } = update; + ensure!( + epoch == self.epoch_state.epoch, + "adding peer observation failed with invalid epoch", + ); + ensure!( + author == sender, + "adding peer observation failed with mismatched author", + ); + + let mut partial_sigs = self.inner_state.lock(); + if partial_sigs.contains_voter(&sender) { + return Ok(None); + } + + ensure!( + self.local_view == peer_view, + "adding peer observation failed with mismatched view" + ); + + // Verify peer signature. + self.epoch_state + .verifier + .verify(sender, &peer_view, &signature)?; + + // All checks passed. Aggregating. + partial_sigs.add_signature(sender, signature); + let voters: BTreeSet = partial_sigs.signatures().keys().copied().collect(); + if self + .epoch_state + .verifier + .check_voting_power(voters.iter(), true) + .is_err() + { + return Ok(None); + } + let multi_sig = self.epoch_state.verifier.aggregate_signatures(&partial_sigs).map_err(|e|anyhow!("adding peer observation failed with partial-to-aggregated conversion error: {e}"))?; + + Ok(Some(QuorumCertifiedUpdate { + update: peer_view, + multi_sig, + })) + } +} + +#[cfg(test)] +mod tests; diff --git a/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs b/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs new file mode 100644 index 0000000000000..07878fbc3a654 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/observation_aggregation/tests.rs @@ -0,0 +1,132 @@ +// Copyright © Aptos Foundation + +use crate::{ + observation_aggregation::ObservationAggregationState, + types::{ObservedUpdate, ObservedUpdateResponse}, +}; +use aptos_crypto::{bls12381, SigningKey, Uniform}; +use aptos_reliable_broadcast::BroadcastStatus; +use aptos_types::{ + epoch_state::EpochState, + jwks::{ + jwk::{JWKMoveStruct, JWK}, + unsupported::UnsupportedJWK, + ProviderJWKs, QuorumCertifiedUpdate, + }, + validator_verifier::{ValidatorConsensusInfo, ValidatorVerifier}, +}; +use move_core_types::account_address::AccountAddress; +use std::sync::Arc; + +#[test] +fn test_observation_aggregation_state() { + let num_validators = 5; + let epoch = 999; + let addrs: Vec = (0..num_validators) + .map(|_| AccountAddress::random()) + .collect(); + let private_keys: Vec = (0..num_validators) + .map(|_| bls12381::PrivateKey::generate_for_testing()) + .collect(); + let public_keys: Vec = (0..num_validators) + .map(|i| bls12381::PublicKey::from(&private_keys[i])) + .collect(); + let voting_powers = [1, 1, 1, 6, 6]; // total voting power: 15, default threshold: 11 + let validator_infos: Vec = (0..num_validators) + .map(|i| ValidatorConsensusInfo::new(addrs[i], public_keys[i].clone(), voting_powers[i])) + .collect(); + let verifier = ValidatorVerifier::new(validator_infos); + let epoch_state = Arc::new(EpochState { epoch, verifier }); + let view_0 = ProviderJWKs { + issuer: b"https::/alice.com".to_vec(), + version: 123, + jwks: vec![JWKMoveStruct::from(JWK::Unsupported( + UnsupportedJWK::new_for_testing("id1", "payload1"), + ))], + }; + let view_1 = ProviderJWKs { + issuer: b"https::/alice.com".to_vec(), + version: 123, + jwks: vec![JWKMoveStruct::from(JWK::Unsupported( + UnsupportedJWK::new_for_testing("id2", "payload2"), + ))], + }; + let ob_agg_state = Arc::new(ObservationAggregationState::new( + epoch_state.clone(), + view_0.clone(), + )); + + // `ObservedUpdate` with incorrect epoch should be rejected. + let result = ob_agg_state.add(addrs[0], ObservedUpdateResponse { + epoch: 998, + update: ObservedUpdate { + author: addrs[0], + observed: view_0.clone(), + signature: private_keys[0].sign(&view_0).unwrap(), + }, + }); + assert!(result.is_err()); + + // `ObservedUpdate` authored by X but sent by Y should be rejected. + let result = ob_agg_state.add(addrs[1], ObservedUpdateResponse { + epoch: 999, + update: ObservedUpdate { + author: addrs[0], + observed: view_0.clone(), + signature: private_keys[0].sign(&view_0).unwrap(), + }, + }); + assert!(result.is_err()); + + // `ObservedUpdate` that cannot be verified should be rejected. + let result = ob_agg_state.add(addrs[2], ObservedUpdateResponse { + epoch: 999, + update: ObservedUpdate { + author: addrs[2], + observed: view_0.clone(), + signature: private_keys[2].sign(&view_1).unwrap(), + }, + }); + assert!(result.is_err()); + + // Good `ObservedUpdate` should be accepted. + let result = ob_agg_state.add(addrs[3], ObservedUpdateResponse { + epoch: 999, + update: ObservedUpdate { + author: addrs[3], + observed: view_0.clone(), + signature: private_keys[3].sign(&view_0).unwrap(), + }, + }); + assert!(matches!(result, Ok(None))); + + // `ObservedUpdate` from contributed author should be ignored. + let result = ob_agg_state.add(addrs[3], ObservedUpdateResponse { + epoch: 999, + update: ObservedUpdate { + author: addrs[3], + observed: view_0.clone(), + signature: private_keys[3].sign(&view_0).unwrap(), + }, + }); + assert!(matches!(result, Ok(None))); + + // Quorum-certified update should be returned if after adding an `ObservedUpdate`, the threshold is exceeded. + let result = ob_agg_state.add(addrs[4], ObservedUpdateResponse { + epoch: 999, + update: ObservedUpdate { + author: addrs[4], + observed: view_0.clone(), + signature: private_keys[4].sign(&view_0).unwrap(), + }, + }); + let QuorumCertifiedUpdate { + update: observed, + multi_sig, + } = result.unwrap().unwrap(); + assert_eq!(view_0, observed); + assert!(epoch_state + .verifier + .verify_multi_signatures(&observed, &multi_sig) + .is_ok()); +} diff --git a/crates/aptos-jwk-consensus/src/update_certifier.rs b/crates/aptos-jwk-consensus/src/update_certifier.rs new file mode 100644 index 0000000000000..2f79115bd5404 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/update_certifier.rs @@ -0,0 +1,63 @@ +// Copyright © Aptos Foundation + +use crate::{ + observation_aggregation::ObservationAggregationState, + types::{JWKConsensusMsg, ObservedUpdateRequest}, +}; +use aptos_channels::aptos_channel; +use aptos_reliable_broadcast::ReliableBroadcast; +use aptos_types::{ + epoch_state::EpochState, + jwks::{ProviderJWKs, QuorumCertifiedUpdate}, +}; +use futures_util::future::{AbortHandle, Abortable}; +use std::sync::Arc; +use tokio_retry::strategy::ExponentialBackoff; + +/// A sub-process of the whole JWK consensus process. +/// Once invoked by `JWKConsensusManager` to `start_produce`, +/// it starts producing a `QuorumCertifiedUpdate` and returns an abort handle. +/// Once an `QuorumCertifiedUpdate` is available, it is sent back via a channel given earlier. +pub trait TUpdateCertifier: Send + Sync { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + qc_update_tx: aptos_channel::Sender<(), QuorumCertifiedUpdate>, + ) -> AbortHandle; +} + +pub struct CertifiedUpdateProducer { + reliable_broadcast: Arc>, +} + +impl CertifiedUpdateProducer { + pub fn new(reliable_broadcast: ReliableBroadcast) -> Self { + Self { + reliable_broadcast: Arc::new(reliable_broadcast), + } + } +} + +impl TUpdateCertifier for CertifiedUpdateProducer { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + qc_update_tx: aptos_channel::Sender<(), QuorumCertifiedUpdate>, + ) -> AbortHandle { + let rb = self.reliable_broadcast.clone(); + let req = ObservedUpdateRequest { + epoch: epoch_state.epoch, + issuer: payload.issuer.clone(), + }; + let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); + let task = async move { + let qc_update = rb.broadcast(req, agg_state).await; + let _ = qc_update_tx.push((), qc_update); + }; + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + tokio::spawn(Abortable::new(task, abort_registration)); + abort_handle + } +} diff --git a/types/src/aggregate_signature.rs b/types/src/aggregate_signature.rs index 0abe6f3dd9f38..3202583b6252d 100644 --- a/types/src/aggregate_signature.rs +++ b/types/src/aggregate_signature.rs @@ -97,4 +97,8 @@ impl PartialSignatures { pub fn signatures(&self) -> &BTreeMap { &self.signatures } + + pub fn contains_voter(&self, voter: &AccountAddress) -> bool { + self.signatures.contains_key(voter) + } } From 2ece2cd2982dfb68bf5619356b15efc87691adec Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Mon, 5 Feb 2024 07:28:55 -0800 Subject: [PATCH 005/328] jwk #5: jwk observation (#11860) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * jwk update quorum certification * jwk observation * update --- .../aptos-jwk-consensus/src/jwk_observer.rs | 136 ++++++++++++++++++ crates/aptos-jwk-consensus/src/lib.rs | 1 + 2 files changed, 137 insertions(+) create mode 100644 crates/aptos-jwk-consensus/src/jwk_observer.rs diff --git a/crates/aptos-jwk-consensus/src/jwk_observer.rs b/crates/aptos-jwk-consensus/src/jwk_observer.rs new file mode 100644 index 0000000000000..8d9988ce99afa --- /dev/null +++ b/crates/aptos-jwk-consensus/src/jwk_observer.rs @@ -0,0 +1,136 @@ +// Copyright © Aptos Foundation + +use anyhow::Result; +use aptos_channels::aptos_channel; +use aptos_logger::{debug, info}; +use aptos_types::jwks::{jwk::JWK, Issuer}; +use futures::{FutureExt, StreamExt}; +use move_core_types::account_address::AccountAddress; +use serde::{Deserialize, Serialize}; +use std::time::Duration; +use tokio::{sync::oneshot, task::JoinHandle, time::MissedTickBehavior}; + +#[derive(Serialize, Deserialize)] +struct OpenIDConfiguration { + issuer: String, + jwks_uri: String, +} + +#[derive(Serialize, Deserialize)] +struct JWKsResponse { + keys: Vec, +} + +/// Given an Open ID configuration URL, fetch its JWKs. +pub async fn fetch_jwks(my_addr: AccountAddress, config_url: Vec) -> Result> { + if cfg!(feature = "smoke-test") { + use reqwest::header; + let maybe_url = String::from_utf8(config_url); + let jwk_url = maybe_url?; + let client = reqwest::Client::new(); + let JWKsResponse { keys } = client + .get(jwk_url.as_str()) + .header(header::COOKIE, my_addr.to_hex()) + .send() + .await? + .json() + .await?; + let jwks = keys.into_iter().map(JWK::from).collect(); + Ok(jwks) + } else { + let maybe_url = String::from_utf8(config_url); + let config_url = maybe_url?; + let client = reqwest::Client::new(); + let OpenIDConfiguration { jwks_uri, .. } = + client.get(config_url.as_str()).send().await?.json().await?; + let JWKsResponse { keys } = client.get(jwks_uri.as_str()).send().await?.json().await?; + let jwks = keys.into_iter().map(JWK::from).collect(); + Ok(jwks) + } +} + +/// A process thread that periodically fetch JWKs of a provider and push it back to JWKManager. +pub struct JWKObserver { + close_tx: oneshot::Sender<()>, + join_handle: JoinHandle<()>, +} + +impl JWKObserver { + pub fn spawn( + my_addr: AccountAddress, + issuer: Issuer, + config_url: Vec, + fetch_interval: Duration, + observation_tx: aptos_channel::Sender<(), (Issuer, Vec)>, + ) -> Self { + let (close_tx, close_rx) = oneshot::channel(); + let join_handle = tokio::spawn(Self::start( + fetch_interval, + my_addr, + issuer.clone(), + config_url.clone(), + observation_tx, + close_rx, + )); + info!( + "[JWK] observer spawned, issuer={:?}, config_url={:?}", + String::from_utf8(issuer), + String::from_utf8(config_url) + ); + Self { + close_tx, + join_handle, + } + } + + async fn start( + fetch_interval: Duration, + my_addr: AccountAddress, + issuer: Issuer, + open_id_config_url: Vec, + observation_tx: aptos_channel::Sender<(), (Issuer, Vec)>, + close_rx: oneshot::Receiver<()>, + ) { + let mut interval = tokio::time::interval(fetch_interval); + interval.set_missed_tick_behavior(MissedTickBehavior::Delay); + let mut close_rx = close_rx.into_stream(); + loop { + tokio::select! { + _ = interval.tick().fuse() => { + let result = fetch_jwks(my_addr, open_id_config_url.clone()).await; + debug!("observe_result={:?}", result); + if let Ok(mut jwks) = result { + jwks.sort(); + let _ = observation_tx.push((), (issuer.clone(), jwks)); + } + }, + _ = close_rx.select_next_some() => { + break; + } + } + } + } + + pub async fn shutdown(self) { + let Self { + close_tx, + join_handle, + } = self; + let _ = close_tx.send(()); + let _ = join_handle.await; + } +} + +#[ignore] +#[tokio::test] +async fn test_fetch_real_jwks() { + let jwks = fetch_jwks( + AccountAddress::ZERO, + "https://www.facebook.com/.well-known/openid-configuration/" + .as_bytes() + .to_vec(), + ) + .await + .unwrap(); + println!("{:?}", jwks); +} diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index f2dc5066e54a9..74c011c537c3f 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -29,6 +29,7 @@ pub fn start_jwk_consensus_runtime( runtime } +pub mod jwk_observer; pub mod network; pub mod network_interface; pub mod observation_aggregation; From 3ffdf139eb9109a173647be4613a4055e559fe88 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Mon, 5 Feb 2024 08:36:39 -0800 Subject: [PATCH 006/328] jwk #6: jwk consensus state transition (#11859) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * jwk update quorum certification * jwk observation * the main jwk consensus state machine * update * update * update * fmt * update * update * update * update * update * lint * update * update --- .../src/certified_update_producer.rs | 64 +++ .../src/jwk_manager/mod.rs | 404 +++++++++++++++ .../src/jwk_manager/tests.rs | 485 ++++++++++++++++++ crates/aptos-jwk-consensus/src/lib.rs | 1 + .../src/update_certifier.rs | 11 +- 5 files changed, 960 insertions(+), 5 deletions(-) create mode 100644 crates/aptos-jwk-consensus/src/certified_update_producer.rs create mode 100644 crates/aptos-jwk-consensus/src/jwk_manager/mod.rs create mode 100644 crates/aptos-jwk-consensus/src/jwk_manager/tests.rs diff --git a/crates/aptos-jwk-consensus/src/certified_update_producer.rs b/crates/aptos-jwk-consensus/src/certified_update_producer.rs new file mode 100644 index 0000000000000..9db8d77d09647 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/certified_update_producer.rs @@ -0,0 +1,64 @@ +// Copyright © Aptos Foundation + +use crate::{ + observation_aggregation::ObservationAggregationState, + types::{JWKConsensusMsg, ObservedUpdateRequest}, +}; +use aptos_channels::aptos_channel; +use aptos_reliable_broadcast::ReliableBroadcast; +use aptos_types::{ + epoch_state::EpochState, + jwks::{Issuer, ProviderJWKs, QuorumCertifiedUpdate}, +}; +use futures_util::future::{AbortHandle, Abortable}; +use std::sync::Arc; +use tokio_retry::strategy::ExponentialBackoff; + +/// A sub-process of the whole JWK consensus process. +/// Once invoked by `JWKConsensusManager` to `start_produce`, +/// it starts producing a `QuorumCertifiedUpdate` and returns an abort handle. +/// Once an `QuorumCertifiedUpdate` is available, it is sent back via a channel given earlier. +pub trait CertifiedUpdateProducer: Send + Sync { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + qc_update_tx: aptos_channel::Sender, + ) -> AbortHandle; +} + +pub struct RealCertifiedUpdateProducer { + reliable_broadcast: Arc>, +} + +impl RealCertifiedUpdateProducer { + pub fn new(reliable_broadcast: ReliableBroadcast) -> Self { + Self { + reliable_broadcast: Arc::new(reliable_broadcast), + } + } +} + +impl CertifiedUpdateProducer for RealCertifiedUpdateProducer { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + qc_update_tx: aptos_channel::Sender, + ) -> AbortHandle { + let rb = self.reliable_broadcast.clone(); + let issuer = payload.issuer.clone(); + let req = ObservedUpdateRequest { + epoch: epoch_state.epoch, + issuer: issuer.clone(), + }; + let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); + let task = async move { + let qc_update = rb.broadcast(req, agg_state).await; + let _ = qc_update_tx.push(issuer, qc_update); + }; + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + tokio::spawn(Abortable::new(task, abort_registration)); + abort_handle + } +} diff --git a/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs b/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs new file mode 100644 index 0000000000000..b098c6985242c --- /dev/null +++ b/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs @@ -0,0 +1,404 @@ +// Copyright © Aptos Foundation + +use crate::{ + jwk_observer::JWKObserver, + network::IncomingRpcRequest, + types::{JWKConsensusMsg, ObservedUpdate, ObservedUpdateResponse}, + update_certifier::TUpdateCertifier, +}; +use anyhow::{anyhow, bail, Result}; +use aptos_channels::{aptos_channel, message_queues::QueueStyle}; +use aptos_crypto::{bls12381::PrivateKey, SigningKey}; +use aptos_logger::{debug, error, info}; +use aptos_types::{ + account_address::AccountAddress, + epoch_state::EpochState, + jwks::{ + jwk::JWKMoveStruct, AllProvidersJWKs, Issuer, ObservedJWKs, ObservedJWKsUpdated, + ProviderJWKs, QuorumCertifiedUpdate, SupportedOIDCProviders, + }, + validator_txn::{Topic, ValidatorTransaction}, +}; +use aptos_validator_transaction_pool::{TxnGuard, VTxnPoolState}; +use futures_channel::oneshot; +use futures_util::{ + future::{join_all, AbortHandle}, + FutureExt, StreamExt, +}; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::Duration, +}; + +/// `JWKManager` executes per-issuer JWK consensus sessions +/// and updates validator txn pool with quorum-certified JWK updates. +pub struct JWKManager { + /// Some useful metadata. + my_addr: AccountAddress, + epoch_state: Arc, + + /// Used to sign JWK observations before sharing them with peers. + consensus_key: Arc, + + /// The sub-process that collects JWK updates from peers and aggregate them into a quorum-certified JWK update. + update_certifier: Arc, + + /// When a quorum-certified JWK update is available, use this to put it into the validator transaction pool. + vtxn_pool: VTxnPoolState, + + /// The JWK consensus states of all the issuers. + states_by_issuer: HashMap, + + /// Whether a CLOSE command has been received. + stopped: bool, + + qc_update_tx: aptos_channel::Sender, + qc_update_rx: aptos_channel::Receiver, + jwk_observers: Vec, +} + +impl JWKManager { + pub fn new( + consensus_key: Arc, + my_addr: AccountAddress, + epoch_state: Arc, + update_certifier: Arc, + vtxn_pool: VTxnPoolState, + ) -> Self { + let (qc_update_tx, qc_update_rx) = aptos_channel::new(QueueStyle::KLAST, 1, None); + Self { + consensus_key, + my_addr, + epoch_state, + update_certifier, + vtxn_pool, + states_by_issuer: HashMap::default(), + stopped: false, + qc_update_tx, + qc_update_rx, + jwk_observers: vec![], + } + } + + pub async fn run( + mut self, + oidc_providers: Option, + observed_jwks: Option, + mut jwk_updated_rx: aptos_channel::Receiver<(), ObservedJWKsUpdated>, + mut rpc_req_rx: aptos_channel::Receiver<(), (AccountAddress, IncomingRpcRequest)>, + close_rx: oneshot::Receiver>, + ) { + self.reset_with_on_chain_state(observed_jwks.unwrap_or_default().into_providers_jwks()) + .unwrap(); + + let (local_observation_tx, mut local_observation_rx) = + aptos_channel::new(QueueStyle::KLAST, 100, None); + + self.jwk_observers = oidc_providers + .unwrap_or_default() + .into_provider_vec() + .into_iter() + .map(|provider| { + JWKObserver::spawn( + self.my_addr, + provider.name.clone(), + provider.config_url.clone(), + Duration::from_secs(10), + local_observation_tx.clone(), + ) + }) + .collect(); + + let mut close_rx = close_rx.into_stream(); + + while !self.stopped { + let handle_result = tokio::select! { + jwk_updated = jwk_updated_rx.select_next_some() => { + let ObservedJWKsUpdated { jwks, .. } = jwk_updated; + self.reset_with_on_chain_state(jwks) + }, + (_sender, msg) = rpc_req_rx.select_next_some() => { + self.process_peer_request(msg) + }, + qc_update = self.qc_update_rx.select_next_some() => { + self.process_quorum_certified_update(qc_update) + }, + (issuer, jwks) = local_observation_rx.select_next_some() => { + let jwks = jwks.into_iter().map(JWKMoveStruct::from).collect(); + self.process_new_observation(issuer, jwks) + }, + ack_tx = close_rx.select_next_some() => { + self.tear_down(ack_tx.ok()).await + } + }; + + if let Err(e) = handle_result { + error!("[JWK] handling_err={}", e); + } + } + } + + async fn tear_down(&mut self, ack_tx: Option>) -> Result<()> { + self.stopped = true; + let futures = std::mem::take(&mut self.jwk_observers) + .into_iter() + .map(JWKObserver::shutdown) + .collect::>(); + join_all(futures).await; + if let Some(tx) = ack_tx { + let _ = tx.send(()); + } + Ok(()) + } + + /// Triggered by an observation thread periodically. + pub fn process_new_observation( + &mut self, + issuer: Issuer, + jwks: Vec, + ) -> Result<()> { + let state = self.states_by_issuer.entry(issuer.clone()).or_default(); + state.observed = Some(jwks.clone()); + if state.observed.as_ref() != state.on_chain.as_ref().map(ProviderJWKs::jwks) { + let observed = ProviderJWKs { + issuer: issuer.clone(), + version: state.on_chain_version() + 1, + jwks, + }; + let signature = self + .consensus_key + .sign(&observed) + .map_err(|e| anyhow!("crypto material error occurred duing signing: {}", e))?; + let abort_handle = self.update_certifier.start_produce( + self.epoch_state.clone(), + observed.clone(), + self.qc_update_tx.clone(), + ); + state.consensus_state = ConsensusState::InProgress { + my_proposal: ObservedUpdate { + author: self.my_addr, + observed: observed.clone(), + signature, + }, + abort_handle_wrapper: QuorumCertProcessGuard::new(abort_handle), + }; + info!("[JWK] update observed, update={:?}", observed); + } + + Ok(()) + } + + /// Invoked on start, or on on-chain JWK updated event. + pub fn reset_with_on_chain_state(&mut self, on_chain_state: AllProvidersJWKs) -> Result<()> { + debug!( + "[JWK] reset_with_on_chain_state: BEGIN: on_chain_state={:?}", + on_chain_state + ); + let onchain_issuer_set: HashSet = on_chain_state + .entries + .iter() + .map(|entry| entry.issuer.clone()) + .collect(); + self.states_by_issuer + .retain(|issuer, _| onchain_issuer_set.contains(issuer)); + for on_chain_provider_jwks in on_chain_state.entries { + let locally_cached = self + .states_by_issuer + .get(&on_chain_provider_jwks.issuer) + .and_then(|s| s.on_chain.as_ref()); + if locally_cached == Some(&on_chain_provider_jwks) { + // The on-chain update did not touch this provider. + // The corresponding local state does not have to be reset. + } else { + self.states_by_issuer.insert( + on_chain_provider_jwks.issuer.clone(), + PerProviderState::new(on_chain_provider_jwks), + ); + } + } + Ok(()) + } + + pub fn process_peer_request(&mut self, rpc_req: IncomingRpcRequest) -> Result<()> { + let IncomingRpcRequest { + msg, + mut response_sender, + sender, + } = rpc_req; + debug!( + "[JWK] process_peer_request: sender={}, is_self={}", + sender, + sender == self.my_addr + ); + match msg { + JWKConsensusMsg::ObservationRequest(request) => { + let state = self.states_by_issuer.entry(request.issuer).or_default(); + let response: Result = match &state.consensus_state { + ConsensusState::NotStarted => Err(anyhow!("observed update unavailable")), + ConsensusState::InProgress { my_proposal, .. } + | ConsensusState::Finished { my_proposal, .. } => Ok( + JWKConsensusMsg::ObservationResponse(ObservedUpdateResponse { + epoch: self.epoch_state.epoch, + update: my_proposal.clone(), + }), + ), + }; + response_sender.send(response); + Ok(()) + }, + _ => { + bail!("unexpected rpc: {}", msg.name()); + }, + } + } + + /// Triggered once the `update_certifier` produced a quorum-certified update. + pub fn process_quorum_certified_update(&mut self, update: QuorumCertifiedUpdate) -> Result<()> { + let issuer = update.update.issuer.clone(); + let state = self.states_by_issuer.entry(issuer.clone()).or_default(); + match &state.consensus_state { + ConsensusState::InProgress { my_proposal, .. } => { + //TODO: counters + let txn = ValidatorTransaction::ObservedJWKUpdate(update.clone()); + let vtxn_guard = + self.vtxn_pool + .put(Topic::JWK_CONSENSUS(issuer), Arc::new(txn), None); + state.consensus_state = ConsensusState::Finished { + vtxn_guard, + my_proposal: my_proposal.clone(), + quorum_certified: update.clone(), + }; + info!("[JWK] qc update obtained, update={:?}", update); + Ok(()) + }, + _ => Err(anyhow!( + "qc update not expected for issuer {:?} in state {}", + update.update.issuer, + state.consensus_state.name() + )), + } + } +} + +/// An instance of this resource is created when `JWKManager` starts the QC update building process for an issuer. +/// Then `JWKManager` needs to hold it. Once this resource is dropped, the corresponding QC update process will be cancelled. +#[derive(Clone, Debug)] +pub struct QuorumCertProcessGuard { + handle: AbortHandle, +} + +impl QuorumCertProcessGuard { + pub fn new(handle: AbortHandle) -> Self { + Self { handle } + } + + #[cfg(test)] + pub fn dummy() -> Self { + let (handle, _) = AbortHandle::new_pair(); + Self { handle } + } +} + +impl Drop for QuorumCertProcessGuard { + fn drop(&mut self) { + let QuorumCertProcessGuard { handle } = self; + handle.abort(); + } +} + +#[derive(Debug, Clone)] +pub enum ConsensusState { + NotStarted, + InProgress { + my_proposal: ObservedUpdate, + abort_handle_wrapper: QuorumCertProcessGuard, + }, + Finished { + vtxn_guard: TxnGuard, + my_proposal: ObservedUpdate, + quorum_certified: QuorumCertifiedUpdate, + }, +} + +impl PartialEq for ConsensusState { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (ConsensusState::NotStarted, ConsensusState::NotStarted) => true, + ( + ConsensusState::InProgress { + my_proposal: update_0, + .. + }, + ConsensusState::InProgress { + my_proposal: update_1, + .. + }, + ) if update_0 == update_1 => true, + ( + ConsensusState::Finished { + my_proposal: update_0, + .. + }, + ConsensusState::Finished { + my_proposal: update_1, + .. + }, + ) if update_0 == update_1 => true, + _ => false, + } + } +} + +impl Eq for ConsensusState {} + +impl ConsensusState { + pub fn name(&self) -> &str { + match self { + ConsensusState::NotStarted => "NotStarted", + ConsensusState::InProgress { .. } => "InProgress", + ConsensusState::Finished { .. } => "Finished", + } + } + + #[cfg(test)] + pub fn my_proposal_cloned(&self) -> ObservedUpdate { + match self { + ConsensusState::InProgress { my_proposal, .. } + | ConsensusState::Finished { my_proposal, .. } => my_proposal.clone(), + _ => panic!("my_proposal unavailable"), + } + } +} + +impl Default for ConsensusState { + fn default() -> Self { + Self::NotStarted + } +} + +#[derive(Clone, Debug, Default, Eq, PartialEq)] +pub struct PerProviderState { + pub on_chain: Option, + pub observed: Option>, + pub consensus_state: ConsensusState, +} + +impl PerProviderState { + pub fn new(provider_jwks: ProviderJWKs) -> Self { + Self { + on_chain: Some(provider_jwks), + observed: None, + consensus_state: ConsensusState::NotStarted, + } + } + + pub fn on_chain_version(&self) -> u64 { + self.on_chain + .as_ref() + .map_or(0, |provider_jwks| provider_jwks.version) + } +} + +#[cfg(test)] +pub mod tests; diff --git a/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs b/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs new file mode 100644 index 0000000000000..d113a71622b66 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/jwk_manager/tests.rs @@ -0,0 +1,485 @@ +// Copyright © Aptos Foundation + +use crate::{ + jwk_manager::{ConsensusState, JWKManager, PerProviderState, QuorumCertProcessGuard}, + network::{DummyRpcResponseSender, IncomingRpcRequest}, + types::{JWKConsensusMsg, ObservedUpdate, ObservedUpdateRequest, ObservedUpdateResponse}, + update_certifier::TUpdateCertifier, +}; +use aptos_bitvec::BitVec; +use aptos_channels::aptos_channel; +use aptos_crypto::{ + bls12381::{PrivateKey, PublicKey, Signature}, + hash::CryptoHash, + SigningKey, Uniform, +}; +use aptos_infallible::{Mutex, RwLock}; +use aptos_types::{ + account_address::AccountAddress, + aggregate_signature::AggregateSignature, + epoch_state::EpochState, + jwks::{ + issuer_from_str, jwk::JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, Issuer, + ProviderJWKs, QuorumCertifiedUpdate, + }, + validator_txn::ValidatorTransaction, + validator_verifier::{ValidatorConsensusInfo, ValidatorVerifier}, +}; +use aptos_validator_transaction_pool::{TransactionFilter, VTxnPoolState}; +use futures_util::future::AbortHandle; +use std::{ + collections::{HashMap, HashSet}, + sync::Arc, + time::{Duration, Instant}, +}; + +#[tokio::test] +async fn test_jwk_manager_state_transition() { + // Setting up an epoch of 4 validators, and simulate the JWKManager in validator 0. + let private_keys: Vec> = (0..4) + .map(|_| Arc::new(PrivateKey::generate_for_testing())) + .collect(); + let public_keys: Vec = private_keys + .iter() + .map(|sk| PublicKey::from(sk.as_ref())) + .collect(); + let addrs: Vec = (0..4).map(|_| AccountAddress::random()).collect(); + let voting_powers: Vec = vec![1, 1, 1, 1]; + let validator_consensus_infos: Vec = (0..4) + .map(|i| ValidatorConsensusInfo::new(addrs[i], public_keys[i].clone(), voting_powers[i])) + .collect(); + let epoch_state = EpochState { + epoch: 999, + verifier: ValidatorVerifier::new(validator_consensus_infos.clone()), + }; + + let update_certifier = DummyUpdateCertifier::default(); + let vtxn_pool = VTxnPoolState::default(); + let mut jwk_manager = JWKManager::new( + private_keys[0].clone(), + addrs[0], + Arc::new(epoch_state), + Arc::new(update_certifier), + vtxn_pool.clone(), + ); + + // In this example, Alice and Bob are 2 existing issuers; Carl was added in the last epoch so no JWKs of Carl is on chain. + let issuer_alice = issuer_from_str("https://alice.info"); + let issuer_bob = issuer_from_str("https://bob.io"); + let issuer_carl = issuer_from_str("https://carl.dev"); + let alice_jwks = vec![ + JWK::Unsupported(UnsupportedJWK::new_for_testing( + "alice_jwk_id_0", + "jwk_payload_0", + )) + .into(), + JWK::Unsupported(UnsupportedJWK::new_for_testing( + "alice_jwk_id_1", + "jwk_payload_1", + )) + .into(), + ]; + let bob_jwks = vec![ + JWK::Unsupported(UnsupportedJWK::new_for_testing( + "bob_jwk_id_0", + "jwk_payload_2", + )) + .into(), + JWK::Unsupported(UnsupportedJWK::new_for_testing( + "bob_jwk_id_1", + "jwk_payload_3", + )) + .into(), + ]; + let on_chain_state_alice_v111 = ProviderJWKs { + issuer: issuer_alice.clone(), + version: 111, + jwks: alice_jwks.clone(), + }; + + let on_chain_state_bob_v222 = ProviderJWKs { + issuer: issuer_bob.clone(), + version: 222, + jwks: bob_jwks.clone(), + }; + + let initial_on_chain_state = AllProvidersJWKs { + entries: vec![ + on_chain_state_alice_v111.clone(), + on_chain_state_bob_v222.clone(), + ], + }; + + // On start, JWKManager is always initialized with the on-chain state. + assert!(jwk_manager + .reset_with_on_chain_state(initial_on_chain_state) + .is_ok()); + let mut expected_states = HashMap::from([ + ( + issuer_alice.clone(), + PerProviderState::new(on_chain_state_alice_v111.clone()), + ), + ( + issuer_bob.clone(), + PerProviderState::new(on_chain_state_bob_v222.clone()), + ), + ]); + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + let rpc_response_collector = Arc::new(RwLock::new(vec![])); + + // When JWK consensus is `NotStarted` for issuer Bob, JWKConsensusManager should: + // reply an error to any observation request and keep the state unchanged. + let bob_ob_req = new_rpc_observation_request( + 999, + issuer_bob.clone(), + addrs[3], + rpc_response_collector.clone(), + ); + assert!(jwk_manager.process_peer_request(bob_ob_req).is_ok()); + let last_invocations = std::mem::take(&mut *rpc_response_collector.write()); + assert!(last_invocations.len() == 1 && last_invocations[0].is_err()); + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + // When JWK consensus is `NotStarted` for issuer Carl, JWKConsensusManager should: + // reply an error to any observation request and keep the state unchanged; + // also create an entry in the state table on the fly. + let carl_ob_req = new_rpc_observation_request( + 999, + issuer_carl.clone(), + addrs[3], + rpc_response_collector.clone(), + ); + assert!(jwk_manager.process_peer_request(carl_ob_req).is_ok()); + let last_invocations = std::mem::take(&mut *rpc_response_collector.write()); + assert!(last_invocations.len() == 1 && last_invocations[0].is_err()); + expected_states.insert(issuer_carl.clone(), PerProviderState::default()); + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + // When JWK consensus is `NotStarted` for issuer Bob, JWKConsensusManager should: + // do nothing to an observation equal to on-chain state (except storing it, which may be unnecessary). + assert!(jwk_manager + .process_new_observation(issuer_bob.clone(), bob_jwks.clone()) + .is_ok()); + expected_states.get_mut(&issuer_bob).unwrap().observed = Some(bob_jwks.clone()); + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + // When JWK consensus is `NotStarted` for issuer Alice, JWKConsensusManager should: + // initiate a JWK consensus session if an update was observed. + let alice_jwks_new = vec![JWK::Unsupported(UnsupportedJWK::new_for_testing( + "alice_jwk_id_1", + "jwk_payload_1", + )) + .into()]; + assert!(jwk_manager + .process_new_observation(issuer_alice.clone(), alice_jwks_new.clone()) + .is_ok()); + { + let expected_alice_state = expected_states.get_mut(&issuer_alice).unwrap(); + expected_alice_state.observed = Some(alice_jwks_new.clone()); + let observed = ProviderJWKs { + issuer: issuer_alice.clone(), + version: 112, // on-chain baseline is at version 111. + jwks: alice_jwks_new.clone(), + }; + let signature = private_keys[0].sign(&observed).unwrap(); + expected_alice_state.consensus_state = ConsensusState::InProgress { + my_proposal: ObservedUpdate { + author: addrs[0], + observed, + signature, + }, + abort_handle_wrapper: QuorumCertProcessGuard::dummy(), + }; + } + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + // If we also found a JWK update for issuer Carl, a separate JWK consensus session should be started. + let carl_jwks_new = vec![JWK::Unsupported(UnsupportedJWK::new_for_testing( + "carl_jwk_id_0", + "jwk_payload_4", + )) + .into()]; + assert!(jwk_manager + .process_new_observation(issuer_carl.clone(), carl_jwks_new.clone()) + .is_ok()); + { + let expected_carl_state = expected_states.get_mut(&issuer_carl).unwrap(); + expected_carl_state.observed = Some(carl_jwks_new.clone()); + let observed = ProviderJWKs { + issuer: issuer_carl.clone(), + version: 1, + jwks: carl_jwks_new.clone(), + }; + let signature = private_keys[0].sign(&observed).unwrap(); + expected_carl_state.consensus_state = ConsensusState::InProgress { + my_proposal: ObservedUpdate { + author: addrs[0], + observed, + signature, + }, + abort_handle_wrapper: QuorumCertProcessGuard::dummy(), + }; + } + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + // Now that there are in-progress consensus sessions for Alice/Carl, + // if receiving an observation request for issuer Alice/Carl, JWKConsensusManager should reply with their signed observation. + let alice_ob_req = new_rpc_observation_request( + 999, + issuer_alice.clone(), + addrs[3], + rpc_response_collector.clone(), + ); + let carl_ob_req = new_rpc_observation_request( + 999, + issuer_carl.clone(), + addrs[3], + rpc_response_collector.clone(), + ); + assert!(jwk_manager.process_peer_request(alice_ob_req).is_ok()); + assert!(jwk_manager.process_peer_request(carl_ob_req).is_ok()); + assert_eq!(expected_states, jwk_manager.states_by_issuer); + let last_invocations: Vec = + std::mem::take(&mut *rpc_response_collector.write()) + .into_iter() + .map(|maybe_msg| maybe_msg.unwrap()) + .collect(); + let expected_responses = vec![ + JWKConsensusMsg::ObservationResponse(ObservedUpdateResponse { + epoch: 999, + update: expected_states + .get(&issuer_alice) + .unwrap() + .consensus_state + .my_proposal_cloned(), + }), + JWKConsensusMsg::ObservationResponse(ObservedUpdateResponse { + epoch: 999, + update: expected_states + .get(&issuer_carl) + .unwrap() + .consensus_state + .my_proposal_cloned(), + }), + ]; + assert_eq!(expected_responses, last_invocations); + + // If Alice rotates again while the consensus session for Alice is in progress, the existing session should be discarded and a new session should start. + let alice_jwks_new_2 = vec![ + JWK::Unsupported(UnsupportedJWK::new_for_testing( + "alice_jwk_id_1", + "jwk_payload_1", + )) + .into(), + JWK::Unsupported(UnsupportedJWK::new_for_testing( + "alice_jwk_id_3", + "jwk_payload_5", + )) + .into(), + ]; + assert!(jwk_manager + .process_new_observation(issuer_alice.clone(), alice_jwks_new_2.clone()) + .is_ok()); + { + let expected_alice_state = expected_states.get_mut(&issuer_alice).unwrap(); + expected_alice_state.observed = Some(alice_jwks_new_2.clone()); + let observed = ProviderJWKs { + issuer: issuer_alice.clone(), + version: 112, + jwks: alice_jwks_new_2.clone(), + }; + let signature = private_keys[0].sign(&observed).unwrap(); + expected_alice_state.consensus_state = ConsensusState::InProgress { + my_proposal: ObservedUpdate { + author: addrs[0], + observed, + signature, + }, + abort_handle_wrapper: QuorumCertProcessGuard::dummy(), + }; + } + assert_eq!(expected_states, jwk_manager.states_by_issuer); + + // For issuer Carl, in state `InProgress`, when receiving a quorum-certified update from the the aggregator: + // the state should be switched to `Finished`; + // Carl's update should be available in validator txn pool. + let qc_jwks_for_carl = expected_states + .get(&issuer_carl) + .unwrap() + .consensus_state + .my_proposal_cloned() + .observed; + let signer_bit_vec = BitVec::from(private_keys.iter().map(|_| true).collect::>()); + let sig = Signature::aggregate( + private_keys + .iter() + .map(|sk| sk.sign(&qc_jwks_for_carl).unwrap()) + .collect::>(), + ) + .unwrap(); + let multi_sig = AggregateSignature::new(signer_bit_vec, Some(sig)); + let qc_update_for_carl = QuorumCertifiedUpdate { + update: qc_jwks_for_carl, + multi_sig, + }; + assert!(jwk_manager + .process_quorum_certified_update(qc_update_for_carl.clone()) + .is_ok()); + { + let expected_carl_state = expected_states.get_mut(&issuer_carl).unwrap(); + expected_carl_state.consensus_state = ConsensusState::Finished { + vtxn_guard: vtxn_pool.dummy_txn_guard(), + my_proposal: expected_carl_state.consensus_state.my_proposal_cloned(), + quorum_certified: qc_update_for_carl.clone(), + }; + } + assert_eq!(expected_states, jwk_manager.states_by_issuer); + let expected_vtxns = vec![ValidatorTransaction::ObservedJWKUpdate( + qc_update_for_carl.clone(), + )]; + let actual_vtxns = vtxn_pool.pull( + Instant::now() + Duration::from_secs(3600), + 999, + 2048, + TransactionFilter::empty(), + ); + assert_eq!(expected_vtxns, actual_vtxns); + + // For issuer Carl, in state 'Finished`, JWKConsensusManager should still reply to observation requests with its own proposal. + let carl_ob_req = new_rpc_observation_request( + 999, + issuer_carl.clone(), + addrs[3], + rpc_response_collector.clone(), + ); + assert!(jwk_manager.process_peer_request(carl_ob_req).is_ok()); + assert_eq!(expected_states, jwk_manager.states_by_issuer); + let expected_responses = vec![JWKConsensusMsg::ObservationResponse( + ObservedUpdateResponse { + epoch: 999, + update: expected_states + .get(&issuer_carl) + .unwrap() + .consensus_state + .my_proposal_cloned(), + }, + )]; + let actual_responses: Vec = + std::mem::take(&mut *rpc_response_collector.write()) + .into_iter() + .map(|maybe_msg| maybe_msg.unwrap()) + .collect(); + assert_eq!(expected_responses, actual_responses); + + // If the consensus session for Alice is also done, JWKConsensusManager should: + // update the state for Alice to `Finished`; + // update the validator txn in the pool to also include the update for Alice. + let qc_jwks_for_alice = expected_states + .get(&issuer_alice) + .unwrap() + .consensus_state + .my_proposal_cloned() + .observed; + let signer_bit_vec = BitVec::from( + private_keys + .iter() + .take(3) + .map(|_| true) + .collect::>(), + ); + let sig = Signature::aggregate( + private_keys + .iter() + .take(3) + .map(|sk| sk.sign(&qc_jwks_for_alice).unwrap()) + .collect::>(), + ) + .unwrap(); + let multi_sig = AggregateSignature::new(signer_bit_vec, Some(sig)); + let qc_update_for_alice = QuorumCertifiedUpdate { + update: qc_jwks_for_alice, + multi_sig, + }; + assert!(jwk_manager + .process_quorum_certified_update(qc_update_for_alice.clone()) + .is_ok()); + { + let expected_alice_state = expected_states.get_mut(&issuer_alice).unwrap(); + expected_alice_state.consensus_state = ConsensusState::Finished { + vtxn_guard: vtxn_pool.dummy_txn_guard(), + my_proposal: expected_alice_state.consensus_state.my_proposal_cloned(), + quorum_certified: qc_update_for_alice.clone(), + }; + } + assert_eq!(expected_states, jwk_manager.states_by_issuer); + let expected_vtxn_hashes = vec![ + ValidatorTransaction::ObservedJWKUpdate(qc_update_for_alice), + ValidatorTransaction::ObservedJWKUpdate(qc_update_for_carl), + ] + .iter() + .map(CryptoHash::hash) + .collect::>(); + + let actual_vtxn_hashes = vtxn_pool + .pull( + Instant::now() + Duration::from_secs(3600), + 999, + 2048, + TransactionFilter::empty(), + ) + .iter() + .map(CryptoHash::hash) + .collect::>(); + assert_eq!(expected_vtxn_hashes, actual_vtxn_hashes); + + // At any time, JWKConsensusManager should fully follow on-chain update notification and re-initialize. + let second_on_chain_state = AllProvidersJWKs { + entries: vec![on_chain_state_alice_v111.clone()], + }; + + assert!(jwk_manager + .reset_with_on_chain_state(second_on_chain_state) + .is_ok()); + expected_states.remove(&issuer_bob); + expected_states.remove(&issuer_carl); + assert_eq!(expected_states, jwk_manager.states_by_issuer); +} + +fn new_rpc_observation_request( + epoch: u64, + issuer: Issuer, + sender: AccountAddress, + response_collector: Arc>>>, +) -> IncomingRpcRequest { + IncomingRpcRequest { + msg: JWKConsensusMsg::ObservationRequest(ObservedUpdateRequest { epoch, issuer }), + sender, + response_sender: Box::new(DummyRpcResponseSender::new(response_collector)), + } +} + +pub struct DummyUpdateCertifier { + pub invocations: Mutex, ProviderJWKs)>>, +} + +impl Default for DummyUpdateCertifier { + fn default() -> Self { + Self { + invocations: Mutex::new(vec![]), + } + } +} + +impl TUpdateCertifier for DummyUpdateCertifier { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + _agg_node_tx: aptos_channel::Sender, + ) -> AbortHandle { + self.invocations.lock().push((epoch_state, payload)); + let (abort_handle, _) = AbortHandle::new_pair(); + abort_handle + } +} diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index 74c011c537c3f..79c6b2fba32bc 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -29,6 +29,7 @@ pub fn start_jwk_consensus_runtime( runtime } +pub mod jwk_manager; pub mod jwk_observer; pub mod network; pub mod network_interface; diff --git a/crates/aptos-jwk-consensus/src/update_certifier.rs b/crates/aptos-jwk-consensus/src/update_certifier.rs index 2f79115bd5404..2cd29cb2032df 100644 --- a/crates/aptos-jwk-consensus/src/update_certifier.rs +++ b/crates/aptos-jwk-consensus/src/update_certifier.rs @@ -8,7 +8,7 @@ use aptos_channels::aptos_channel; use aptos_reliable_broadcast::ReliableBroadcast; use aptos_types::{ epoch_state::EpochState, - jwks::{ProviderJWKs, QuorumCertifiedUpdate}, + jwks::{Issuer, ProviderJWKs, QuorumCertifiedUpdate}, }; use futures_util::future::{AbortHandle, Abortable}; use std::sync::Arc; @@ -23,7 +23,7 @@ pub trait TUpdateCertifier: Send + Sync { &self, epoch_state: Arc, payload: ProviderJWKs, - qc_update_tx: aptos_channel::Sender<(), QuorumCertifiedUpdate>, + qc_update_tx: aptos_channel::Sender, ) -> AbortHandle; } @@ -44,17 +44,18 @@ impl TUpdateCertifier for CertifiedUpdateProducer { &self, epoch_state: Arc, payload: ProviderJWKs, - qc_update_tx: aptos_channel::Sender<(), QuorumCertifiedUpdate>, + qc_update_tx: aptos_channel::Sender, ) -> AbortHandle { let rb = self.reliable_broadcast.clone(); + let issuer = payload.issuer.clone(); let req = ObservedUpdateRequest { epoch: epoch_state.epoch, - issuer: payload.issuer.clone(), + issuer: issuer.clone(), }; let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); let task = async move { let qc_update = rb.broadcast(req, agg_state).await; - let _ = qc_update_tx.push((), qc_update); + let _ = qc_update_tx.push(issuer, qc_update); }; let (abort_handle, abort_registration) = AbortHandle::new_pair(); tokio::spawn(Abortable::new(task, abort_registration)); From dba97f7afc1e49ee857ea7569870828a9c163923 Mon Sep 17 00:00:00 2001 From: Gerardo Di Giacomo Date: Mon, 5 Feb 2024 09:44:19 -0800 Subject: [PATCH 007/328] Update Docker images (#11893) Co-authored-by: gedigi --- docker/builder/docker-bake-rust-all.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/builder/docker-bake-rust-all.hcl b/docker/builder/docker-bake-rust-all.hcl index 0bd7db9079f43..83986c154fd68 100644 --- a/docker/builder/docker-bake-rust-all.hcl +++ b/docker/builder/docker-bake-rust-all.hcl @@ -70,7 +70,7 @@ target "debian-base" { dockerfile = "docker/builder/debian-base.Dockerfile" contexts = { # Run `docker buildx imagetools inspect debian:bullseye` to find the latest multi-platform hash - debian = "docker-image://debian:bullseye@sha256:71cb300d5448af821aedfe63afd55ba05f45a6a79f00dcd131b96b780bb99fe4" + debian = "docker-image://debian:bullseye@sha256:44cfd77e3dbebfa8a0545d9fd1bee6e874cf6998a3bbfb5cccf34919df4e3360" } } From 3cd435c2cdcfb6dcbff07baa24e4e20585c9c348 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Mon, 5 Feb 2024 10:06:51 -0800 Subject: [PATCH 008/328] jwk #7: epoch manager (#11858) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * jwk update quorum certification * jwk observation * the main jwk consensus state machine * jwk consensus epoch manager * update * update * update --- .../src/certified_update_producer.rs | 64 ----- .../aptos-jwk-consensus/src/epoch_manager.rs | 225 ++++++++++++++++++ crates/aptos-jwk-consensus/src/lib.rs | 1 + .../src/update_certifier.rs | 6 +- types/src/contract_event.rs | 19 ++ 5 files changed, 248 insertions(+), 67 deletions(-) delete mode 100644 crates/aptos-jwk-consensus/src/certified_update_producer.rs create mode 100644 crates/aptos-jwk-consensus/src/epoch_manager.rs diff --git a/crates/aptos-jwk-consensus/src/certified_update_producer.rs b/crates/aptos-jwk-consensus/src/certified_update_producer.rs deleted file mode 100644 index 9db8d77d09647..0000000000000 --- a/crates/aptos-jwk-consensus/src/certified_update_producer.rs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright © Aptos Foundation - -use crate::{ - observation_aggregation::ObservationAggregationState, - types::{JWKConsensusMsg, ObservedUpdateRequest}, -}; -use aptos_channels::aptos_channel; -use aptos_reliable_broadcast::ReliableBroadcast; -use aptos_types::{ - epoch_state::EpochState, - jwks::{Issuer, ProviderJWKs, QuorumCertifiedUpdate}, -}; -use futures_util::future::{AbortHandle, Abortable}; -use std::sync::Arc; -use tokio_retry::strategy::ExponentialBackoff; - -/// A sub-process of the whole JWK consensus process. -/// Once invoked by `JWKConsensusManager` to `start_produce`, -/// it starts producing a `QuorumCertifiedUpdate` and returns an abort handle. -/// Once an `QuorumCertifiedUpdate` is available, it is sent back via a channel given earlier. -pub trait CertifiedUpdateProducer: Send + Sync { - fn start_produce( - &self, - epoch_state: Arc, - payload: ProviderJWKs, - qc_update_tx: aptos_channel::Sender, - ) -> AbortHandle; -} - -pub struct RealCertifiedUpdateProducer { - reliable_broadcast: Arc>, -} - -impl RealCertifiedUpdateProducer { - pub fn new(reliable_broadcast: ReliableBroadcast) -> Self { - Self { - reliable_broadcast: Arc::new(reliable_broadcast), - } - } -} - -impl CertifiedUpdateProducer for RealCertifiedUpdateProducer { - fn start_produce( - &self, - epoch_state: Arc, - payload: ProviderJWKs, - qc_update_tx: aptos_channel::Sender, - ) -> AbortHandle { - let rb = self.reliable_broadcast.clone(); - let issuer = payload.issuer.clone(); - let req = ObservedUpdateRequest { - epoch: epoch_state.epoch, - issuer: issuer.clone(), - }; - let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); - let task = async move { - let qc_update = rb.broadcast(req, agg_state).await; - let _ = qc_update_tx.push(issuer, qc_update); - }; - let (abort_handle, abort_registration) = AbortHandle::new_pair(); - tokio::spawn(Abortable::new(task, abort_registration)); - abort_handle - } -} diff --git a/crates/aptos-jwk-consensus/src/epoch_manager.rs b/crates/aptos-jwk-consensus/src/epoch_manager.rs new file mode 100644 index 0000000000000..308e145654391 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/epoch_manager.rs @@ -0,0 +1,225 @@ +// Copyright © Aptos Foundation + +use crate::{ + jwk_manager::JWKManager, + network::{IncomingRpcRequest, NetworkReceivers, NetworkSender}, + network_interface::JWKConsensusNetworkClient, + types::JWKConsensusMsg, + update_certifier::UpdateCertifier, +}; +use anyhow::Result; +use aptos_bounded_executor::BoundedExecutor; +use aptos_channels::{aptos_channel, message_queues::QueueStyle}; +use aptos_consensus_types::common::Author; +use aptos_crypto::bls12381::PrivateKey; +use aptos_event_notifications::{ + EventNotification, EventNotificationListener, ReconfigNotification, + ReconfigNotificationListener, +}; +use aptos_logger::{error, info}; +use aptos_network::{application::interface::NetworkClient, protocols::network::Event}; +use aptos_reliable_broadcast::ReliableBroadcast; +use aptos_types::{ + account_address::AccountAddress, + epoch_state::EpochState, + jwks::{ObservedJWKs, ObservedJWKsUpdated, SupportedOIDCProviders}, + on_chain_config::{ + FeatureFlag, Features, OnChainConfigPayload, OnChainConfigProvider, ValidatorSet, + }, +}; +use aptos_validator_transaction_pool::VTxnPoolState; +use futures::StreamExt; +use futures_channel::oneshot; +use std::{sync::Arc, time::Duration}; +use tokio_retry::strategy::ExponentialBackoff; + +pub struct EpochManager { + // some useful metadata + my_addr: AccountAddress, + epoch_state: Option>, + + // credential + consensus_key: Arc, + + // events we subscribe + reconfig_events: ReconfigNotificationListener

, + jwk_updated_events: EventNotificationListener, + + // message channels to JWK manager + jwk_updated_event_txs: Option>, + jwk_rpc_msg_tx: Option>, + jwk_manager_close_tx: Option>>, + + // network utils + self_sender: aptos_channels::Sender>, + network_sender: JWKConsensusNetworkClient>, + + // vtxn pool handle + vtxn_pool: VTxnPoolState, +} + +impl EpochManager

{ + pub fn new( + my_addr: AccountAddress, + consensus_key: PrivateKey, + reconfig_events: ReconfigNotificationListener

, + jwk_updated_events: EventNotificationListener, + self_sender: aptos_channels::Sender>, + network_sender: JWKConsensusNetworkClient>, + vtxn_pool: VTxnPoolState, + ) -> Self { + Self { + my_addr, + consensus_key: Arc::new(consensus_key), + epoch_state: None, + reconfig_events, + jwk_updated_events, + self_sender, + network_sender, + vtxn_pool, + jwk_updated_event_txs: None, + jwk_rpc_msg_tx: None, + jwk_manager_close_tx: None, + } + } + + /// On a new RPC request, forward to JWK consensus manager, if it is alive. + fn process_rpc_request( + &mut self, + peer_id: Author, + rpc_request: IncomingRpcRequest, + ) -> Result<()> { + if Some(rpc_request.msg.epoch()) == self.epoch_state.as_ref().map(|s| s.epoch) { + if let Some(tx) = &self.jwk_rpc_msg_tx { + let _ = tx.push((), (peer_id, rpc_request)); + } + } + Ok(()) + } + + /// On a on-chain JWK updated events, forward to JWK consensus manager if it is alive. + fn process_onchain_event(&mut self, notification: EventNotification) -> Result<()> { + let EventNotification { + subscribed_events, .. + } = notification; + for event in subscribed_events { + if let Ok(jwk_event) = ObservedJWKsUpdated::try_from(&event) { + if let Some(tx) = self.jwk_updated_event_txs.as_ref() { + let _ = tx.push((), jwk_event); + } + } + } + Ok(()) + } + + pub async fn start(mut self, mut network_receivers: NetworkReceivers) { + self.await_reconfig_notification().await; + loop { + let handle_result = tokio::select! { + reconfig_notification = self.reconfig_events.select_next_some() => { + self.on_new_epoch(reconfig_notification).await + }, + event = self.jwk_updated_events.select_next_some() => { + self.process_onchain_event(event) + }, + (peer, rpc_request) = network_receivers.rpc_rx.select_next_some() => { + self.process_rpc_request(peer, rpc_request) + } + }; + + if let Err(e) = handle_result { + error!("{}", e); + } + } + } + + async fn await_reconfig_notification(&mut self) { + let reconfig_notification = self + .reconfig_events + .next() + .await + .expect("Reconfig sender dropped, unable to start new epoch"); + self.start_new_epoch(reconfig_notification.on_chain_configs) + .await; + } + + async fn start_new_epoch(&mut self, payload: OnChainConfigPayload

) { + let validator_set: ValidatorSet = payload + .get() + .expect("failed to get ValidatorSet from payload"); + + let epoch_state = Arc::new(EpochState { + epoch: payload.epoch(), + verifier: (&validator_set).into(), + }); + self.epoch_state = Some(epoch_state.clone()); + info!("[JWK] start_new_epoch: new_epoch={}", epoch_state.epoch); + + let features = payload.get::().unwrap_or_default(); + + if features.is_enabled(FeatureFlag::JWK_CONSENSUS) { + let onchain_oidc_provider_set = payload.get::().ok(); + let onchain_observed_jwks = payload.get::().ok(); + info!("[JWK] JWK manager init, epoch={}", epoch_state.epoch); + let network_sender = NetworkSender::new( + self.my_addr, + self.network_sender.clone(), + self.self_sender.clone(), + ); + let rb = ReliableBroadcast::new( + epoch_state.verifier.get_ordered_account_addresses(), + Arc::new(network_sender), + ExponentialBackoff::from_millis(5), + aptos_time_service::TimeService::real(), + Duration::from_millis(1000), + BoundedExecutor::new(8, tokio::runtime::Handle::current()), + ); + let update_certifier = UpdateCertifier::new(rb); + + let jwk_consensus_manager = JWKManager::new( + self.consensus_key.clone(), + self.my_addr, + epoch_state.clone(), + Arc::new(update_certifier), + self.vtxn_pool.clone(), + ); + + let (jwk_event_tx, jwk_event_rx) = aptos_channel::new(QueueStyle::KLAST, 1, None); + self.jwk_updated_event_txs = Some(jwk_event_tx); + let (jwk_rpc_msg_tx, jwk_rpc_msg_rx) = aptos_channel::new(QueueStyle::FIFO, 100, None); + + let (jwk_manager_close_tx, jwk_manager_close_rx) = oneshot::channel(); + self.jwk_rpc_msg_tx = Some(jwk_rpc_msg_tx); + self.jwk_manager_close_tx = Some(jwk_manager_close_tx); + + tokio::spawn(jwk_consensus_manager.run( + onchain_oidc_provider_set, + onchain_observed_jwks, + jwk_event_rx, + jwk_rpc_msg_rx, + jwk_manager_close_rx, + )); + info!( + "jwk consensus manager spawned for epoch {}", + epoch_state.epoch + ); + } + } + + async fn on_new_epoch(&mut self, reconfig_notification: ReconfigNotification

) -> Result<()> { + self.shutdown_current_processor().await; + self.start_new_epoch(reconfig_notification.on_chain_configs) + .await; + Ok(()) + } + + async fn shutdown_current_processor(&mut self) { + if let Some(tx) = self.jwk_manager_close_tx.take() { + let (ack_tx, ack_rx) = oneshot::channel(); + let _ = tx.send(ack_tx); + let _ = ack_rx.await; + } + + self.jwk_updated_event_txs = None; + } +} diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index 79c6b2fba32bc..2ee3f8405dad7 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -29,6 +29,7 @@ pub fn start_jwk_consensus_runtime( runtime } +pub mod epoch_manager; pub mod jwk_manager; pub mod jwk_observer; pub mod network; diff --git a/crates/aptos-jwk-consensus/src/update_certifier.rs b/crates/aptos-jwk-consensus/src/update_certifier.rs index 2cd29cb2032df..b2f380f45258e 100644 --- a/crates/aptos-jwk-consensus/src/update_certifier.rs +++ b/crates/aptos-jwk-consensus/src/update_certifier.rs @@ -27,11 +27,11 @@ pub trait TUpdateCertifier: Send + Sync { ) -> AbortHandle; } -pub struct CertifiedUpdateProducer { +pub struct UpdateCertifier { reliable_broadcast: Arc>, } -impl CertifiedUpdateProducer { +impl UpdateCertifier { pub fn new(reliable_broadcast: ReliableBroadcast) -> Self { Self { reliable_broadcast: Arc::new(reliable_broadcast), @@ -39,7 +39,7 @@ impl CertifiedUpdateProducer { } } -impl TUpdateCertifier for CertifiedUpdateProducer { +impl TUpdateCertifier for UpdateCertifier { fn start_produce( &self, epoch_state: Arc, diff --git a/types/src/contract_event.rs b/types/src/contract_event.rs index c3f1d9addc472..10fbdaf41aab4 100644 --- a/types/src/contract_event.rs +++ b/types/src/contract_event.rs @@ -6,6 +6,7 @@ use crate::{ account_config::{DepositEvent, NewBlockEvent, NewEpochEvent, WithdrawEvent}, dkg::DKGStartEvent, event::EventKey, + jwks::ObservedJWKsUpdated, on_chain_config::new_epoch_event_key, transaction::Version, }; @@ -360,6 +361,24 @@ impl TryFrom<&ContractEvent> for DepositEvent { } } +impl TryFrom<&ContractEvent> for ObservedJWKsUpdated { + type Error = Error; + + fn try_from(event: &ContractEvent) -> Result { + match event { + ContractEvent::V1(_) => { + bail!("conversion to `ObservedJWKsUpdated` failed with wrong event version") + }, + ContractEvent::V2(v2) => { + if v2.type_tag != TypeTag::Struct(Box::new(Self::struct_tag())) { + bail!("conversion to `ObservedJWKsUpdated` failed with wrong type tag"); + } + bcs::from_bytes(&v2.event_data).map_err(Into::into) + }, + } + } +} + impl std::fmt::Debug for ContractEvent { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { From 546e72663a7acb88c214d56c40d33eb03ca0a61e Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Mon, 5 Feb 2024 14:12:46 -0800 Subject: [PATCH 009/328] jwk #8: jwk consensus wired into node (#11861) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * jwk update quorum certification * jwk observation * the main jwk consensus state machine * jwk consensus epoch manager * update * jwk consensus wired into node * update * update * update * fmt * debug * debug * debug * debug * fmt --- Cargo.lock | 1 + aptos-node/Cargo.toml | 1 + aptos-node/src/lib.rs | 74 ++++++++++++------- aptos-node/src/state_sync.rs | 4 +- config/src/config/identity_config.rs | 17 +---- .../src/certified_update_producer.rs | 65 ++++++++++++++++ crates/aptos-jwk-consensus/src/counters.rs | 13 ++++ crates/aptos-jwk-consensus/src/lib.rs | 43 +++++++---- execution/executor-types/src/lib.rs | 2 +- 9 files changed, 158 insertions(+), 62 deletions(-) create mode 100644 crates/aptos-jwk-consensus/src/certified_update_producer.rs create mode 100644 crates/aptos-jwk-consensus/src/counters.rs diff --git a/Cargo.lock b/Cargo.lock index d1bdd32c4d426..fe5b054e7744d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3083,6 +3083,7 @@ dependencies = [ "aptos-peer-monitoring-service-server", "aptos-peer-monitoring-service-types", "aptos-runtimes", + "aptos-safety-rules", "aptos-secure-storage", "aptos-state-sync-driver", "aptos-storage-interface", diff --git a/aptos-node/Cargo.toml b/aptos-node/Cargo.toml index 2b5ca01938778..9e87b7bc9cb7d 100644 --- a/aptos-node/Cargo.toml +++ b/aptos-node/Cargo.toml @@ -51,6 +51,7 @@ aptos-peer-monitoring-service-client = { workspace = true } aptos-peer-monitoring-service-server = { workspace = true } aptos-peer-monitoring-service-types = { workspace = true } aptos-runtimes = { workspace = true } +aptos-safety-rules = { workspace = true } aptos-secure-storage = { workspace = true } aptos-state-sync-driver = { workspace = true } aptos-storage-interface = { workspace = true } diff --git a/aptos-node/src/lib.rs b/aptos-node/src/lib.rs index a98369f493f4a..5834b0e5bdab8 100644 --- a/aptos-node/src/lib.rs +++ b/aptos-node/src/lib.rs @@ -20,11 +20,14 @@ use anyhow::anyhow; use aptos_admin_service::AdminService; use aptos_api::bootstrap as bootstrap_api; use aptos_build_info::build_information; -use aptos_config::config::{merge_node_config, NodeConfig, PersistableConfig}; +use aptos_config::config::{ + merge_node_config, InitialSafetyRulesConfig, NodeConfig, PersistableConfig, +}; use aptos_dkg_runtime::start_dkg_runtime; use aptos_framework::ReleaseBundle; use aptos_jwk_consensus::start_jwk_consensus_runtime; use aptos_logger::{prelude::*, telemetry_log_writer::TelemetryLog, Level, LoggerFilterUpdater}; +use aptos_safety_rules::safety_rules_manager::load_consensus_key_from_secure_storage; use aptos_state_sync_driver::driver_factory::StateSyncRuntimes; use aptos_types::chain_id::ChainId; use aptos_validator_transaction_pool::VTxnPoolState; @@ -657,17 +660,24 @@ pub fn setup_environment_and_start_node( mempool_client_receiver, peers_and_metadata, ); - let vtxn_pool = VTxnPoolState::default(); - let maybe_dkg_dealer_sk = node_config - .consensus - .safety_rules - .initial_safety_rules_config - .identity_blob() - .ok() - .and_then(|blob| blob.try_into_dkg_dealer_private_key()); + // Ensure consensus key in secure DB. + if !matches!( + node_config + .consensus + .safety_rules + .initial_safety_rules_config, + InitialSafetyRulesConfig::None + ) { + aptos_safety_rules::safety_rules_manager::storage(&node_config.consensus.safety_rules); + } + + let vtxn_pool = VTxnPoolState::default(); + let maybe_dkg_dealer_sk = + load_consensus_key_from_secure_storage(&node_config.consensus.safety_rules); + debug!("maybe_dkg_dealer_sk={:?}", maybe_dkg_dealer_sk); let dkg_runtime = match (dkg_network_interfaces, maybe_dkg_dealer_sk) { - (Some(interfaces), Some(dkg_dealer_sk)) => { + (Some(interfaces), Ok(dkg_dealer_sk)) => { let ApplicationNetworkInterfaces { network_client, network_service_events, @@ -689,24 +699,32 @@ pub fn setup_environment_and_start_node( _ => None, }; - let jwk_consensus_runtime = if let Some(obj) = jwk_consensus_network_interfaces { - let ApplicationNetworkInterfaces { - network_client, - network_service_events, - } = obj; - let (reconfig_events, onchain_jwk_updated_events) = jwk_consensus_subscriptions.expect( - "JWK consensus needs to listen to NewEpochEvents and OnChainJWKMapUpdated events.", - ); - let jwk_consensus_runtime = start_jwk_consensus_runtime( - network_client, - network_service_events, - vtxn_pool.clone(), - reconfig_events, - onchain_jwk_updated_events, - ); - Some(jwk_consensus_runtime) - } else { - None + let maybe_jwk_consensus_key = + load_consensus_key_from_secure_storage(&node_config.consensus.safety_rules); + debug!("maybe_jwk_consensus_key={:?}", maybe_jwk_consensus_key); + + let jwk_consensus_runtime = match (jwk_consensus_network_interfaces, maybe_jwk_consensus_key) { + (Some(interfaces), Ok(consensus_key)) => { + let ApplicationNetworkInterfaces { + network_client, + network_service_events, + } = interfaces; + let (reconfig_events, onchain_jwk_updated_events) = jwk_consensus_subscriptions.expect( + "JWK consensus needs to listen to NewEpochEvents and OnChainJWKMapUpdated events.", + ); + let my_addr = node_config.validator_network.as_ref().unwrap().peer_id(); + let jwk_consensus_runtime = start_jwk_consensus_runtime( + my_addr, + consensus_key, + network_client, + network_service_events, + reconfig_events, + onchain_jwk_updated_events, + vtxn_pool.clone(), + ); + Some(jwk_consensus_runtime) + }, + _ => None, }; // Create the consensus runtime (this blocks on state sync first) diff --git a/aptos-node/src/state_sync.rs b/aptos-node/src/state_sync.rs index 83cc9483e57e5..4ae8f6492f948 100644 --- a/aptos-node/src/state_sync.rs +++ b/aptos-node/src/state_sync.rs @@ -53,7 +53,7 @@ pub fn create_event_subscription_service( Option<( ReconfigNotificationListener, EventNotificationListener, - )>, // (reconfig_events, jwk_map_updated_events) for JWK consensus + )>, // (reconfig_events, jwk_updated_events) for JWK consensus ) { // Create the event subscription service let mut event_subscription_service = @@ -92,7 +92,7 @@ pub fn create_event_subscription_service( .subscribe_to_reconfigurations() .expect("JWK consensus must subscribe to reconfigurations"); let jwk_updated_events = event_subscription_service - .subscribe_to_events(vec![], vec!["0x1::jwks::OnChainJWKMapUpdated".to_string()]) + .subscribe_to_events(vec![], vec!["0x1::jwks::ObservedJWKsUpdated".to_string()]) .expect("JWK consensus must subscribe to DKG events"); Some((reconfig_events, jwk_updated_events)) } else { diff --git a/config/src/config/identity_config.rs b/config/src/config/identity_config.rs index 7026a35105505..f113fdb2c82ec 100644 --- a/config/src/config/identity_config.rs +++ b/config/src/config/identity_config.rs @@ -3,10 +3,7 @@ use crate::{config::SecureBackend, keys::ConfigKey}; use aptos_crypto::{bls12381, ed25519::Ed25519PrivateKey, x25519}; -use aptos_types::{ - account_address::{AccountAddress, AccountAddress as PeerId}, - dkg::{DKGTrait, DefaultDKG}, -}; +use aptos_types::account_address::{AccountAddress, AccountAddress as PeerId}; use serde::{Deserialize, Serialize}; use std::{ fs, @@ -40,18 +37,6 @@ impl IdentityBlob { let mut file = File::open(path)?; Ok(file.write_all(serde_yaml::to_string(self)?.as_bytes())?) } - - pub fn try_into_dkg_dealer_private_key( - self, - ) -> Option<::DealerPrivateKey> { - self.consensus_private_key - } - - pub fn try_into_dkg_new_validator_decrypt_key( - self, - ) -> Option<::NewValidatorDecryptKey> { - self.consensus_private_key - } } #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] diff --git a/crates/aptos-jwk-consensus/src/certified_update_producer.rs b/crates/aptos-jwk-consensus/src/certified_update_producer.rs new file mode 100644 index 0000000000000..d60c241573f4e --- /dev/null +++ b/crates/aptos-jwk-consensus/src/certified_update_producer.rs @@ -0,0 +1,65 @@ +// Copyright © Aptos Foundation + +use crate::{ + observation_aggregation::ObservationAggregationState, + types::{JWKConsensusMsg, ObservedUpdateRequest}, +}; +use aptos_channels::aptos_channel; +use aptos_reliable_broadcast::ReliableBroadcast; +use aptos_types::{ + epoch_state::EpochState, + jwks::{ProviderJWKs, QuorumCertifiedUpdate}, +}; +use futures_util::future::{AbortHandle, Abortable}; +use std::sync::Arc; +use tokio_retry::strategy::ExponentialBackoff; + +/// A sub-process of the whole JWK consensus process. +/// Once invoked by `JWKConsensusManager` to `start_produce`, +/// it starts producing a `QuorumCertifiedUpdate` and returns an abort handle. +/// Once an `QuorumCertifiedUpdate` is available, it is sent back via a channel given earlier. +pub trait CertifiedUpdateProducer: Send + Sync { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + qc_update_tx: Option>, + ) -> AbortHandle; +} + +pub struct RealCertifiedUpdateProducer { + reliable_broadcast: Arc>, +} + +impl RealCertifiedUpdateProducer { + pub fn new(reliable_broadcast: ReliableBroadcast) -> Self { + Self { + reliable_broadcast: Arc::new(reliable_broadcast), + } + } +} + +impl CertifiedUpdateProducer for RealCertifiedUpdateProducer { + fn start_produce( + &self, + epoch_state: Arc, + payload: ProviderJWKs, + qc_update_tx: Option>, + ) -> AbortHandle { + let rb = self.reliable_broadcast.clone(); + let req = ObservedUpdateRequest { + epoch: epoch_state.epoch, + issuer: payload.issuer.clone(), + }; + let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); + let task = async move { + let qc_update = rb.broadcast(req, agg_state).await; + if let Some(tx) = qc_update_tx { + let _ = tx.push((), qc_update); + } + }; + let (abort_handle, abort_registration) = AbortHandle::new_pair(); + tokio::spawn(Abortable::new(task, abort_registration)); + abort_handle + } +} diff --git a/crates/aptos-jwk-consensus/src/counters.rs b/crates/aptos-jwk-consensus/src/counters.rs new file mode 100644 index 0000000000000..18ec2bf99a862 --- /dev/null +++ b/crates/aptos-jwk-consensus/src/counters.rs @@ -0,0 +1,13 @@ +// Copyright © Aptos Foundation + +use aptos_metrics_core::{register_int_gauge, IntGauge}; +use once_cell::sync::Lazy; + +/// Count of the pending messages sent to itself in the channel +pub static PENDING_SELF_MESSAGES: Lazy = Lazy::new(|| { + register_int_gauge!( + "aptos_jwk_consensus_pending_self_messages", + "Count of the pending JWK consensus messages sent to itself in the channel" + ) + .unwrap() +}); diff --git a/crates/aptos-jwk-consensus/src/lib.rs b/crates/aptos-jwk-consensus/src/lib.rs index 2ee3f8405dad7..2d23907e396dd 100644 --- a/crates/aptos-jwk-consensus/src/lib.rs +++ b/crates/aptos-jwk-consensus/src/lib.rs @@ -1,34 +1,47 @@ // Copyright © Aptos Foundation -use crate::types::JWKConsensusMsg; +use crate::{ + epoch_manager::EpochManager, network::NetworkTask, + network_interface::JWKConsensusNetworkClient, types::JWKConsensusMsg, +}; +use aptos_crypto::bls12381::PrivateKey; use aptos_event_notifications::{ DbBackedOnChainConfig, EventNotificationListener, ReconfigNotificationListener, }; use aptos_network::application::interface::{NetworkClient, NetworkServiceEvents}; +use aptos_types::account_address::AccountAddress; use aptos_validator_transaction_pool::VTxnPoolState; -use futures_util::StreamExt; use tokio::runtime::Runtime; #[allow(clippy::let_and_return)] pub fn start_jwk_consensus_runtime( - _network_client: NetworkClient, - _network_service_events: NetworkServiceEvents, - _vtxn_pool: VTxnPoolState, - mut reconfig_events: ReconfigNotificationListener, - mut onchain_jwk_updated_events: EventNotificationListener, + my_addr: AccountAddress, + consensus_key: PrivateKey, + network_client: NetworkClient, + network_service_events: NetworkServiceEvents, + reconfig_events: ReconfigNotificationListener, + jwk_updated_events: EventNotificationListener, + vtxn_pool_writer: VTxnPoolState, ) -> Runtime { let runtime = aptos_runtimes::spawn_named_runtime("jwk".into(), Some(4)); - runtime.spawn(async move { - loop { - tokio::select! { - _ = reconfig_events.select_next_some() => {}, - _ = onchain_jwk_updated_events.select_next_some() => {}, - } - } - }); + let (self_sender, self_receiver) = aptos_channels::new(1_024, &counters::PENDING_SELF_MESSAGES); + let jwk_consensus_network_client = JWKConsensusNetworkClient::new(network_client); + let epoch_manager = EpochManager::new( + my_addr, + consensus_key, + reconfig_events, + jwk_updated_events, + self_sender, + jwk_consensus_network_client, + vtxn_pool_writer, + ); + let (network_task, network_receiver) = NetworkTask::new(network_service_events, self_receiver); + runtime.spawn(network_task.start()); + runtime.spawn(epoch_manager.start(network_receiver)); runtime } +pub mod counters; pub mod epoch_manager; pub mod jwk_manager; pub mod jwk_observer; diff --git a/execution/executor-types/src/lib.rs b/execution/executor-types/src/lib.rs index 0d588e86b4871..579fbca31280c 100644 --- a/execution/executor-types/src/lib.rs +++ b/execution/executor-types/src/lib.rs @@ -530,6 +530,6 @@ pub fn should_forward_to_subscription_service(event: &ContractEvent) -> bool { event.type_tag().to_string().as_str(), "0x1::reconfiguration::NewEpochEvent" | "0x1::dkg::DKGStartEvent" - | "0x1::jwks::OnChainJWKMapUpdated" + | "0x1::jwks::ObservedJWKsUpdated" ) } From c5a1b598540ee6aaab1a9b27e2d550cd8e7f04f9 Mon Sep 17 00:00:00 2001 From: Justin Chang <37165464+just-in-chang@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:33:55 -0800 Subject: [PATCH 010/328] [NFT Metadata Crawler] Change dedupe + retry logic (#11887) * Change dedupe + retry logic * lint * boolean * Move commit logic --- .../src/models/nft_metadata_crawler_uris.rs | 22 +- .../src/utils/constants.rs | 3 + .../nft-metadata-crawler-parser/src/worker.rs | 229 ++++++++++-------- 3 files changed, 146 insertions(+), 108 deletions(-) diff --git a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs index 4316b1f6b4797..898e4f3a69eb8 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs @@ -1,6 +1,9 @@ // Copyright © Aptos Foundation -use crate::schema::nft_metadata_crawler::parsed_asset_uris; +use crate::{ + models::nft_metadata_crawler_uris_query::NFTMetadataCrawlerURIsQuery, + schema::nft_metadata_crawler::parsed_asset_uris, +}; use diesel::prelude::*; use field_count::FieldCount; use serde::{Deserialize, Serialize}; @@ -153,3 +156,20 @@ impl NFTMetadataCrawlerURIs { self.do_not_parse = do_not_parse; } } + +impl From for NFTMetadataCrawlerURIs { + fn from(query: NFTMetadataCrawlerURIsQuery) -> Self { + Self { + asset_uri: query.asset_uri, + raw_image_uri: query.raw_image_uri, + raw_animation_uri: query.raw_animation_uri, + cdn_json_uri: query.cdn_json_uri, + cdn_image_uri: query.cdn_image_uri, + cdn_animation_uri: query.cdn_animation_uri, + json_parser_retry_count: query.json_parser_retry_count, + image_optimizer_retry_count: query.image_optimizer_retry_count, + animation_optimizer_retry_count: query.animation_optimizer_retry_count, + do_not_parse: query.do_not_parse, + } + } +} diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/constants.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/constants.rs index 7bae24d8cb476..f13a6008eb601 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/constants.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/constants.rs @@ -12,6 +12,9 @@ pub const MAX_JSON_REQUEST_RETRY_SECONDS: u64 = 30; /// Allocate 90 seconds for downloading large image files pub const MAX_IMAGE_REQUEST_RETRY_SECONDS: u64 = 90; +/// Max number of retries for a given asset_uri +pub const MAX_NUM_PARSE_RETRIES: i32 = 3; + /// Default 15 MB maximum file size for files to be downloaded pub const DEFAULT_MAX_FILE_SIZE_BYTES: u32 = 15_000_000; diff --git a/ecosystem/nft-metadata-crawler-parser/src/worker.rs b/ecosystem/nft-metadata-crawler-parser/src/worker.rs index f6df5743ba3c9..d2e4eb63d47dd 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/worker.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/worker.rs @@ -9,6 +9,7 @@ use crate::{ utils::{ constants::{ DEFAULT_IMAGE_QUALITY, DEFAULT_MAX_FILE_SIZE_BYTES, DEFAULT_MAX_IMAGE_DIMENSIONS, + MAX_NUM_PARSE_RETRIES, }, counters::{ DUPLICATE_ASSET_URI_COUNT, DUPLICATE_RAW_ANIMATION_URI_COUNT, @@ -80,15 +81,14 @@ impl Worker { // Exit if not force or if asset_uri has already been parsed let prev_model = NFTMetadataCrawlerURIsQuery::get_by_asset_uri(self.asset_uri.clone(), &mut self.conn); - if !self.force && prev_model.is_some() { - self.log_info("Duplicate asset_uri found, skipping parse"); + if let Some(pm) = prev_model { DUPLICATE_ASSET_URI_COUNT.inc(); - return Ok(()); - } - - if prev_model.unwrap_or_default().do_not_parse { - self.log_info("do_not_parse is true, skipping parse"); - return Ok(()); + if !self.force && pm.do_not_parse { + self.log_info("asset_uri has been marked as do_not_parse, skipping parse"); + SKIP_URI_COUNT.with_label_values(&["do_not_parse"]).inc(); + return Ok(()); + } + self.model = pm.into(); } // Skip if asset_uri contains any of the uris in URI_SKIP_LIST @@ -111,87 +111,90 @@ impl Worker { return Ok(()); } - // Parse asset_uri - self.log_info("Parsing asset_uri"); - let json_uri = URIParser::parse( - self.config.ipfs_prefix.clone(), - self.model.get_asset_uri(), - self.config.ipfs_auth_key.clone(), - ) - .unwrap_or_else(|_| { - self.log_warn("Failed to parse asset_uri", None); - PARSE_URI_TYPE_COUNT.with_label_values(&["other"]).inc(); - self.model.get_asset_uri() - }); - - // Parse JSON for raw_image_uri and raw_animation_uri - self.log_info("Starting JSON parsing"); - let (raw_image_uri, raw_animation_uri, json) = JSONParser::parse( - json_uri, - self.config - .max_file_size_bytes - .unwrap_or(DEFAULT_MAX_FILE_SIZE_BYTES), - ) - .await - .unwrap_or_else(|e| { - // Increment retry count if JSON parsing fails - self.log_warn("JSON parsing failed", Some(&e)); - self.model.increment_json_parser_retry_count(); - (None, None, Value::Null) - }); - - self.model.set_raw_image_uri(raw_image_uri); - self.model.set_raw_animation_uri(raw_animation_uri); - - // Save parsed JSON to GCS - if json != Value::Null { - self.log_info("Writing JSON to GCS"); - let cdn_json_uri_result = write_json_to_gcs( - self.config.bucket.clone(), - self.asset_data_id.clone(), - &json, - &self.gcs_client, + if self.force || self.model.get_cdn_json_uri().is_none() { + // Parse asset_uri + self.log_info("Parsing asset_uri"); + let json_uri = URIParser::parse( + self.config.ipfs_prefix.clone(), + self.model.get_asset_uri(), + self.config.ipfs_auth_key.clone(), ) - .await; + .unwrap_or_else(|_| { + self.log_warn("Failed to parse asset_uri", None); + PARSE_URI_TYPE_COUNT.with_label_values(&["other"]).inc(); + self.model.get_asset_uri() + }); - if let Err(e) = cdn_json_uri_result.as_ref() { - self.log_warn( - "Failed to write JSON to GCS, maybe upload timed out?", - Some(e), - ); - } + // Parse JSON for raw_image_uri and raw_animation_uri + self.log_info("Starting JSON parsing"); + let (raw_image_uri, raw_animation_uri, json) = JSONParser::parse( + json_uri, + self.config + .max_file_size_bytes + .unwrap_or(DEFAULT_MAX_FILE_SIZE_BYTES), + ) + .await + .unwrap_or_else(|e| { + // Increment retry count if JSON parsing fails + self.log_warn("JSON parsing failed", Some(&e)); + self.model.increment_json_parser_retry_count(); + (None, None, Value::Null) + }); - let cdn_json_uri = cdn_json_uri_result - .map(|value| format!("{}{}", self.config.cdn_prefix, value)) - .ok(); - self.model.set_cdn_json_uri(cdn_json_uri); - } + self.model.set_raw_image_uri(raw_image_uri); + self.model.set_raw_animation_uri(raw_animation_uri); - // Commit model to Postgres - self.log_info("Committing JSON to Postgres"); - if let Err(e) = upsert_uris(&mut self.conn, &self.model) { - self.log_error("Commit to Postgres failed", &e); + // Save parsed JSON to GCS + if json != Value::Null { + self.log_info("Writing JSON to GCS"); + let cdn_json_uri_result = write_json_to_gcs( + self.config.bucket.clone(), + self.asset_data_id.clone(), + &json, + &self.gcs_client, + ) + .await; + + if let Err(e) = cdn_json_uri_result.as_ref() { + self.log_warn( + "Failed to write JSON to GCS, maybe upload timed out?", + Some(e), + ); + } + + let cdn_json_uri = cdn_json_uri_result + .map(|value| format!("{}{}", self.config.cdn_prefix, value)) + .ok(); + self.model.set_cdn_json_uri(cdn_json_uri); + } + + // Commit model to Postgres + self.log_info("Committing JSON to Postgres"); + if let Err(e) = upsert_uris(&mut self.conn, &self.model) { + self.log_error("Commit to Postgres failed", &e); + } } // Deduplicate raw_image_uri // Proceed with image optimization of force or if raw_image_uri has not been parsed // Since we default to asset_uri, this check works if raw_image_uri is null because deduplication for asset_uri has already taken place - if self.force - || self.model.get_raw_image_uri().map_or(true, |uri_option| { - match NFTMetadataCrawlerURIsQuery::get_by_raw_image_uri( - self.asset_uri.clone(), - uri_option, - &mut self.conn, - ) { - Some(uris) => { - self.log_info("Duplicate raw_image_uri found"); - DUPLICATE_RAW_IMAGE_URI_COUNT.inc(); - self.model.set_cdn_image_uri(uris.cdn_image_uri); - false - }, - None => true, - } - }) + if (self.force || self.model.get_cdn_image_uri().is_none()) + && (self.model.get_cdn_image_uri().is_some() + || self.model.get_raw_image_uri().map_or(true, |uri_option| { + match NFTMetadataCrawlerURIsQuery::get_by_raw_image_uri( + self.asset_uri.clone(), + uri_option, + &mut self.conn, + ) { + Some(uris) => { + self.log_info("Duplicate raw_image_uri found"); + DUPLICATE_RAW_IMAGE_URI_COUNT.inc(); + self.model.set_cdn_image_uri(uris.cdn_image_uri); + false + }, + None => true, + } + })) { // Parse raw_image_uri, use asset_uri if parsing fails self.log_info("Parsing raw_image_uri"); @@ -233,8 +236,8 @@ impl Worker { (vec![], ImageFormat::Png) }); - if image.is_empty() && json == Value::Null { - self.log_info("Image and JSON are empty, skipping parse, marking as do_not_parse"); + if image.is_empty() { + self.log_info("Image is empty, skipping parse"); self.model.set_do_not_parse(true); SKIP_URI_COUNT.with_label_values(&["empty"]).inc(); if let Err(e) = upsert_uris(&mut self.conn, &self.model) { @@ -267,33 +270,34 @@ impl Worker { .ok(); self.model.set_cdn_image_uri(cdn_image_uri); } - } - // Commit model to Postgres - self.log_info("Committing image to Postgres"); - if let Err(e) = upsert_uris(&mut self.conn, &self.model) { - self.log_error("Commit to Postgres failed", &e); + // Commit model to Postgres + self.log_info("Committing image to Postgres"); + if let Err(e) = upsert_uris(&mut self.conn, &self.model) { + self.log_error("Commit to Postgres failed", &e); + } } // Deduplicate raw_animation_uri // Set raw_animation_uri_option to None if not force and raw_animation_uri already exists let mut raw_animation_uri_option = self.model.get_raw_animation_uri(); - if !self.force - && raw_animation_uri_option.clone().map_or(true, |uri| { - match NFTMetadataCrawlerURIsQuery::get_by_raw_animation_uri( - self.asset_uri.clone(), - uri, - &mut self.conn, - ) { - Some(uris) => { - self.log_info("Duplicate raw_animation_uri found"); - DUPLICATE_RAW_ANIMATION_URI_COUNT.inc(); - self.model.set_cdn_animation_uri(uris.cdn_animation_uri); - true - }, - None => true, - } - }) + if self.model.get_cdn_animation_uri().is_some() + || !self.force + && raw_animation_uri_option.clone().map_or(true, |uri| { + match NFTMetadataCrawlerURIsQuery::get_by_raw_animation_uri( + self.asset_uri.clone(), + uri, + &mut self.conn, + ) { + Some(uris) => { + self.log_info("Duplicate raw_animation_uri found"); + DUPLICATE_RAW_ANIMATION_URI_COUNT.inc(); + self.model.set_cdn_animation_uri(uris.cdn_animation_uri); + true + }, + None => true, + } + }) { raw_animation_uri_option = None; } @@ -356,12 +360,23 @@ impl Worker { .ok(); self.model.set_cdn_animation_uri(cdn_animation_uri); } + + // Commit model to Postgres + self.log_info("Committing animation to Postgres"); + if let Err(e) = upsert_uris(&mut self.conn, &self.model) { + self.log_error("Commit to Postgres failed", &e); + } } - // Commit model to Postgres - self.log_info("Committing animation to Postgres"); - if let Err(e) = upsert_uris(&mut self.conn, &self.model) { - self.log_error("Commit to Postgres failed", &e); + if self.model.get_json_parser_retry_count() > MAX_NUM_PARSE_RETRIES + || self.model.get_image_optimizer_retry_count() > MAX_NUM_PARSE_RETRIES + || self.model.get_animation_optimizer_retry_count() > MAX_NUM_PARSE_RETRIES + { + self.log_info("Retry count exceeded, marking as do_not_parse"); + self.model.set_do_not_parse(true); + if let Err(e) = upsert_uris(&mut self.conn, &self.model) { + self.log_error("Commit to Postgres failed", &e); + } } PARSER_SUCCESSES_COUNT.inc(); From 0aaf5de7a1b5eabe100495e430bae9010fab44f9 Mon Sep 17 00:00:00 2001 From: Max Kaplan <1482859+CapCap@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:18:03 -0800 Subject: [PATCH 011/328] [GRPC] Don't limit prost recursion (#11901) --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a4d6be9b4cff1..a38f2f4190375 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -610,8 +610,8 @@ prometheus-http-query = "0.5.2" prometheus-parse = "0.2.4" proptest = "1.4.0" proptest-derive = "0.4.0" -prost = "0.12.1" -prost-types = "0.12.1" +prost = { version = "0.12.3", features = ["no-recursion-limit"] } +prost-types = "0.12.3" quanta = "0.10.1" quote = "1.0.18" rand = "0.7.3" From 8b514bb85ebfcb6847451982348526d6a1692592 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Mon, 5 Feb 2024 16:00:05 -0800 Subject: [PATCH 012/328] jwk #9: smoke tests (#11862) * jwk types update * update * update * jwk txn and execution * consensus ensure jwk txns are expected * update * jwk consensus network type defs * update cargo.toml * update * update * update * lint * jwk update quorum certification * jwk observation * the main jwk consensus state machine * jwk consensus epoch manager * update * jwk consensus wired into node * update * update * jwk consensus smoke tests * update --- Cargo.lock | 1 + testsuite/forge/src/backend/local/cargo.rs | 4 +- testsuite/smoke-test/Cargo.toml | 1 + .../smoke-test/src/jwks/dummy_provider/mod.rs | 109 +++++++++++++ .../jwks/dummy_provider/request_handler.rs | 118 ++++++++++++++ .../src/jwks/jwk_consensus_basic.rs | 147 ++++++++++++++++++ .../src/jwks/jwk_consensus_per_issuer.rs | 94 +++++++++++ .../jwk_consensus_provider_change_mind.rs | 104 +++++++++++++ .../smoke-test/src/{jwks.rs => jwks/mod.rs} | 52 ++++++- 9 files changed, 625 insertions(+), 5 deletions(-) create mode 100644 testsuite/smoke-test/src/jwks/dummy_provider/mod.rs create mode 100644 testsuite/smoke-test/src/jwks/dummy_provider/request_handler.rs create mode 100644 testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs create mode 100644 testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs create mode 100644 testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs rename testsuite/smoke-test/src/{jwks.rs => jwks/mod.rs} (61%) diff --git a/Cargo.lock b/Cargo.lock index fe5b054e7744d..0d2f8010dfc39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14936,6 +14936,7 @@ dependencies = [ "diesel", "futures", "hex", + "hyper", "move-core-types", "num_cpus", "once_cell", diff --git a/testsuite/forge/src/backend/local/cargo.rs b/testsuite/forge/src/backend/local/cargo.rs index cdb97b0a53dbc..93af06ac2d8c7 100644 --- a/testsuite/forge/src/backend/local/cargo.rs +++ b/testsuite/forge/src/backend/local/cargo.rs @@ -171,9 +171,9 @@ pub fn git_merge_base>(rev: R) -> Result { pub fn cargo_build_common_args() -> Vec<&'static str> { let mut args = if build_aptos_node_without_indexer() { - vec!["build", "--features=failpoints"] + vec!["build", "--features=failpoints,smoke-test"] } else { - vec!["build", "--features=failpoints,indexer"] + vec!["build", "--features=failpoints,indexer,smoke-test"] }; if build_consensus_only_node() { args.push("--features=consensus-only-perf-test"); diff --git a/testsuite/smoke-test/Cargo.toml b/testsuite/smoke-test/Cargo.toml index 3f9cb5338d7e0..acbb13ca84256 100644 --- a/testsuite/smoke-test/Cargo.toml +++ b/testsuite/smoke-test/Cargo.toml @@ -50,6 +50,7 @@ diesel = { workspace = true, features = [ "serde_json", ] } hex = { workspace = true } +hyper = { workspace = true } move-core-types = { workspace = true } proptest = { workspace = true } reqwest = { workspace = true } diff --git a/testsuite/smoke-test/src/jwks/dummy_provider/mod.rs b/testsuite/smoke-test/src/jwks/dummy_provider/mod.rs new file mode 100644 index 0000000000000..f82a6b9bee95c --- /dev/null +++ b/testsuite/smoke-test/src/jwks/dummy_provider/mod.rs @@ -0,0 +1,109 @@ +// Copyright © Aptos Foundation + +use aptos_infallible::RwLock; +use hyper::{ + service::{make_service_fn, service_fn}, + Body, Request, Response, Server, +}; +use request_handler::RequestHandler; +use std::{convert::Infallible, mem, net::SocketAddr, sync::Arc}; +use tokio::{ + sync::{ + oneshot, + oneshot::{Receiver, Sender}, + }, + task::JoinHandle, +}; + +pub(crate) mod request_handler; + +/// A dummy OIDC provider. +pub struct DummyProvider { + close_tx: Sender<()>, + open_id_config_url: String, + handler_holder: Arc>>>, + server_join_handle: JoinHandle<()>, +} + +impl DummyProvider { + pub(crate) async fn spawn() -> Self { + let addr = SocketAddr::from(([127, 0, 0, 1], 0)); + let handler_holder = Arc::new(RwLock::new(None)); + let (port_tx, port_rx) = oneshot::channel::(); + let (close_tx, close_rx) = oneshot::channel::<()>(); + let server_join_handle = tokio::spawn(Self::run_server( + addr, + handler_holder.clone(), + port_tx, + close_rx, + )); + let actual_port = port_rx.await.unwrap(); + let open_id_config_url = format!("http://127.0.0.1:{}", actual_port); + Self { + close_tx, + open_id_config_url, + handler_holder, + server_join_handle, + } + } + + pub fn open_id_config_url(&self) -> String { + self.open_id_config_url.clone() + } + + pub fn update_request_handler( + &self, + handler: Option>, + ) -> Option> { + mem::replace(&mut *self.handler_holder.write(), handler) + } + + pub async fn shutdown(self) { + let DummyProvider { + close_tx, + server_join_handle, + .. + } = self; + close_tx.send(()).unwrap(); + server_join_handle.await.unwrap(); + } +} + +// Private functions. +impl DummyProvider { + async fn run_server( + addr: SocketAddr, + handler_holder: Arc>>>, + port_tx: Sender, + close_rx: Receiver<()>, + ) { + let make_svc = make_service_fn(move |_| { + let handler_holder_clone = handler_holder.clone(); + async move { + Ok::<_, Infallible>(service_fn(move |req| { + Self::handle_request(req, handler_holder_clone.clone()) + })) + } + }); + + let server = Server::bind(&addr).serve(make_svc); + let actual_addr = server.local_addr(); + port_tx.send(actual_addr.port()).unwrap(); + + // Graceful shutdown + let graceful = server.with_graceful_shutdown(async { + close_rx.await.unwrap(); + }); + + graceful.await.unwrap(); + } + + async fn handle_request( + request: Request, + handler_holder: Arc>>>, + ) -> Result, Infallible> { + let handler = handler_holder.write(); + let raw_response = handler.as_ref().unwrap().handle(request); + Ok(Response::new(Body::from(raw_response))) + } +} diff --git a/testsuite/smoke-test/src/jwks/dummy_provider/request_handler.rs b/testsuite/smoke-test/src/jwks/dummy_provider/request_handler.rs new file mode 100644 index 0000000000000..5310931ef1af7 --- /dev/null +++ b/testsuite/smoke-test/src/jwks/dummy_provider/request_handler.rs @@ -0,0 +1,118 @@ +// Copyright © Aptos Foundation + +use aptos_infallible::Mutex; +use hyper::{Body, Request}; +use move_core_types::account_address::AccountAddress; +use std::{collections::HashSet, str::FromStr}; + +/// A handler that handles JWK requests from a validator, +/// assuming the validator account address is written as the COOKIE. +pub trait RequestHandler: Send + Sync { + fn handle(&self, request: Request) -> Vec; +} + +pub struct StaticContentServer { + content: Vec, +} + +impl StaticContentServer { + pub fn new(content: Vec) -> Self { + Self { content } + } + + pub fn new_str(content: &str) -> Self { + Self::new(content.as_bytes().to_vec()) + } +} + +impl RequestHandler for StaticContentServer { + fn handle(&self, _origin: Request) -> Vec { + self.content.clone() + } +} + +fn origin_from_cookie(request: &Request) -> AccountAddress { + let cookie = request + .headers() + .get(hyper::header::COOKIE) + .unwrap() + .to_str() + .unwrap(); + AccountAddress::from_str(cookie).unwrap() +} + +/// The first `k` requesters will get content A forever, the rest will get content B forever. +pub struct EquivocatingServer { + content_a: Vec, + content_b: Vec, + k: usize, + requesters_observed: Mutex>, +} + +impl EquivocatingServer { + pub fn new(content_a: Vec, content_b: Vec, k: usize) -> Self { + Self { + content_a, + content_b, + k, + requesters_observed: Mutex::new(HashSet::new()), + } + } +} + +impl RequestHandler for EquivocatingServer { + fn handle(&self, request: Request) -> Vec { + let mut requesters_observed = self.requesters_observed.lock(); + let origin = origin_from_cookie(&request); + if requesters_observed.len() < self.k { + requesters_observed.insert(origin); + } + + if requesters_observed.contains(&origin) { + self.content_a.clone() + } else { + self.content_b.clone() + } + } +} + +/// This server first replies with `initial_thoughts`. +/// After enough audience receives it for at least once, it switches its reply to `second_thoughts`. +/// +/// This behavior simulates the situation where a provider performs a 2nd key rotation right after the 1st. +pub struct MindChangingServer { + initial_thoughts: Vec, + second_thoughts: Vec, + change_mind_threshold: usize, + requesters_observed: Mutex>, +} + +impl MindChangingServer { + pub fn new( + initial_thoughts: Vec, + second_thoughts: Vec, + change_mind_threshold: usize, + ) -> Self { + Self { + initial_thoughts, + second_thoughts, + change_mind_threshold, + requesters_observed: Mutex::new(HashSet::new()), + } + } +} + +impl RequestHandler for MindChangingServer { + fn handle(&self, request: Request) -> Vec { + let mut requesters_observed = self.requesters_observed.lock(); + let origin = origin_from_cookie(&request); + if requesters_observed.contains(&origin) + || requesters_observed.len() >= self.change_mind_threshold + { + self.second_thoughts.clone() + } else { + requesters_observed.insert(origin); + self.initial_thoughts.clone() + } + } +} diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs new file mode 100644 index 0000000000000..0df449657d22b --- /dev/null +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs @@ -0,0 +1,147 @@ +// Copyright © Aptos Foundation + +use crate::{ + jwks::{ + dummy_provider::{ + request_handler::{EquivocatingServer, StaticContentServer}, + DummyProvider, + }, + get_patched_jwks, put_provider_on_chain, + }, + smoke_test_environment::SwarmBuilder, +}; +use aptos_forge::{NodeExt, Swarm, SwarmExt}; +use aptos_logger::{debug, info}; +use aptos_types::jwks::{ + jwk::JWK, rsa::RSA_JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, OIDCProvider, + ProviderJWKs, +}; +use std::{sync::Arc, time::Duration}; +use tokio::time::sleep; + +/// The validators should agree on the JWK after provider set is changed/JWK is rotated. +#[tokio::test] +async fn jwk_consensus_basic() { + let epoch_duration_secs = 30; + + let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) + .with_aptos() + .with_init_genesis_config(Arc::new(move |conf| { + conf.epoch_duration_secs = epoch_duration_secs; + })) + .build_with_cli(0) + .await; + let client = swarm.validators().next().unwrap().rest_client(); + let root_idx = cli.add_account_with_address_to_cli( + swarm.root_key(), + swarm.chain_info().root_account().address(), + ); + swarm + .wait_for_all_nodes_to_catchup_to_epoch(2, Duration::from_secs(epoch_duration_secs * 2)) + .await + .expect("Epoch 2 taking too long to arrive!"); + + info!("Initially the provider set is empty. So should be the JWK map."); + + sleep(Duration::from_secs(10)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert!(patched_jwks.jwks.entries.is_empty()); + + info!("Adding some providers."); + let (provider_alice, provider_bob) = + tokio::join!(DummyProvider::spawn(), DummyProvider::spawn()); + + provider_alice.update_request_handler(Some(Arc::new(StaticContentServer::new_str( + r#" +{ + "keys": [ + {"kid":"kid1", "kty":"RSA", "e":"AQAB", "n":"n1", "alg":"RS384", "use":"sig"}, + {"n":"n0", "kty":"RSA", "use":"sig", "alg":"RS256", "e":"AQAB", "kid":"kid0"} + ] +} +"#, + )))); + provider_bob.update_request_handler(Some(Arc::new(StaticContentServer::new( + r#"{"keys": ["BOB_JWK_V0"]}"#.as_bytes().to_vec(), + )))); + let providers = vec![ + OIDCProvider { + name: b"https://alice.io".to_vec(), + config_url: provider_alice.open_id_config_url().into_bytes(), + }, + OIDCProvider { + name: b"https://bob.dev".to_vec(), + config_url: provider_bob.open_id_config_url().into_bytes(), + }, + ]; + let txn_summary = put_provider_on_chain(cli, root_idx, providers).await; + debug!("txn_summary={:?}", txn_summary); + + info!("Waiting for an on-chain update. 10 sec should be enough."); + sleep(Duration::from_secs(10)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert_eq!( + AllProvidersJWKs { + entries: vec![ + ProviderJWKs { + issuer: b"https://alice.io".to_vec(), + version: 1, + jwks: vec![ + JWK::RSA(RSA_JWK::new_256_aqab("kid0", "n0")).into(), + JWK::RSA(RSA_JWK::new_from_strs("kid1", "RSA", "RS384", "AQAB", "n1")) + .into(), + ], + }, + ProviderJWKs { + issuer: b"https://bob.dev".to_vec(), + version: 1, + jwks: vec![JWK::Unsupported(UnsupportedJWK::new_with_payload( + "\"BOB_JWK_V0\"" + )) + .into()], + }, + ] + }, + patched_jwks.jwks + ); + + info!("Rotating Alice keys. Also making https://alice.io gently equivocate."); + provider_alice.update_request_handler(Some(Arc::new(EquivocatingServer::new( + r#"{"keys": ["ALICE_JWK_V1A"]}"#.as_bytes().to_vec(), + r#"{"keys": ["ALICE_JWK_V1B"]}"#.as_bytes().to_vec(), + 1, + )))); + + info!("Waiting for an on-chain update. 30 sec should be enough."); + sleep(Duration::from_secs(30)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert_eq!( + AllProvidersJWKs { + entries: vec![ + ProviderJWKs { + issuer: b"https://alice.io".to_vec(), + version: 2, + jwks: vec![JWK::Unsupported(UnsupportedJWK::new_with_payload( + "\"ALICE_JWK_V1B\"" + )) + .into()], + }, + ProviderJWKs { + issuer: b"https://bob.dev".to_vec(), + version: 1, + jwks: vec![JWK::Unsupported(UnsupportedJWK::new_with_payload( + "\"BOB_JWK_V0\"" + )) + .into()], + }, + ] + }, + patched_jwks.jwks + ); + + info!("Tear down."); + provider_alice.shutdown().await; +} diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs new file mode 100644 index 0000000000000..e271c2bb9cd67 --- /dev/null +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs @@ -0,0 +1,94 @@ +// Copyright © Aptos Foundation + +use crate::{ + jwks::{ + dummy_provider::{ + request_handler::{EquivocatingServer, StaticContentServer}, + DummyProvider, + }, + get_patched_jwks, put_provider_on_chain, + }, + smoke_test_environment::SwarmBuilder, +}; +use aptos_forge::{NodeExt, Swarm, SwarmExt}; +use aptos_logger::{debug, info}; +use aptos_types::jwks::{ + jwk::JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, OIDCProvider, ProviderJWKs, +}; +use std::{sync::Arc, time::Duration}; +use tokio::time::sleep; + +/// The validators should do JWK consensus per issuer: +/// one problematic issuer should not block valid updates of other issuers. +#[tokio::test] +async fn jwk_consensus_per_issuer() { + let epoch_duration_secs = 30; + + let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) + .with_aptos() + .with_init_genesis_config(Arc::new(move |conf| { + conf.epoch_duration_secs = epoch_duration_secs; + })) + .build_with_cli(0) + .await; + let client = swarm.validators().next().unwrap().rest_client(); + let root_idx = cli.add_account_with_address_to_cli( + swarm.root_key(), + swarm.chain_info().root_account().address(), + ); + swarm + .wait_for_all_nodes_to_catchup_to_epoch(2, Duration::from_secs(epoch_duration_secs * 2)) + .await + .expect("Epoch 2 taking too long to arrive!"); + + info!("Initially the provider set is empty. So should be the JWK map."); + + sleep(Duration::from_secs(10)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert!(patched_jwks.jwks.entries.is_empty()); + + info!("Adding some providers, one seriously equivocating, the other well behaving."); + let (provider_alice, provider_bob) = + tokio::join!(DummyProvider::spawn(), DummyProvider::spawn()); + provider_alice.update_request_handler(Some(Arc::new(EquivocatingServer::new( + r#"{"keys": ["ALICE_JWK_V1A"]}"#.as_bytes().to_vec(), + r#"{"keys": ["ALICE_JWK_V1B"]}"#.as_bytes().to_vec(), + 2, + )))); + provider_bob.update_request_handler(Some(Arc::new(StaticContentServer::new( + r#"{"keys": ["BOB_JWK_V0"]}"#.as_bytes().to_vec(), + )))); + let providers = vec![ + OIDCProvider { + name: b"https://alice.io".to_vec(), + config_url: provider_alice.open_id_config_url().into_bytes(), + }, + OIDCProvider { + name: b"https://bob.dev".to_vec(), + config_url: provider_bob.open_id_config_url().into_bytes(), + }, + ]; + let txn_summary = put_provider_on_chain(cli, root_idx, providers).await; + debug!("txn_summary={:?}", txn_summary); + + info!("Wait for 60 secs and there should only update for Bob, not Alice."); + sleep(Duration::from_secs(60)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert_eq!( + AllProvidersJWKs { + entries: vec![ProviderJWKs { + issuer: b"https://bob.dev".to_vec(), + version: 1, + jwks: vec![ + JWK::Unsupported(UnsupportedJWK::new_with_payload("\"BOB_JWK_V0\"")).into() + ], + }] + }, + patched_jwks.jwks + ); + + info!("Tear down."); + provider_alice.shutdown().await; +} diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs new file mode 100644 index 0000000000000..7fad520c48ce1 --- /dev/null +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs @@ -0,0 +1,104 @@ +// Copyright © Aptos Foundation + +use crate::{ + jwks::{ + dummy_provider::{ + request_handler::{MindChangingServer, StaticContentServer}, + DummyProvider, + }, + get_patched_jwks, put_provider_on_chain, + }, + smoke_test_environment::SwarmBuilder, +}; +use aptos_forge::{NodeExt, Swarm, SwarmExt}; +use aptos_logger::{debug, info}; +use aptos_types::jwks::{ + jwk::JWK, unsupported::UnsupportedJWK, AllProvidersJWKs, OIDCProvider, ProviderJWKs, +}; +use std::{sync::Arc, time::Duration}; +use tokio::time::sleep; + +/// The validators should be able to reach JWK consensus +/// even if a provider double-rotates its key in a very short period of time. +/// First rotation may have been observed by some validators. +#[tokio::test] +async fn jwk_consensus_provider_change_mind() { + // Big epoch duration to ensure epoch change does not help reset validators if they are stuck. + let epoch_duration_secs = 1800; + + let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) + .with_aptos() + .with_init_genesis_config(Arc::new(move |conf| { + conf.epoch_duration_secs = epoch_duration_secs; + })) + .build_with_cli(0) + .await; + let client = swarm.validators().next().unwrap().rest_client(); + let root_idx = cli.add_account_with_address_to_cli( + swarm.root_key(), + swarm.chain_info().root_account().address(), + ); + swarm + .wait_for_all_nodes_to_catchup_to_epoch(2, Duration::from_secs(epoch_duration_secs * 2)) + .await + .expect("Epoch 2 taking too long to arrive!"); + + info!("Initially the provider set is empty. So should be the ObservedJWKs."); + + sleep(Duration::from_secs(10)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert!(patched_jwks.jwks.entries.is_empty()); + + info!("Adding some providers."); + let (provider_alice, provider_bob) = + tokio::join!(DummyProvider::spawn(), DummyProvider::spawn()); + provider_alice.update_request_handler(Some(Arc::new(StaticContentServer::new( + r#"{"keys": ["ALICE_JWK_V0"]}"#.as_bytes().to_vec(), + )))); + provider_bob.update_request_handler(Some(Arc::new(MindChangingServer::new( + r#"{"keys": ["BOB_JWK_V0"]}"#.as_bytes().to_vec(), + r#"{"keys": ["BOB_JWK_V0_1"]}"#.as_bytes().to_vec(), + 2, + )))); + let providers = vec![ + OIDCProvider { + name: b"https://alice.io".to_vec(), + config_url: provider_alice.open_id_config_url().into_bytes(), + }, + OIDCProvider { + name: b"https://bob.dev".to_vec(), + config_url: provider_bob.open_id_config_url().into_bytes(), + }, + ]; + let txn_summary = put_provider_on_chain(cli, root_idx, providers).await; + debug!("txn_summary={:?}", txn_summary); + + info!("Waiting for an on-chain update. 30 secs should be enough."); + sleep(Duration::from_secs(30)).await; + let patched_jwks = get_patched_jwks(&client).await; + debug!("patched_jwks={:?}", patched_jwks); + assert_eq!( + AllProvidersJWKs { + entries: vec![ + ProviderJWKs { + issuer: b"https://alice.io".to_vec(), + version: 1, + jwks: vec![JWK::Unsupported(UnsupportedJWK::new_with_payload( + "\"ALICE_JWK_V0\"" + )) + .into()], + }, + ProviderJWKs { + issuer: b"https://bob.dev".to_vec(), + version: 1, + jwks: vec![JWK::Unsupported(UnsupportedJWK::new_with_payload( + "\"BOB_JWK_V0_1\"" + )) + .into()], + }, + ] + }, + patched_jwks.jwks + ); +} diff --git a/testsuite/smoke-test/src/jwks.rs b/testsuite/smoke-test/src/jwks/mod.rs similarity index 61% rename from testsuite/smoke-test/src/jwks.rs rename to testsuite/smoke-test/src/jwks/mod.rs index 6509a35b1d32c..2740ef1fc7df9 100644 --- a/testsuite/smoke-test/src/jwks.rs +++ b/testsuite/smoke-test/src/jwks/mod.rs @@ -1,18 +1,64 @@ // Copyright © Aptos Foundation +mod dummy_provider; +mod jwk_consensus_basic; +mod jwk_consensus_per_issuer; +mod jwk_consensus_provider_change_mind; + use crate::smoke_test_environment::SwarmBuilder; +use aptos::{common::types::TransactionSummary, test::CliTestFramework}; use aptos_forge::{NodeExt, Swarm, SwarmExt}; use aptos_logger::{debug, info}; use aptos_rest_client::Client; use aptos_types::jwks::{ jwk::{JWKMoveStruct, JWK}, unsupported::UnsupportedJWK, - AllProvidersJWKs, PatchedJWKs, ProviderJWKs, + AllProvidersJWKs, OIDCProvider, PatchedJWKs, ProviderJWKs, }; use move_core_types::account_address::AccountAddress; use std::time::Duration; -async fn get_latest_jwkset(rest_client: &Client) -> PatchedJWKs { +pub async fn put_provider_on_chain( + cli: CliTestFramework, + account_idx: usize, + providers: Vec, +) -> TransactionSummary { + let implementation = providers + .into_iter() + .map(|provider| { + let OIDCProvider { name, config_url } = provider; + format!( + r#" + let issuer = b"{}"; + let config_url = b"{}"; + jwks::upsert_oidc_provider(&framework_signer, issuer, config_url); +"#, + String::from_utf8(name).unwrap(), + String::from_utf8(config_url).unwrap(), + ) + }) + .collect::>() + .join(""); + + let add_dummy_provider_script = format!( + r#" +script {{ + use aptos_framework::aptos_governance; + use aptos_framework::jwks; + fun main(core_resources: &signer) {{ + let framework_signer = aptos_governance::get_signer_testnet_only(core_resources, @0000000000000000000000000000000000000000000000000000000000000001); + {implementation} + aptos_governance::reconfigure(&framework_signer); + }} +}} +"#, + ); + cli.run_script(account_idx, &add_dummy_provider_script) + .await + .unwrap() +} + +async fn get_patched_jwks(rest_client: &Client) -> PatchedJWKs { let maybe_response = rest_client .get_account_resource_bcs::(AccountAddress::ONE, "0x1::jwks::PatchedJWKs") .await; @@ -58,7 +104,7 @@ script { debug!("txn_summary={:?}", txn_summary); info!("Use resource API to check the patch result."); - let patched_jwks = get_latest_jwkset(&client).await; + let patched_jwks = get_patched_jwks(&client).await; debug!("patched_jwks={:?}", patched_jwks); let expected_providers_jwks = AllProvidersJWKs { From 8c4c16ef2c6d2baa37b0ef83e47ae6af080246a1 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Mon, 5 Feb 2024 16:21:29 -0800 Subject: [PATCH 013/328] [aip-43] Separate Concurrent Fungible Assets feature flag, for later release (#11871) --- .../src/components/feature_flags.rs | 9 +- .../aptos-framework/doc/fungible_asset.md | 4 +- .../sources/fungible_asset.move | 6 +- .../aptos-token-objects/doc/collection.md | 6 +- .../aptos-token-objects/doc/token.md | 14 +- .../sources/collection.move | 6 +- .../aptos-token-objects/sources/token.move | 16 +- .../framework/move-stdlib/doc/features.md | 152 ++++++++++++++++-- .../move-stdlib/sources/configs/features.move | 46 ++++-- types/src/on_chain_config/aptos_features.rs | 3 +- 10 files changed, 209 insertions(+), 53 deletions(-) diff --git a/aptos-move/aptos-release-builder/src/components/feature_flags.rs b/aptos-move/aptos-release-builder/src/components/feature_flags.rs index 0e972c6e93ee4..50e443259b6f3 100644 --- a/aptos-move/aptos-release-builder/src/components/feature_flags.rs +++ b/aptos-move/aptos-release-builder/src/components/feature_flags.rs @@ -87,7 +87,7 @@ pub enum FeatureFlag { SponsoredAutomaticAccountCreation, FeePayerAccountOptional, AggregatorV2DelayedFields, - ConcurrentAssets, + ConcurrentTokenV2, LimitMaxIdentifierLength, OperatorBeneficiaryChange, VMBinaryFormatV7, @@ -100,6 +100,7 @@ pub enum FeatureFlag { ZkIdZkLessSignature, RemoveDetailedError, JWKConsensus, + ConcurrentFungibleAssets, } fn generate_features_blob(writer: &CodeWriter, data: &[u64]) { @@ -242,7 +243,7 @@ impl From for AptosFeatureFlag { FeatureFlag::AggregatorV2DelayedFields => { AptosFeatureFlag::AGGREGATOR_V2_DELAYED_FIELDS }, - FeatureFlag::ConcurrentAssets => AptosFeatureFlag::CONCURRENT_ASSETS, + FeatureFlag::ConcurrentTokenV2 => AptosFeatureFlag::CONCURRENT_TOKEN_V2, FeatureFlag::LimitMaxIdentifierLength => AptosFeatureFlag::LIMIT_MAX_IDENTIFIER_LENGTH, FeatureFlag::OperatorBeneficiaryChange => AptosFeatureFlag::OPERATOR_BENEFICIARY_CHANGE, FeatureFlag::ResourceGroupsChargeAsSizeSum => { @@ -258,6 +259,7 @@ impl From for AptosFeatureFlag { FeatureFlag::ZkIdZkLessSignature => AptosFeatureFlag::ZK_ID_ZKLESS_SIGNATURE, FeatureFlag::RemoveDetailedError => AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH, FeatureFlag::JWKConsensus => AptosFeatureFlag::JWK_CONSENSUS, + FeatureFlag::ConcurrentFungibleAssets => AptosFeatureFlag::CONCURRENT_FUNGIBLE_ASSETS, } } } @@ -323,7 +325,7 @@ impl From for FeatureFlag { AptosFeatureFlag::AGGREGATOR_V2_DELAYED_FIELDS => { FeatureFlag::AggregatorV2DelayedFields }, - AptosFeatureFlag::CONCURRENT_ASSETS => FeatureFlag::ConcurrentAssets, + AptosFeatureFlag::CONCURRENT_TOKEN_V2 => FeatureFlag::ConcurrentTokenV2, AptosFeatureFlag::LIMIT_MAX_IDENTIFIER_LENGTH => FeatureFlag::LimitMaxIdentifierLength, AptosFeatureFlag::OPERATOR_BENEFICIARY_CHANGE => FeatureFlag::OperatorBeneficiaryChange, AptosFeatureFlag::RESOURCE_GROUPS_CHARGE_AS_SIZE_SUM => { @@ -339,6 +341,7 @@ impl From for FeatureFlag { AptosFeatureFlag::ZK_ID_ZKLESS_SIGNATURE => FeatureFlag::ZkIdZkLessSignature, AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH => FeatureFlag::RemoveDetailedError, AptosFeatureFlag::JWK_CONSENSUS => FeatureFlag::JWKConsensus, + AptosFeatureFlag::CONCURRENT_FUNGIBLE_ASSETS => FeatureFlag::ConcurrentFungibleAssets, } } } diff --git a/aptos-move/framework/aptos-framework/doc/fungible_asset.md b/aptos-move/framework/aptos-framework/doc/fungible_asset.md index e3dbc070fd5e7..4a4b54fba8a79 100644 --- a/aptos-move/framework/aptos-framework/doc/fungible_asset.md +++ b/aptos-move/framework/aptos-framework/doc/fungible_asset.md @@ -913,7 +913,7 @@ if option::some(MAX_U128) is used, it is treated as unlimited supply. } ); - if (features::concurrent_assets_enabled()) { + if (features::concurrent_fungible_assets_enabled()) { let unlimited = option::is_none(&maximum_supply); move_to(metadata_object_signer, ConcurrentSupply { current: if (unlimited) { @@ -2220,7 +2220,7 @@ Decrease the supply of a fungible asset by burning. ) acquires Supply { let metadata_object_address = object::address_from_extend_ref(ref); let metadata_object_signer = object::generate_signer_for_extending(ref); - assert!(features::concurrent_assets_enabled(), error::invalid_argument(ECONCURRENT_SUPPLY_NOT_ENABLED)); + assert!(features::concurrent_fungible_assets_enabled(), error::invalid_argument(ECONCURRENT_SUPPLY_NOT_ENABLED)); assert!(exists<Supply>(metadata_object_address), error::not_found(ESUPPLY_NOT_FOUND)); let Supply { current, diff --git a/aptos-move/framework/aptos-framework/sources/fungible_asset.move b/aptos-move/framework/aptos-framework/sources/fungible_asset.move index 723f41b633e16..6aec86d057e41 100644 --- a/aptos-move/framework/aptos-framework/sources/fungible_asset.move +++ b/aptos-move/framework/aptos-framework/sources/fungible_asset.move @@ -188,7 +188,7 @@ module aptos_framework::fungible_asset { } ); - if (features::concurrent_assets_enabled()) { + if (features::concurrent_fungible_assets_enabled()) { let unlimited = option::is_none(&maximum_supply); move_to(metadata_object_signer, ConcurrentSupply { current: if (unlimited) { @@ -635,7 +635,7 @@ module aptos_framework::fungible_asset { ) acquires Supply { let metadata_object_address = object::address_from_extend_ref(ref); let metadata_object_signer = object::generate_signer_for_extending(ref); - assert!(features::concurrent_assets_enabled(), error::invalid_argument(ECONCURRENT_SUPPLY_NOT_ENABLED)); + assert!(features::concurrent_fungible_assets_enabled(), error::invalid_argument(ECONCURRENT_SUPPLY_NOT_ENABLED)); assert!(exists(metadata_object_address), error::not_found(ESUPPLY_NOT_FOUND)); let Supply { current, @@ -856,7 +856,7 @@ module aptos_framework::fungible_asset { fx: &signer, creator: &signer ) acquires Supply, ConcurrentSupply, FungibleStore { - let feature = features::get_concurrent_assets_feature(); + let feature = features::get_concurrent_fungible_assets_feature(); let agg_feature = features::get_aggregator_v2_api_feature(); features::change_feature_flags(fx, vector[], vector[feature, agg_feature]); diff --git a/aptos-move/framework/aptos-token-objects/doc/collection.md b/aptos-move/framework/aptos-token-objects/doc/collection.md index 12d4cbe18732f..d0babdf457994 100644 --- a/aptos-move/framework/aptos-token-objects/doc/collection.md +++ b/aptos-move/framework/aptos-token-objects/doc/collection.md @@ -618,7 +618,7 @@ Beyond that, it adds supply tracking with events. let constructor_ref = object::create_named_object(creator, collection_seed); let object_signer = object::generate_signer(&constructor_ref); - if (features::concurrent_assets_enabled()) { + if (features::concurrent_token_v2_enabled()) { let supply = ConcurrentSupply { current_supply: aggregator_v2::create_aggregator(max_supply), total_minted: aggregator_v2::create_unbounded_aggregator(), @@ -687,7 +687,7 @@ the supply of tokens. let constructor_ref = object::create_named_object(creator, collection_seed); let object_signer = object::generate_signer(&constructor_ref); - if (features::concurrent_assets_enabled()) { + if (features::concurrent_token_v2_enabled()) { let supply = ConcurrentSupply { current_supply: aggregator_v2::create_unbounded_aggregator(), total_minted: aggregator_v2::create_unbounded_aggregator(), @@ -1121,7 +1121,7 @@ Creates a MutatorRef, which gates the ability to mutate any fields that support ) acquires FixedSupply, UnlimitedSupply { let metadata_object_address = object::address_from_extend_ref(ref); let metadata_object_signer = object::generate_signer_for_extending(ref); - assert!(features::concurrent_assets_enabled(), error::invalid_argument(ECONCURRENT_NOT_ENABLED)); + assert!(features::concurrent_token_v2_enabled(), error::invalid_argument(ECONCURRENT_NOT_ENABLED)); let (supply, current_supply, total_minted, burn_events, mint_events) = if (exists<FixedSupply>(metadata_object_address)) { let FixedSupply { diff --git a/aptos-move/framework/aptos-token-objects/doc/token.md b/aptos-move/framework/aptos-token-objects/doc/token.md index 904d5214952e5..a8d5c231c484b 100644 --- a/aptos-move/framework/aptos-token-objects/doc/token.md +++ b/aptos-move/framework/aptos-token-objects/doc/token.md @@ -88,7 +88,7 @@ Represents the common fields to all tokens.

Deprecated in favor of index inside TokenIdentifiers. - Will be populated until concurrent_assets_enabled feature flag is enabled. + Will be populated until concurrent_token_v2_enabled feature flag is enabled. Unique identifier within the collection, optional, 0 means unassigned
@@ -103,7 +103,7 @@ Represents the common fields to all tokens.
Deprecated in favor of name inside TokenIdentifiers. - Will be populated until concurrent_assets_enabled feature flag is enabled. + Will be populated until concurrent_token_v2_enabled feature flag is enabled. The name of the token, which should be unique within the collection; the length of name should be smaller than 128, characters, eg: "Aptos Animal #1234" @@ -440,7 +440,7 @@ The token name is over the maximum length // Flag which controls whether any functions from aggregator_v2 module can be called. let aggregator_api_enabled = features::aggregator_v2_api_enabled(); // Flag which controls whether we are going to still continue writing to deprecated fields. - let concurrent_assets_enabled = features::concurrent_assets_enabled(); + let concurrent_token_v2_enabled = features::concurrent_token_v2_enabled(); let (deprecated_index, deprecated_name) = if (aggregator_api_enabled) { let index = option::destroy_with_default( @@ -455,15 +455,15 @@ The token name is over the maximum length aggregator_v2::create_derived_string(name_prefix) }; - // Until concurrent_assets_enabled is enabled, we still need to write to deprecated fields. + // Until concurrent_token_v2_enabled is enabled, we still need to write to deprecated fields. // Otherwise we put empty values there. // (we need to do these calls before creating token_concurrent, to avoid copying objects) - let deprecated_index = if (concurrent_assets_enabled) { + let deprecated_index = if (concurrent_token_v2_enabled) { 0 } else { aggregator_v2::read_snapshot(&index) }; - let deprecated_name = if (concurrent_assets_enabled) { + let deprecated_name = if (concurrent_token_v2_enabled) { string::utf8(b"") } else { aggregator_v2::read_derived_string(&name) @@ -559,7 +559,7 @@ for additional specialization. Creates a new token object with a unique address and returns the ConstructorRef for additional specialization. The name is created by concatenating the (name_prefix, index, name_suffix). -After flag concurrent_assets_enabled is enabled, this function will allow +After flag concurrent_token_v2_enabled is enabled, this function will allow creating tokens in parallel, from the same collection, while providing sequential names. diff --git a/aptos-move/framework/aptos-token-objects/sources/collection.move b/aptos-move/framework/aptos-token-objects/sources/collection.move index cebd3b3e07f15..dfb0ad9eaa985 100644 --- a/aptos-move/framework/aptos-token-objects/sources/collection.move +++ b/aptos-move/framework/aptos-token-objects/sources/collection.move @@ -156,7 +156,7 @@ module aptos_token_objects::collection { let constructor_ref = object::create_named_object(creator, collection_seed); let object_signer = object::generate_signer(&constructor_ref); - if (features::concurrent_assets_enabled()) { + if (features::concurrent_token_v2_enabled()) { let supply = ConcurrentSupply { current_supply: aggregator_v2::create_aggregator(max_supply), total_minted: aggregator_v2::create_unbounded_aggregator(), @@ -205,7 +205,7 @@ module aptos_token_objects::collection { let constructor_ref = object::create_named_object(creator, collection_seed); let object_signer = object::generate_signer(&constructor_ref); - if (features::concurrent_assets_enabled()) { + if (features::concurrent_token_v2_enabled()) { let supply = ConcurrentSupply { current_supply: aggregator_v2::create_unbounded_aggregator(), total_minted: aggregator_v2::create_unbounded_aggregator(), @@ -459,7 +459,7 @@ module aptos_token_objects::collection { ) acquires FixedSupply, UnlimitedSupply { let metadata_object_address = object::address_from_extend_ref(ref); let metadata_object_signer = object::generate_signer_for_extending(ref); - assert!(features::concurrent_assets_enabled(), error::invalid_argument(ECONCURRENT_NOT_ENABLED)); + assert!(features::concurrent_token_v2_enabled(), error::invalid_argument(ECONCURRENT_NOT_ENABLED)); let (supply, current_supply, total_minted, burn_events, mint_events) = if (exists(metadata_object_address)) { let FixedSupply { diff --git a/aptos-move/framework/aptos-token-objects/sources/token.move b/aptos-move/framework/aptos-token-objects/sources/token.move index cd1b8ecf43784..b1a5a9ff79797 100644 --- a/aptos-move/framework/aptos-token-objects/sources/token.move +++ b/aptos-move/framework/aptos-token-objects/sources/token.move @@ -44,14 +44,14 @@ module aptos_token_objects::token { /// The collection from which this token resides. collection: Object, /// Deprecated in favor of `index` inside TokenIdentifiers. - /// Will be populated until concurrent_assets_enabled feature flag is enabled. + /// Will be populated until concurrent_token_v2_enabled feature flag is enabled. /// /// Unique identifier within the collection, optional, 0 means unassigned index: u64, // DEPRECATED /// A brief description of the token. description: String, /// Deprecated in favor of `name` inside TokenIdentifiers. - /// Will be populated until concurrent_assets_enabled feature flag is enabled. + /// Will be populated until concurrent_token_v2_enabled feature flag is enabled. /// /// The name of the token, which should be unique within the collection; the length of name /// should be smaller than 128, characters, eg: "Aptos Animal #1234" @@ -133,7 +133,7 @@ module aptos_token_objects::token { // Flag which controls whether any functions from aggregator_v2 module can be called. let aggregator_api_enabled = features::aggregator_v2_api_enabled(); // Flag which controls whether we are going to still continue writing to deprecated fields. - let concurrent_assets_enabled = features::concurrent_assets_enabled(); + let concurrent_token_v2_enabled = features::concurrent_token_v2_enabled(); let (deprecated_index, deprecated_name) = if (aggregator_api_enabled) { let index = option::destroy_with_default( @@ -148,15 +148,15 @@ module aptos_token_objects::token { aggregator_v2::create_derived_string(name_prefix) }; - // Until concurrent_assets_enabled is enabled, we still need to write to deprecated fields. + // Until concurrent_token_v2_enabled is enabled, we still need to write to deprecated fields. // Otherwise we put empty values there. // (we need to do these calls before creating token_concurrent, to avoid copying objects) - let deprecated_index = if (concurrent_assets_enabled) { + let deprecated_index = if (concurrent_token_v2_enabled) { 0 } else { aggregator_v2::read_snapshot(&index) }; - let deprecated_name = if (concurrent_assets_enabled) { + let deprecated_name = if (concurrent_token_v2_enabled) { string::utf8(b"") } else { aggregator_v2::read_derived_string(&name) @@ -223,7 +223,7 @@ module aptos_token_objects::token { /// Creates a new token object with a unique address and returns the ConstructorRef /// for additional specialization. /// The name is created by concatenating the (name_prefix, index, name_suffix). - /// After flag concurrent_assets_enabled is enabled, this function will allow + /// After flag concurrent_token_v2_enabled is enabled, this function will allow /// creating tokens in parallel, from the same collection, while providing sequential names. public fun create_numbered_token( creator: &signer, @@ -775,7 +775,7 @@ module aptos_token_objects::token { fun test_upgrade_to_concurrent_and_numbered_tokens(fx: &signer, creator: &signer) acquires Token, TokenIdentifiers { use std::debug; - let feature = features::get_concurrent_assets_feature(); + let feature = features::get_concurrent_token_v2_feature(); let agg_feature = features::get_aggregator_v2_api_feature(); let auid_feature = features::get_auids(); let module_event_feature = features::get_module_event_feature(); diff --git a/aptos-move/framework/move-stdlib/doc/features.md b/aptos-move/framework/move-stdlib/doc/features.md index 87f2ec8117eda..b2f4aa35085f2 100644 --- a/aptos-move/framework/move-stdlib/doc/features.md +++ b/aptos-move/framework/move-stdlib/doc/features.md @@ -76,6 +76,8 @@ return true. - [Function `aggregator_snapshots_enabled`](#0x1_features_aggregator_snapshots_enabled) - [Function `get_sponsored_automatic_account_creation`](#0x1_features_get_sponsored_automatic_account_creation) - [Function `sponsored_automatic_account_creation_enabled`](#0x1_features_sponsored_automatic_account_creation_enabled) +- [Function `get_concurrent_token_v2_feature`](#0x1_features_get_concurrent_token_v2_feature) +- [Function `concurrent_token_v2_enabled`](#0x1_features_concurrent_token_v2_enabled) - [Function `get_concurrent_assets_feature`](#0x1_features_get_concurrent_assets_feature) - [Function `concurrent_assets_enabled`](#0x1_features_concurrent_assets_enabled) - [Function `get_operator_beneficiary_change_feature`](#0x1_features_get_operator_beneficiary_change_feature) @@ -90,6 +92,8 @@ return true. - [Function `zkid_zkless_feature_enabled`](#0x1_features_zkid_zkless_feature_enabled) - [Function `get_jwk_consensus_feature`](#0x1_features_get_jwk_consensus_feature) - [Function `jwk_consensus_enabled`](#0x1_features_jwk_consensus_enabled) +- [Function `get_concurrent_fungible_assets_feature`](#0x1_features_get_concurrent_fungible_assets_feature) +- [Function `concurrent_fungible_assets_enabled`](#0x1_features_concurrent_fungible_assets_enabled) - [Function `change_feature_flags`](#0x1_features_change_feature_flags) - [Function `is_enabled`](#0x1_features_is_enabled) - [Function `set`](#0x1_features_set) @@ -284,14 +288,26 @@ Lifetime: transient - + + +Whether enable Fungible Asset creation +to create higher throughput concurrent variants. +Lifetime: transient + + +
const CONCURRENT_FUNGIBLE_ASSETS: u64 = 49;
+
+ + + + Whether enable TokenV2 collection creation and Fungible Asset creation to create higher throughput concurrent variants. Lifetime: transient -
const CONCURRENT_ASSETS: u64 = 37;
+
const CONCURRENT_TOKEN_V2: u64 = 37;
 
@@ -351,6 +367,15 @@ The provided signer has not a framework address. + + + + +
const EINVALID_FEATURE: u64 = 1;
+
+ + + @@ -1571,7 +1596,8 @@ Lifetime: transient -
public fun get_aggregator_snapshots_feature(): u64
+
#[deprecated]
+public fun get_aggregator_snapshots_feature(): u64
 
@@ -1580,7 +1606,9 @@ Lifetime: transient Implementation -
public fun get_aggregator_snapshots_feature(): u64 { AGGREGATOR_V2_API }
+
public fun get_aggregator_snapshots_feature(): u64 {
+    abort error::invalid_argument(EINVALID_FEATURE)
+}
 
@@ -1593,7 +1621,8 @@ Lifetime: transient -
public fun aggregator_snapshots_enabled(): bool
+
#[deprecated]
+public fun aggregator_snapshots_enabled(): bool
 
@@ -1602,8 +1631,8 @@ Lifetime: transient Implementation -
public fun aggregator_snapshots_enabled(): bool acquires Features {
-    is_enabled(AGGREGATOR_V2_API)
+
public fun aggregator_snapshots_enabled(): bool {
+    abort error::invalid_argument(EINVALID_FEATURE)
 }
 
@@ -1655,6 +1684,53 @@ Lifetime: transient + + + + +## Function `get_concurrent_token_v2_feature` + + + +
public fun get_concurrent_token_v2_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_concurrent_token_v2_feature(): u64 { CONCURRENT_TOKEN_V2 }
+
+ + + +
+ + + +## Function `concurrent_token_v2_enabled` + + + +
public fun concurrent_token_v2_enabled(): bool
+
+ + + +
+Implementation + + +
public fun concurrent_token_v2_enabled(): bool acquires Features {
+    // concurrent token v2 cannot be used if aggregator v2 api is not enabled.
+    is_enabled(CONCURRENT_TOKEN_V2) && aggregator_v2_api_enabled()
+}
+
+ + +
@@ -1663,7 +1739,8 @@ Lifetime: transient -
public fun get_concurrent_assets_feature(): u64
+
#[deprecated]
+public fun get_concurrent_assets_feature(): u64
 
@@ -1672,7 +1749,9 @@ Lifetime: transient Implementation -
public fun get_concurrent_assets_feature(): u64 { CONCURRENT_ASSETS }
+
public fun get_concurrent_assets_feature(): u64 {
+    abort error::invalid_argument(EINVALID_FEATURE)
+}
 
@@ -1685,7 +1764,8 @@ Lifetime: transient -
public fun concurrent_assets_enabled(): bool
+
#[deprecated]
+public fun concurrent_assets_enabled(): bool
 
@@ -1694,9 +1774,8 @@ Lifetime: transient Implementation -
public fun concurrent_assets_enabled(): bool acquires Features {
-    // concurrent assets cannot be used if aggregator v2 api is not enabled.
-    is_enabled(CONCURRENT_ASSETS) && aggregator_v2_api_enabled()
+
public fun concurrent_assets_enabled(): bool {
+    abort error::invalid_argument(EINVALID_FEATURE)
 }
 
@@ -1978,6 +2057,53 @@ Lifetime: transient + + + + +## Function `get_concurrent_fungible_assets_feature` + + + +
public fun get_concurrent_fungible_assets_feature(): u64
+
+ + + +
+Implementation + + +
public fun get_concurrent_fungible_assets_feature(): u64 { CONCURRENT_FUNGIBLE_ASSETS }
+
+ + + +
+ + + +## Function `concurrent_fungible_assets_enabled` + + + +
public fun concurrent_fungible_assets_enabled(): bool
+
+ + + +
+Implementation + + +
public fun concurrent_fungible_assets_enabled(): bool acquires Features {
+    // concurrent fungible assets cannot be used if aggregator v2 api is not enabled.
+    is_enabled(CONCURRENT_FUNGIBLE_ASSETS) && aggregator_v2_api_enabled()
+}
+
+ + +
diff --git a/aptos-move/framework/move-stdlib/sources/configs/features.move b/aptos-move/framework/move-stdlib/sources/configs/features.move index 53189fc2408ed..682844df3e5ed 100644 --- a/aptos-move/framework/move-stdlib/sources/configs/features.move +++ b/aptos-move/framework/move-stdlib/sources/configs/features.move @@ -27,6 +27,8 @@ module std::features { use std::signer; use std::vector; + const EINVALID_FEATURE: u64 = 1; + // -------------------------------------------------------------------------------------------- // Code Publishing @@ -253,12 +255,14 @@ module std::features { is_enabled(AGGREGATOR_V2_API) } - // Backed by same flag as get_aggregator_v2_api_feature - public fun get_aggregator_snapshots_feature(): u64 { AGGREGATOR_V2_API } + #[deprecated] + public fun get_aggregator_snapshots_feature(): u64 { + abort error::invalid_argument(EINVALID_FEATURE) + } - // Backed by same flag as aggregator_v2_api_enabled - public fun aggregator_snapshots_enabled(): bool acquires Features { - is_enabled(AGGREGATOR_V2_API) + #[deprecated] + public fun aggregator_snapshots_enabled(): bool { + abort error::invalid_argument(EINVALID_FEATURE) } const SAFER_RESOURCE_GROUPS: u64 = 31; @@ -287,13 +291,23 @@ module std::features { /// Whether enable TokenV2 collection creation and Fungible Asset creation /// to create higher throughput concurrent variants. /// Lifetime: transient - const CONCURRENT_ASSETS: u64 = 37; + const CONCURRENT_TOKEN_V2: u64 = 37; + + public fun get_concurrent_token_v2_feature(): u64 { CONCURRENT_TOKEN_V2 } - public fun get_concurrent_assets_feature(): u64 { CONCURRENT_ASSETS } + public fun concurrent_token_v2_enabled(): bool acquires Features { + // concurrent token v2 cannot be used if aggregator v2 api is not enabled. + is_enabled(CONCURRENT_TOKEN_V2) && aggregator_v2_api_enabled() + } + + #[deprecated] + public fun get_concurrent_assets_feature(): u64 { + abort error::invalid_argument(EINVALID_FEATURE) + } - public fun concurrent_assets_enabled(): bool acquires Features { - // concurrent assets cannot be used if aggregator v2 api is not enabled. - is_enabled(CONCURRENT_ASSETS) && aggregator_v2_api_enabled() + #[deprecated] + public fun concurrent_assets_enabled(): bool { + abort error::invalid_argument(EINVALID_FEATURE) } const LIMIT_MAX_IDENTIFIER_LENGTH: u64 = 38; @@ -366,6 +380,18 @@ module std::features { is_enabled(JWK_CONSENSUS) } + /// Whether enable Fungible Asset creation + /// to create higher throughput concurrent variants. + /// Lifetime: transient + const CONCURRENT_FUNGIBLE_ASSETS: u64 = 49; + + public fun get_concurrent_fungible_assets_feature(): u64 { CONCURRENT_FUNGIBLE_ASSETS } + + public fun concurrent_fungible_assets_enabled(): bool acquires Features { + // concurrent fungible assets cannot be used if aggregator v2 api is not enabled. + is_enabled(CONCURRENT_FUNGIBLE_ASSETS) && aggregator_v2_api_enabled() + } + // ============================================================================================ // Feature Flag Implementation diff --git a/types/src/on_chain_config/aptos_features.rs b/types/src/on_chain_config/aptos_features.rs index 657126ba35e85..34db3a108c79e 100644 --- a/types/src/on_chain_config/aptos_features.rs +++ b/types/src/on_chain_config/aptos_features.rs @@ -44,7 +44,7 @@ pub enum FeatureFlag { SPONSORED_AUTOMATIC_ACCOUNT_V1_CREATION = 34, FEE_PAYER_ACCOUNT_OPTIONAL = 35, AGGREGATOR_V2_DELAYED_FIELDS = 36, - CONCURRENT_ASSETS = 37, + CONCURRENT_TOKEN_V2 = 37, LIMIT_MAX_IDENTIFIER_LENGTH = 38, OPERATOR_BENEFICIARY_CHANGE = 39, VM_BINARY_FORMAT_V7 = 40, @@ -57,6 +57,7 @@ pub enum FeatureFlag { ZK_ID_ZKLESS_SIGNATURE = 47, REMOVE_DETAILED_ERROR_FROM_HASH = 48, JWK_CONSENSUS = 49, + CONCURRENT_FUNGIBLE_ASSETS = 50, } /// Representation of features on chain as a bitset. From cbd1144498b225cfdb2d3644db760a9401866be9 Mon Sep 17 00:00:00 2001 From: "Brian (Sunghoon) Cho" Date: Mon, 5 Feb 2024 16:28:15 -0800 Subject: [PATCH 014/328] [forge] revert genesis to pre-#11842 (#11896) ### Description #11842 removed consensus config and execution config so they were not applied to forge ### Test Plan Ran ad-hoc forge test that overrides execution config and observed it is overridden: https://github.com/aptos-labs/aptos-core/actions/runs/7788659630 --- terraform/helm/genesis/templates/genesis.yaml | 6 ++++++ terraform/helm/genesis/values.yaml | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/terraform/helm/genesis/templates/genesis.yaml b/terraform/helm/genesis/templates/genesis.yaml index 6d5716a25e6fe..1298d39676d2c 100644 --- a/terraform/helm/genesis/templates/genesis.yaml +++ b/terraform/helm/genesis/templates/genesis.yaml @@ -25,6 +25,12 @@ data: rewards_apy_percentage: {{ .Values.chain.rewards_apy_percentage | int }} voting_duration_secs: {{ .Values.chain.voting_duration_secs | int }} voting_power_increase_limit: {{ .Values.chain.voting_power_increase_limit | int }} + {{- with .Values.chain.on_chain_consensus_config}} + on_chain_consensus_config: {{ . | toJson }} + {{- end}} + {{- with .Values.chain.on_chain_execution_config}} + on_chain_execution_config: {{ . | toJson }} + {{- end}} --- diff --git a/terraform/helm/genesis/values.yaml b/terraform/helm/genesis/values.yaml index 4a8c859e61859..50bb124cda2d9 100644 --- a/terraform/helm/genesis/values.yaml +++ b/terraform/helm/genesis/values.yaml @@ -31,6 +31,10 @@ chain: rewards_apy_percentage: 10 # -- Minimum price per gas unit min_price_per_gas_unit: 1 + # -- Onchain Consensus Config + on_chain_consensus_config: + # -- Onchain Execution Config + on_chain_execution_config: # -- Default image tag to use for all tools images imageTag: testnet From 3a98f0bf523f2ed9c23469e6d9ce93c6dcc3af49 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:02:59 -0800 Subject: [PATCH 015/328] [simple] Transaction generator improvements (#11863) Description don't fail if only stale seq_num are received from rest endpoint workflow: make delay_between_stages_s configurable make init_max_gas_per_txn cli argument ReducedBatchWrapperTransactionGeneratorCreator utility, useful for tournament --- crates/transaction-emitter-lib/src/args.rs | 3 + crates/transaction-emitter-lib/src/cluster.rs | 5 +- .../src/emitter/mod.rs | 32 +++++-- .../transaction-emitter-lib/src/wrappers.rs | 4 + .../src/bounded_batch_wrapper.rs | 45 ++++++++++ crates/transaction-generator-lib/src/lib.rs | 14 +++- .../src/workflow_delegator.rs | 83 +++++++++++++++---- 7 files changed, 159 insertions(+), 27 deletions(-) create mode 100644 crates/transaction-generator-lib/src/bounded_batch_wrapper.rs diff --git a/crates/transaction-emitter-lib/src/args.rs b/crates/transaction-emitter-lib/src/args.rs index 53c23620a196a..2087ac0347619 100644 --- a/crates/transaction-emitter-lib/src/args.rs +++ b/crates/transaction-emitter-lib/src/args.rs @@ -164,6 +164,9 @@ pub struct EmitArgs { #[clap(long)] pub max_gas_per_txn: Option, + #[clap(long)] + pub init_max_gas_per_txn: Option, + #[clap(long)] pub init_gas_price_multiplier: Option, diff --git a/crates/transaction-emitter-lib/src/cluster.rs b/crates/transaction-emitter-lib/src/cluster.rs index a6090f714ee14..4a5cecd44b99b 100644 --- a/crates/transaction-emitter-lib/src/cluster.rs +++ b/crates/transaction-emitter-lib/src/cluster.rs @@ -96,9 +96,10 @@ impl Cluster { let state_timestamp = state.timestamp_usecs / 1000000; if state.chain_id != chain_id.id() { warn!( - "Excluding client {} running wrong chain {}", + "Excluding client {} running wrong chain {}, instead of {}", instance.peer_name(), - state.chain_id + state.chain_id, + chain_id.id(), ); } else if state_timestamp + 20 + fetch_time_s < max_timestamp { warn!( diff --git a/crates/transaction-emitter-lib/src/emitter/mod.rs b/crates/transaction-emitter-lib/src/emitter/mod.rs index d41517a96e157..ab7adfe6d275c 100644 --- a/crates/transaction-emitter-lib/src/emitter/mod.rs +++ b/crates/transaction-emitter-lib/src/emitter/mod.rs @@ -124,6 +124,7 @@ pub struct EmitJobRequest { max_gas_per_txn: u64, gas_price: u64, + init_max_gas_per_txn: u64, init_gas_price_multiplier: u64, mint_to_root: bool, @@ -157,6 +158,7 @@ impl Default for EmitJobRequest { transaction_mix_per_phase: vec![vec![(TransactionType::default(), 1)]], max_gas_per_txn: aptos_global_constants::MAX_GAS_AMOUNT, gas_price: aptos_global_constants::GAS_UNIT_PRICE, + init_max_gas_per_txn: aptos_global_constants::MAX_GAS_AMOUNT, init_gas_price_multiplier: 10, mint_to_root: false, txn_expiration_time_secs: 60, @@ -194,6 +196,11 @@ impl EmitJobRequest { self } + pub fn init_max_gas_per_txn(mut self, init_max_gas_per_txn: u64) -> Self { + self.init_max_gas_per_txn = init_max_gas_per_txn; + self + } + pub fn init_gas_price_multiplier(mut self, init_gas_price_multiplier: u64) -> Self { self.init_gas_price_multiplier = init_gas_price_multiplier; self @@ -534,7 +541,12 @@ impl EmitJob { .map(|p| &p[cur_phase]) .unwrap_or(&default_stats); prev_stats = Some(stats); - info!("phase {}: {}", cur_phase, delta.rate()); + info!( + "[{:?}s stat] phase {}: {}", + window.as_secs(), + cur_phase, + delta.rate() + ); } } @@ -594,6 +606,7 @@ impl TxnEmitter { (mode_params.txn_expiration_time_secs as f64 * req.init_expiration_multiplier) as u64; let init_txn_factory = txn_factory .clone() + .with_max_gas_amount(req.init_max_gas_per_txn) .with_gas_unit_price(req.gas_price * req.init_gas_price_multiplier) .with_transaction_expiration_time(init_expiration_time); let init_retries: usize = @@ -917,11 +930,18 @@ fn update_seq_num_and_get_num_expired( |(address, (start_seq_num, end_seq_num))| match latest_fetched_counts.get(address) { Some(count) => { assert!(*count <= *end_seq_num); - assert!(*count >= *start_seq_num); - ( - (*count - *start_seq_num) as usize, - (*end_seq_num - *count) as usize, - ) + if *count >= *start_seq_num { + ( + (*count - *start_seq_num) as usize, + (*end_seq_num - *count) as usize, + ) + } else { + debug!( + "Stale sequence_number fetched for {}, start_seq_num {}, fetched {}", + address, start_seq_num, *count + ); + (0, (*end_seq_num - *start_seq_num) as usize) + } }, None => (0, (end_seq_num - start_seq_num) as usize), }, diff --git a/crates/transaction-emitter-lib/src/wrappers.rs b/crates/transaction-emitter-lib/src/wrappers.rs index 922f7c7808a7e..41aa83c5e4ab7 100644 --- a/crates/transaction-emitter-lib/src/wrappers.rs +++ b/crates/transaction-emitter-lib/src/wrappers.rs @@ -110,6 +110,10 @@ pub async fn emit_transactions_with_cluster( emit_job_request = emit_job_request.max_gas_per_txn(max_gas_per_txn); } + if let Some(init_max_gas_per_txn) = args.init_max_gas_per_txn { + emit_job_request = emit_job_request.init_max_gas_per_txn(init_max_gas_per_txn); + } + if let Some(init_gas_price_multiplier) = args.init_gas_price_multiplier { emit_job_request = emit_job_request.init_gas_price_multiplier(init_gas_price_multiplier); } diff --git a/crates/transaction-generator-lib/src/bounded_batch_wrapper.rs b/crates/transaction-generator-lib/src/bounded_batch_wrapper.rs new file mode 100644 index 0000000000000..c3b79dc621578 --- /dev/null +++ b/crates/transaction-generator-lib/src/bounded_batch_wrapper.rs @@ -0,0 +1,45 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{TransactionGenerator, TransactionGeneratorCreator}; +use aptos_sdk::types::{transaction::SignedTransaction, LocalAccount}; + +struct BoundedBatchWrapperTransactionGenerator { + batch_size: usize, + generator: Box, +} + +impl TransactionGenerator for BoundedBatchWrapperTransactionGenerator { + fn generate_transactions( + &mut self, + account: &LocalAccount, + num_to_create: usize, + ) -> Vec { + self.generator + .generate_transactions(account, num_to_create.min(self.batch_size)) + } +} + +pub struct BoundedBatchWrapperTransactionGeneratorCreator { + batch_size: usize, + generator_creator: Box, +} + +impl BoundedBatchWrapperTransactionGeneratorCreator { + #[allow(unused)] + pub fn new(batch_size: usize, generator_creator: Box) -> Self { + Self { + batch_size, + generator_creator, + } + } +} + +impl TransactionGeneratorCreator for BoundedBatchWrapperTransactionGeneratorCreator { + fn create_transaction_generator(&self) -> Box { + Box::new(BoundedBatchWrapperTransactionGenerator { + batch_size: self.batch_size, + generator: self.generator_creator.create_transaction_generator(), + }) + } +} diff --git a/crates/transaction-generator-lib/src/lib.rs b/crates/transaction-generator-lib/src/lib.rs index fda62c551915e..978dac080b91b 100644 --- a/crates/transaction-generator-lib/src/lib.rs +++ b/crates/transaction-generator-lib/src/lib.rs @@ -27,6 +27,7 @@ mod account_generator; mod accounts_pool_wrapper; pub mod args; mod batch_transfer; +mod bounded_batch_wrapper; mod call_custom_modules; mod entry_points; mod p2p_transaction_generator; @@ -81,7 +82,7 @@ pub enum TransactionType { workflow_kind: WorkflowKind, num_modules: usize, use_account_pool: bool, - move_stages_by_phase: bool, + progress_type: WorkflowProgress, }, } @@ -90,6 +91,12 @@ pub enum WorkflowKind { CreateThenMint { count: usize, creation_balance: u64 }, } +#[derive(Debug, Copy, Clone)] +pub enum WorkflowProgress { + MoveByPhases, + WhenDone { delay_between_stages_s: u64 }, +} + impl Default for TransactionType { fn default() -> Self { TransactionTypeArg::CoinTransfer.materialize(1, false) @@ -318,7 +325,7 @@ pub async fn create_txn_generator_creator( num_modules, use_account_pool, workflow_kind, - move_stages_by_phase, + progress_type, } => Box::new( WorkflowTxnGeneratorCreator::create_workload( *workflow_kind, @@ -328,7 +335,8 @@ pub async fn create_txn_generator_creator( txn_executor, *num_modules, use_account_pool.then(|| accounts_pool.clone()), - move_stages_by_phase.then(|| cur_phase.clone()), + cur_phase.clone(), + *progress_type, ) .await, ), diff --git a/crates/transaction-generator-lib/src/workflow_delegator.rs b/crates/transaction-generator-lib/src/workflow_delegator.rs index a24451d9e38da..52d1525cd967e 100644 --- a/crates/transaction-generator-lib/src/workflow_delegator.rs +++ b/crates/transaction-generator-lib/src/workflow_delegator.rs @@ -6,6 +6,7 @@ use crate::{ call_custom_modules::CustomModulesDelegationGeneratorCreator, entry_points::EntryPointTransactionGenerator, EntryPoints, ObjectPool, ReliableTransactionSubmitter, TransactionGenerator, TransactionGeneratorCreator, WorkflowKind, + WorkflowProgress, }; use aptos_logger::{info, sample, sample::SampleRate}; use aptos_sdk::{ @@ -15,10 +16,10 @@ use aptos_sdk::{ use std::{ cmp, sync::{ - atomic::{AtomicUsize, Ordering}, + atomic::{AtomicU64, AtomicUsize, Ordering}, Arc, }, - time::Duration, + time::{Duration, SystemTime, UNIX_EPOCH}, }; #[derive(Clone)] @@ -26,14 +27,36 @@ enum StageTracking { // stage is externally modified ExternallySet(Arc), // we move to a next stage when all accounts have finished with the current stage - WhenDone(Arc), + WhenDone { + stage_counter: Arc, + stage_start_time: Arc, + delay_between_stages: Duration, + }, } impl StageTracking { - fn load_current_stage(&self) -> usize { + fn current_timestamp() -> u64 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() + } + + fn load_current_stage(&self) -> Option { match self { - StageTracking::ExternallySet(stage) | StageTracking::WhenDone(stage) => { - stage.load(Ordering::Relaxed) + StageTracking::ExternallySet(stage_counter) => { + Some(stage_counter.load(Ordering::Relaxed)) + }, + StageTracking::WhenDone { + stage_counter, + stage_start_time, + .. + } => { + if stage_start_time.load(Ordering::Relaxed) > Self::current_timestamp() { + None + } else { + Some(stage_counter.load(Ordering::Relaxed)) + } }, } } @@ -94,7 +117,16 @@ impl TransactionGenerator for WorkflowTxnGenerator { mut num_to_create: usize, ) -> Vec { assert_ne!(num_to_create, 0); - let mut stage = self.stage.load_current_stage(); + let stage = match self.stage.load_current_stage() { + Some(stage) => stage, + None => { + sample!( + SampleRate::Duration(Duration::from_secs(2)), + info!("Waiting for delay before next stage"); + ); + return Vec::new(); + }, + }; if stage == 0 { // We can treat completed_for_first_stage as a stream of indices [0, +inf), @@ -110,29 +142,41 @@ impl TransactionGenerator for WorkflowTxnGenerator { // acts as coordinator, as it will generate as many transactions as number of accounts it could grab from the pool. match &self.stage { - StageTracking::WhenDone(stage_counter) => { + StageTracking::WhenDone { + stage_counter, + stage_start_time, + delay_between_stages, + } => { if stage == 0 { if num_to_create == 0 { info!("TransactionGenerator Workflow: Stage 0 is full with {} accounts, moving to stage 1", self.pool_per_stage.first().unwrap().len()); + stage_start_time.store( + StageTracking::current_timestamp() + delay_between_stages.as_secs(), + Ordering::Relaxed, + ); let _ = stage_counter.compare_exchange( 0, 1, Ordering::Relaxed, Ordering::Relaxed, ); - stage = 1; + return Vec::new(); } } else if stage < self.pool_per_stage.len() && self.pool_per_stage.get(stage - 1).unwrap().len() == 0 { info!("TransactionGenerator Workflow: Stage {} has consumed all accounts, moving to stage {}", stage, stage + 1); + stage_start_time.store( + StageTracking::current_timestamp() + delay_between_stages.as_secs(), + Ordering::Relaxed, + ); let _ = stage_counter.compare_exchange( stage, stage + 1, Ordering::Relaxed, Ordering::Relaxed, ); - stage += 1; + return Vec::new(); } }, StageTracking::ExternallySet(_) => { @@ -189,17 +233,24 @@ impl WorkflowTxnGeneratorCreator { txn_executor: &dyn ReliableTransactionSubmitter, num_modules: usize, _initial_account_pool: Option>>, - cur_phase: Option>, + cur_phase: Arc, + progress_type: WorkflowProgress, ) -> Self { - let stage_tracking = cur_phase.map_or_else( - || StageTracking::WhenDone(Arc::new(AtomicUsize::new(0))), - StageTracking::ExternallySet, - ); + let stage_tracking = match progress_type { + WorkflowProgress::MoveByPhases => StageTracking::ExternallySet(cur_phase), + WorkflowProgress::WhenDone { + delay_between_stages_s, + } => StageTracking::WhenDone { + stage_counter: Arc::new(AtomicUsize::new(0)), + stage_start_time: Arc::new(AtomicU64::new(0)), + delay_between_stages: Duration::from_secs(delay_between_stages_s), + }, + }; println!( "Creating workload with stage tracking: {:?}", match &stage_tracking { StageTracking::ExternallySet(_) => "ExternallySet", - StageTracking::WhenDone(_) => "WhenDone", + StageTracking::WhenDone { .. } => "WhenDone", } ); match workflow_kind { From 7c0ada517646024df0e15c16cbd279eb90500ddb Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Mon, 5 Feb 2024 21:52:39 -0800 Subject: [PATCH 016/328] [dag] refactor/improve dag health monitoring (#11362) * [dag] refactor dag health monitor * [dag] move reading commit events from order_rule * wait backoff time with 3f+1 --- .pre-commit-config.yaml | 4 +- config/src/config/dag_consensus_config.rs | 3 +- consensus/src/dag/adapter.rs | 30 ++++- .../leader_reputation_adapter.rs | 61 +++------ consensus/src/dag/anchor_election/mod.rs | 10 +- .../src/dag/anchor_election/round_robin.rs | 12 +- consensus/src/dag/bootstrap.rs | 124 +++++++++++++----- consensus/src/dag/dag_driver.rs | 61 ++------- consensus/src/dag/health/backoff.rs | 80 +++++++++++ consensus/src/dag/health/chain_health.rs | 94 +++++++++++++ consensus/src/dag/health/mod.rs | 13 ++ consensus/src/dag/health/pipeline_health.rs | 66 ++++++++++ consensus/src/dag/mod.rs | 1 + consensus/src/dag/order_rule.rs | 41 +++--- consensus/src/dag/round_state.rs | 25 ++-- consensus/src/dag/tests/dag_driver_tests.rs | 25 ++-- consensus/src/dag/tests/order_rule_tests.rs | 2 +- consensus/src/liveness/leader_reputation.rs | 14 +- types/src/on_chain_config/consensus_config.rs | 20 +++ types/src/on_chain_config/mod.rs | 5 +- 20 files changed, 494 insertions(+), 197 deletions(-) create mode 100644 consensus/src/dag/health/backoff.rs create mode 100644 consensus/src/dag/health/chain_health.rs create mode 100644 consensus/src/dag/health/mod.rs create mode 100644 consensus/src/dag/health/pipeline_health.rs diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3478423c0a237..ad9e60dc30620 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,7 +2,7 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v4.5.0 hooks: - id: trailing-whitespace files: \.(rs|move)$ @@ -13,7 +13,7 @@ repos: - --maxkb=2000 # Once this issue is resolved, we can add the full license check: https://github.com/Lucas-C/pre-commit-hooks/issues/68 - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: v1.3.0 + rev: v1.5.4 hooks: - id: insert-license files: ^(?!third_party/).*\.rs$ diff --git a/config/src/config/dag_consensus_config.rs b/config/src/config/dag_consensus_config.rs index ef05279e6cb0d..90f81430c6c78 100644 --- a/config/src/config/dag_consensus_config.rs +++ b/config/src/config/dag_consensus_config.rs @@ -2,7 +2,7 @@ use super::{ config_sanitizer::ConfigSanitizer, node_config_loader::NodeType, ChainHealthBackoffValues, - Error, NodeConfig, QuorumStoreConfig, + Error, NodeConfig, PipelineBackpressureValues, QuorumStoreConfig, }; use aptos_types::chain_id::ChainId; use serde::{Deserialize, Serialize}; @@ -143,6 +143,7 @@ pub struct DagConsensusConfig { pub fetcher_config: DagFetcherConfig, pub round_state_config: DagRoundStateConfig, pub chain_backoff_config: Vec, + pub pipeline_backpressure_config: Vec, #[serde(default = "QuorumStoreConfig::default_for_dag")] pub quorum_store: QuorumStoreConfig, } diff --git a/consensus/src/dag/adapter.rs b/consensus/src/dag/adapter.rs index 2eb9cf40427fe..9237a7c08d858 100644 --- a/consensus/src/dag/adapter.rs +++ b/consensus/src/dag/adapter.rs @@ -23,7 +23,7 @@ use aptos_consensus_types::{ use aptos_crypto::HashValue; use aptos_executor_types::StateComputeResult; use aptos_infallible::RwLock; -use aptos_logger::error; +use aptos_logger::{error, info}; use aptos_storage_interface::DbReader; use aptos_types::{ account_config::NewBlockEvent, @@ -35,7 +35,11 @@ use aptos_types::{ }; use async_trait::async_trait; use futures_channel::mpsc::UnboundedSender; -use std::{collections::HashMap, sync::Arc}; +use std::{ + collections::{BTreeMap, HashMap}, + sync::Arc, + time::{Duration, Instant}, +}; pub trait OrderedNotifier: Send + Sync { fn send_ordered_nodes( @@ -89,6 +93,7 @@ pub(super) struct OrderedNotifierAdapter { parent_block_info: Arc>, epoch_state: Arc, ledger_info_provider: Arc>, + block_ordered_ts: Arc>>, } impl OrderedNotifierAdapter { @@ -105,6 +110,18 @@ impl OrderedNotifierAdapter { parent_block_info: Arc::new(RwLock::new(parent_block_info)), epoch_state, ledger_info_provider, + block_ordered_ts: Arc::new(RwLock::new(BTreeMap::new())), + } + } + + pub(super) fn pipeline_pending_latency(&self) -> Duration { + match self.block_ordered_ts.read().first_key_value() { + Some((round, timestamp)) => { + let latency = timestamp.elapsed(); + info!(round = round, latency = latency, "pipeline pending latency"); + latency + }, + None => Duration::ZERO, } } } @@ -172,6 +189,12 @@ impl OrderedNotifier for OrderedNotifierAdapter { let ledger_info_provider = self.ledger_info_provider.clone(); let dag = self.dag.clone(); *self.parent_block_info.write() = block_info.clone(); + + self.block_ordered_ts + .write() + .insert(block_info.round(), Instant::now()); + let block_created_ts = self.block_ordered_ts.clone(); + let blocks_to_send = OrderedBlocks { ordered_blocks: vec![block], ordered_proof: LedgerInfoWithSignatures::new( @@ -181,6 +204,9 @@ impl OrderedNotifier for OrderedNotifierAdapter { callback: Box::new( move |committed_blocks: &[Arc], commit_decision: LedgerInfoWithSignatures| { + block_created_ts + .write() + .split_off(&(commit_decision.commit_info().round() + 1)); dag.write() .commit_callback(commit_decision.commit_info().round()); ledger_info_provider diff --git a/consensus/src/dag/anchor_election/leader_reputation_adapter.rs b/consensus/src/dag/anchor_election/leader_reputation_adapter.rs index 441e7f74d873e..ea34d450eb937 100644 --- a/consensus/src/dag/anchor_election/leader_reputation_adapter.rs +++ b/consensus/src/dag/anchor_election/leader_reputation_adapter.rs @@ -1,13 +1,15 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::TChainHealthBackoff; use crate::{ - counters::CHAIN_HEALTH_BACKOFF_TRIGGERED, - dag::{anchor_election::AnchorElection, storage::CommitEvent}, + dag::{ + anchor_election::{AnchorElection, CommitHistory}, + storage::CommitEvent, + }, liveness::{ - leader_reputation::{LeaderReputation, MetadataBackend, ReputationHeuristic}, - proposal_generator::ChainHealthBackoffConfig, + leader_reputation::{ + LeaderReputation, MetadataBackend, ReputationHeuristic, VotingPowerRatio, + }, proposer_election::ProposerElection, }, }; @@ -20,7 +22,6 @@ use move_core_types::account_address::AccountAddress; use std::{ collections::{HashMap, VecDeque}, sync::Arc, - time::Duration, }; pub struct MetadataBackendAdapter { @@ -100,7 +101,6 @@ impl MetadataBackend for MetadataBackendAdapter { pub struct LeaderReputationAdapter { reputation: LeaderReputation, data_source: Arc, - chain_health_backoff_config: ChainHealthBackoffConfig, } impl LeaderReputationAdapter { @@ -111,7 +111,6 @@ impl LeaderReputationAdapter { backend: Arc, heuristic: Box, window_for_chain_health: usize, - chain_health_backoff_config: ChainHealthBackoffConfig, ) -> Self { Self { reputation: LeaderReputation::new( @@ -125,24 +124,7 @@ impl LeaderReputationAdapter { window_for_chain_health, ), data_source: backend, - chain_health_backoff_config, - } - } - - fn get_chain_health_backoff( - &self, - round: u64, - ) -> (f64, Option<&aptos_config::config::ChainHealthBackoffValues>) { - let mut voting_power_ratio = self.reputation.get_voting_power_participation_ratio(round); - // TODO: fix this once leader reputation is fixed - if voting_power_ratio < 0.67 { - voting_power_ratio = 1.0; } - - let chain_health_backoff = self - .chain_health_backoff_config - .get_backoff(voting_power_ratio); - (voting_power_ratio, chain_health_backoff) } } @@ -156,27 +138,14 @@ impl AnchorElection for LeaderReputationAdapter { } } -impl TChainHealthBackoff for LeaderReputationAdapter { - fn get_round_backoff(&self, round: Round) -> (f64, Option) { - let (voting_power_ratio, chain_health_backoff) = self.get_chain_health_backoff(round); - let backoff_duration = if let Some(value) = chain_health_backoff { - CHAIN_HEALTH_BACKOFF_TRIGGERED.observe(1.0); - Some(Duration::from_millis(value.backoff_proposal_delay_ms)) - } else { - CHAIN_HEALTH_BACKOFF_TRIGGERED.observe(0.0); - None - }; - (voting_power_ratio, backoff_duration) - } +impl CommitHistory for LeaderReputationAdapter { + fn get_voting_power_participation_ratio(&self, round: Round) -> VotingPowerRatio { + let mut voting_power_ratio = self.reputation.get_voting_power_participation_ratio(round); + // TODO: fix this once leader reputation is fixed + if voting_power_ratio < 0.67 { + voting_power_ratio = 1.0; + } - fn get_round_payload_limits(&self, round: Round) -> (f64, Option<(u64, u64)>) { - let (voting_power_ratio, chain_health_backoff) = self.get_chain_health_backoff(round); - let backoff_limits = chain_health_backoff.map(|value| { - ( - value.max_sending_block_txns_override, - value.max_sending_block_bytes_override, - ) - }); - (voting_power_ratio, backoff_limits) + voting_power_ratio } } diff --git a/consensus/src/dag/anchor_election/mod.rs b/consensus/src/dag/anchor_election/mod.rs index 5666de15f3a00..53db6db738250 100644 --- a/consensus/src/dag/anchor_election/mod.rs +++ b/consensus/src/dag/anchor_election/mod.rs @@ -1,9 +1,8 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::dag::storage::CommitEvent; +use crate::{dag::storage::CommitEvent, liveness::leader_reputation::VotingPowerRatio}; use aptos_consensus_types::common::{Author, Round}; -use std::time::Duration; pub trait AnchorElection: Send + Sync { fn get_anchor(&self, round: Round) -> Author; @@ -11,15 +10,12 @@ pub trait AnchorElection: Send + Sync { fn update_reputation(&self, commit_event: CommitEvent); } -pub trait TChainHealthBackoff: Send + Sync { - fn get_round_backoff(&self, round: Round) -> (f64, Option); - - fn get_round_payload_limits(&self, round: Round) -> (f64, Option<(u64, u64)>); +pub trait CommitHistory: Send + Sync { + fn get_voting_power_participation_ratio(&self, round: Round) -> VotingPowerRatio; } mod leader_reputation_adapter; mod round_robin; pub use leader_reputation_adapter::{LeaderReputationAdapter, MetadataBackendAdapter}; -#[cfg(test)] pub use round_robin::RoundRobinAnchorElection; diff --git a/consensus/src/dag/anchor_election/round_robin.rs b/consensus/src/dag/anchor_election/round_robin.rs index 7bb745bce1b4c..ee1b6e5f53442 100644 --- a/consensus/src/dag/anchor_election/round_robin.rs +++ b/consensus/src/dag/anchor_election/round_robin.rs @@ -1,7 +1,11 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::dag::{anchor_election::AnchorElection, storage::CommitEvent}; +use super::CommitHistory; +use crate::{ + dag::{anchor_election::AnchorElection, storage::CommitEvent}, + liveness::leader_reputation::VotingPowerRatio, +}; use aptos_consensus_types::common::{Author, Round}; pub struct RoundRobinAnchorElection { @@ -21,3 +25,9 @@ impl AnchorElection for RoundRobinAnchorElection { fn update_reputation(&self, _event: CommitEvent) {} } + +impl CommitHistory for RoundRobinAnchorElection { + fn get_voting_power_participation_ratio(&self, _round: Round) -> VotingPowerRatio { + 1.0 + } +} diff --git a/consensus/src/dag/bootstrap.rs b/consensus/src/dag/bootstrap.rs index f671b957c9f05..013c88089ebd5 100644 --- a/consensus/src/dag/bootstrap.rs +++ b/consensus/src/dag/bootstrap.rs @@ -2,16 +2,17 @@ use super::{ adapter::{OrderedNotifierAdapter, TLedgerInfoProvider}, - anchor_election::AnchorElection, + anchor_election::{AnchorElection, CommitHistory, RoundRobinAnchorElection}, dag_driver::DagDriver, dag_fetcher::{DagFetcher, DagFetcherService, FetchRequestHandler}, dag_handler::NetworkHandler, dag_network::TDAGNetworkSender, dag_state_sync::{DagStateSynchronizer, StateSyncTrigger}, dag_store::Dag, + health::{ChainHealthBackoff, HealthBackoff, PipelineLatencyBasedBackpressure, TChainHealth}, order_rule::OrderRule, rb_handler::NodeBroadcastHandler, - storage::DAGStorage, + storage::{CommitEvent, DAGStorage}, types::{CertifiedNodeMessage, DAGMessage}, DAGRpcResult, ProofNotifier, }; @@ -25,7 +26,7 @@ use crate::{ }, liveness::{ leader_reputation::{ProposerAndVoterHeuristic, ReputationHeuristic}, - proposal_generator::ChainHealthBackoffConfig, + proposal_generator::{ChainHealthBackoffConfig, PipelineBackpressureConfig}, }, monitor, network::IncomingDAGRequest, @@ -46,7 +47,11 @@ use aptos_logger::{debug, info}; use aptos_reliable_broadcast::{RBNetworkSender, ReliableBroadcast}; use aptos_types::{ epoch_state::EpochState, - on_chain_config::{DagConsensusConfigV1, FeatureFlag, Features, ValidatorTxnConfig}, + on_chain_config::{ + AnchorElectionMode, DagConsensusConfigV1, FeatureFlag, Features, + LeaderReputationType::{ProposerAndVoter, ProposerAndVoterV2}, + ProposerAndVoterConfig, ValidatorTxnConfig, + }, validator_signer::ValidatorSigner, }; use async_trait::async_trait; @@ -68,7 +73,8 @@ struct BootstrapBaseState { dag_store: Arc>, order_rule: OrderRule, ledger_info_provider: Arc, - leader_reputation_adapter: Arc, + ordered_notifier: Arc, + commit_history: Arc, } #[enum_dispatch(TDagMode)] @@ -377,7 +383,10 @@ impl DagBootstrapper { } } - fn build_leader_reputation_components(&self) -> Arc { + fn build_leader_reputation_components( + &self, + config: &ProposerAndVoterConfig, + ) -> Arc { let num_validators = self.epoch_state.verifier.len(); // TODO: support multiple epochs let metadata_adapter = Arc::new(MetadataBackendAdapter::new( @@ -393,12 +402,12 @@ impl DagBootstrapper { // TODO: use onchain config let heuristic: Box = Box::new(ProposerAndVoterHeuristic::new( self.self_peer, - 1000, - 10, - 1, - 10, - num_validators, - num_validators * 10, + config.active_weight, + config.inactive_weight, + config.failed_weight, + config.failure_threshold_percent, + num_validators * config.voter_window_num_validators_multiplier, + num_validators * config.proposer_window_num_validators_multiplier, false, )); @@ -419,15 +428,57 @@ impl DagBootstrapper { metadata_adapter, heuristic, 100, - ChainHealthBackoffConfig::new(self.config.chain_backoff_config.clone()), )) } + fn build_anchor_election( + &self, + ) -> ( + Arc, + Arc, + Option>, + ) { + match &self.onchain_config.anchor_election_mode { + AnchorElectionMode::RoundRobin => { + let election = Arc::new(RoundRobinAnchorElection::new( + self.epoch_state.verifier.get_ordered_account_addresses(), + )); + (election.clone(), election, None) + }, + AnchorElectionMode::LeaderReputation(reputation_type) => { + let (commit_events, leader_reputation) = match reputation_type { + ProposerAndVoterV2(config) => { + let commit_events = self + .storage + .get_latest_k_committed_events( + config.voter_window_num_validators_multiplier as u64 + * self.epoch_state.verifier.len() as u64, + ) + .expect("Failed to read commit events from storage"); + ( + commit_events, + self.build_leader_reputation_components(config), + ) + }, + ProposerAndVoter(_) => unreachable!("unsupported mode"), + }; + + ( + leader_reputation.clone(), + leader_reputation, + Some(commit_events), + ) + }, + } + } + fn bootstrap_dag_store( &self, anchor_election: Arc, + commit_history: Arc, + commit_events: Option>, dag_window_size_config: u64, - ) -> (Arc>, OrderRule, Arc) { + ) -> BootstrapBaseState { let ledger_info_from_storage = self .storage .get_latest_ledger_info() @@ -457,7 +508,7 @@ impl DagBootstrapper { dag_window_size_config, ))); - let notifier = Arc::new(OrderedNotifierAdapter::new( + let ordered_notifier = Arc::new(OrderedNotifierAdapter::new( self.ordered_nodes_tx.clone(), dag.clone(), self.epoch_state.clone(), @@ -470,12 +521,18 @@ impl DagBootstrapper { commit_round + 1, dag.clone(), anchor_election.clone(), - notifier, - self.storage.clone(), + ordered_notifier.clone(), self.onchain_config.dag_ordering_causal_history_window as Round, + commit_events, ); - (dag, order_rule, ledger_info_provider) + BootstrapBaseState { + dag_store: dag, + order_rule, + ledger_info_provider, + ordered_notifier, + commit_history, + } } fn bootstrap_components( @@ -503,7 +560,8 @@ impl DagBootstrapper { dag_store, ledger_info_provider, order_rule, - leader_reputation_adapter, + ordered_notifier, + commit_history, } = base_state; let state_sync_trigger = StateSyncTrigger::new( @@ -531,10 +589,19 @@ impl DagBootstrapper { new_round_tx, self.epoch_state.clone(), Duration::from_millis(round_state_config.adaptive_responsive_minimum_wait_time_ms), - leader_reputation_adapter.clone(), )), ); + let chain_health: Arc = ChainHealthBackoff::new( + ChainHealthBackoffConfig::new(self.config.chain_backoff_config.clone()), + commit_history.clone(), + ); + let pipeline_health = PipelineLatencyBasedBackpressure::new( + PipelineBackpressureConfig::new(self.config.pipeline_backpressure_config.clone()), + ordered_notifier.clone(), + ); + let health_backoff = + HealthBackoff::new(self.epoch_state.clone(), chain_health, pipeline_health); let dag_driver = DagDriver::new( self.self_peer, self.epoch_state.clone(), @@ -549,7 +616,7 @@ impl DagBootstrapper { round_state, self.onchain_config.dag_ordering_causal_history_window as Round, self.config.node_payload_config.clone(), - leader_reputation_adapter.clone(), + health_backoff, self.quorum_store_enabled, ); let rb_handler = NodeBroadcastHandler::new( @@ -579,20 +646,15 @@ impl DagBootstrapper { } fn full_bootstrap(&self) -> (BootstrapBaseState, NetworkHandler, DagFetcherService) { - let leader_reputation_adapter = self.build_leader_reputation_components(); + let (anchor_election, commit_history, commit_events) = self.build_anchor_election(); - let (dag_store, order_rule, ledger_info_provider) = self.bootstrap_dag_store( - leader_reputation_adapter.clone(), + let base_state = self.bootstrap_dag_store( + anchor_election.clone(), + commit_history, + commit_events, self.onchain_config.dag_ordering_causal_history_window as u64, ); - let base_state = BootstrapBaseState { - dag_store, - order_rule, - ledger_info_provider, - leader_reputation_adapter, - }; - let (handler, fetch_service) = self.bootstrap_components(&base_state); (base_state, handler, fetch_service) } diff --git a/consensus/src/dag/dag_driver.rs b/consensus/src/dag/dag_driver.rs index 628f86af07f21..6c9b9141ad6e8 100644 --- a/consensus/src/dag/dag_driver.rs +++ b/consensus/src/dag/dag_driver.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::anchor_election::TChainHealthBackoff; +use super::health::HealthBackoff; use crate::{ dag::{ adapter::TLedgerInfoProvider, @@ -58,7 +58,7 @@ pub(crate) struct DagDriver { round_state: RoundState, window_size_config: Round, payload_config: DagPayloadConfig, - chain_backoff: Arc, + health_backoff: HealthBackoff, quorum_store_enabled: bool, } @@ -78,7 +78,7 @@ impl DagDriver { round_state: RoundState, window_size_config: Round, payload_config: DagPayloadConfig, - chain_backoff: Arc, + health_backoff: HealthBackoff, quorum_store_enabled: bool, ) -> Self { let pending_node = storage @@ -102,7 +102,7 @@ impl DagDriver { round_state, window_size_config, payload_config, - chain_backoff, + health_backoff, quorum_store_enabled, }; @@ -151,8 +151,12 @@ impl DagDriver { .unwrap_or_default(), ) }; + + let minimum_delay = self + .health_backoff + .backoff_duration(highest_strong_link_round + 1); self.round_state - .check_for_new_round(highest_strong_link_round, strong_links) + .check_for_new_round(highest_strong_link_round, strong_links, minimum_delay) .await; Ok(()) } @@ -206,7 +210,9 @@ impl DagDriver { (validator_payload_filter, payload_filter) }; - let (max_txns, max_size_bytes) = self.calculate_payload_limits(new_round); + let (max_txns, max_size_bytes) = self + .health_backoff + .calculate_payload_limits(new_round, &self.payload_config); let (validator_txns, payload) = match self .payload_client @@ -302,49 +308,6 @@ impl DagDriver { prev_handle.abort(); } } - - fn calculate_payload_limits(&self, round: Round) -> (u64, u64) { - let (voting_power_ratio, maybe_backoff_limits) = - self.chain_backoff.get_round_payload_limits(round); - debug!( - "calculate_payload_limits voting_power_ratio {}", - voting_power_ratio - ); - let (max_txns_per_round, max_size_per_round_bytes) = { - if let Some((backoff_max_txns, backoff_max_size_bytes)) = maybe_backoff_limits { - ( - self.payload_config - .max_sending_txns_per_round - .min(backoff_max_txns), - self.payload_config - .max_sending_size_per_round_bytes - .min(backoff_max_size_bytes), - ) - } else { - ( - self.payload_config.max_sending_txns_per_round, - self.payload_config.max_sending_size_per_round_bytes, - ) - } - }; - // TODO: warn/panic if division yields 0 txns - let max_txns = max_txns_per_round - .saturating_div( - (self.epoch_state.verifier.len() as f64 * voting_power_ratio) - .ceil() - .max(1.0) as u64, - ) - .max(1); - let max_txn_size_bytes = max_size_per_round_bytes - .saturating_div( - (self.epoch_state.verifier.len() as f64 * voting_power_ratio) - .ceil() - .max(1.0) as u64, - ) - .max(1024); - - (max_txns, max_txn_size_bytes) - } } #[async_trait] diff --git a/consensus/src/dag/health/backoff.rs b/consensus/src/dag/health/backoff.rs new file mode 100644 index 0000000000000..425aa1fd3895a --- /dev/null +++ b/consensus/src/dag/health/backoff.rs @@ -0,0 +1,80 @@ +// Copyright © Aptos Foundation + +use super::{pipeline_health::TPipelineHealth, TChainHealth}; +use aptos_config::config::DagPayloadConfig; +use aptos_consensus_types::common::Round; +use aptos_types::epoch_state::EpochState; +use std::{sync::Arc, time::Duration}; + +pub struct HealthBackoff { + epoch_state: Arc, + chain_health: Arc, + pipeline_health: Arc, +} + +impl HealthBackoff { + pub fn new( + epoch_state: Arc, + chain_health: Arc, + pipeline_health: Arc, + ) -> Self { + Self { + epoch_state, + chain_health, + pipeline_health, + } + } + + pub fn calculate_payload_limits( + &self, + round: Round, + payload_config: &DagPayloadConfig, + ) -> (u64, u64) { + let chain_backoff = self + .chain_health + .get_round_payload_limits(round) + .unwrap_or((u64::MAX, u64::MAX)); + let pipeline_backoff = self + .pipeline_health + .get_payload_limits() + .unwrap_or((u64::MAX, u64::MAX)); + let voting_power_ratio = self.chain_health.voting_power_ratio(round); + + let max_txns_per_round = [ + payload_config.max_sending_txns_per_round, + chain_backoff.0, + pipeline_backoff.0, + ] + .into_iter() + .min() + .expect("must not be empty"); + + let max_size_per_round_bytes = [ + payload_config.max_sending_size_per_round_bytes, + chain_backoff.1, + pipeline_backoff.1, + ] + .into_iter() + .min() + .expect("must not be empty"); + + // TODO: figure out receiver side checks + let max_txns = max_txns_per_round.saturating_div( + (self.epoch_state.verifier.len() as f64 * voting_power_ratio).ceil() as u64, + ); + let max_txn_size_bytes = max_size_per_round_bytes.saturating_div( + (self.epoch_state.verifier.len() as f64 * voting_power_ratio).ceil() as u64, + ); + + (max_txns, max_txn_size_bytes) + } + + pub fn backoff_duration(&self, round: Round) -> Duration { + let chain_backoff = self.chain_health.get_round_backoff(round); + let pipeline_backoff = self.pipeline_health.get_backoff(); + + chain_backoff + .unwrap_or_default() + .max(pipeline_backoff.unwrap_or_default()) + } +} diff --git a/consensus/src/dag/health/chain_health.rs b/consensus/src/dag/health/chain_health.rs new file mode 100644 index 0000000000000..9206d2ac1f17d --- /dev/null +++ b/consensus/src/dag/health/chain_health.rs @@ -0,0 +1,94 @@ +// Copyright © Aptos Foundation + +use crate::{ + counters::CHAIN_HEALTH_BACKOFF_TRIGGERED, + dag::anchor_election::CommitHistory, + liveness::{leader_reputation::VotingPowerRatio, proposal_generator::ChainHealthBackoffConfig}, +}; +use aptos_config::config::ChainHealthBackoffValues; +use aptos_consensus_types::common::Round; +use std::{sync::Arc, time::Duration}; + +pub trait TChainHealth: Send + Sync { + fn get_round_backoff(&self, round: Round) -> Option; + + fn get_round_payload_limits(&self, round: Round) -> Option<(u64, u64)>; + + fn voting_power_ratio(&self, round: Round) -> VotingPowerRatio; +} + +pub struct NoChainHealth {} + +impl NoChainHealth { + pub fn new() -> Arc { + Arc::new(Self {}) + } +} + +impl TChainHealth for NoChainHealth { + fn get_round_backoff(&self, _round: Round) -> Option { + None + } + + fn get_round_payload_limits(&self, _round: Round) -> Option<(u64, u64)> { + None + } + + fn voting_power_ratio(&self, _round: Round) -> VotingPowerRatio { + 1.0 + } +} + +pub struct ChainHealthBackoff { + config: ChainHealthBackoffConfig, + commit_history: Arc, +} + +impl ChainHealthBackoff { + pub fn new( + config: ChainHealthBackoffConfig, + commit_history: Arc, + ) -> Arc { + Arc::new(Self { + commit_history, + config, + }) + } + + fn get_chain_health_backoff(&self, round: Round) -> Option<&ChainHealthBackoffValues> { + let voting_power_ratio = self + .commit_history + .get_voting_power_participation_ratio(round); + let chain_health_backoff = self.config.get_backoff(voting_power_ratio); + + chain_health_backoff + } +} + +impl TChainHealth for ChainHealthBackoff { + fn get_round_backoff(&self, round: Round) -> Option { + let chain_health_backoff = self.get_chain_health_backoff(round); + if let Some(value) = chain_health_backoff { + CHAIN_HEALTH_BACKOFF_TRIGGERED.observe(1.0); + Some(Duration::from_millis(value.backoff_proposal_delay_ms)) + } else { + CHAIN_HEALTH_BACKOFF_TRIGGERED.observe(0.0); + None + } + } + + fn get_round_payload_limits(&self, round: Round) -> Option<(u64, u64)> { + let chain_health_backoff = self.get_chain_health_backoff(round); + chain_health_backoff.map(|value| { + ( + value.max_sending_block_txns_override, + value.max_sending_block_bytes_override, + ) + }) + } + + fn voting_power_ratio(&self, round: Round) -> VotingPowerRatio { + self.commit_history + .get_voting_power_participation_ratio(round) + } +} diff --git a/consensus/src/dag/health/mod.rs b/consensus/src/dag/health/mod.rs new file mode 100644 index 0000000000000..462763ec77f9d --- /dev/null +++ b/consensus/src/dag/health/mod.rs @@ -0,0 +1,13 @@ +// Copyright © Aptos Foundation + +mod backoff; +mod chain_health; +mod pipeline_health; + +pub use backoff::HealthBackoff; +#[cfg(test)] +pub use chain_health::NoChainHealth; +pub use chain_health::{ChainHealthBackoff, TChainHealth}; +#[cfg(test)] +pub use pipeline_health::NoPipelineBackpressure; +pub use pipeline_health::PipelineLatencyBasedBackpressure; diff --git a/consensus/src/dag/health/pipeline_health.rs b/consensus/src/dag/health/pipeline_health.rs new file mode 100644 index 0000000000000..fba40fe895068 --- /dev/null +++ b/consensus/src/dag/health/pipeline_health.rs @@ -0,0 +1,66 @@ +// Copyright © Aptos Foundation + +use crate::{ + dag::adapter::OrderedNotifierAdapter, liveness::proposal_generator::PipelineBackpressureConfig, +}; +use std::{sync::Arc, time::Duration}; + +pub trait TPipelineHealth: Send + Sync { + fn get_backoff(&self) -> Option; + + fn get_payload_limits(&self) -> Option<(u64, u64)>; +} + +pub struct NoPipelineBackpressure {} + +impl NoPipelineBackpressure { + pub fn new() -> Arc { + Arc::new(Self {}) + } +} + +impl TPipelineHealth for NoPipelineBackpressure { + fn get_backoff(&self) -> Option { + None + } + + fn get_payload_limits(&self) -> Option<(u64, u64)> { + None + } +} + +pub struct PipelineLatencyBasedBackpressure { + pipeline_config: PipelineBackpressureConfig, + adapter: Arc, +} + +impl PipelineLatencyBasedBackpressure { + pub(in crate::dag) fn new( + pipeline_config: PipelineBackpressureConfig, + adapter: Arc, + ) -> Arc { + Arc::new(Self { + pipeline_config, + adapter, + }) + } +} + +impl TPipelineHealth for PipelineLatencyBasedBackpressure { + fn get_backoff(&self) -> Option { + let latency = self.adapter.pipeline_pending_latency(); + self.pipeline_config + .get_backoff(latency) + .map(|config| Duration::from_millis(config.backpressure_proposal_delay_ms)) + } + + fn get_payload_limits(&self) -> Option<(u64, u64)> { + let latency = self.adapter.pipeline_pending_latency(); + self.pipeline_config.get_backoff(latency).map(|config| { + ( + config.max_sending_block_txns_override, + config.max_sending_block_bytes_override, + ) + }) + } +} diff --git a/consensus/src/dag/mod.rs b/consensus/src/dag/mod.rs index 930e9c9118b24..4b5611d84e9ca 100644 --- a/consensus/src/dag/mod.rs +++ b/consensus/src/dag/mod.rs @@ -13,6 +13,7 @@ mod dag_network; mod dag_state_sync; mod dag_store; mod errors; +mod health; mod observability; mod order_rule; mod rb_handler; diff --git a/consensus/src/dag/order_rule.rs b/consensus/src/dag/order_rule.rs index 38cbfa213c61e..bbc899ad2d059 100644 --- a/consensus/src/dag/order_rule.rs +++ b/consensus/src/dag/order_rule.rs @@ -9,7 +9,7 @@ use crate::dag::{ logging::{LogEvent, LogSchema}, tracing::{observe_node, NodeStage}, }, - storage::{CommitEvent, DAGStorage}, + storage::CommitEvent, types::NodeMetadata, CertifiedNode, }; @@ -27,7 +27,6 @@ pub struct OrderRule { dag: Arc>, anchor_election: Arc, notifier: Arc, - storage: Arc, dag_window_size_config: Round, } @@ -38,29 +37,28 @@ impl OrderRule { dag: Arc>, anchor_election: Arc, notifier: Arc, - storage: Arc, dag_window_size_config: Round, + commit_events: Option>, ) -> Self { - let commit_events = storage - .get_latest_k_committed_events(10 * epoch_state.verifier.len() as u64) - .expect("Failed to read commit events from storage"); - // make sure it's sorted - assert!(commit_events - .windows(2) - .all(|w| (w[0].epoch(), w[0].round()) < (w[1].epoch(), w[1].round()))); - for event in commit_events { - if event.epoch() == epoch_state.epoch { - let maybe_anchor = dag - .read() - .get_node_by_round_author(event.round(), event.author()) - .cloned(); - if let Some(anchor) = maybe_anchor { - dag.write() - .reachable_mut(&anchor, None) - .for_each(|node_status| node_status.mark_as_ordered()); + if let Some(commit_events) = commit_events { + // make sure it's sorted + assert!(commit_events + .windows(2) + .all(|w| (w[0].epoch(), w[0].round()) < (w[1].epoch(), w[1].round()))); + for event in commit_events { + if event.epoch() == epoch_state.epoch { + let maybe_anchor = dag + .read() + .get_node_by_round_author(event.round(), event.author()) + .cloned(); + if let Some(anchor) = maybe_anchor { + dag.write() + .reachable_mut(&anchor, None) + .for_each(|node_status| node_status.mark_as_ordered()); + } } + anchor_election.update_reputation(event); } - anchor_election.update_reputation(event); } let mut order_rule = Self { epoch_state, @@ -68,7 +66,6 @@ impl OrderRule { dag, anchor_election, notifier, - storage, dag_window_size_config, }; // re-check if anything can be ordered to recover pending anchors diff --git a/consensus/src/dag/round_state.rs b/consensus/src/dag/round_state.rs index 5185fe69e80a0..53c6c7e3ba7b9 100644 --- a/consensus/src/dag/round_state.rs +++ b/consensus/src/dag/round_state.rs @@ -1,7 +1,6 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::anchor_election::TChainHealthBackoff; use crate::dag::{ observability::tracing::{observe_round, RoundStage}, types::NodeCertificate, @@ -35,6 +34,7 @@ impl RoundState { &mut self, highest_strong_links_round: Round, strong_links: Vec, + minimum_delay: Duration, ) { match self.current_round.cmp(&highest_strong_links_round) { // we're behind, move forward immediately @@ -44,7 +44,7 @@ impl RoundState { }, Ordering::Equal => { self.responsive_check - .check_for_new_round(highest_strong_links_round, strong_links) + .check_for_new_round(highest_strong_links_round, strong_links, minimum_delay) .await }, Ordering::Greater => (), @@ -68,6 +68,7 @@ pub trait ResponsiveCheck: Send { &mut self, highest_strong_links_round: Round, strong_links: Vec, + health_backoff_delay: Duration, ); fn reset(&mut self); @@ -90,6 +91,7 @@ impl ResponsiveCheck for OptimisticResponsive { &mut self, highest_strong_links_round: Round, _strong_links: Vec, + _health_backoff_delay: Duration, ) { let new_round = highest_strong_links_round + 1; let _ = self.event_sender.send(new_round).await; @@ -105,16 +107,15 @@ enum State { } /// More sophisticated strategy to move round forward given 2f+1 strong links -/// Delay if backpressure is triggered. (TODO) +/// Delay if backpressure is triggered. /// Move as soon as 3f+1 is ready. (TODO: make it configurable) -/// Move if minimal wait time is reached. (TODO: make it configurable) +/// Move if minimal wait time is reached. pub struct AdaptiveResponsive { epoch_state: Arc, start_time: Duration, minimal_wait_time: Duration, event_sender: tokio::sync::mpsc::Sender, state: State, - chain_backoff: Arc, } impl AdaptiveResponsive { @@ -122,7 +123,6 @@ impl AdaptiveResponsive { event_sender: tokio::sync::mpsc::Sender, epoch_state: Arc, minimal_wait_time: Duration, - chain_backoff: Arc, ) -> Self { Self { epoch_state, @@ -130,7 +130,6 @@ impl AdaptiveResponsive { minimal_wait_time, event_sender, state: State::Initial, - chain_backoff, } } } @@ -141,6 +140,7 @@ impl ResponsiveCheck for AdaptiveResponsive { &mut self, highest_strong_links_round: Round, strong_links: Vec, + health_backoff_delay: Duration, ) { if matches!(self.state, State::Sent) { return; @@ -156,17 +156,16 @@ impl ResponsiveCheck for AdaptiveResponsive { .sum_voting_power(strong_links.iter().map(|cert| cert.metadata().author())) .expect("Unable to sum voting power from strong links"); - let (_, backoff_duration) = self.chain_backoff.get_round_backoff(new_round); - let wait_time = if let Some(duration) = backoff_duration { - duration.max(self.minimal_wait_time) + let (wait_time, is_health_backoff) = if self.minimal_wait_time < health_backoff_delay { + (health_backoff_delay, true) } else { - self.minimal_wait_time + (self.minimal_wait_time, false) }; - // voting power == 3f+1 or pass minimal wait time + // voting power == 3f+1 and pass wait time if health backoff let duration_since_start = duration_since_epoch().saturating_sub(self.start_time); if voting_power == self.epoch_state.verifier.total_voting_power() - || duration_since_start >= wait_time + && (duration_since_start >= wait_time || !is_health_backoff) { let _ = self.event_sender.send(new_round).await; if let State::Scheduled(handle) = std::mem::replace(&mut self.state, State::Sent) { diff --git a/consensus/src/dag/tests/dag_driver_tests.rs b/consensus/src/dag/tests/dag_driver_tests.rs index b2ef0a85bf82e..7be1231c1bc2d 100644 --- a/consensus/src/dag/tests/dag_driver_tests.rs +++ b/consensus/src/dag/tests/dag_driver_tests.rs @@ -3,12 +3,13 @@ use crate::{ dag::{ adapter::TLedgerInfoProvider, - anchor_election::{RoundRobinAnchorElection, TChainHealthBackoff}, + anchor_election::RoundRobinAnchorElection, dag_driver::DagDriver, dag_fetcher::TFetchRequester, dag_network::{RpcWithFallback, TDAGNetworkSender}, dag_store::Dag, errors::DagDriverError, + health::{HealthBackoff, NoChainHealth, NoPipelineBackpressure}, order_rule::OrderRule, round_state::{OptimisticResponsive, RoundState}, tests::{ @@ -96,18 +97,6 @@ impl TLedgerInfoProvider for MockLedgerInfoProvider { } } -struct MockChainHealthBackoff {} - -impl TChainHealthBackoff for MockChainHealthBackoff { - fn get_round_backoff(&self, _round: Round) -> (f64, Option) { - (1.0, None) - } - - fn get_round_payload_limits(&self, _round: Round) -> (f64, Option<(u64, u64)>) { - (1.0, None) - } -} - struct MockFetchRequester {} impl TFetchRequester for MockFetchRequester { @@ -158,8 +147,8 @@ fn setup( dag.clone(), Arc::new(RoundRobinAnchorElection::new(validators)), Arc::new(TestNotifier { tx }), - storage.clone(), TEST_DAG_WINDOW as Round, + None, ); let fetch_requester = Arc::new(MockFetchRequester {}); @@ -175,7 +164,7 @@ fn setup( DagDriver::new( signers[0].author(), - epoch_state, + epoch_state.clone(), dag, Arc::new(MockPayloadClient::new(None)), rb, @@ -187,7 +176,11 @@ fn setup( round_state, TEST_DAG_WINDOW as Round, DagPayloadConfig::default(), - Arc::new(MockChainHealthBackoff {}), + HealthBackoff::new( + epoch_state, + NoChainHealth::new(), + NoPipelineBackpressure::new(), + ), false, ) } diff --git a/consensus/src/dag/tests/order_rule_tests.rs b/consensus/src/dag/tests/order_rule_tests.rs index a628e3ce7aba6..857ac8fd5fc3f 100644 --- a/consensus/src/dag/tests/order_rule_tests.rs +++ b/consensus/src/dag/tests/order_rule_tests.rs @@ -106,8 +106,8 @@ fn create_order_rule( dag, anchor_election, Arc::new(TestNotifier { tx }), - Arc::new(MockStorage::new()), TEST_DAG_WINDOW as Round, + None, ), rx, ) diff --git a/consensus/src/liveness/leader_reputation.rs b/consensus/src/liveness/leader_reputation.rs index 3fa740825cbd5..29349b8980782 100644 --- a/consensus/src/liveness/leader_reputation.rs +++ b/consensus/src/liveness/leader_reputation.rs @@ -30,6 +30,8 @@ use std::{ sync::Arc, }; +pub type VotingPowerRatio = f64; + /// Interface to query committed NewBlockEvent. pub trait MetadataBackend: Send + Sync { /// Return a contiguous NewBlockEvent window in which last one is at target_round or @@ -576,7 +578,11 @@ impl LeaderReputation { // Compute chain health metrics, and // - return participating voting power percentage for the window_for_chain_health // - update metric counters for different windows - fn compute_chain_health_and_add_metrics(&self, history: &[NewBlockEvent], round: Round) -> f64 { + fn compute_chain_health_and_add_metrics( + &self, + history: &[NewBlockEvent], + round: Round, + ) -> VotingPowerRatio { let candidates = self.epoch_to_proposers.get(&self.epoch).unwrap(); // use f64 counter, as total voting power is u128 let total_voting_power = self.voting_powers.iter().map(|v| *v as f64).sum(); @@ -639,7 +645,7 @@ impl LeaderReputation { if chosen { // do not treat chain as unhealthy, if chain just started, and we don't have enough history to decide. - let voting_power_participation_ratio = + let voting_power_participation_ratio: VotingPowerRatio = if history.len() < *participants_window_size && self.epoch <= 2 { 1.0 } else if total_voting_power >= 1.0 { @@ -671,7 +677,7 @@ impl ProposerElection for LeaderReputation { fn get_valid_proposer_and_voting_power_participation_ratio( &self, round: Round, - ) -> (Author, f64) { + ) -> (Author, VotingPowerRatio) { let target_round = round.saturating_sub(self.exclude_round); let (sliding_window, root_hash) = self.backend.get_block_metadata(self.epoch, target_round); let voting_power_participation_ratio = @@ -713,7 +719,7 @@ impl ProposerElection for LeaderReputation { .0 } - fn get_voting_power_participation_ratio(&self, round: Round) -> f64 { + fn get_voting_power_participation_ratio(&self, round: Round) -> VotingPowerRatio { self.get_valid_proposer_and_voting_power_participation_ratio(round) .1 } diff --git a/types/src/on_chain_config/consensus_config.rs b/types/src/on_chain_config/consensus_config.rs index 39be0d7358731..8af9db1c62605 100644 --- a/types/src/on_chain_config/consensus_config.rs +++ b/types/src/on_chain_config/consensus_config.rs @@ -374,9 +374,17 @@ pub struct ProposerAndVoterConfig { pub use_history_from_previous_epoch_max_count: u32, } +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "snake_case")] +pub enum AnchorElectionMode { + RoundRobin, + LeaderReputation(LeaderReputationType), +} + #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] pub struct DagConsensusConfigV1 { pub dag_ordering_causal_history_window: usize, + pub anchor_election_mode: AnchorElectionMode, } impl Default for DagConsensusConfigV1 { @@ -384,6 +392,18 @@ impl Default for DagConsensusConfigV1 { fn default() -> Self { Self { dag_ordering_causal_history_window: 10, + anchor_election_mode: AnchorElectionMode::LeaderReputation( + LeaderReputationType::ProposerAndVoterV2(ProposerAndVoterConfig { + active_weight: 1000, + inactive_weight: 10, + failed_weight: 1, + failure_threshold_percent: 10, + proposer_window_num_validators_multiplier: 10, + voter_window_num_validators_multiplier: 1, + weight_by_voting_power: true, + use_history_from_previous_epoch_max_count: 5, + }), + ), } } } diff --git a/types/src/on_chain_config/mod.rs b/types/src/on_chain_config/mod.rs index 9468fb3938967..fee2010623a21 100644 --- a/types/src/on_chain_config/mod.rs +++ b/types/src/on_chain_config/mod.rs @@ -38,8 +38,9 @@ pub use self::{ Version, APTOS_MAX_KNOWN_VERSION, APTOS_VERSION_2, APTOS_VERSION_3, APTOS_VERSION_4, }, consensus_config::{ - ConsensusAlgorithmConfig, ConsensusConfigV1, DagConsensusConfigV1, LeaderReputationType, - OnChainConsensusConfig, ProposerAndVoterConfig, ProposerElectionType, ValidatorTxnConfig, + AnchorElectionMode, ConsensusAlgorithmConfig, ConsensusConfigV1, DagConsensusConfigV1, + LeaderReputationType, OnChainConsensusConfig, ProposerAndVoterConfig, ProposerElectionType, + ValidatorTxnConfig, }, execution_config::{ BlockGasLimitType, ExecutionConfigV1, ExecutionConfigV2, OnChainExecutionConfig, From 2aadfebce1eb180a785101e8acfcdc89f2694cae Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Mon, 5 Feb 2024 22:54:47 -0800 Subject: [PATCH 017/328] [dag] stop voting based on pipeline latency (#11407) --- Cargo.lock | 547 ++++++++++---------- config/src/config/dag_consensus_config.rs | 21 +- consensus/src/dag/adapter.rs | 2 +- consensus/src/dag/bootstrap.rs | 13 +- consensus/src/dag/errors.rs | 2 + consensus/src/dag/health/backoff.rs | 5 + consensus/src/dag/health/pipeline_health.rs | 14 + consensus/src/dag/rb_handler.rs | 9 + consensus/src/dag/tests/rb_handler_tests.rs | 25 +- 9 files changed, 353 insertions(+), 285 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d2f8010dfc39..52d0b8cb98ecf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,9 +13,9 @@ name = "abstract-domain-derive" version = "0.1.0" dependencies = [ "move-stackless-bytecode", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -268,7 +268,7 @@ dependencies = [ "bcs 0.1.4", "bollard", "chrono", - "clap 4.4.12", + "clap 4.4.14", "clap_complete", "codespan-reporting", "dashmap", @@ -563,7 +563,7 @@ dependencies = [ "async-trait", "bcs 0.1.4", "bytes", - "clap 4.4.12", + "clap 4.4.14", "csv", "futures", "itertools 0.10.5", @@ -680,7 +680,7 @@ dependencies = [ "aptos-metrics-core", "aptos-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "criterion", "dashmap", "itertools 0.10.5", @@ -729,7 +729,7 @@ name = "aptos-cargo-cli" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.12", + "clap 4.4.14", "clap-verbosity-flag", "determinator", "env_logger", @@ -757,7 +757,7 @@ name = "aptos-cli-common" version = "1.0.0" dependencies = [ "anstyle", - "clap 4.4.12", + "clap 4.4.14", "clap_complete", ] @@ -784,7 +784,7 @@ dependencies = [ "aptos-vm-logging", "aptos-vm-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "futures", "itertools 0.10.5", "move-binary-format", @@ -905,7 +905,7 @@ dependencies = [ "bytes", "chrono", "claims", - "clap 4.4.12", + "clap 4.4.14", "dashmap", "enum_dispatch", "fail 0.5.1", @@ -1048,7 +1048,7 @@ name = "aptos-crypto-derive" version = "0.0.3" dependencies = [ "anyhow", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -1149,7 +1149,7 @@ dependencies = [ "bcs 0.1.4", "byteorder", "claims", - "clap 4.4.12", + "clap 4.4.14", "dashmap", "either", "itertools 0.10.5", @@ -1221,7 +1221,7 @@ dependencies = [ "aptos-vm", "async-trait", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "itertools 0.10.5", "owo-colors", "tokio", @@ -1237,7 +1237,7 @@ dependencies = [ "aptos-logger", "aptos-move-debugger", "aptos-push-metrics", - "clap 4.4.12", + "clap 4.4.14", "tokio", ] @@ -1324,7 +1324,7 @@ name = "aptos-enum-conversion-derive" version = "0.0.3" dependencies = [ "anyhow", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", "trybuild", @@ -1443,7 +1443,7 @@ dependencies = [ "async-trait", "bcs 0.1.4", "chrono", - "clap 4.4.12", + "clap 4.4.14", "derivative", "indicatif 0.15.0", "itertools 0.10.5", @@ -1480,7 +1480,7 @@ dependencies = [ "aptos-types", "aptos-vm", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "crossbeam-channel", "ctrlc", "dashmap", @@ -1607,7 +1607,7 @@ dependencies = [ "aptos-faucet-core", "aptos-logger", "aptos-sdk", - "clap 4.4.12", + "clap 4.4.14", "tokio", ] @@ -1623,7 +1623,7 @@ dependencies = [ "aptos-sdk", "async-trait", "captcha", - "clap 4.4.12", + "clap 4.4.14", "deadpool-redis", "enum_dispatch", "futures", @@ -1665,7 +1665,7 @@ dependencies = [ "anyhow", "aptos-faucet-core", "aptos-logger", - "clap 4.4.12", + "clap 4.4.14", "tokio", ] @@ -1677,7 +1677,7 @@ dependencies = [ "aptos-logger", "aptos-node-checker", "aptos-sdk", - "clap 4.4.12", + "clap 4.4.14", "env_logger", "futures", "gcp-bigquery-client", @@ -1714,7 +1714,7 @@ dependencies = [ "aptos-transaction-generator-lib", "async-trait", "chrono", - "clap 4.4.12", + "clap 4.4.14", "either", "futures", "hex", @@ -1757,7 +1757,7 @@ dependencies = [ "aptos-testcases", "async-trait", "chrono", - "clap 4.4.12", + "clap 4.4.14", "futures", "jemallocator", "once_cell", @@ -1800,7 +1800,7 @@ dependencies = [ "bulletproofs", "byteorder", "claims", - "clap 4.4.12", + "clap 4.4.14", "codespan-reporting", "curve25519-dalek-ng", "either", @@ -1882,7 +1882,7 @@ dependencies = [ "aptos-vault-client", "bcs 0.1.4", "byteorder", - "clap 4.4.12", + "clap 4.4.14", "datatest-stable", "hex", "move-binary-format", @@ -1923,7 +1923,7 @@ dependencies = [ "aptos-types", "aptos-vm-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "float-cmp", "move-binary-format", "move-bytecode-source-map", @@ -1995,7 +1995,7 @@ dependencies = [ "aptos-package-builder", "aptos-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-core-types", "move-model", "tempfile", @@ -2066,7 +2066,7 @@ dependencies = [ "bcs 0.1.4", "bigdecimal", "chrono", - "clap 4.4.12", + "clap 4.4.14", "diesel", "diesel_migrations", "field_count", @@ -2099,7 +2099,7 @@ dependencies = [ "async-trait", "backoff", "base64 0.13.1", - "clap 4.4.12", + "clap 4.4.14", "futures", "futures-core", "once_cell", @@ -2128,7 +2128,7 @@ dependencies = [ "backtrace", "base64 0.13.1", "bytes", - "clap 4.4.12", + "clap 4.4.14", "cloud-storage", "dashmap", "enum_dispatch", @@ -2171,7 +2171,7 @@ dependencies = [ "aptos-runtimes", "async-trait", "base64 0.13.1", - "clap 4.4.12", + "clap 4.4.14", "cloud-storage", "futures", "once_cell", @@ -2200,7 +2200,7 @@ dependencies = [ "aptos-runtimes", "async-trait", "base64 0.13.1", - "clap 4.4.12", + "clap 4.4.14", "cloud-storage", "futures", "futures-util", @@ -2291,7 +2291,7 @@ dependencies = [ "async-trait", "backoff", "base64 0.13.1", - "clap 4.4.12", + "clap 4.4.14", "futures", "futures-core", "futures-util", @@ -2322,7 +2322,7 @@ dependencies = [ "aptos-runtimes", "async-trait", "backtrace", - "clap 4.4.12", + "clap 4.4.14", "futures", "prometheus", "serde", @@ -2405,7 +2405,7 @@ dependencies = [ "backtrace", "base64 0.13.1", "chrono", - "clap 4.4.12", + "clap 4.4.14", "cloud-storage", "flate2", "futures", @@ -2601,7 +2601,7 @@ dependencies = [ name = "aptos-log-derive" version = "0.1.0" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -2743,7 +2743,7 @@ dependencies = [ "aptos-vm-logging", "aptos-vm-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-binary-format", "move-cli", "move-compiler", @@ -2765,7 +2765,7 @@ dependencies = [ "aptos-gas-schedule", "aptos-types", "aptos-vm", - "clap 4.4.12", + "clap 4.4.14", "move-cli", "move-package", "move-prover", @@ -2975,7 +2975,7 @@ dependencies = [ "aptos-logger", "aptos-network", "aptos-types", - "clap 4.4.12", + "clap 4.4.14", "futures", "serde", "tokio", @@ -3022,7 +3022,7 @@ dependencies = [ "base64 0.13.1", "bytes", "chrono", - "clap 4.4.12", + "clap 4.4.14", "csv", "diesel", "diesel_migrations", @@ -3098,7 +3098,7 @@ dependencies = [ "aptos-validator-transaction-pool", "aptos-vm", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "either", "fail 0.5.1", "futures", @@ -3130,7 +3130,7 @@ dependencies = [ "aptos-sdk", "aptos-transaction-emitter-lib", "async-trait", - "clap 4.4.12", + "clap 4.4.14", "const_format", "env_logger", "futures", @@ -3177,7 +3177,7 @@ dependencies = [ name = "aptos-num-variants" version = "0.1.0" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -3204,7 +3204,7 @@ dependencies = [ "aptos-mempool", "aptos-storage-interface", "aptos-types", - "clap 4.4.12", + "clap 4.4.14", ] [[package]] @@ -3388,7 +3388,7 @@ dependencies = [ "aptos-types", "aptos-vm-genesis", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "futures", "git2 0.16.1", "handlebars", @@ -3450,7 +3450,7 @@ dependencies = [ "aptos-types", "bcs 0.1.4", "bytes", - "clap 4.4.12", + "clap 4.4.14", "futures", "hex", "move-binary-format", @@ -3497,7 +3497,7 @@ dependencies = [ "aptos-types", "aptos-warp-webserver", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "futures", "hex", "itertools 0.10.5", @@ -3522,7 +3522,7 @@ dependencies = [ "aptos-logger", "aptos-rosetta", "aptos-types", - "clap 4.4.12", + "clap 4.4.14", "serde", "serde_json", "tokio", @@ -3639,7 +3639,7 @@ dependencies = [ "aptos-framework", "aptos-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "heck 0.4.1", "move-core-types", "once_cell", @@ -3960,7 +3960,7 @@ dependencies = [ "bcs 0.1.4", "chrono", "claims", - "clap 4.4.12", + "clap 4.4.14", "debug-ignore", "flate2", "futures", @@ -4057,7 +4057,7 @@ dependencies = [ "aptos-types", "aptos-vm", "aptos-vm-logging", - "clap 4.4.12", + "clap 4.4.14", "criterion", "criterion-cpu-time", "num_cpus", @@ -4075,7 +4075,7 @@ dependencies = [ "aptos-logger", "aptos-sdk", "aptos-transaction-emitter-lib", - "clap 4.4.12", + "clap 4.4.14", "futures", "rand 0.7.3", "tokio", @@ -4097,7 +4097,7 @@ dependencies = [ "aptos-transaction-generator-lib", "aptos-types", "async-trait", - "clap 4.4.12", + "clap 4.4.14", "futures", "itertools 0.10.5", "once_cell", @@ -4119,7 +4119,7 @@ dependencies = [ "aptos-logger", "aptos-sdk", "async-trait", - "clap 4.4.12", + "clap 4.4.14", "move-binary-format", "once_cell", "rand 0.7.3", @@ -4143,7 +4143,7 @@ dependencies = [ "aptos-vm", "aptos-vm-genesis", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "datatest-stable", "hex", "move-binary-format", @@ -4342,7 +4342,7 @@ dependencies = [ "aptos-language-e2e-tests", "aptos-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-binary-format", "move-bytecode-source-map", "move-core-types", @@ -4401,7 +4401,7 @@ dependencies = [ "aptos-vm", "aptos-vm-genesis", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "glob", "move-binary-format", "move-core-types", @@ -4611,7 +4611,7 @@ checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ "num-bigint 0.4.4", "num-traits", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -4676,7 +4676,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -4805,7 +4805,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" dependencies = [ "concurrent-queue", - "event-listener 4.0.2", + "event-listener 4.0.3", "event-listener-strategy", "futures-core", "pin-project-lite", @@ -4834,7 +4834,7 @@ dependencies = [ "async-task", "concurrent-queue", "fastrand 2.0.1", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "slab", ] @@ -4849,7 +4849,7 @@ dependencies = [ "async-io 2.2.2", "async-lock 3.2.0", "blocking", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "once_cell", ] @@ -4883,7 +4883,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "parking", "polling 3.3.1", "rustix 0.38.28", @@ -4907,7 +4907,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" dependencies = [ - "event-listener 4.0.2", + "event-listener 4.0.3", "event-listener-strategy", "pin-project-lite", ] @@ -4953,9 +4953,9 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -5020,16 +5020,16 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "async-task" -version = "4.6.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d90cd0b264dfdd8eb5bad0a2c217c1f88fa96a8573f40e7b12de23fb468f46" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" @@ -5037,9 +5037,9 @@ version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -5066,7 +5066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -5078,7 +5078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -5238,9 +5238,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" [[package]] name = "base64-url" @@ -5248,7 +5248,7 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb9fb9fb058cc3063b5fc88d9a21eefa2735871498a04e1650da76ed511c8569" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", ] [[package]] @@ -5339,7 +5339,7 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3deeecb812ca5300b7d3f66f730cc2ebd3511c3d36c691dd79c165d5b19a26e3" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -5380,12 +5380,12 @@ dependencies = [ "lazycell", "peeking_take_while", "prettyplease", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "regex", "rustc-hash", "shlex", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -5541,7 +5541,7 @@ dependencies = [ "async-task", "fastrand 2.0.1", "futures-io", - "futures-lite 2.1.0", + "futures-lite 2.2.0", "piper", "tracing", ] @@ -5580,7 +5580,7 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f03db470b3c0213c47e978da93200259a1eb4dae2e5512cba9955e2b540a6fc6" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "bollard-stubs", "bytes", "futures-core", @@ -6002,9 +6002,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.12" +version = "4.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d" +checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2" dependencies = [ "clap_builder", "clap_derive 4.4.7", @@ -6016,15 +6016,15 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c90e95e5bd4e8ac34fa6f37c774b0c6f8ed06ea90c79931fd448fcf941a9767" dependencies = [ - "clap 4.4.12", + "clap 4.4.14", "log", ] [[package]] name = "clap_builder" -version = "4.4.12" +version = "4.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9" +checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370" dependencies = [ "anstream", "anstyle", @@ -6038,7 +6038,7 @@ version = "4.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97aeaa95557bd02f23fbb662f981670c3d20c5a26e69f7354b28f57092437fcd" dependencies = [ - "clap 4.4.12", + "clap 4.4.14", ] [[package]] @@ -6049,7 +6049,7 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck 0.4.1", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -6061,9 +6061,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -6262,7 +6262,7 @@ version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "unicode-xid 0.2.4", ] @@ -6303,7 +6303,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7efb37c3e1ccb1ff97164ad95ac1606e8ccd35b3fa0a7d99a304c7f4a428cc24" dependencies = [ "aes-gcm", - "base64 0.21.5", + "base64 0.21.6", "hkdf 0.12.4", "hmac 0.12.1", "percent-encoding", @@ -6379,9 +6379,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -6443,11 +6443,10 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb9105919ca8e40d437fc9cbb8f1975d916f1bd28afe795a48aae32a2cc8920" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "cfg-if", "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", @@ -6457,54 +6456,46 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.17" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-queue" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc6598521bb5a83d491e8c1fe51db7296019d2ca3cb93cc6c2a20369a4d78a2" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossterm" @@ -6742,7 +6733,7 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "strsim 0.10.0", "syn 1.0.109", @@ -6756,7 +6747,7 @@ checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "strsim 0.10.0", "syn 1.0.109", @@ -6770,10 +6761,10 @@ checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "strsim 0.10.0", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -6806,7 +6797,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core 0.20.3", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -6933,7 +6924,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -6944,9 +6935,9 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -6956,7 +6947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "rustc_version", "syn 1.0.109", @@ -7039,9 +7030,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef8337737574f55a468005a83499da720f20c65586241ffea339db9ecdfd2b44" dependencies = [ "diesel_table_macro_syntax", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -7061,7 +7052,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -7366,9 +7357,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f33313078bb8d4d05a2733a94ac4c2d8a0df9a2b84424ebf4f33bfc224a890e" dependencies = [ "once_cell", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -7588,9 +7579,9 @@ dependencies = [ [[package]] name = "event-listener" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "218a870470cce1469024e9fb66b901aa983929d81304a1cdb299f28118e550d5" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", @@ -7603,7 +7594,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" dependencies = [ - "event-listener 4.0.2", + "event-listener 4.0.3", "pin-project-lite", ] @@ -7990,9 +7981,9 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -8105,9 +8096,9 @@ dependencies = [ [[package]] name = "futures-lite" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" dependencies = [ "fastrand 2.0.1", "futures-core", @@ -8122,9 +8113,9 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -8271,7 +8262,7 @@ dependencies = [ "aptos-network", "aptos-types", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-core-types", "rand 0.7.3", "serde", @@ -8462,7 +8453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "931bedb2264cb00f914b0a6a5c304e34865c34306632d3932e0951a073e4a67d" dependencies = [ "async-trait", - "base64 0.21.5", + "base64 0.21.6", "google-cloud-metadata", "google-cloud-token", "home", @@ -8541,7 +8532,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22c57ca1d971d7c6f852c02eda4e87e88b1247b6ed8be9fa5b2768c68b0f2ca5" dependencies = [ "async-stream", - "base64 0.21.5", + "base64 0.21.6", "bytes", "futures-util", "google-cloud-auth", @@ -8751,7 +8742,7 @@ version = "7.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "byteorder", "flate2", "nom", @@ -8764,7 +8755,7 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "bytes", "headers-core", "http", @@ -8970,7 +8961,7 @@ dependencies = [ "assert-json-diff", "async-object-pool", "async-trait", - "base64 0.21.5", + "base64 0.21.6", "basic-cookies", "crossbeam-utils", "form_urlencoded", @@ -9157,9 +9148,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" dependencies = [ "crossbeam-deque", "globset", @@ -9246,7 +9237,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -9280,7 +9271,7 @@ checksum = "0a0c890c85da4bab7bce4204c707396bbd3c6c8a681716a51c8814cfc2b682df" dependencies = [ "anyhow", "proc-macro-hack", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -9291,7 +9282,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b139284b5cf57ecfa712bcc66950bb635b31aff41c188e8a4cfc758eca374a3f" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", ] @@ -9355,7 +9346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "321f0f839cd44a4686e9504b0a62b4d69a50b62072144c71c68f5873c167b8d9" dependencies = [ "ahash 0.8.7", - "clap 4.4.12", + "clap 4.4.14", "crossbeam-channel", "crossbeam-utils", "dashmap", @@ -9606,7 +9597,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "pem 1.1.1", "ring 0.16.20", "serde", @@ -9708,7 +9699,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98ff3d647085c6c025083efad0435890867f4bea042fc62d408ab3aeb1cdf66" dependencies = [ "darling 0.13.4", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "serde_json", "syn 1.0.109", @@ -9852,9 +9843,9 @@ checksum = "db13adb97ab515a3691f56e4dbab09283d0b86cb45abd991d8634a9d6f501760" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libfuzzer-sys" @@ -10009,9 +10000,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.12" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" +checksum = "5f526fdd09d99e19742883e43de41e1aa9e36db0c7ab7f935165d611c5cccc66" dependencies = [ "cc", "libc", @@ -10048,7 +10039,7 @@ name = "listener" version = "0.1.0" dependencies = [ "bytes", - "clap 4.4.12", + "clap 4.4.14", "tokio", ] @@ -10162,7 +10153,7 @@ name = "macros" version = "0.1.0" source = "git+https://github.com/niroco/diesel_async_migrations?rev=11f331b73c5cfcc894380074f748d8fda710ac12#11f331b73c5cfcc894380074f748d8fda710ac12" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", ] @@ -10278,7 +10269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cce3325ac70e67bbab5bd837a31cae01f1a6db64e0e744a33cb03a543469ef08" dependencies = [ "migrations_internals", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", ] @@ -10369,7 +10360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ce75669015c4f47b289fd4d4f56e894e4c96003ffdf3ac51313126f94c6cbb" dependencies = [ "cfg-if", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -10394,7 +10385,7 @@ dependencies = [ "anyhow", "aptos-framework", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-binary-format", ] @@ -10430,7 +10421,7 @@ name = "move-analyzer" version = "1.0.0" dependencies = [ "anyhow", - "clap 4.4.12", + "clap 4.4.14", "codespan-reporting", "crossbeam", "derivative", @@ -10542,7 +10533,7 @@ name = "move-bytecode-viewer" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.12", + "clap 4.4.14", "crossterm 0.26.1", "move-binary-format", "move-bytecode-source-map", @@ -10560,7 +10551,7 @@ dependencies = [ "anyhow", "bcs 0.1.4", "bytes", - "clap 4.4.12", + "clap 4.4.14", "codespan-reporting", "colored", "datatest-stable", @@ -10623,7 +10614,7 @@ version = "0.0.1" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "codespan-reporting", "datatest-stable", "difference", @@ -10662,7 +10653,7 @@ dependencies = [ "abstract-domain-derive", "anyhow", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "codespan", "codespan-reporting", "datatest-stable", @@ -10730,7 +10721,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "codespan", "colored", "move-binary-format", @@ -10748,7 +10739,7 @@ name = "move-disassembler" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.12", + "clap 4.4.14", "colored", "move-binary-format", "move-bytecode-source-map", @@ -10815,7 +10806,7 @@ name = "move-explain" version = "0.1.0" dependencies = [ "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-command-line-common", "move-core-types", ] @@ -10826,7 +10817,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "move-binary-format", "move-bytecode-source-map", "move-bytecode-verifier", @@ -10924,7 +10915,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bcs 0.1.4", - "clap 4.4.12", + "clap 4.4.14", "colored", "datatest-stable", "dirs-next", @@ -10965,7 +10956,7 @@ dependencies = [ "anyhow", "async-trait", "atty", - "clap 4.4.12", + "clap 4.4.14", "codespan", "codespan-reporting", "datatest-stable", @@ -11037,7 +11028,7 @@ dependencies = [ "anyhow", "async-trait", "atty", - "clap 4.4.12", + "clap 4.4.14", "codespan", "codespan-reporting", "datatest-stable", @@ -11196,7 +11187,7 @@ version = "0.1.0" dependencies = [ "anyhow", "atty", - "clap 4.4.12", + "clap 4.4.14", "codespan", "codespan-reporting", "datatest-stable", @@ -11238,7 +11229,7 @@ name = "move-transactional-test-runner" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.12", + "clap 4.4.14", "colored", "datatest-stable", "difference", @@ -11274,7 +11265,7 @@ dependencies = [ "anyhow", "better_any", "bytes", - "clap 4.4.12", + "clap 4.4.14", "codespan-reporting", "colored", "datatest-stable", @@ -11435,7 +11426,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -11559,7 +11550,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be7d33be719c6f4d09e64e27c1ef4e73485dc4cc1f4d22201f89860a7fe22e22" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -11571,7 +11562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "066b468120587a402f0b47d8f80035c921f6a46f8209efd0632a89a16f5188a4" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -11698,7 +11689,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -11864,9 +11855,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -11945,7 +11936,7 @@ checksum = "03f2cb802b5bdfdf52f1ffa0b54ce105e4d346e91990dd571f86c91321ad49e2" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -11958,7 +11949,7 @@ checksum = "5f7d21ccd03305a674437ee1248f3ab5d4b1db095cf1caf49f1713ddf61956b7" dependencies = [ "Inflector", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -12040,7 +12031,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1557010476e0595c9b568d16dcfb81b93cdeb157612726f5170d31aa707bed27" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -12052,7 +12043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ "proc-macro-crate 2.0.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -12258,9 +12249,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", @@ -12269,9 +12260,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde" dependencies = [ "pest", "pest_generator", @@ -12279,22 +12270,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d" dependencies = [ "once_cell", "pest", @@ -12392,7 +12383,7 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -12403,9 +12394,9 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -12558,9 +12549,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ddcf4680d8d867e1e375116203846acb088483fa2070244f90589f458bbb31" dependencies = [ "proc-macro-crate 2.0.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -12599,7 +12590,7 @@ dependencies = [ "indexmap 1.9.3", "mime", "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "regex", "syn 1.0.109", @@ -12663,7 +12654,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597c3287a549da151aca6ada2795ecde089c7527bd5093114e8e0e1c3f0e52b1" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -12690,7 +12681,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "byteorder", "bytes", "fallible-iterator", @@ -12829,8 +12820,8 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ - "proc-macro2 1.0.75", - "syn 2.0.47", + "proc-macro2 1.0.76", + "syn 2.0.48", ] [[package]] @@ -12909,7 +12900,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", "version_check", @@ -12921,7 +12912,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "version_check", ] @@ -12949,9 +12940,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] @@ -12969,7 +12960,7 @@ dependencies = [ "bcs 0.1.4", "bigdecimal", "chrono", - "clap 4.4.12", + "clap 4.4.14", "diesel", "diesel-async", "diesel_async_migrations", @@ -13097,7 +13088,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cf16337405ca084e9c78985114633b6827711d22b9e6ef6c6c0d665eb3f0b6e" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -13130,7 +13121,7 @@ checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools 0.10.5", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -13143,9 +13134,9 @@ checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", "itertools 0.11.0", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -13197,7 +13188,7 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", - "clap 4.4.12", + "clap 4.4.14", "codespan-reporting", "hex", "itertools 0.10.5", @@ -13333,7 +13324,7 @@ version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", ] [[package]] @@ -13579,9 +13570,9 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -13635,7 +13626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ "async-compression", - "base64 0.21.5", + "base64 0.21.6", "bytes", "cookie 0.16.2", "cookie_store", @@ -13815,7 +13806,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -13897,7 +13888,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5015e68a0685a95ade3eee617ff7101ab6a3fc689203101ca16ebc16f2b89c66" dependencies = [ "cfg-if", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "rustc_version", "syn 1.0.109", @@ -14031,7 +14022,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", ] [[package]] @@ -14129,7 +14120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeb2780690380592f86205aa4ee49815feb2acad8c2f59e6dd207148c3f1fcd" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -14141,7 +14132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" dependencies = [ "proc-macro-crate 1.3.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -14298,7 +14289,7 @@ name = "sender" version = "0.1.0" dependencies = [ "bytes", - "clap 4.4.12", + "clap 4.4.14", "event-listener 2.5.3", "quanta", "tokio", @@ -14306,9 +14297,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] @@ -14391,20 +14382,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fbd975230bada99c8bb618e0c365c2eefa219158d5c6c29610fd09ff1833257" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "indexmap 2.1.0", "itoa", @@ -14439,9 +14430,9 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -14471,7 +14462,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "chrono", "hex", "indexmap 1.9.3", @@ -14489,9 +14480,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ "darling 0.20.3", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -14547,7 +14538,7 @@ dependencies = [ "anyhow", "async-trait", "backtrace", - "clap 4.4.12", + "clap 4.4.14", "futures", "prometheus", "serde", @@ -14980,7 +14971,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -15129,7 +15120,7 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -15159,7 +15150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "rustversion", "syn 1.0.109", @@ -15172,10 +15163,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ "heck 0.4.1", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "rustversion", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -15230,18 +15221,18 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.47" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "unicode-ident", ] @@ -15405,9 +15396,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" dependencies = [ "cfg-if", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -15416,9 +15407,9 @@ version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", "test-case-core", ] @@ -15426,7 +15417,7 @@ dependencies = [ name = "test-generation" version = "0.1.0" dependencies = [ - "clap 4.4.12", + "clap 4.4.14", "crossbeam-channel", "getrandom 0.2.11", "hex", @@ -15452,7 +15443,7 @@ name = "testdiff" version = "0.1.0" dependencies = [ "anyhow", - "clap 4.4.12", + "clap 4.4.14", "itertools 0.10.5", "once_cell", "walkdir", @@ -15509,9 +15500,9 @@ version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -15664,9 +15655,9 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -15900,7 +15891,7 @@ dependencies = [ "async-stream", "async-trait", "axum 0.6.20", - "base64 0.21.5", + "base64 0.21.6", "bytes", "flate2", "futures-core", @@ -15934,7 +15925,7 @@ dependencies = [ "async-stream", "async-trait", "axum 0.6.20", - "base64 0.21.5", + "base64 0.21.6", "bytes", "flate2", "h2", @@ -16059,7 +16050,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ad0c048e114d19d1140662762bfdb10682f3bc806d8be18af846600214dd9af" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", "syn 1.0.109", ] @@ -16082,9 +16073,9 @@ version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -16204,9 +16195,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.87" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6b2fc10a33500845468aa7c06567a9226581b24f03c6f891e6dda2dc9a1c8b" +checksum = "76de4f783e610194f6c98bfd53f9fc52bb2e0d02c947621e8a0f4ecc799b2880" dependencies = [ "basic-toml", "glob", @@ -16572,9 +16563,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "value-bag" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ce5bb364b23e66b528d03168df78b38c0f7b6fe17386928f29d5ab2e7cb2f7" +checksum = "dd65ff0de3304a013e6dfeb7324e1cd389a8a000e582e3c9c9fae82ced778e26" [[package]] name = "variant_count" @@ -16727,9 +16718,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", "wasm-bindgen-shared", ] @@ -16761,9 +16752,9 @@ version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -17133,9 +17124,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.32" +version = "0.5.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8434aeec7b290e8da5c3f0d628cb0eac6cabcb31d14bb74f779a08109a5914d6" +checksum = "b7520bbdec7211caa7c4e682eb1fbe07abe20cee6756b6e00f537c82c11816aa" dependencies = [ "memchr", ] @@ -17249,9 +17240,9 @@ version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] @@ -17269,9 +17260,9 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ - "proc-macro2 1.0.75", + "proc-macro2 1.0.76", "quote 1.0.35", - "syn 2.0.47", + "syn 2.0.48", ] [[package]] diff --git a/config/src/config/dag_consensus_config.rs b/config/src/config/dag_consensus_config.rs index 90f81430c6c78..2011f0697ed7b 100644 --- a/config/src/config/dag_consensus_config.rs +++ b/config/src/config/dag_consensus_config.rs @@ -135,6 +135,24 @@ impl Default for DagRoundStateConfig { } } +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[serde(default, deny_unknown_fields)] +pub struct DagHealthConfig { + pub chain_backoff_config: Vec, + pub voter_pipeline_latency_limit_ms: u64, + pub pipeline_backpressure_config: Vec, +} + +impl Default for DagHealthConfig { + fn default() -> Self { + Self { + chain_backoff_config: Vec::new(), + voter_pipeline_latency_limit_ms: 30_000, + pipeline_backpressure_config: Vec::new(), + } + } +} + #[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)] #[serde(default, deny_unknown_fields)] pub struct DagConsensusConfig { @@ -142,8 +160,7 @@ pub struct DagConsensusConfig { pub rb_config: ReliableBroadcastConfig, pub fetcher_config: DagFetcherConfig, pub round_state_config: DagRoundStateConfig, - pub chain_backoff_config: Vec, - pub pipeline_backpressure_config: Vec, + pub health_config: DagHealthConfig, #[serde(default = "QuorumStoreConfig::default_for_dag")] pub quorum_store: QuorumStoreConfig, } diff --git a/consensus/src/dag/adapter.rs b/consensus/src/dag/adapter.rs index 9237a7c08d858..3cca20d15e3b6 100644 --- a/consensus/src/dag/adapter.rs +++ b/consensus/src/dag/adapter.rs @@ -206,7 +206,7 @@ impl OrderedNotifier for OrderedNotifierAdapter { commit_decision: LedgerInfoWithSignatures| { block_created_ts .write() - .split_off(&(commit_decision.commit_info().round() + 1)); + .retain(|&round, _| round > commit_decision.commit_info().round()); dag.write() .commit_callback(commit_decision.commit_info().round()); ledger_info_provider diff --git a/consensus/src/dag/bootstrap.rs b/consensus/src/dag/bootstrap.rs index 013c88089ebd5..f1ade85ebe65b 100644 --- a/consensus/src/dag/bootstrap.rs +++ b/consensus/src/dag/bootstrap.rs @@ -593,11 +593,17 @@ impl DagBootstrapper { ); let chain_health: Arc = ChainHealthBackoff::new( - ChainHealthBackoffConfig::new(self.config.chain_backoff_config.clone()), + ChainHealthBackoffConfig::new(self.config.health_config.chain_backoff_config.clone()), commit_history.clone(), ); let pipeline_health = PipelineLatencyBasedBackpressure::new( - PipelineBackpressureConfig::new(self.config.pipeline_backpressure_config.clone()), + Duration::from_millis(self.config.health_config.voter_pipeline_latency_limit_ms), + PipelineBackpressureConfig::new( + self.config + .health_config + .pipeline_backpressure_config + .clone(), + ), ordered_notifier.clone(), ); let health_backoff = @@ -616,7 +622,7 @@ impl DagBootstrapper { round_state, self.onchain_config.dag_ordering_causal_history_window as Round, self.config.node_payload_config.clone(), - health_backoff, + health_backoff.clone(), self.quorum_store_enabled, ); let rb_handler = NodeBroadcastHandler::new( @@ -628,6 +634,7 @@ impl DagBootstrapper { self.config.node_payload_config.clone(), self.vtxn_config.clone(), self.features.clone(), + health_backoff, ); let fetch_handler = FetchRequestHandler::new(dag_store.clone(), self.epoch_state.clone()); diff --git a/consensus/src/dag/errors.rs b/consensus/src/dag/errors.rs index 39bdbae82c5c3..7c5e71da20836 100644 --- a/consensus/src/dag/errors.rs +++ b/consensus/src/dag/errors.rs @@ -14,6 +14,8 @@ pub enum NodeBroadcastHandleError { MissingParents, #[error("stale round number")] StaleRound(Round), + #[error("refused to vote")] + VoteRefused, } #[derive(Clone, Debug, ThisError, Serialize, Deserialize)] diff --git a/consensus/src/dag/health/backoff.rs b/consensus/src/dag/health/backoff.rs index 425aa1fd3895a..262d196aeb7e3 100644 --- a/consensus/src/dag/health/backoff.rs +++ b/consensus/src/dag/health/backoff.rs @@ -6,6 +6,7 @@ use aptos_consensus_types::common::Round; use aptos_types::epoch_state::EpochState; use std::{sync::Arc, time::Duration}; +#[derive(Clone)] pub struct HealthBackoff { epoch_state: Arc, chain_health: Arc, @@ -77,4 +78,8 @@ impl HealthBackoff { .unwrap_or_default() .max(pipeline_backoff.unwrap_or_default()) } + + pub fn stop_voting(&self) -> bool { + self.pipeline_health.stop_voting() + } } diff --git a/consensus/src/dag/health/pipeline_health.rs b/consensus/src/dag/health/pipeline_health.rs index fba40fe895068..d3c59c6ead75d 100644 --- a/consensus/src/dag/health/pipeline_health.rs +++ b/consensus/src/dag/health/pipeline_health.rs @@ -9,6 +9,8 @@ pub trait TPipelineHealth: Send + Sync { fn get_backoff(&self) -> Option; fn get_payload_limits(&self) -> Option<(u64, u64)>; + + fn stop_voting(&self) -> bool; } pub struct NoPipelineBackpressure {} @@ -27,19 +29,26 @@ impl TPipelineHealth for NoPipelineBackpressure { fn get_payload_limits(&self) -> Option<(u64, u64)> { None } + + fn stop_voting(&self) -> bool { + false + } } pub struct PipelineLatencyBasedBackpressure { + voter_pipeline_latency_limit: Duration, pipeline_config: PipelineBackpressureConfig, adapter: Arc, } impl PipelineLatencyBasedBackpressure { pub(in crate::dag) fn new( + voter_pipeline_latency_limit: Duration, pipeline_config: PipelineBackpressureConfig, adapter: Arc, ) -> Arc { Arc::new(Self { + voter_pipeline_latency_limit, pipeline_config, adapter, }) @@ -63,4 +72,9 @@ impl TPipelineHealth for PipelineLatencyBasedBackpressure { ) }) } + + fn stop_voting(&self) -> bool { + let latency = self.adapter.pipeline_pending_latency(); + latency > self.voter_pipeline_latency_limit + } } diff --git a/consensus/src/dag/rb_handler.rs b/consensus/src/dag/rb_handler.rs index 8f8afaa57aaab..df80b810249b5 100644 --- a/consensus/src/dag/rb_handler.rs +++ b/consensus/src/dag/rb_handler.rs @@ -1,6 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +use super::health::HealthBackoff; use crate::{ dag::{ dag_fetcher::TFetchRequester, @@ -41,6 +42,7 @@ pub(crate) struct NodeBroadcastHandler { payload_config: DagPayloadConfig, vtxn_config: ValidatorTxnConfig, features: Features, + health_backoff: HealthBackoff, } impl NodeBroadcastHandler { @@ -53,6 +55,7 @@ impl NodeBroadcastHandler { payload_config: DagPayloadConfig, vtxn_config: ValidatorTxnConfig, features: Features, + health_backoff: HealthBackoff, ) -> Self { let epoch = epoch_state.epoch; let votes_by_round_peer = read_votes_from_storage(&storage, epoch); @@ -67,6 +70,7 @@ impl NodeBroadcastHandler { payload_config, vtxn_config, features, + health_backoff, } } @@ -189,6 +193,11 @@ impl RpcHandler for NodeBroadcastHandler { type Response = Vote; async fn process(&mut self, node: Self::Request) -> anyhow::Result { + ensure!( + !self.health_backoff.stop_voting(), + NodeBroadcastHandleError::VoteRefused + ); + let node = self.validate(node)?; observe_node(node.timestamp(), NodeStage::NodeReceived); debug!(LogSchema::new(LogEvent::ReceiveNode) diff --git a/consensus/src/dag/tests/rb_handler_tests.rs b/consensus/src/dag/tests/rb_handler_tests.rs index 47e47d5ab421f..ac510a3fc5685 100644 --- a/consensus/src/dag/tests/rb_handler_tests.rs +++ b/consensus/src/dag/tests/rb_handler_tests.rs @@ -5,6 +5,7 @@ use crate::dag::{ dag_fetcher::TFetchRequester, dag_store::Dag, errors::NodeBroadcastHandleError, + health::{HealthBackoff, NoChainHealth, NoPipelineBackpressure}, rb_handler::NodeBroadcastHandler, storage::DAGStorage, tests::{ @@ -57,6 +58,12 @@ async fn test_node_broadcast_receiver_succeed() { TEST_DAG_WINDOW, ))); + let health_backoff = HealthBackoff::new( + epoch_state.clone(), + NoChainHealth::new(), + NoPipelineBackpressure::new(), + ); + let wellformed_node = new_node(1, 10, signers[0].author(), vec![]); let equivocating_node = new_node(1, 20, signers[0].author(), vec![]); @@ -71,6 +78,7 @@ async fn test_node_broadcast_receiver_succeed() { DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), Features::default(), + health_backoff, ); let expected_result = Vote::new( @@ -118,6 +126,11 @@ async fn test_node_broadcast_receiver_failure() { DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), Features::default(), + HealthBackoff::new( + epoch_state.clone(), + NoChainHealth::new(), + NoPipelineBackpressure::new(), + ), ) }) .collect(); @@ -202,6 +215,11 @@ async fn test_node_broadcast_receiver_storage() { DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), Features::default(), + HealthBackoff::new( + epoch_state.clone(), + NoChainHealth::new(), + NoPipelineBackpressure::new(), + ), ); let sig = rb_receiver.process(node).await.expect("must succeed"); @@ -213,12 +231,17 @@ async fn test_node_broadcast_receiver_storage() { let mut rb_receiver = NodeBroadcastHandler::new( dag, signers[3].clone(), - epoch_state, + epoch_state.clone(), storage.clone(), Arc::new(MockFetchRequester {}), DagPayloadConfig::default(), ValidatorTxnConfig::default_disabled(), Features::default(), + HealthBackoff::new( + epoch_state, + NoChainHealth::new(), + NoPipelineBackpressure::new(), + ), ); assert_ok!(rb_receiver.gc_before_round(2)); assert_eq!(storage.get_votes().unwrap().len(), 0); From 046544f9910bd38405b553fe7e14f1bac1260676 Mon Sep 17 00:00:00 2001 From: "Andrea Cappa (zi0Black)" <13380579+zi0Black@users.noreply.github.com> Date: Tue, 6 Feb 2024 18:26:36 +0100 Subject: [PATCH 018/328] Provide Corpus to OSS-Fuzz via fuzz.sh (#11831) * Corpus download added * Added Doc * [Fuzzing] Ignore false positive invariant violations * [Fuzzing] Ignore couple false positive invariant violations * [Fuzzing] Fuzz different types of TX authenticators * Debug, Apply Patch Logic, Perf Improv * Removed link * Small fix and clean-up --------- Co-authored-by: Your Name Co-authored-by: Aleksandre Khokhiashvili --- .../001FakeExecutorDisableMultiThread.patch | 146 ++++++++++++++++++ testsuite/fuzzer/README.md | 14 ++ testsuite/fuzzer/fuzz.sh | 55 ++++++- .../move/aptosvm_publish_and_run.rs | 3 +- 4 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 testsuite/fuzzer/Patches/001FakeExecutorDisableMultiThread.patch diff --git a/testsuite/fuzzer/Patches/001FakeExecutorDisableMultiThread.patch b/testsuite/fuzzer/Patches/001FakeExecutorDisableMultiThread.patch new file mode 100644 index 0000000000000..a33097516b3ed --- /dev/null +++ b/testsuite/fuzzer/Patches/001FakeExecutorDisableMultiThread.patch @@ -0,0 +1,146 @@ +diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs +index fee3fcdadd..fae1653841 100644 +--- a/aptos-move/aptos-vm/src/aptos_vm.rs ++++ b/aptos-move/aptos-vm/src/aptos_vm.rs +@@ -114,7 +114,7 @@ static TIMED_FEATURE_OVERRIDE: OnceCell = OnceCell::new(); + pub static RAYON_EXEC_POOL: Lazy> = Lazy::new(|| { + Arc::new( + rayon::ThreadPoolBuilder::new() +- .num_threads(num_cpus::get()) ++ .num_threads(1) + .thread_name(|index| format!("par_exec-{}", index)) + .build() + .unwrap(), +diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs +index 76b94ce0e9..e8e38f72a0 100644 +--- a/aptos-move/e2e-tests/src/executor.rs ++++ b/aptos-move/e2e-tests/src/executor.rs +@@ -116,9 +116,9 @@ pub enum ExecutorMode { + pub struct FakeExecutor { + data_store: FakeDataStore, + event_store: Vec, +- executor_thread_pool: Arc, ++ //executor_thread_pool: Arc, + block_time: u64, +- executed_output: Option, ++ //executed_output: Option, + trace_dir: Option, + rng: KeyGen, + /// If set, determines whether or not to execute a comparison test with the parallel +@@ -138,18 +138,18 @@ pub enum GasMeterType { + impl FakeExecutor { + /// Creates an executor from a genesis [`WriteSet`]. + pub fn from_genesis(write_set: &WriteSet, chain_id: ChainId) -> Self { +- let executor_thread_pool = Arc::new( +- rayon::ThreadPoolBuilder::new() +- .num_threads(num_cpus::get()) +- .build() +- .unwrap(), +- ); ++ //let executor_thread_pool = Arc::new( ++ // rayon::ThreadPoolBuilder::new() ++ // .num_threads(num_cpus::get()) ++ // .build() ++ // .unwrap(), ++ //); + let mut executor = FakeExecutor { + data_store: FakeDataStore::default(), + event_store: Vec::new(), +- executor_thread_pool, ++ //executor_thread_pool, + block_time: 0, +- executed_output: None, ++ //executed_output: None, + trace_dir: None, + rng: KeyGen::from_seed(RNG_SEED), + executor_mode: None, +@@ -219,18 +219,18 @@ impl FakeExecutor { + + /// Creates an executor in which no genesis state has been applied yet. + pub fn no_genesis() -> Self { +- let executor_thread_pool = Arc::new( +- rayon::ThreadPoolBuilder::new() +- .num_threads(num_cpus::get()) +- .build() +- .unwrap(), +- ); ++ //let executor_thread_pool = Arc::new( ++ // rayon::ThreadPoolBuilder::new() ++ // .num_threads(num_cpus::get()) ++ // .build() ++ // .unwrap(), ++ //); + FakeExecutor { + data_store: FakeDataStore::default(), + event_store: Vec::new(), +- executor_thread_pool, ++ //executor_thread_pool, + block_time: 0, +- executed_output: None, ++ //executed_output: None, + trace_dir: None, + rng: KeyGen::from_seed(RNG_SEED), + executor_mode: None, +@@ -243,7 +243,7 @@ impl FakeExecutor { + // 'test_name' includes ':' in the names, lets re-write these to be '_'s so that these + // files can persist on windows machines. + let file_name = test_name.replace(':', "_"); +- self.executed_output = Some(GoldenOutputs::new(&file_name)); ++ //self.executed_output = Some(GoldenOutputs::new(&file_name)); + self.set_tracing(test_name, file_name) + } + +@@ -251,7 +251,7 @@ impl FakeExecutor { + // 'test_name' includes ':' in the names, lets re-write these to be '_'s so that these + // files can persist on windows machines. + let file_name = test_name.replace(':', "_"); +- self.executed_output = Some(GoldenOutputs::new_at_path(PathBuf::from(path), &file_name)); ++ //self.executed_output = Some(GoldenOutputs::new_at_path(PathBuf::from(path), &file_name)); + self.set_tracing(test_name, file_name) + } + +@@ -475,18 +475,19 @@ impl FakeExecutor { + txn_block: &[SignatureVerifiedTransaction], + onchain_config: BlockExecutorConfigFromOnchain, + ) -> Result, VMStatus> { +- BlockAptosVM::execute_block::<_, NoOpTransactionCommitHook>( +- self.executor_thread_pool.clone(), +- txn_block, +- &self.data_store, +- BlockExecutorConfig { +- local: BlockExecutorLocalConfig { +- concurrency_level: usize::min(4, num_cpus::get()), +- }, +- onchain: onchain_config, +- }, +- None, +- ).map(BlockOutput::into_transaction_outputs_forced) ++ //BlockAptosVM::execute_block::<_, NoOpTransactionCommitHook>( ++ // self.executor_thread_pool.clone(), ++ // txn_block, ++ // &self.data_store, ++ // BlockExecutorConfig { ++ // local: BlockExecutorLocalConfig { ++ // concurrency_level: usize::min(4, num_cpus::get()), ++ // }, ++ // onchain: onchain_config, ++ // }, ++ // None, ++ //).map(BlockOutput::into_transaction_outputs_forced) ++ todo!() + } + + pub fn execute_transaction_block( +@@ -554,9 +555,9 @@ impl FakeExecutor { + + let output = sequential_output.or(parallel_output).unwrap(); + +- if let Some(logger) = &self.executed_output { +- logger.log(format!("{:#?}\n", output).as_str()); +- } ++ //if let Some(logger) = &self.executed_output { ++ // logger.log(format!("{:#?}\n", output).as_str()); ++ //} + + // dump serialized transaction output after execution, if tracing + if let Some(trace_dir) = &self.trace_dir { diff --git a/testsuite/fuzzer/README.md b/testsuite/fuzzer/README.md index f3df6033ef920..c33bc198058b2 100644 --- a/testsuite/fuzzer/README.md +++ b/testsuite/fuzzer/README.md @@ -77,6 +77,20 @@ Note that `Arbitrary` must be implemented (or derived) for all types used in the #### Implementing the fuzz logic The `fuzz_target!` macro receives data from the fuzzer. Implement logic to convert the fuzzer input into a format that the targeted function or module can process. Check existing fuzz targets for examples. +### OSS-Fuzz Corpus +Create a `.zip` archive containing your fuzzer's corpus and name it according to the following format: `[fuzzer_name]_seed_corpus.zip` (e.g., `move_aptosvm_publish_and_run_seed_corpus.zip`). Follow these steps for hosting and integrating the archive: + +1. **Upload to Public Hosting:** If you choose Google Drive, ensure the archive is publicly accessible via a shared link. + +2. **(GDrive Only) Modify the URL:** Replace `FILEID` in the URL template with your file's ID. The template URL is: + ``` + https://docs.google.com/uc?export=download&id=FILEID + ``` + +3. **Update `fuzz.sh`:** Insert the modified URL into the `CORPUS_ZIPS` array within the "fuzz.sh" script. + +When building in the OSS-Fuzz environment, `fuzz.sh` will place the corpus archive correctly alongside your fuzzer's binary. OSS-Fuzz then selects the proper archive, using its contents to feed the fuzzer. + ### Best Practices for Writing Fuzz Targets - **Focus on Target Functionality:** Choose functions or modules critical to your application's functionality and security. - **Handle Diverse Inputs:** Ensure that the harness can handle a wide range of input formats and sizes. diff --git a/testsuite/fuzzer/fuzz.sh b/testsuite/fuzzer/fuzz.sh index aef5f2aeb1d0d..68b0eeb50ce82 100755 --- a/testsuite/fuzzer/fuzz.sh +++ b/testsuite/fuzzer/fuzz.sh @@ -3,6 +3,9 @@ export RUSTFLAGS="${RUSTFLAGS} --cfg tokio_unstable" export EXTRAFLAGS="-Ztarget-applies-to-host -Zhost-config" +# GDRIVE format https://docs.google.com/uc?export=download&id=DOCID +CORPUS_ZIPS=() + function info() { echo "[info] $1" } @@ -39,16 +42,20 @@ function usage() { "run") echo "Usage: $0 run [testcase]" ;; + "debug") + echo "Usage: $0 debug " + ;; "test") echo "Usage: $0 test" ;; *) - echo "Usage: $0 " + echo "Usage: $0 " echo " add adds a new fuzz target" echo " build builds fuzz targets" echo " build-oss-fuzz builds fuzz targets for oss-fuzz" echo " list lists existing fuzz targets" echo " run runs a fuzz target" + echo " debug debugs a fuzz target with a testcase" echo " test tests all fuzz targets" ;; esac @@ -75,9 +82,17 @@ function build-oss-fuzz() { usage build-oss-fuzz fi oss_fuzz_out=$1 - mkdir -p $oss_fuzz_out + mkdir -p "$oss_fuzz_out" mkdir -p ./target + # Apply all git patch from Patches directory + wd=$(pwd) + for patch in $(find "$wd/Patches" -type f); do + info "Applying patch $patch" + git -C "$wd/../.." apply "$patch" + done + + # Workaround for build failures on oss-fuzz # Owner: @zi0Black # Issue: Some dependencies requires to compile C/C++ code and it result in build failure on oss-fuzz using provided flags. @@ -92,6 +107,11 @@ function build-oss-fuzz() { error "Build failed. Exiting." fi find ./target/*/release/ -maxdepth 1 -type f -perm /111 -exec cp {} $oss_fuzz_out \; + + # Download corpus zip + for corpus_zip in "${CORPUS_ZIPS[@]}"; do + wget --content-disposition -P "$oss_fuzz_out" "$corpus_zip" + done } function run() { @@ -102,7 +122,7 @@ function run() { testcase=$2 if [ ! -z "$testcase" ]; then if [ -f "$testcase" ]; then - testcase="-runs=1 $testcase" + testcase="$testcase -- -runs=1" else error "$testcase does not exist" fi @@ -111,6 +131,31 @@ function run() { cargo_fuzz run $fuzz_target $testcase } +# use rust-gdb to debug a fuzz target with a testcase +function debug() { + if [ -z "$1" ]; then + usage debug + fi + fuzz_target=$1 + testcase=$2 + if [ -z "$testcase" ]; then + error "No testcase provided" + fi + if [ ! -f "$testcase" ]; then + error "$testcase does not exist" + fi + info "Debugging $fuzz_target with $testcase" + # find the binary + binary=$(find ./target -name $fuzz_target -type f -executable) + if [ -z "$binary" ]; then + error "Could not find binary for $fuzz_target" + fi + # run the binary with rust-gdb + export LSAN_OPTIONS=verbosity=1:log_threads=1 + export RUST_BACKTRACE=1 + rust-gdb --args $binary $testcase -- -runs=1 +} + function test() { for fuzz_target in $(list); do info "Testing $fuzz_target" @@ -197,6 +242,10 @@ case "$1" in shift run "$@" ;; + "debug") + shift + debug "$@" + ;; "test") shift test diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs index c808559ce3dfb..8e81845df7d34 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs @@ -420,7 +420,8 @@ fn run_case(mut input: RunnableState) -> Result<(), Corpus> { // exec tx tdbg!("exec start"); let mut old_res = None; - const N_EXTRA_RERUNS: usize = 3; + const N_EXTRA_RERUNS: usize = 0; + #[allow(clippy::reversed_empty_ranges)] for _ in 0..N_EXTRA_RERUNS { let res = vm.execute_block(vec![tx.clone()]); if let Some(old_res) = old_res { From 4cd22ce69da47cc4024a876758cee4c1bffe08bb Mon Sep 17 00:00:00 2001 From: "Brian R. Murphy" <132495859+brmataptos@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:27:01 -0800 Subject: [PATCH 019/328] Fix Issue #11850 by extending move-model AST visitor to be able to hook BeforeBody in a Block expression (#11916) Fix Issue #11850, a bug in flow_insensitive_checkers struct SymbolVisitor which should process the binding of a Block expression (which is the RHS of a let expression's variable assignment) in the outer context, while processing the body in the context with the let variable(s) bound. This was achieved by extending AST's ExpData::visit_pre_post to visit_positions which provides hooks not just Pre and Post subexpression traversal, but also at useful control points: PreBody for Block expressions, and a few other points which will be useful in other analyses. --- .../src/flow_insensitive_checkers.rs | 78 ++++++----- .../tests/bytecode-generator/tuple.exp | 8 -- .../bytecode-generator/tuple_invalid.exp | 8 +- .../checking/naming/generics_shadowing.exp | 8 -- .../tests/checking/typing/assign_tuple.exp | 8 +- .../tests/checking/unused/local_var.exp | 33 +++++ .../tests/checking/unused/local_var.move | 9 ++ .../copy-propagation/dead_assignment_1.exp | 8 -- .../tests/inlining/multi_param.exp | 15 +-- .../tests/no-safety/simple_map_keys.exp | 15 +-- third_party/move/move-model/src/ast.rs | 125 +++++++++++++----- 11 files changed, 190 insertions(+), 125 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp create mode 100644 third_party/move/move-compiler-v2/tests/checking/unused/local_var.move diff --git a/third_party/move/move-compiler-v2/src/flow_insensitive_checkers.rs b/third_party/move/move-compiler-v2/src/flow_insensitive_checkers.rs index 859324fa8408b..0d15c426eb097 100644 --- a/third_party/move/move-compiler-v2/src/flow_insensitive_checkers.rs +++ b/third_party/move/move-compiler-v2/src/flow_insensitive_checkers.rs @@ -8,7 +8,7 @@ use codespan_reporting::diagnostic::Severity; use move_model::{ - ast::{ExpData, TempIndex}, + ast::{ExpData, TempIndex, VisitorPosition}, model::{GlobalEnv, Loc, NodeId, Parameter}, symbol::Symbol, }; @@ -30,7 +30,7 @@ pub fn check_for_unused_vars_and_params(env: &mut GlobalEnv) { fn find_unused_params_and_vars(env: &GlobalEnv, params: &[Parameter], exp: &ExpData) { let mut visitor = SymbolVisitor::new(env, params); - exp.visit_pre_post(&mut |post, exp_data| visitor.entry(post, exp_data)); + exp.visit_positions(&mut |position, exp_data| visitor.entry(position, exp_data)); visitor.check_parameter_usage(); } @@ -99,52 +99,62 @@ impl<'env, 'params> SymbolVisitor<'env, 'params> { } } - fn entry(&mut self, post: bool, e: &ExpData) -> bool { + fn entry(&mut self, position: VisitorPosition, e: &ExpData) -> bool { use ExpData::*; + use VisitorPosition::*; match e { Block(_, pat, _, _) => { - if !post { - self.seen_uses.enter_scope(); - } else { - // postorder - for (id, var) in pat.vars() { - self.node_symbol_decl_visitor(post, &id, &var, "local variable"); - } - self.seen_uses.exit_scope(); - } + match position { + BeforeBody => self.seen_uses.enter_scope(), + Post => { + for (id, var) in pat.vars() { + self.node_symbol_decl_visitor(true, &id, &var, "local variable"); + } + self.seen_uses.exit_scope(); + }, + Pre | MidMutate | BeforeThen | BeforeElse => {}, + }; }, Lambda(_, pat, _) => { - if !post { - self.seen_uses.enter_scope(); - } else { - // postorder - for (id, var) in pat.vars() { - self.node_symbol_decl_visitor(post, &id, &var, "parameter"); - } - self.seen_uses.exit_scope(); - } + match position { + Pre => self.seen_uses.enter_scope(), + Post => { + for (id, var) in pat.vars() { + self.node_symbol_decl_visitor(true, &id, &var, "parameter"); + } + self.seen_uses.exit_scope(); + }, + BeforeBody | MidMutate | BeforeThen | BeforeElse => {}, + }; }, Quant(_, _, ranges, ..) => { - if !post { - self.seen_uses.enter_scope(); - } else { - // postorder - for (id, var) in ranges.iter().flat_map(|(pat, _)| pat.vars().into_iter()) { - self.node_symbol_decl_visitor(post, &id, &var, "range parameter"); - } - self.seen_uses.exit_scope(); - } + match position { + Pre => self.seen_uses.enter_scope(), + Post => { + for (id, var) in ranges.iter().flat_map(|(pat, _)| pat.vars().into_iter()) { + self.node_symbol_decl_visitor(true, &id, &var, "range parameter"); + } + self.seen_uses.exit_scope(); + }, + BeforeBody | MidMutate | BeforeThen | BeforeElse => {}, + }; }, Assign(_, pat, _) => { - for (id, sym) in pat.vars().iter() { - self.node_symbol_use_visitor(post, id, sym); + if let Post = position { + for (id, sym) in pat.vars().iter() { + self.node_symbol_use_visitor(true, id, sym); + } } }, LocalVar(id, sym) => { - self.node_symbol_use_visitor(post, id, sym); + if let Post = position { + self.node_symbol_use_visitor(true, id, sym); + } }, Temporary(id, idx) => { - self.node_tmp_use_visitor(post, id, idx); + if let Post = position { + self.node_tmp_use_visitor(true, id, idx); + } }, _ => {}, } diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp index c1a5b3d1abf50..c0c82a2c5cbdd 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple.exp @@ -1,11 +1,3 @@ - -Diagnostics: -warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` - ┌─ tests/bytecode-generator/tuple.move:11:19 - │ -11 │ fun use_tuple(x: u64): u64 { - │ ^ - // ---- Model Dump module 0x42::tuple { struct S { diff --git a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp index b694a72b8b72f..bc3ded817abf0 100644 --- a/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp +++ b/third_party/move/move-compiler-v2/tests/bytecode-generator/tuple_invalid.exp @@ -1,10 +1,10 @@ Diagnostics: -warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` - ┌─ tests/bytecode-generator/tuple_invalid.move:11:20 +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/bytecode-generator/tuple_invalid.move:12:13 │ -11 │ fun use_tuple1(x: u64): u64 { - │ ^ +12 │ let x = tuple(x); + │ ^ // ---- Model Dump module 0x42::tuple_invalid { diff --git a/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp b/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp index db1ac8c729b7f..eab4f41536ed7 100644 --- a/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp +++ b/third_party/move/move-compiler-v2/tests/checking/naming/generics_shadowing.exp @@ -1,11 +1,3 @@ - -Diagnostics: -warning: Unused parameter `s`. Consider removing or prefixing with an underscore: `_s` - ┌─ tests/checking/naming/generics_shadowing.move:6:29 - │ -6 │ fun foo(s: S): S { - │ ^ - // ---- Model Dump module 0x2::M { struct S { diff --git a/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp b/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp index 9a2ccc6fdd700..ae5b1361b9e47 100644 --- a/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp +++ b/third_party/move/move-compiler-v2/tests/checking/typing/assign_tuple.exp @@ -1,10 +1,10 @@ Diagnostics: -warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` - ┌─ tests/checking/typing/assign_tuple.move:11:20 +warning: Unused local variable `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/checking/typing/assign_tuple.move:12:13 │ -11 │ fun use_tuple1(x: u64): u64 { - │ ^ +12 │ let x = tuple(x); + │ ^ // ---- Model Dump module 0x42::tuple_invalid { diff --git a/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp b/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp new file mode 100644 index 0000000000000..470d6d2d2ca3d --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/unused/local_var.exp @@ -0,0 +1,33 @@ +// ---- Model Dump +module 0xc0ffee::m { + public fun test(): u64 { + { + let x: u64 = 1; + { + let x: u64 = Add(x, 1); + { + let y: u64 = 2; + { + let y: u64 = Add(y, 1); + Add(x, y) + } + } + } + } + } + spec fun $test(): u64 { + { + let x: u256 = 1; + { + let x: num = Add(x, 1); + { + let y: u256 = 2; + { + let y: num = Add(y, 1); + Add(x, y) + } + } + } + } + } +} // end 0xc0ffee::m diff --git a/third_party/move/move-compiler-v2/tests/checking/unused/local_var.move b/third_party/move/move-compiler-v2/tests/checking/unused/local_var.move new file mode 100644 index 0000000000000..15b366e8435d8 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/checking/unused/local_var.move @@ -0,0 +1,9 @@ +module 0xc0ffee::m { + public fun test(): u64 { + let x = 1; + let x = x + 1; + let y = 2; + let y = y + 1; + x + y + } +} diff --git a/third_party/move/move-compiler-v2/tests/copy-propagation/dead_assignment_1.exp b/third_party/move/move-compiler-v2/tests/copy-propagation/dead_assignment_1.exp index 9be6936bbb747..3857e27ad61fa 100644 --- a/third_party/move/move-compiler-v2/tests/copy-propagation/dead_assignment_1.exp +++ b/third_party/move/move-compiler-v2/tests/copy-propagation/dead_assignment_1.exp @@ -1,11 +1,3 @@ - -Diagnostics: -warning: Unused local variable `a`. Consider removing or prefixing with an underscore: `_a` - ┌─ tests/copy-propagation/dead_assignment_1.move:3:13 - │ -3 │ let a = p; - │ ^ - ============ initial bytecode ================ [variant baseline] diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param.exp index 3aafe113fad6b..a6db107b3b9ca 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/inlining/multi_param.exp @@ -1,12 +1,3 @@ -comparison between v1 and v2 failed: -= processed 2 tasks -= -+ task 0 'publish'. lines 1-29: -+ warning: Unused parameter `elem`. Consider removing or prefixing with an underscore: `_elem` -+ ┌─ TEMPFILE:17:30 -+ │ -+ 17 │ for_each_ref_mut(v, |elem| { -+ │ ^^^^ -+ -+ -+ +processed 2 tasks + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-compiler-v2/transactional-tests/tests/no-safety/simple_map_keys.exp b/third_party/move/move-compiler-v2/transactional-tests/tests/no-safety/simple_map_keys.exp index 618e0759dca45..a6db107b3b9ca 100644 --- a/third_party/move/move-compiler-v2/transactional-tests/tests/no-safety/simple_map_keys.exp +++ b/third_party/move/move-compiler-v2/transactional-tests/tests/no-safety/simple_map_keys.exp @@ -1,12 +1,3 @@ -comparison between v1 and v2 failed: -= processed 2 tasks -= -+ task 0 'publish'. lines 1-48: -+ warning: Unused parameter `e`. Consider removing or prefixing with an underscore: `_e` -+ ┌─ TEMPFILE:13:29 -+ │ -+ 13 │ map_ref(&map.data, |e| { -+ │ ^ -+ -+ -+ +processed 2 tasks + +==> Compiler v2 delivered same results! diff --git a/third_party/move/move-model/src/ast.rs b/third_party/move/move-model/src/ast.rs index 0c1e2fc064c74..d469c4b32d1c5 100644 --- a/third_party/move/move-model/src/ast.rs +++ b/third_party/move/move-model/src/ast.rs @@ -569,6 +569,16 @@ pub enum RewriteResult { Unchanged(Exp), } +/// Visitor position +pub enum VisitorPosition { + Pre, // before visiting any subexpressions + MidMutate, // after RHS and before LHS of Mutate expression. + BeforeBody, // Before body of Block expression. + BeforeThen, // Before then clause of IfElse expression. + BeforeElse, // Before else clause of IfElse expression. + Post, // after visiting all subexpressions +} + impl ExpData { /// Version of `into` which does not require type annotations. pub fn into_exp(self) -> Exp { @@ -915,98 +925,143 @@ impl ExpData { where F: FnMut(bool, &ExpData) -> bool, { - let _ = self.visit_pre_post_impl(&mut |x, e| if visitor(x, e) { Some(()) } else { None }); + let _ = self.visit_positions_impl(&mut |x, e| { + use VisitorPosition::*; + let should_continue = match x { + Pre => visitor(false, e), + Post => visitor(true, e), + MidMutate | BeforeBody | BeforeThen | BeforeElse => true, + }; + if should_continue { + Some(()) + } else { + None + } + }); + } + + /// Recursively visits expression, calling visitor for key control points of each sub-expression. + /// `visitor(Pre, ...)` will be called before descending into each expression, and + /// `visitor(Post, ...)` will be called after the descent. For a few expressions, + /// additional visitor calls will also be made at key control points between recursive + /// calls: + /// - for `Mutate(..., lhs, rhs)`, visits `rhs` before `lhs` (following execution control flow), + /// with a call to `visitor(MidMutate, ...)` between the two recursive calls + /// - for `Block(..., binding, body)` visits `binding` before `body`, with a call to + /// `visitor(BeforeBody, ...)` between the two recursive calls. + /// - for `IfElse(..., cond, then, else)` first recursively visits `cond`, then calls + /// `visitor(BeforeThen, ...)`, then visits `then`, then calls `visitor(BeforeElse, ...)`, + /// then visits `else`. + /// + /// In every case, if `visitor` returns `false`, then the visit is stopped early; otherwise + /// the the visit will continue. + pub fn visit_positions(&self, visitor: &mut F) + where + F: FnMut(VisitorPosition, &ExpData) -> bool, + { + let _ = self.visit_positions_impl(&mut |x, e| { + if visitor(x, e) { + Some(()) + } else { + None + } + }); } /// Visitor implementation uses `Option<()>` to implement short-cutting without verbosity. /// - `visitor` returns `None` to indicate that visit should stop early, and `Some(())` to continue. - /// - `visit_pre_post` returns `None` if visitor returned `None`. - fn visit_pre_post_impl(&self, visitor: &mut F) -> Option<()> + /// - `visit_positions_impl` returns `None` if visitor returned `None`. + /// See `visit_positions` for more + fn visit_positions_impl(&self, visitor: &mut F) -> Option<()> where - F: FnMut(bool, &ExpData) -> Option<()>, + F: FnMut(VisitorPosition, &ExpData) -> Option<()>, { use ExpData::*; - visitor(false, self)?; + visitor(VisitorPosition::Pre, self)?; match self { Call(_, _, args) => { for exp in args { - exp.visit_pre_post_impl(visitor)?; + exp.visit_positions_impl(visitor)?; } }, Invoke(_, target, args) => { - target.visit_pre_post_impl(visitor)?; + target.visit_positions_impl(visitor)?; for exp in args { - exp.visit_pre_post_impl(visitor)?; + exp.visit_positions_impl(visitor)?; } }, - Lambda(_, _, body) => body.visit_pre_post_impl(visitor)?, + Lambda(_, _, body) => body.visit_positions_impl(visitor)?, Quant(_, _, ranges, triggers, condition, body) => { for (_, range) in ranges { - range.visit_pre_post_impl(visitor)?; + range.visit_positions_impl(visitor)?; } for trigger in triggers { for e in trigger { - e.visit_pre_post_impl(visitor)?; + e.visit_positions_impl(visitor)?; } } if let Some(exp) = condition { - exp.visit_pre_post_impl(visitor)?; + exp.visit_positions_impl(visitor)?; } - body.visit_pre_post_impl(visitor)?; + body.visit_positions_impl(visitor)?; }, Block(_, _, binding, body) => { if let Some(exp) = binding { - exp.visit_pre_post_impl(visitor)?; + exp.visit_positions_impl(visitor)?; } - body.visit_pre_post_impl(visitor)?; + visitor(VisitorPosition::BeforeBody, self)?; + body.visit_positions_impl(visitor)?; }, IfElse(_, c, t, e) => { - c.visit_pre_post_impl(visitor)?; - t.visit_pre_post_impl(visitor)?; - e.visit_pre_post_impl(visitor)?; + c.visit_positions_impl(visitor)?; + visitor(VisitorPosition::BeforeThen, self)?; + t.visit_positions_impl(visitor)?; + visitor(VisitorPosition::BeforeElse, self)?; + e.visit_positions_impl(visitor)?; }, - Loop(_, e) => e.visit_pre_post_impl(visitor)?, - Return(_, e) => e.visit_pre_post_impl(visitor)?, + Loop(_, e) => e.visit_positions_impl(visitor)?, + Return(_, e) => e.visit_positions_impl(visitor)?, Sequence(_, es) => { for e in es { - e.visit_pre_post_impl(visitor)?; + e.visit_positions_impl(visitor)?; } }, - Assign(_, _, e) => e.visit_pre_post_impl(visitor)?, + Assign(_, _, e) => e.visit_positions_impl(visitor)?, Mutate(_, lhs, rhs) => { - lhs.visit_pre_post_impl(visitor)?; - rhs.visit_pre_post_impl(visitor)?; + rhs.visit_positions_impl(visitor)?; + visitor(VisitorPosition::MidMutate, self)?; + lhs.visit_positions_impl(visitor)?; }, - SpecBlock(_, spec) => Self::visit_pre_post_spec_impl(spec, visitor)?, + SpecBlock(_, spec) => Self::visit_positions_spec_impl(spec, visitor)?, // Explicitly list all enum variants LoopCont(..) | Value(..) | LocalVar(..) | Temporary(..) | Invalid(..) => {}, } - visitor(true, self) + visitor(VisitorPosition::Post, self) } - fn visit_pre_post_spec_impl(spec: &Spec, visitor: &mut F) -> Option<()> + fn visit_positions_spec_impl(spec: &Spec, visitor: &mut F) -> Option<()> where - F: FnMut(bool, &ExpData) -> Option<()>, + F: FnMut(VisitorPosition, &ExpData) -> Option<()>, { for cond in &spec.conditions { - Self::visit_pre_post_cond_impl(cond, visitor)?; + Self::visit_positions_cond_impl(cond, visitor)?; } for impl_spec in spec.on_impl.values() { - Self::visit_pre_post_spec_impl(impl_spec, visitor)?; + Self::visit_positions_spec_impl(impl_spec, visitor)?; } for cond in spec.update_map.values() { - Self::visit_pre_post_cond_impl(cond, visitor)?; + Self::visit_positions_cond_impl(cond, visitor)?; } Some(()) } - fn visit_pre_post_cond_impl(cond: &Condition, visitor: &mut F) -> Option<()> + fn visit_positions_cond_impl(cond: &Condition, visitor: &mut F) -> Option<()> where - F: FnMut(bool, &ExpData) -> Option<()>, + F: FnMut(VisitorPosition, &ExpData) -> Option<()>, { - cond.exp.visit_pre_post_impl(visitor)?; + cond.exp.visit_positions_impl(visitor)?; for exp in &cond.additional_exps { - exp.visit_pre_post_impl(visitor)?; + exp.visit_positions_impl(visitor)?; } Some(()) } From 177096a5448dbc9dbae7e0ac337a1afa77f3b457 Mon Sep 17 00:00:00 2001 From: Justin Chang <37165464+just-in-chang@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:58:36 -0800 Subject: [PATCH 020/328] [NFT Metadata Crawler] Fix faulty migration (#11910) --- .../migrations/2024-01-31-221845_add_not_parsable_column/up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecosystem/nft-metadata-crawler-parser/migrations/2024-01-31-221845_add_not_parsable_column/up.sql b/ecosystem/nft-metadata-crawler-parser/migrations/2024-01-31-221845_add_not_parsable_column/up.sql index 59313b9765afb..1558d9550a963 100644 --- a/ecosystem/nft-metadata-crawler-parser/migrations/2024-01-31-221845_add_not_parsable_column/up.sql +++ b/ecosystem/nft-metadata-crawler-parser/migrations/2024-01-31-221845_add_not_parsable_column/up.sql @@ -1 +1 @@ -ALTER TABLE IF NOT EXISTS nft_metadata_crawler.parsed_asset_uris ADD COLUMN do_not_parse BOOLEAN NOT NULL DEFAULT FALSE; +ALTER TABLE IF EXISTS nft_metadata_crawler.parsed_asset_uris ADD COLUMN do_not_parse BOOLEAN NOT NULL DEFAULT FALSE; From 8a60b1eef069d6a72a6b7a5a0804f1ba85d1ad17 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:14:04 -0800 Subject: [PATCH 021/328] [agg_v2] First pass over TODOs (#11898) removing leftover TODOs that seem already addressed. --- aptos-move/aptos-aggregator/src/delayed_field_extension.rs | 5 +---- aptos-move/aptos-vm/src/data_cache.rs | 2 -- aptos-move/aptos-vm/src/move_vm_ext/session.rs | 1 - aptos-move/aptos-vm/src/move_vm_ext/write_op_converter.rs | 1 - aptos-move/block-executor/src/proptest_types/types.rs | 2 +- 5 files changed, 2 insertions(+), 9 deletions(-) diff --git a/aptos-move/aptos-aggregator/src/delayed_field_extension.rs b/aptos-move/aptos-aggregator/src/delayed_field_extension.rs index ce4c3dd7fbd44..895d6fe67a993 100644 --- a/aptos-move/aptos-aggregator/src/delayed_field_extension.rs +++ b/aptos-move/aptos-aggregator/src/delayed_field_extension.rs @@ -22,10 +22,7 @@ fn get_delayed_field_value_from_storage( id: &DelayedFieldID, resolver: &dyn DelayedFieldResolver, ) -> Result> { - resolver - .get_delayed_field_value(id) - // TODO[agg_v2](fix): Is this error mapping correct? - .map_err(|_err| PanicOr::Or(DelayedFieldsSpeculativeError::NotFound(*id))) + resolver.get_delayed_field_value(id) } /// Stores all information about aggregators (how many have been created or diff --git a/aptos-move/aptos-vm/src/data_cache.rs b/aptos-move/aptos-vm/src/data_cache.rs index 9652dcc9f26cf..9a3734163edbb 100644 --- a/aptos-move/aptos-vm/src/data_cache.rs +++ b/aptos-move/aptos-vm/src/data_cache.rs @@ -117,12 +117,10 @@ impl<'e, E: ExecutorView> StorageAdapter<'e, E> { address: &AccountAddress, struct_tag: &StructTag, metadata: &[Metadata], - // Question: Is maybe_layout = Some(..) iff the layout has an aggregator v2 maybe_layout: Option<&MoveTypeLayout>, ) -> PartialVMResult<(Option, usize)> { let resource_group = get_resource_group_from_metadata(struct_tag, metadata); if let Some(resource_group) = resource_group { - // TODO[agg_v2](fix) pass the layout to resource groups let key = StateKey::access_path(AccessPath::resource_group_access_path( *address, resource_group.clone(), diff --git a/aptos-move/aptos-vm/src/move_vm_ext/session.rs b/aptos-move/aptos-vm/src/move_vm_ext/session.rs index ea67d8db4eea0..201c0c9ac2917 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/session.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/session.rs @@ -306,7 +306,6 @@ impl<'r, 'l> SessionExt<'r, 'l> { /// /// V1 Resource group change set behavior keeps ops for individual resources separate, not /// merging them into the a single op corresponding to the whole resource group (V0). - /// TODO[agg_v2](fix) Resource groups are currently not handled correctly in terms of propagating MoveTypeLayout fn split_and_merge_resource_groups( runtime: &MoveVM, remote: &dyn AptosMoveResolver, 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 4ca7a6fe6e585..31d3d74d52a3a 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 @@ -244,7 +244,6 @@ impl<'r> WriteOpConverter<'r> { // except it encodes the (speculative) size of the group after applying the updates // which is used for charging storage fees. Moreover, the metadata computation occurs // fully backwards compatibly, and lets obtain final storage op by replacing bytes. - // TODO[agg_v2](fix) fix layout for RG let metadata_op = if post_group_size.get() == 0 { MoveStorageOp::Delete } else if pre_group_size.get() == 0 { diff --git a/aptos-move/block-executor/src/proptest_types/types.rs b/aptos-move/block-executor/src/proptest_types/types.rs index 48efb8faef094..f3b011066cf79 100644 --- a/aptos-move/block-executor/src/proptest_types/types.rs +++ b/aptos-move/block-executor/src/proptest_types/types.rs @@ -1064,7 +1064,7 @@ where self.events.iter().map(|e| (e.clone(), None)).collect() } - // TODO[agg_v2](fix) Using the concrete type layout here. Should we find a way to use generics? + // TODO[agg_v2](cleanup) Using the concrete type layout here. Should we find a way to use generics? fn resource_group_write_set( &self, ) -> Vec<( From b703936a8dcb4286830d1649fd5b8f2e9cdc05a0 Mon Sep 17 00:00:00 2001 From: zhoujunma Date: Tue, 6 Feb 2024 11:43:12 -0800 Subject: [PATCH 022/328] jwk misc updates (#11917) * smoke test with full node * update * fmt * update --- aptos-move/aptos-vm/src/validator_txns/jwk.rs | 17 +++- .../framework/aptos-framework/doc/jwks.md | 44 +++++++++- .../aptos-framework/sources/account.move | 2 +- .../aptos-framework/sources/jwks.move | 67 ++++++++++++++- .../src/certified_update_producer.rs | 65 --------------- .../aptos-jwk-consensus/src/epoch_manager.rs | 25 ++++-- .../src/jwk_manager/mod.rs | 83 +++++++++++++++---- .../aptos-jwk-consensus/src/jwk_observer.rs | 8 +- .../src/observation_aggregation/mod.rs | 33 +++++++- .../src/update_certifier.rs | 15 ++++ .../src/jwks/jwk_consensus_basic.rs | 1 + .../src/jwks/jwk_consensus_per_issuer.rs | 1 + .../jwk_consensus_provider_change_mind.rs | 1 + 13 files changed, 259 insertions(+), 103 deletions(-) delete mode 100644 crates/aptos-jwk-consensus/src/certified_update_producer.rs diff --git a/aptos-move/aptos-vm/src/validator_txns/jwk.rs b/aptos-move/aptos-vm/src/validator_txns/jwk.rs index f302e3ee7e2fa..e0c68ed41dae9 100644 --- a/aptos-move/aptos-vm/src/validator_txns/jwk.rs +++ b/aptos-move/aptos-vm/src/validator_txns/jwk.rs @@ -14,6 +14,7 @@ use crate::{ }, AptosVM, }; +use aptos_logger::debug; use aptos_types::{ fee_statement::FeeStatement, jwks, @@ -33,6 +34,7 @@ use move_core_types::{ use move_vm_types::gas::UnmeteredGasMeter; use std::collections::HashMap; +#[derive(Debug)] enum ExpectedFailure { // Move equivalent: `errors::invalid_argument(*)` IncorrectVersion = 0x010103, @@ -57,16 +59,27 @@ impl AptosVM { session_id: SessionId, update: jwks::QuorumCertifiedUpdate, ) -> Result<(VMStatus, VMOutput), VMStatus> { + debug!("Processing jwk transaction"); match self.process_jwk_update_inner(resolver, log_context, session_id, update) { - Ok((vm_status, vm_output)) => Ok((vm_status, vm_output)), + Ok((vm_status, vm_output)) => { + debug!("Processing jwk transaction ok."); + Ok((vm_status, vm_output)) + }, Err(Expected(failure)) => { // Pretend we are inside Move, and expected failures are like Move aborts. + debug!("Processing dkg transaction expected failure: {:?}", failure); Ok(( VMStatus::MoveAbort(AbortLocation::Script, failure as u64), VMOutput::empty_with_status(TransactionStatus::Discard(StatusCode::ABORTED)), )) }, - Err(Unexpected(vm_status)) => Err(vm_status), + Err(Unexpected(vm_status)) => { + debug!( + "Processing jwk transaction unexpected failure: {:?}", + vm_status + ); + Err(vm_status) + }, } } diff --git a/aptos-move/framework/aptos-framework/doc/jwks.md b/aptos-move/framework/aptos-framework/doc/jwks.md index 2166154629728..c8448032df8a4 100644 --- a/aptos-move/framework/aptos-framework/doc/jwks.md +++ b/aptos-move/framework/aptos-framework/doc/jwks.md @@ -42,6 +42,7 @@ have a simple layout which is easily accessible in Rust. - [Function `initialize`](#0x1_jwks_initialize) - [Function `remove_oidc_provider_internal`](#0x1_jwks_remove_oidc_provider_internal) - [Function `upsert_into_observed_jwks`](#0x1_jwks_upsert_into_observed_jwks) +- [Function `remove_issuer_from_observed_jwks`](#0x1_jwks_remove_issuer_from_observed_jwks) - [Function `regenerate_patched_jwks`](#0x1_jwks_regenerate_patched_jwks) - [Function `try_get_jwk_by_issuer`](#0x1_jwks_try_get_jwk_by_issuer) - [Function `try_get_jwk_by_id`](#0x1_jwks_try_get_jwk_by_id) @@ -796,6 +797,10 @@ Remove an OIDC provider from the ObservedJWKs. +It does NOT touch ObservedJWKs or Patches. +If you are disabling a provider, you probably also need remove_issuer_from_observed_jwks() and possibly set_patches(). +
public fun remove_oidc_provider(fx: &signer, name: vector<u8>): option::Option<vector<u8>>
 
@@ -1020,7 +1025,7 @@ Create a JWK of variant public(friend) fun initialize(fx: &signer) +
public fun initialize(fx: &signer)
 
@@ -1029,7 +1034,7 @@ Initialize some JWK resources. Should only be invoked by genesis. Implementation -
public(friend) fun initialize(fx: &signer) {
+
public fun initialize(fx: &signer) {
     system_addresses::assert_aptos_framework(fx);
     move_to(fx, SupportedOIDCProviders { providers: vector[] });
     move_to(fx, ObservedJWKs { jwks: AllProvidersJWKs { entries: vector[] } });
@@ -1113,6 +1118,41 @@ and its version equals to the
 
 
 
+
+
+
+
+## Function `remove_issuer_from_observed_jwks`
+
+Only used by governance to delete an issuer from ObservedJWKs, if it exists.
+
+Return the potentially existing ProviderJWKs of the given issuer.
+
+
+
public fun remove_issuer_from_observed_jwks(fx: &signer, issuer: vector<u8>): option::Option<jwks::ProviderJWKs>
+
+ + + +
+Implementation + + +
public fun remove_issuer_from_observed_jwks(fx: &signer, issuer: vector<u8>): Option<ProviderJWKs> acquires ObservedJWKs, PatchedJWKs, Patches {
+    system_addresses::assert_aptos_framework(fx);
+    let observed_jwks = borrow_global_mut<ObservedJWKs>(@aptos_framework);
+    let old_value = remove_issuer(&mut observed_jwks.jwks, issuer);
+
+    let epoch = reconfiguration::current_epoch();
+    emit(ObservedJWKsUpdated { epoch, jwks: observed_jwks.jwks });
+    regenerate_patched_jwks();
+
+    old_value
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-framework/sources/account.move b/aptos-move/framework/aptos-framework/sources/account.move index 9543c4e9f0d04..b91da76192d95 100644 --- a/aptos-move/framework/aptos-framework/sources/account.move +++ b/aptos-move/framework/aptos-framework/sources/account.move @@ -1003,7 +1003,7 @@ module aptos_framework::account { // Maul the signature and make sure the call would fail let invalid_signature = ed25519::signature_to_bytes(&sig); let first_sig_byte = vector::borrow_mut(&mut invalid_signature, 0); - *first_sig_byte = *first_sig_byte + 1; + *first_sig_byte = *first_sig_byte ^ 1; offer_signer_capability(&alice, invalid_signature, 0, alice_pk_bytes, bob_addr); } diff --git a/aptos-move/framework/aptos-framework/sources/jwks.move b/aptos-move/framework/aptos-framework/sources/jwks.move index b87a71c85f4b5..745fec4c6f25c 100644 --- a/aptos-move/framework/aptos-framework/sources/jwks.move +++ b/aptos-move/framework/aptos-framework/sources/jwks.move @@ -187,6 +187,10 @@ module aptos_framework::jwks { /// Remove an OIDC provider from the `SupportedOIDCProviders` resource. /// Can only be called in a governance proposal. /// Returns the old config URL of the provider, if any, as an `Option`. + /// + /// NOTE: this only stops validators from watching the provider and generate updates to `ObservedJWKs`. + /// It does NOT touch `ObservedJWKs` or `Patches`. + /// If you are disabling a provider, you probably also need `remove_issuer_from_observed_jwks()` and possibly `set_patches()`. public fun remove_oidc_provider(fx: &signer, name: vector): Option> acquires SupportedOIDCProviders { system_addresses::assert_aptos_framework(fx); @@ -250,7 +254,7 @@ module aptos_framework::jwks { } /// Initialize some JWK resources. Should only be invoked by genesis. - public(friend) fun initialize(fx: &signer) { + public fun initialize(fx: &signer) { system_addresses::assert_aptos_framework(fx); move_to(fx, SupportedOIDCProviders { providers: vector[] }); move_to(fx, ObservedJWKs { jwks: AllProvidersJWKs { entries: vector[] } }); @@ -291,6 +295,21 @@ module aptos_framework::jwks { regenerate_patched_jwks(); } + /// Only used by governance to delete an issuer from `ObservedJWKs`, if it exists. + /// + /// Return the potentially existing `ProviderJWKs` of the given issuer. + public fun remove_issuer_from_observed_jwks(fx: &signer, issuer: vector): Option acquires ObservedJWKs, PatchedJWKs, Patches { + system_addresses::assert_aptos_framework(fx); + let observed_jwks = borrow_global_mut(@aptos_framework); + let old_value = remove_issuer(&mut observed_jwks.jwks, issuer); + + let epoch = reconfiguration::current_epoch(); + emit(ObservedJWKsUpdated { epoch, jwks: observed_jwks.jwks }); + regenerate_patched_jwks(); + + old_value + } + /// Regenerate `PatchedJWKs` from `ObservedJWKs` and `Patches` and save the result. fun regenerate_patched_jwks() acquires PatchedJWKs, Patches, ObservedJWKs { let jwks = borrow_global(@aptos_framework).jwks; @@ -493,6 +512,52 @@ module aptos_framework::jwks { initialize(aptos_framework); } + #[test(fx = @aptos_framework)] + fun test_observed_jwks_operations(fx: &signer) acquires ObservedJWKs, PatchedJWKs, Patches { + initialize_for_test(fx); + let jwk_0 = new_unsupported_jwk(b"key_id_0", b"key_payload_0"); + let jwk_1 = new_unsupported_jwk(b"key_id_1", b"key_payload_1"); + let jwk_2 = new_unsupported_jwk(b"key_id_2", b"key_payload_2"); + let jwk_3 = new_unsupported_jwk(b"key_id_3", b"key_payload_3"); + let jwk_4 = new_unsupported_jwk(b"key_id_4", b"key_payload_4"); + let expected = AllProvidersJWKs{ entries: vector[] }; + assert!(expected == borrow_global(@aptos_framework).jwks, 1); + + let alice_jwks_v1 = ProviderJWKs { + issuer: b"alice", + version: 1, + jwks: vector[jwk_0, jwk_1], + }; + let bob_jwks_v1 = ProviderJWKs{ + issuer: b"bob", + version: 1, + jwks: vector[jwk_2, jwk_3], + }; + upsert_into_observed_jwks(fx, vector[bob_jwks_v1]); + upsert_into_observed_jwks(fx, vector[alice_jwks_v1]); + let expected = AllProvidersJWKs{ entries: vector[ + alice_jwks_v1, + bob_jwks_v1, + ] }; + assert!(expected == borrow_global(@aptos_framework).jwks, 2); + + let alice_jwks_v2 = ProviderJWKs { + issuer: b"alice", + version: 2, + jwks: vector[jwk_1, jwk_4], + }; + upsert_into_observed_jwks(fx, vector[alice_jwks_v2]); + let expected = AllProvidersJWKs{ entries: vector[ + alice_jwks_v2, + bob_jwks_v1, + ] }; + assert!(expected == borrow_global(@aptos_framework).jwks, 3); + + remove_issuer_from_observed_jwks(fx, b"alice"); + let expected = AllProvidersJWKs{ entries: vector[bob_jwks_v1] }; + assert!(expected == borrow_global(@aptos_framework).jwks, 4); + } + #[test] fun test_apply_patch() { let jwks = AllProvidersJWKs { diff --git a/crates/aptos-jwk-consensus/src/certified_update_producer.rs b/crates/aptos-jwk-consensus/src/certified_update_producer.rs deleted file mode 100644 index d60c241573f4e..0000000000000 --- a/crates/aptos-jwk-consensus/src/certified_update_producer.rs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright © Aptos Foundation - -use crate::{ - observation_aggregation::ObservationAggregationState, - types::{JWKConsensusMsg, ObservedUpdateRequest}, -}; -use aptos_channels::aptos_channel; -use aptos_reliable_broadcast::ReliableBroadcast; -use aptos_types::{ - epoch_state::EpochState, - jwks::{ProviderJWKs, QuorumCertifiedUpdate}, -}; -use futures_util::future::{AbortHandle, Abortable}; -use std::sync::Arc; -use tokio_retry::strategy::ExponentialBackoff; - -/// A sub-process of the whole JWK consensus process. -/// Once invoked by `JWKConsensusManager` to `start_produce`, -/// it starts producing a `QuorumCertifiedUpdate` and returns an abort handle. -/// Once an `QuorumCertifiedUpdate` is available, it is sent back via a channel given earlier. -pub trait CertifiedUpdateProducer: Send + Sync { - fn start_produce( - &self, - epoch_state: Arc, - payload: ProviderJWKs, - qc_update_tx: Option>, - ) -> AbortHandle; -} - -pub struct RealCertifiedUpdateProducer { - reliable_broadcast: Arc>, -} - -impl RealCertifiedUpdateProducer { - pub fn new(reliable_broadcast: ReliableBroadcast) -> Self { - Self { - reliable_broadcast: Arc::new(reliable_broadcast), - } - } -} - -impl CertifiedUpdateProducer for RealCertifiedUpdateProducer { - fn start_produce( - &self, - epoch_state: Arc, - payload: ProviderJWKs, - qc_update_tx: Option>, - ) -> AbortHandle { - let rb = self.reliable_broadcast.clone(); - let req = ObservedUpdateRequest { - epoch: epoch_state.epoch, - issuer: payload.issuer.clone(), - }; - let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); - let task = async move { - let qc_update = rb.broadcast(req, agg_state).await; - if let Some(tx) = qc_update_tx { - let _ = tx.push((), qc_update); - } - }; - let (abort_handle, abort_registration) = AbortHandle::new_pair(); - tokio::spawn(Abortable::new(task, abort_registration)); - abort_handle - } -} diff --git a/crates/aptos-jwk-consensus/src/epoch_manager.rs b/crates/aptos-jwk-consensus/src/epoch_manager.rs index 308e145654391..d07ad2fd6b3e0 100644 --- a/crates/aptos-jwk-consensus/src/epoch_manager.rs +++ b/crates/aptos-jwk-consensus/src/epoch_manager.rs @@ -47,7 +47,8 @@ pub struct EpochManager { // message channels to JWK manager jwk_updated_event_txs: Option>, - jwk_rpc_msg_tx: Option>, + jwk_rpc_msg_tx: + Option>, jwk_manager_close_tx: Option>>, // network utils @@ -91,7 +92,7 @@ impl EpochManager

{ ) -> Result<()> { if Some(rpc_request.msg.epoch()) == self.epoch_state.as_ref().map(|s| s.epoch) { if let Some(tx) = &self.jwk_rpc_msg_tx { - let _ = tx.push((), (peer_id, rpc_request)); + let _ = tx.push(peer_id, (peer_id, rpc_request)); } } Ok(()) @@ -153,14 +154,23 @@ impl EpochManager

{ verifier: (&validator_set).into(), }); self.epoch_state = Some(epoch_state.clone()); - info!("[JWK] start_new_epoch: new_epoch={}", epoch_state.epoch); + let my_index = epoch_state + .verifier + .address_to_validator_index() + .get(&self.my_addr) + .copied(); + + info!( + epoch = epoch_state.epoch, + "EpochManager starting new epoch." + ); let features = payload.get::().unwrap_or_default(); - if features.is_enabled(FeatureFlag::JWK_CONSENSUS) { + if features.is_enabled(FeatureFlag::JWK_CONSENSUS) && my_index.is_some() { let onchain_oidc_provider_set = payload.get::().ok(); let onchain_observed_jwks = payload.get::().ok(); - info!("[JWK] JWK manager init, epoch={}", epoch_state.epoch); + info!(epoch = epoch_state.epoch, "JWKManager starting."); let network_sender = NetworkSender::new( self.my_addr, self.network_sender.clone(), @@ -199,10 +209,7 @@ impl EpochManager

{ jwk_rpc_msg_rx, jwk_manager_close_rx, )); - info!( - "jwk consensus manager spawned for epoch {}", - epoch_state.epoch - ); + info!(epoch = epoch_state.epoch, "JWKManager spawned.",); } } diff --git a/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs b/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs index b098c6985242c..746508ce59a33 100644 --- a/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs +++ b/crates/aptos-jwk-consensus/src/jwk_manager/mod.rs @@ -86,7 +86,10 @@ impl JWKManager { oidc_providers: Option, observed_jwks: Option, mut jwk_updated_rx: aptos_channel::Receiver<(), ObservedJWKsUpdated>, - mut rpc_req_rx: aptos_channel::Receiver<(), (AccountAddress, IncomingRpcRequest)>, + mut rpc_req_rx: aptos_channel::Receiver< + AccountAddress, + (AccountAddress, IncomingRpcRequest), + >, close_rx: oneshot::Receiver>, ) { self.reset_with_on_chain_state(observed_jwks.unwrap_or_default().into_providers_jwks()) @@ -101,6 +104,7 @@ impl JWKManager { .into_iter() .map(|provider| { JWKObserver::spawn( + self.epoch_state.epoch, self.my_addr, provider.name.clone(), provider.config_url.clone(), @@ -134,7 +138,10 @@ impl JWKManager { }; if let Err(e) = handle_result { - error!("[JWK] handling_err={}", e); + error!( + epoch = self.epoch_state.epoch, + "JWKManager handling error: {}", e + ); } } } @@ -158,6 +165,11 @@ impl JWKManager { issuer: Issuer, jwks: Vec, ) -> Result<()> { + debug!( + epoch = self.epoch_state.epoch, + issuer = String::from_utf8(issuer.clone()).ok(), + "Processing new observation." + ); let state = self.states_by_issuer.entry(issuer.clone()).or_default(); state.observed = Some(jwks.clone()); if state.observed.as_ref() != state.on_chain.as_ref().map(ProviderJWKs::jwks) { @@ -169,7 +181,7 @@ impl JWKManager { let signature = self .consensus_key .sign(&observed) - .map_err(|e| anyhow!("crypto material error occurred duing signing: {}", e))?; + .map_err(|e| anyhow!("crypto material error occurred duing signing: {e}"))?; let abort_handle = self.update_certifier.start_produce( self.epoch_state.clone(), observed.clone(), @@ -191,18 +203,30 @@ impl JWKManager { /// Invoked on start, or on on-chain JWK updated event. pub fn reset_with_on_chain_state(&mut self, on_chain_state: AllProvidersJWKs) -> Result<()> { - debug!( - "[JWK] reset_with_on_chain_state: BEGIN: on_chain_state={:?}", - on_chain_state + info!( + epoch = self.epoch_state.epoch, + "reset_with_on_chain_state starting." ); let onchain_issuer_set: HashSet = on_chain_state .entries .iter() .map(|entry| entry.issuer.clone()) .collect(); + let local_issuer_set: HashSet = self.states_by_issuer.keys().cloned().collect(); + + for issuer in local_issuer_set.difference(&onchain_issuer_set) { + info!( + epoch = self.epoch_state.epoch, + op = "delete", + issuer = issuer.clone(), + "reset_with_on_chain_state" + ); + } + self.states_by_issuer .retain(|issuer, _| onchain_issuer_set.contains(issuer)); for on_chain_provider_jwks in on_chain_state.entries { + let issuer = on_chain_provider_jwks.issuer.clone(); let locally_cached = self .states_by_issuer .get(&on_chain_provider_jwks.issuer) @@ -210,13 +234,34 @@ impl JWKManager { if locally_cached == Some(&on_chain_provider_jwks) { // The on-chain update did not touch this provider. // The corresponding local state does not have to be reset. + info!( + epoch = self.epoch_state.epoch, + op = "no-op", + issuer = issuer, + "reset_with_on_chain_state" + ); } else { - self.states_by_issuer.insert( + let old_value = self.states_by_issuer.insert( on_chain_provider_jwks.issuer.clone(), PerProviderState::new(on_chain_provider_jwks), ); + let op = if old_value.is_some() { + "update" + } else { + "insert" + }; + info!( + epoch = self.epoch_state.epoch, + op = op, + issuer = issuer, + "reset_with_on_chain_state" + ); } } + info!( + epoch = self.epoch_state.epoch, + "reset_with_on_chain_state finished." + ); Ok(()) } @@ -224,13 +269,8 @@ impl JWKManager { let IncomingRpcRequest { msg, mut response_sender, - sender, + .. } = rpc_req; - debug!( - "[JWK] process_peer_request: sender={}, is_self={}", - sender, - sender == self.my_addr - ); match msg { JWKConsensusMsg::ObservationRequest(request) => { let state = self.states_by_issuer.entry(request.issuer).or_default(); @@ -256,6 +296,12 @@ impl JWKManager { /// Triggered once the `update_certifier` produced a quorum-certified update. pub fn process_quorum_certified_update(&mut self, update: QuorumCertifiedUpdate) -> Result<()> { let issuer = update.update.issuer.clone(); + info!( + epoch = self.epoch_state.epoch, + issuer = String::from_utf8(issuer.clone()).ok(), + version = update.update.version, + "JWKManager processing certified update." + ); let state = self.states_by_issuer.entry(issuer.clone()).or_default(); match &state.consensus_state { ConsensusState::InProgress { my_proposal, .. } => { @@ -263,18 +309,23 @@ impl JWKManager { let txn = ValidatorTransaction::ObservedJWKUpdate(update.clone()); let vtxn_guard = self.vtxn_pool - .put(Topic::JWK_CONSENSUS(issuer), Arc::new(txn), None); + .put(Topic::JWK_CONSENSUS(issuer.clone()), Arc::new(txn), None); state.consensus_state = ConsensusState::Finished { vtxn_guard, my_proposal: my_proposal.clone(), quorum_certified: update.clone(), }; - info!("[JWK] qc update obtained, update={:?}", update); + info!( + epoch = self.epoch_state.epoch, + issuer = String::from_utf8(issuer).ok(), + version = update.update.version, + "certified update accepted." + ); Ok(()) }, _ => Err(anyhow!( "qc update not expected for issuer {:?} in state {}", - update.update.issuer, + String::from_utf8(issuer.clone()), state.consensus_state.name() )), } diff --git a/crates/aptos-jwk-consensus/src/jwk_observer.rs b/crates/aptos-jwk-consensus/src/jwk_observer.rs index 8d9988ce99afa..16057fdabbdcb 100644 --- a/crates/aptos-jwk-consensus/src/jwk_observer.rs +++ b/crates/aptos-jwk-consensus/src/jwk_observer.rs @@ -57,6 +57,7 @@ pub struct JWKObserver { impl JWKObserver { pub fn spawn( + epoch: u64, my_addr: AccountAddress, issuer: Issuer, config_url: Vec, @@ -73,9 +74,10 @@ impl JWKObserver { close_rx, )); info!( - "[JWK] observer spawned, issuer={:?}, config_url={:?}", - String::from_utf8(issuer), - String::from_utf8(config_url) + epoch = epoch, + issuer = String::from_utf8(issuer).ok(), + config_url = String::from_utf8(config_url).ok(), + "JWKObserver spawned." ); Self { close_tx, diff --git a/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs b/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs index cc8dc22049404..58c2f55f1c5e1 100644 --- a/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs +++ b/crates/aptos-jwk-consensus/src/observation_aggregation/mod.rs @@ -6,11 +6,13 @@ use crate::types::{ use anyhow::{anyhow, ensure}; use aptos_consensus_types::common::Author; use aptos_infallible::Mutex; +use aptos_logger::info; use aptos_reliable_broadcast::BroadcastStatus; use aptos_types::{ aggregate_signature::PartialSignatures, epoch_state::EpochState, jwks::{ProviderJWKs, QuorumCertifiedUpdate}, + validator_verifier::VerifyError, }; use move_core_types::account_address::AccountAddress; use std::{collections::BTreeSet, sync::Arc}; @@ -58,6 +60,13 @@ impl BroadcastStatus for Arc { "adding peer observation failed with mismatched author", ); + let peer_power = self.epoch_state.verifier.get_voting_power(&author); + ensure!( + peer_power.is_some(), + "adding peer observation failed with illegal signer" + ); + let peer_power = peer_power.unwrap(); + let mut partial_sigs = self.inner_state.lock(); if partial_sigs.contains_voter(&sender) { return Ok(None); @@ -76,12 +85,28 @@ impl BroadcastStatus for Arc { // All checks passed. Aggregating. partial_sigs.add_signature(sender, signature); let voters: BTreeSet = partial_sigs.signatures().keys().copied().collect(); - if self + let power_check_result = self .epoch_state .verifier - .check_voting_power(voters.iter(), true) - .is_err() - { + .check_voting_power(voters.iter(), true); + let new_total_power = match &power_check_result { + Ok(x) => Some(*x), + Err(VerifyError::TooLittleVotingPower { voting_power, .. }) => Some(*voting_power), + _ => None, + }; + + info!( + epoch = self.epoch_state.epoch, + peer = sender, + issuer = String::from_utf8(self.local_view.issuer.clone()).ok(), + peer_power = peer_power, + new_total_power = new_total_power, + threshold = self.epoch_state.verifier.quorum_voting_power(), + threshold_exceeded = power_check_result.is_ok(), + "Peer vote aggregated." + ); + + if power_check_result.is_err() { return Ok(None); } let multi_sig = self.epoch_state.verifier.aggregate_signatures(&partial_sigs).map_err(|e|anyhow!("adding peer observation failed with partial-to-aggregated conversion error: {e}"))?; diff --git a/crates/aptos-jwk-consensus/src/update_certifier.rs b/crates/aptos-jwk-consensus/src/update_certifier.rs index b2f380f45258e..ccc8cd5c274e3 100644 --- a/crates/aptos-jwk-consensus/src/update_certifier.rs +++ b/crates/aptos-jwk-consensus/src/update_certifier.rs @@ -5,6 +5,7 @@ use crate::{ types::{JWKConsensusMsg, ObservedUpdateRequest}, }; use aptos_channels::aptos_channel; +use aptos_logger::info; use aptos_reliable_broadcast::ReliableBroadcast; use aptos_types::{ epoch_state::EpochState, @@ -46,7 +47,15 @@ impl TUpdateCertifier for UpdateCertifier { payload: ProviderJWKs, qc_update_tx: aptos_channel::Sender, ) -> AbortHandle { + let version = payload.version; + info!( + epoch = epoch_state.epoch, + issuer = String::from_utf8(payload.issuer.clone()).ok(), + version = version, + "Start certifying update." + ); let rb = self.reliable_broadcast.clone(); + let epoch = epoch_state.epoch; let issuer = payload.issuer.clone(); let req = ObservedUpdateRequest { epoch: epoch_state.epoch, @@ -55,6 +64,12 @@ impl TUpdateCertifier for UpdateCertifier { let agg_state = Arc::new(ObservationAggregationState::new(epoch_state, payload)); let task = async move { let qc_update = rb.broadcast(req, agg_state).await; + info!( + epoch = epoch, + issuer = String::from_utf8(issuer.clone()).ok(), + version = version, + "Certified update obtained." + ); let _ = qc_update_tx.push(issuer, qc_update); }; let (abort_handle, abort_registration) = AbortHandle::new_pair(); diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs index 0df449657d22b..16850606ad34b 100644 --- a/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_basic.rs @@ -25,6 +25,7 @@ async fn jwk_consensus_basic() { let epoch_duration_secs = 30; let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) + .with_num_fullnodes(1) .with_aptos() .with_init_genesis_config(Arc::new(move |conf| { conf.epoch_duration_secs = epoch_duration_secs; diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs index e271c2bb9cd67..c0d6859c0dd60 100644 --- a/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_per_issuer.rs @@ -25,6 +25,7 @@ async fn jwk_consensus_per_issuer() { let epoch_duration_secs = 30; let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) + .with_num_fullnodes(1) .with_aptos() .with_init_genesis_config(Arc::new(move |conf| { conf.epoch_duration_secs = epoch_duration_secs; diff --git a/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs b/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs index 7fad520c48ce1..10b8cfece6c39 100644 --- a/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs +++ b/testsuite/smoke-test/src/jwks/jwk_consensus_provider_change_mind.rs @@ -27,6 +27,7 @@ async fn jwk_consensus_provider_change_mind() { let epoch_duration_secs = 1800; let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) + .with_num_fullnodes(1) .with_aptos() .with_init_genesis_config(Arc::new(move |conf| { conf.epoch_duration_secs = epoch_duration_secs; From c4fd61080de775ec34e1354db522c4116ded7803 Mon Sep 17 00:00:00 2001 From: "Brian (Sunghoon) Cho" Date: Tue, 6 Feb 2024 13:57:52 -0800 Subject: [PATCH 023/328] [consensus] reduce block size to 2500, simplify logic by removing quorum store overrides (#11880) ### Description With the improvements in VM load time, it's no longer necessary to have a very large block size for throughput. In fact, with the block gas limits, a large block size can be bad, because it leads to frequent block cuts. With targeting a smaller block size, there's no more reason to have a separate quorum store enabled size. So combined into a single block size and simplified the logic. ### Test Plan Run e2e perf test. --- config/src/config/consensus_config.rs | 85 ++++--------------- config/src/config/quorum_store_config.rs | 4 +- consensus/src/epoch_manager.rs | 6 +- consensus/src/round_manager.rs | 15 +--- consensus/src/round_manager_test.rs | 4 +- testsuite/forge-cli/src/main.rs | 23 ++--- .../consensus/consensus_fault_tolerance.rs | 3 - testsuite/smoke-test/src/rest_api.rs | 2 - 8 files changed, 30 insertions(+), 112 deletions(-) diff --git a/config/src/config/consensus_config.rs b/config/src/config/consensus_config.rs index 66724bf0fb3a4..83564f58cd6d0 100644 --- a/config/src/config/consensus_config.rs +++ b/config/src/config/consensus_config.rs @@ -11,22 +11,17 @@ use cfg_if::cfg_if; use serde::{Deserialize, Serialize}; use std::path::PathBuf; -pub(crate) const MAX_SENDING_BLOCK_TXNS_QUORUM_STORE_OVERRIDE: u64 = 4000; +pub(crate) const MAX_SENDING_BLOCK_TXNS: u64 = 2500; #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(default, deny_unknown_fields)] pub struct ConsensusConfig { // length of inbound queue of messages pub max_network_channel_size: usize, - // Use getters to read the correct value with/without quorum store. pub max_sending_block_txns: u64, - pub max_sending_block_txns_quorum_store_override: u64, pub max_sending_block_bytes: u64, - pub max_sending_block_bytes_quorum_store_override: u64, pub max_receiving_block_txns: u64, - pub max_receiving_block_txns_quorum_store_override: u64, pub max_receiving_block_bytes: u64, - pub max_receiving_block_bytes_quorum_store_override: u64, pub max_pruned_blocks_in_mem: usize, // Timeout for consensus to get an ack from mempool for executed transactions (in milliseconds) pub mempool_executed_txn_timeout_ms: u64, @@ -144,18 +139,10 @@ impl Default for ConsensusConfig { fn default() -> ConsensusConfig { ConsensusConfig { max_network_channel_size: 1024, - max_sending_block_txns: 2500, - max_sending_block_txns_quorum_store_override: - MAX_SENDING_BLOCK_TXNS_QUORUM_STORE_OVERRIDE, - // defaulting to under 0.5s to broadcast the proposal to 100 validators - // over 1gbps link - max_sending_block_bytes: 600 * 1024, // 600 KB - max_sending_block_bytes_quorum_store_override: 5 * 1024 * 1024, // 5MB - max_receiving_block_txns: 10000, - max_receiving_block_txns_quorum_store_override: 10000 - .max(2 * MAX_SENDING_BLOCK_TXNS_QUORUM_STORE_OVERRIDE), - max_receiving_block_bytes: 3 * 1024 * 1024, // 3MB - max_receiving_block_bytes_quorum_store_override: 6 * 1024 * 1024, // 6MB + max_sending_block_txns: MAX_SENDING_BLOCK_TXNS, + max_sending_block_bytes: 3 * 1024 * 1024, // 3MB + max_receiving_block_txns: 10000.max(2 * MAX_SENDING_BLOCK_TXNS), + max_receiving_block_bytes: 6 * 1024 * 1024, // 6MB max_pruned_blocks_in_mem: 100, mempool_executed_txn_timeout_ms: 1000, mempool_txn_pull_timeout_ms: 1000, @@ -308,38 +295,6 @@ impl ConsensusConfig { } } - pub fn max_sending_block_txns(&self, quorum_store_enabled: bool) -> u64 { - if quorum_store_enabled { - self.max_sending_block_txns_quorum_store_override - } else { - self.max_sending_block_txns - } - } - - pub fn max_sending_block_bytes(&self, quorum_store_enabled: bool) -> u64 { - if quorum_store_enabled { - self.max_sending_block_bytes_quorum_store_override - } else { - self.max_sending_block_bytes - } - } - - pub fn max_receiving_block_txns(&self, quorum_store_enabled: bool) -> u64 { - if quorum_store_enabled { - self.max_receiving_block_txns_quorum_store_override - } else { - self.max_receiving_block_txns - } - } - - pub fn max_receiving_block_bytes(&self, quorum_store_enabled: bool) -> u64 { - if quorum_store_enabled { - self.max_receiving_block_bytes_quorum_store_override - } else { - self.max_receiving_block_bytes - } - } - fn sanitize_send_recv_block_limits( sanitizer_name: &str, config: &ConsensusConfig, @@ -355,16 +310,6 @@ impl ConsensusConfig { config.max_receiving_block_bytes, "bytes", ), - ( - config.max_sending_block_txns_quorum_store_override, - config.max_receiving_block_txns_quorum_store_override, - "txns_quorum_store_override", - ), - ( - config.max_sending_block_bytes_quorum_store_override, - config.max_receiving_block_bytes_quorum_store_override, - "bytes_quorum_store_override", - ), ]; for (send, recv, label) in &send_recv_pairs { if *send > *recv { @@ -385,12 +330,12 @@ impl ConsensusConfig { let mut recv_batch_send_block_pairs = vec![ ( config.quorum_store.receiver_max_batch_txns as u64, - config.max_sending_block_txns_quorum_store_override, + config.max_sending_block_txns, "txns".to_string(), ), ( config.quorum_store.receiver_max_batch_bytes as u64, - config.max_sending_block_bytes_quorum_store_override, + config.max_sending_block_bytes, "bytes".to_string(), ), ]; @@ -543,12 +488,12 @@ mod test { } #[test] - fn test_send_recv_quorum_store_block_txn_override() { + fn test_send_recv_block_txn_override() { // Create a node config with invalid block txn limits let node_config = NodeConfig { consensus: ConsensusConfig { - max_sending_block_txns_quorum_store_override: 100, - max_receiving_block_txns_quorum_store_override: 50, + max_sending_block_txns: 100, + max_receiving_block_txns: 50, ..Default::default() }, ..Default::default() @@ -565,12 +510,12 @@ mod test { } #[test] - fn test_send_recv_quorum_store_block_byte_override() { + fn test_send_recv_block_byte_override() { // Create a node config with invalid block byte limits let node_config = NodeConfig { consensus: ConsensusConfig { - max_sending_block_bytes_quorum_store_override: 100, - max_receiving_block_bytes_quorum_store_override: 50, + max_sending_block_bytes: 100, + max_receiving_block_bytes: 50, ..Default::default() }, ..Default::default() @@ -591,7 +536,7 @@ mod test { // Create a node config with invalid batch txn limits let node_config = NodeConfig { consensus: ConsensusConfig { - max_sending_block_txns_quorum_store_override: 100, + max_sending_block_txns: 100, quorum_store: QuorumStoreConfig { receiver_max_batch_txns: 101, ..Default::default() @@ -612,7 +557,7 @@ mod test { // Create a node config with invalid batch byte limits let node_config = NodeConfig { consensus: ConsensusConfig { - max_sending_block_bytes_quorum_store_override: 100, + max_sending_block_bytes: 100, quorum_store: QuorumStoreConfig { receiver_max_batch_bytes: 101, ..Default::default() diff --git a/config/src/config/quorum_store_config.rs b/config/src/config/quorum_store_config.rs index fb677646d2d60..09cb992cfa403 100644 --- a/config/src/config/quorum_store_config.rs +++ b/config/src/config/quorum_store_config.rs @@ -3,7 +3,6 @@ use crate::config::{ config_sanitizer::ConfigSanitizer, node_config_loader::NodeType, Error, NodeConfig, - MAX_SENDING_BLOCK_TXNS_QUORUM_STORE_OVERRIDE, }; use aptos_global_constants::DEFAULT_BUCKETS; use aptos_types::chain_id::ChainId; @@ -29,7 +28,8 @@ impl Default for QuorumStoreBackPressureConfig { fn default() -> QuorumStoreBackPressureConfig { QuorumStoreBackPressureConfig { // QS will be backpressured if the remaining total txns is more than this number - backlog_txn_limit_count: MAX_SENDING_BLOCK_TXNS_QUORUM_STORE_OVERRIDE * 4, + // Roughly, target TPS * commit latency seconds + backlog_txn_limit_count: 8000 * 2, // QS will create batches at the max rate until this number is reached backlog_per_validator_batch_limit_count: 4, decrease_duration_ms: 1000, diff --git a/consensus/src/epoch_manager.rs b/consensus/src/epoch_manager.rs index 6ffd58555c4f4..b294cc28dbd3c 100644 --- a/consensus/src/epoch_manager.rs +++ b/consensus/src/epoch_manager.rs @@ -892,10 +892,8 @@ impl EpochManager

{ payload_client, self.time_service.clone(), Duration::from_millis(self.config.quorum_store_poll_time_ms), - self.config - .max_sending_block_txns(self.quorum_store_enabled), - self.config - .max_sending_block_bytes(self.quorum_store_enabled), + self.config.max_sending_block_txns, + self.config.max_sending_block_bytes, onchain_consensus_config.max_failed_authors_to_store(), pipeline_backpressure_config, chain_health_backoff_config, diff --git a/consensus/src/round_manager.rs b/consensus/src/round_manager.rs index b0880f377e0ab..7c34e0979d6cd 100644 --- a/consensus/src/round_manager.rs +++ b/consensus/src/round_manager.rs @@ -689,25 +689,18 @@ impl RoundManager { let payload_len = proposal.payload().map_or(0, |payload| payload.len()); let payload_size = proposal.payload().map_or(0, |payload| payload.size()); ensure!( - num_validator_txns + payload_len as u64 - <= self - .local_config - .max_receiving_block_txns(self.onchain_config.quorum_store_enabled()), + num_validator_txns + payload_len as u64 <= self.local_config.max_receiving_block_txns, "Payload len {} exceeds the limit {}", payload_len, - self.local_config - .max_receiving_block_txns(self.onchain_config.quorum_store_enabled()), + self.local_config.max_receiving_block_txns, ); ensure!( validator_txns_total_bytes + payload_size as u64 - <= self - .local_config - .max_receiving_block_bytes(self.onchain_config.quorum_store_enabled()), + <= self.local_config.max_receiving_block_bytes, "Payload size {} exceeds the limit {}", payload_size, - self.local_config - .max_receiving_block_bytes(self.onchain_config.quorum_store_enabled()), + self.local_config.max_receiving_block_bytes, ); ensure!( diff --git a/consensus/src/round_manager_test.rs b/consensus/src/round_manager_test.rs index 2cc270ce9ada4..cbba3a30c8460 100644 --- a/consensus/src/round_manager_test.rs +++ b/consensus/src/round_manager_test.rs @@ -2152,8 +2152,8 @@ fn no_vote_on_proposal_ext_when_receiving_limit_exceeded() { }; let local_config = ConsensusConfig { - max_receiving_block_txns_quorum_store_override: 10, - max_receiving_block_bytes_quorum_store_override: 800, + max_receiving_block_txns: 10, + max_receiving_block_bytes: 800, ..Default::default() }; diff --git a/testsuite/forge-cli/src/main.rs b/testsuite/forge-cli/src/main.rs index 24f66dbe391cf..88abed486a844 100644 --- a/testsuite/forge-cli/src/main.rs +++ b/testsuite/forge-cli/src/main.rs @@ -791,18 +791,10 @@ fn run_consensus_only_realistic_env_max_tps() -> ForgeConfig { fn optimize_for_maximum_throughput(config: &mut NodeConfig) { mempool_config_practically_non_expiring(&mut config.mempool); - config - .consensus - .max_sending_block_txns_quorum_store_override = 30000; - config - .consensus - .max_receiving_block_txns_quorum_store_override = 40000; - config - .consensus - .max_sending_block_bytes_quorum_store_override = 10 * 1024 * 1024; - config - .consensus - .max_receiving_block_bytes_quorum_store_override = 12 * 1024 * 1024; + config.consensus.max_sending_block_txns = 30000; + config.consensus.max_receiving_block_txns = 40000; + config.consensus.max_sending_block_bytes = 10 * 1024 * 1024; + config.consensus.max_receiving_block_bytes = 12 * 1024 * 1024; config.consensus.pipeline_backpressure = vec![]; config.consensus.chain_health_backoff = vec![]; @@ -2030,12 +2022,7 @@ fn changing_working_quorum_test_helper( let block_size = (target_tps / 4) as u64; config.consensus.max_sending_block_txns = block_size; - config - .consensus - .max_sending_block_txns_quorum_store_override = block_size; - config - .consensus - .max_receiving_block_txns_quorum_store_override = block_size; + config.consensus.max_receiving_block_txns = block_size; config.consensus.round_initial_timeout_ms = 500; config.consensus.round_timeout_backoff_exponent_base = 1.0; config.consensus.quorum_store_poll_time_ms = 100; diff --git a/testsuite/smoke-test/src/consensus/consensus_fault_tolerance.rs b/testsuite/smoke-test/src/consensus/consensus_fault_tolerance.rs index 26e2722fd1c44..4f8825b56dc5e 100644 --- a/testsuite/smoke-test/src/consensus/consensus_fault_tolerance.rs +++ b/testsuite/smoke-test/src/consensus/consensus_fault_tolerance.rs @@ -26,9 +26,6 @@ pub async fn create_swarm(num_nodes: usize, max_block_txns: u64) -> LocalSwarm { .with_init_config(Arc::new(move |_, config, _| { config.api.failpoints_enabled = true; config.consensus.max_sending_block_txns = max_block_txns; - config - .consensus - .max_sending_block_txns_quorum_store_override = max_block_txns; config.consensus.quorum_store.sender_max_batch_txns = config .consensus .quorum_store diff --git a/testsuite/smoke-test/src/rest_api.rs b/testsuite/smoke-test/src/rest_api.rs index 4768172cae3e0..c546068bd4fba 100644 --- a/testsuite/smoke-test/src/rest_api.rs +++ b/testsuite/smoke-test/src/rest_api.rs @@ -187,7 +187,6 @@ async fn test_gas_estimation_txns_limit() { conf.consensus.quorum_store_poll_time_ms = 200; conf.consensus.wait_for_full_blocks_above_pending_blocks = 0; conf.consensus.max_sending_block_txns = max_block_txns; - conf.consensus.max_sending_block_txns_quorum_store_override = max_block_txns; conf.consensus.quorum_store.sender_max_batch_txns = conf .consensus .quorum_store @@ -226,7 +225,6 @@ async fn test_gas_estimation_gas_used_limit() { conf.consensus.quorum_store_poll_time_ms = 200; conf.consensus.wait_for_full_blocks_above_pending_blocks = 0; conf.consensus.max_sending_block_txns = max_block_txns; - conf.consensus.max_sending_block_txns_quorum_store_override = max_block_txns; conf.consensus.quorum_store.sender_max_batch_txns = conf .consensus .quorum_store From 8a258b7fd242e3ead67d29bfd807b42793b12509 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 23:24:27 +0000 Subject: [PATCH 024/328] Bump shlex from 1.2.0 to 1.3.0 (#11730) Bumps [shlex](https://github.com/comex/rust-shlex) from 1.2.0 to 1.3.0. - [Changelog](https://github.com/comex/rust-shlex/blob/master/CHANGELOG.md) - [Commits](https://github.com/comex/rust-shlex/commits) --- updated-dependencies: - dependency-name: shlex dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52d0b8cb98ecf..857f06af272da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14681,9 +14681,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" From 92d450c6f9b2a50948eacd1bfa2174c5940f487f Mon Sep 17 00:00:00 2001 From: Rati Gelashvili Date: Tue, 6 Feb 2024 19:13:36 -0500 Subject: [PATCH 025/328] [Block Executor] Fix halting logic (#11899) --- Cargo.lock | 1 + aptos-move/aptos-vm/src/block_executor/mod.rs | 2 +- aptos-move/block-executor/Cargo.toml | 2 + aptos-move/block-executor/src/errors.rs | 39 +++- aptos-move/block-executor/src/executor.rs | 194 ++++++++---------- .../src/proptest_types/baseline.rs | 22 +- .../src/proptest_types/bencher.rs | 4 +- .../src/proptest_types/tests.rs | 30 ++- aptos-move/block-executor/src/scheduler.rs | 36 +++- .../src/txn_last_input_output.rs | 65 +++--- .../block-executor/src/unit_tests/mod.rs | 57 ++++- 11 files changed, 262 insertions(+), 190 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 857f06af272da..7ee8635c683a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -654,6 +654,7 @@ dependencies = [ "crossbeam", "dashmap", "derivative", + "fail 0.5.1", "itertools 0.10.5", "move-binary-format", "move-core-types", diff --git a/aptos-move/aptos-vm/src/block_executor/mod.rs b/aptos-move/aptos-vm/src/block_executor/mod.rs index e7bd292fb3c61..e1bb1cba256a0 100644 --- a/aptos-move/aptos-vm/src/block_executor/mod.rs +++ b/aptos-move/aptos-vm/src/block_executor/mod.rs @@ -432,7 +432,7 @@ impl BlockAptosVM { e ) }, - Err(BlockExecutionError::FatalVMError((err, _))) => Err(err), + Err(BlockExecutionError::FatalVMError(err)) => Err(err), } } } diff --git a/aptos-move/block-executor/Cargo.toml b/aptos-move/block-executor/Cargo.toml index 62336db296435..b6cceaeacf2d7 100644 --- a/aptos-move/block-executor/Cargo.toml +++ b/aptos-move/block-executor/Cargo.toml @@ -32,6 +32,7 @@ criterion = { workspace = true, optional = true } crossbeam = { workspace = true } dashmap = { workspace = true } derivative = { workspace = true } +fail = { workspace = true } move-binary-format = { workspace = true } move-core-types = { workspace = true } move-vm-types = { workspace = true } @@ -48,6 +49,7 @@ serde = { workspace = true } [dev-dependencies] aptos-aggregator = { workspace = true, features = ["testing"] } criterion = { workspace = true } +fail = { workspace = true, features = ["failpoints"] } itertools = { workspace = true } proptest = { workspace = true } proptest-derive = { workspace = true } diff --git a/aptos-move/block-executor/src/errors.rs b/aptos-move/block-executor/src/errors.rs index f88c279055e99..ecd50bcf06e5b 100644 --- a/aptos-move/block-executor/src/errors.rs +++ b/aptos-move/block-executor/src/errors.rs @@ -3,28 +3,45 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_aggregator::types::PanicOr; +use aptos_logger::{debug, error}; use aptos_mvhashmap::types::TxnIndex; use aptos_types::delayed_fields::PanicError; +use aptos_vm_logging::{alert, prelude::*}; #[derive(Clone, Debug, PartialEq, Eq)] +/// Logging is bottlenecked in constructors. pub enum IntentionalFallbackToSequential { - /// The same module access path for module was both read & written during speculative executions. - /// This may trigger a race due to the Move-VM loader cache implementation, and mitigation requires - /// aborting the parallel execution pipeline and falling back to the sequential execution. - /// TODO: (short-mid term) relax the limitation, and (mid-long term) provide proper multi-versioning - /// for code (like data) for the cache. + // The same module access path for module was both read & written during speculative executions. + // This may trigger a race due to the Move-VM loader cache implementation, and mitigation requires + // aborting the parallel execution pipeline and falling back to the sequential execution. + // TODO: provide proper multi-versioning for code (like data) for the cache. ModulePathReadWrite, - /// We defensively check resource group serialization error in the commit phase. - /// TODO: should trigger invariant violation in the transaction itself. - ResourceGroupSerializationError(String), + // This is not PanicError because we need to match the error variant to provide a specialized + // fallback logic if a resource group serialization error occurs. + ResourceGroupSerializationError, +} + +impl IntentionalFallbackToSequential { + pub(crate) fn module_path_read_write(error_msg: String, txn_idx: TxnIndex) -> Self { + // Module R/W is an expected fallback behavior, no alert is required. + debug!("[Execution] At txn {}, {:?}", txn_idx, error_msg); + + IntentionalFallbackToSequential::ModulePathReadWrite + } + + pub(crate) fn resource_group_serialization_error(error_msg: String, txn_idx: TxnIndex) -> Self { + alert!("[Execution] At txn {}, {:?}", txn_idx, error_msg); + + IntentionalFallbackToSequential::ResourceGroupSerializationError + } } #[derive(Clone, Debug, PartialEq, Eq)] pub enum BlockExecutionError { FallbackToSequential(PanicOr), - /// Execution of a thread yields a non-recoverable error from the VM. Such an error will be propagated - /// back to the caller (leading to the block execution getting aborted). - FatalVMError((E, TxnIndex)), + /// If the unrecoverable VM error occurs during sequential execution (e.g. fallback), + /// the error is propagated back to the caller (block execution is aborted). + FatalVMError(E), } pub type BlockExecutionResult = Result>; diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index 7e48e9b1b5f2c..0dd958e01545d 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -24,7 +24,7 @@ use aptos_aggregator::{ types::{code_invariant_error, expect_ok, PanicOr}, }; use aptos_drop_helper::DEFAULT_DROPPER; -use aptos_logger::{debug, error, info}; +use aptos_logger::{debug, error}; use aptos_mvhashmap::{ types::{Incarnation, MVDataOutput, MVDelayedFieldsError, TxnIndex, ValueWithLayout}, unsync_map::UnsyncMap, @@ -46,6 +46,7 @@ use aptos_vm_types::change_set::randomly_check_layout_matches; use bytes::Bytes; use claims::assert_none; use core::panic; +use fail::fail_point; use move_core_types::value::MoveTypeLayout; use num_cpus; use rand::{thread_rng, Rng}; @@ -54,7 +55,10 @@ use std::{ cell::RefCell, collections::{BTreeMap, HashMap, HashSet}, marker::{PhantomData, Sync}, - sync::{atomic::AtomicU32, Arc}, + sync::{ + atomic::{AtomicBool, AtomicU32, Ordering}, + Arc, + }, }; pub struct BlockExecutor { @@ -238,20 +242,26 @@ where apply_updates(&output)?; ExecutionStatus::SkipRest(output) }, - ExecutionStatus::Abort(err) => { - // Record the status indicating abort. - ExecutionStatus::Abort(BlockExecutionError::FatalVMError((err, idx_to_execute))) - }, ExecutionStatus::SpeculativeExecutionAbortError(msg) => { read_set.capture_delayed_field_read_error(&PanicOr::Or( MVDelayedFieldsError::DeltaApplicationFailure, )); ExecutionStatus::SpeculativeExecutionAbortError(msg) }, + ExecutionStatus::Abort(err) => { + // Abort indicates an unrecoverable VM failure, and should not occur + // even due to speculation. Thus, we do not need to finish execution and + // can directly return an error. + return Err(code_invariant_error(format!( + "FatalVMError from parallel execution {:?} at txn {}", + err, idx_to_execute + )) + .into()); + }, ExecutionStatus::DelayedFieldsCodeInvariantError(msg) => { return Err(code_invariant_error(format!( - "Transaction execution failed with DelayedFieldsCodeInvariantError: {:?}", - msg + "[Execution] At txn {}, failed with DelayedFieldsCodeInvariantError: {:?}", + idx_to_execute, msg )) .into()); }, @@ -276,7 +286,10 @@ where if !last_input_output.record(idx_to_execute, read_set, result) { return Err(PanicOr::Or( - IntentionalFallbackToSequential::ModulePathReadWrite, + IntentionalFallbackToSequential::module_path_read_write( + "Module read & write".into(), + idx_to_execute, + ), )); } Ok(updates_outside) @@ -422,7 +435,7 @@ where shared_counter: &AtomicU32, executor: &E, block: &[T], - ) -> BlockExecutionResult<(), E::Error> { + ) -> Result<(), PanicOr> { let mut block_limit_processor = shared_commit_state.acquire(); while let Some((txn_idx, incarnation)) = scheduler.try_commit() { @@ -527,7 +540,6 @@ where let group_metadata_ops = last_input_output.group_metadata_ops(txn_idx); let mut finalized_groups = Vec::with_capacity(group_metadata_ops.len()); - let mut maybe_code_error = Ok(()); for (group_key, metadata_op) in group_metadata_ops.into_iter() { // finalize_group copies Arc of values and the Tags (TODO: optimize as needed). let finalized_result = versioned_cache @@ -538,53 +550,39 @@ where finalized_groups.push((group_key, metadata_op, finalized_group)); }, Err(err) => { - maybe_code_error = Err(err.into()); - break; + return Err(err.into()); }, } } - if maybe_code_error.is_ok() { - if let Some(group_reads_needing_delayed_field_exchange) = - last_input_output.group_reads_needing_delayed_field_exchange(txn_idx) + if let Some(group_reads_needing_delayed_field_exchange) = + last_input_output.group_reads_needing_delayed_field_exchange(txn_idx) + { + for (group_key, metadata_op) in + group_reads_needing_delayed_field_exchange.into_iter() { - for (group_key, metadata_op) in - group_reads_needing_delayed_field_exchange.into_iter() - { - let finalized_result = versioned_cache - .group_data() - .get_last_committed_group(&group_key); - match process_finalized_group(finalized_result, metadata_op.is_deletion()) { - Ok(finalized_group) => { - finalized_groups.push((group_key, metadata_op, finalized_group)); - }, - Err(err) => { - maybe_code_error = Err(err.into()); - break; - }, - } - if maybe_code_error.is_err() { - break; - } + let finalized_result = versioned_cache + .group_data() + .get_last_committed_group(&group_key); + match process_finalized_group(finalized_result, metadata_op.is_deletion()) { + Ok(finalized_group) => { + finalized_groups.push((group_key, metadata_op, finalized_group)); + }, + Err(err) => { + return Err(err.into()); + }, } } } - // We return an error (leads to halting the execution) in the following cases: - // 1) Code invariant violation. - // 2) We detect module read/write intersection - // 3) A transaction triggered an Abort - - last_input_output.record_finalized_group(txn_idx, finalized_groups); + // Note that module read/write intersection would be detected on record, and directly + // propagated as an error. Similarly, an unrecoverable VM failure, would also be + // directly propagated as error even from a speculative transaction execution. - // We cover cases 1 and 2 here - maybe_code_error.and_then(|_| last_input_output.module_rw_intersection_ok())?; + // An additional invariant check on the recorded outputs. + last_input_output.check_execution_status_during_commit(txn_idx)?; - // Next, we handle 3, an abort / an unrecoverable VM error. - if let Some(err) = last_input_output.aborted_execution_status(txn_idx) { - assert!(matches!(err, BlockExecutionError::FatalVMError(_))); - return Err(err); - } + last_input_output.record_finalized_group(txn_idx, finalized_groups); // While the above propagate errors and lead to eventually halting parallel execution, // below we may halt the execution without an error in cases when: @@ -606,8 +604,11 @@ where txn_idx + 1, scheduler.num_txns(), ); + fail_point!("commit-all-halt-err", |_| Err(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + ))); } - break; + return Ok(()); } } Ok(()) @@ -777,6 +778,7 @@ where fn serialize_groups( finalized_groups: Vec<(T::Key, T::Value, Vec<(T::Tag, Arc)>)>, + txn_idx: TxnIndex, ) -> Result, PanicOr> { finalized_groups .into_iter() @@ -795,8 +797,9 @@ where let res = bcs::to_bytes(&btree) .map_err(|e| { PanicOr::Or( - IntentionalFallbackToSequential::ResourceGroupSerializationError( + IntentionalFallbackToSequential::resource_group_serialization_error( format!("Unexpected resource group error {:?}", e), + txn_idx, ), ) }) @@ -874,7 +877,7 @@ where base_view, ); - let serialized_groups = Self::serialize_groups(patched_finalized_groups)?; + let serialized_groups = Self::serialize_groups(patched_finalized_groups, txn_idx)?; last_input_output.record_materialized_txn_output( txn_idx, @@ -930,7 +933,7 @@ where shared_counter: &AtomicU32, shared_commit_state: &ExplicitSyncWrapper>, final_results: &ExplicitSyncWrapper>, - ) -> BlockExecutionResult<(), E::Error> { + ) -> Result<(), PanicOr> { // Make executor for each task. TODO: fast concurrent executor. let init_timer = VM_INIT_SECONDS.start_timer(); let executor = E::init(*executor_arguments); @@ -1035,7 +1038,7 @@ where executor_initial_arguments: E::Argument, signature_verified_block: &[T], base_view: &S, - ) -> BlockExecutionResult, E::Error> { + ) -> Result, PanicOr> { let _timer = PARALLEL_EXECUTION_SECONDS.start_timer(); // Using parallel execution with 1 thread currently will not work as it // will only have a coordinator role but no workers for rolling commit. @@ -1060,7 +1063,7 @@ where self.config.onchain.block_gas_limit_type.clone(), num_txns, )); - let shared_maybe_error = ExplicitSyncWrapper::new(Ok(())); + let shared_maybe_error = AtomicBool::new(false); let final_results = ExplicitSyncWrapper::new(Vec::with_capacity(num_txns)); @@ -1091,21 +1094,16 @@ where &shared_commit_state, &final_results, ) { - if scheduler.halt() { - // Only one thread / worker will successfully halt, hence below - // ExplicitSyncWrapper acquires are safe. - - if let BlockExecutionError::FatalVMError((inner_err, txn_idx)) = &e { - let block_limit_processor = shared_commit_state.acquire(); - info!("Block execution was aborted due to {:?}", inner_err); - block_limit_processor.finish_parallel_update_counters_and_log_info( - txn_idx + 1, - scheduler.num_txns(), - ); - } - - *shared_maybe_error.acquire() = Err(e); - } + // If there are multiple errors, they all get logged: + // IntentionalFallbackToSequential variant is logged at construction, + // and below we log CodeInvariantErrors. + if let PanicOr::CodeInvariantError(err_msg) = &e { + alert!("[BlockSTM] worker loop: CodeInvariantError({:?})", err_msg); + }; + shared_maybe_error.store(true, Ordering::SeqCst); + + // Make sure to halt the scheduler if it hasn't already been halted. + scheduler.halt(); } }); } @@ -1117,9 +1115,15 @@ where // TODO add block end info to output. // block_limit_processor.is_block_limit_reached(); - shared_maybe_error - .into_inner() - .map(|()| BlockOutput::new(final_results.into_inner())) + (!shared_maybe_error.load(Ordering::SeqCst)) + .then(|| BlockOutput::new(final_results.into_inner())) + .ok_or(PanicOr::Or( + // All errors (if more than one) have been logged, and here any error + // leads to a sequential fallback. We use serialization error for now + // to be defensive and avoid any scenarios where the fallback would not + // have the specialized logic enabled. TODO: refactor. + IntentionalFallbackToSequential::ResourceGroupSerializationError, + )) } fn apply_output_sequential( @@ -1362,8 +1366,9 @@ where &latest_view, ); - let serialized_groups = Self::serialize_groups(patched_finalized_groups) - .map_err(BlockExecutionError::FallbackToSequential)?; + let serialized_groups = + Self::serialize_groups(patched_finalized_groups, idx as TxnIndex) + .map_err(BlockExecutionError::FallbackToSequential)?; // TODO[agg_v2] patch resources in groups and provide explicitly output.incorporate_materialized_txn_output( @@ -1394,8 +1399,14 @@ where if let Some(commit_hook) = &self.transaction_commit_hook { commit_hook.on_execution_aborted(idx as TxnIndex); } - // Record the status indicating abort. - return Err(BlockExecutionError::FatalVMError((err, idx as TxnIndex))); + alert!("Fatal VM error by transaction {}", idx as TxnIndex); + // Record the status indicating the unrecoverable VM failure. + return Err(BlockExecutionError::FatalVMError(err)); + }, + ExecutionStatus::DelayedFieldsCodeInvariantError(msg) => { + return Err(BlockExecutionError::FallbackToSequential( + code_invariant_error(msg).into(), + )); }, ExecutionStatus::SpeculativeExecutionAbortError(msg) => { panic!( @@ -1403,15 +1414,6 @@ where msg ); }, - ExecutionStatus::DelayedFieldsCodeInvariantError(msg) => { - error!( - "Sequential execution failed with DelayedFieldsCodeInvariantError: {:?}", - msg - ); - return Err(BlockExecutionError::FallbackToSequential( - PanicOr::CodeInvariantError(msg), - )); - }, }; // When the txn is a SkipRest txn, halt sequential execution. if must_skip { @@ -1446,6 +1448,7 @@ where signature_verified_block, base_view, ) + .map_err(BlockExecutionError::FallbackToSequential) } else { self.execute_transactions_sequential( executor_arguments, @@ -1457,26 +1460,9 @@ where // Sequential execution fallback // Only worth doing if we did parallel before, i.e. if we did a different pass. if self.config.local.concurrency_level > 1 { - if let Err(BlockExecutionError::FallbackToSequential(e)) = &ret { - match e { - PanicOr::Or(IntentionalFallbackToSequential::ModulePathReadWrite) => { - debug!("[Execution]: Module read & written, sequential fallback"); - }, - PanicOr::Or( - IntentionalFallbackToSequential::ResourceGroupSerializationError(msg), - ) => { - error!( - "[Execution]: ResourceGroupSerializationError {}, sequential fallback", - msg - ); - }, - PanicOr::CodeInvariantError(msg) => { - error!( - "[Execution]: CodeInvariantError({:?}), sequential fallback", - msg - ); - }, - }; + if let Err(BlockExecutionError::FallbackToSequential(_)) = &ret { + // Any error logs are already written at appropriate levels. + debug!("Sequential_fallback occurred"); // All logs from the parallel execution should be cleared and not reported. // Clear by re-initializing the speculative logs. diff --git a/aptos-move/block-executor/src/proptest_types/baseline.rs b/aptos-move/block-executor/src/proptest_types/baseline.rs index 6e9e6e65b2e66..6cafa4cc2f741 100644 --- a/aptos-move/block-executor/src/proptest_types/baseline.rs +++ b/aptos-move/block-executor/src/proptest_types/baseline.rs @@ -105,6 +105,9 @@ impl BaselineOutput { let mut read_values = vec![]; let mut resolved_deltas = vec![]; let mut group_reads = vec![]; + + let has_abort = txns.iter().any(|txn| matches!(txn, MockTransaction::Abort)); + for txn in txns.iter() { match txn { MockTransaction::Abort => { @@ -124,11 +127,17 @@ impl BaselineOutput { incarnation_counter, incarnation_behaviors, } => { + let incarnation = incarnation_counter.load(Ordering::SeqCst); + if incarnation == 0 { + // Must have never executed because an Abort transaction caused a halt. + assert!(has_abort); + break; + } + // Determine the behavior of the latest incarnation of the transaction. The index // is based on the value of the incarnation counter prior to the fetch_add during // the last mock execution, and is >= 1 because there is at least one execution. - let last_incarnation = (incarnation_counter.load(Ordering::SeqCst) - 1) - % incarnation_behaviors.len(); + let last_incarnation = (incarnation - 1) % incarnation_behaviors.len(); match incarnation_behaviors[last_incarnation] .deltas @@ -255,6 +264,7 @@ impl BaselineOutput { .collect(); // Test group read results. let read_len = reads.as_ref().unwrap().len(); + assert_eq!( group_read_results.len(), output.read_results.len() - read_len @@ -362,14 +372,14 @@ impl BaselineOutput { assert_none!(output.materialized_delta_writes.get()); }); }, - Err(BlockExecutionError::FatalVMError((idx, executor_idx))) => { - assert_eq!(*idx, *executor_idx as usize); + Err(BlockExecutionError::FatalVMError(idx)) => { assert_matches!(&self.status, BaselineStatus::Aborted); assert_eq!(*idx, self.read_values.len()); assert_eq!(*idx, self.resolved_deltas.len()); }, - Err(BlockExecutionError::FallbackToSequential(e)) => { - unimplemented!("not tested here FallbackToSequential({:?})", e) + Err(BlockExecutionError::FallbackToSequential(_)) => { + // Parallel execution currently returns an arbitrary error to fallback. + // TODO: adjust the logic to be able to test better. }, } } diff --git a/aptos-move/block-executor/src/proptest_types/bencher.rs b/aptos-move/block-executor/src/proptest_types/bencher.rs index d85ea60d3c85e..a9da9740b0b80 100644 --- a/aptos-move/block-executor/src/proptest_types/bencher.rs +++ b/aptos-move/block-executor/src/proptest_types/bencher.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ + errors::BlockExecutionError, executor::BlockExecutor, proptest_types::{ baseline::BaselineOutput, @@ -138,6 +139,7 @@ where >::new(config, executor_thread_pool, None) .execute_transactions_parallel((), &self.transactions, &data_view); - self.baseline_output.assert_output(&output); + self.baseline_output + .assert_output(&output.map_err(BlockExecutionError::FallbackToSequential)); } } diff --git a/aptos-move/block-executor/src/proptest_types/tests.rs b/aptos-move/block-executor/src/proptest_types/tests.rs index d2b54cbb68ced..738bc32c78096 100644 --- a/aptos-move/block-executor/src/proptest_types/tests.rs +++ b/aptos-move/block-executor/src/proptest_types/tests.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - errors::{BlockExecutionError, IntentionalFallbackToSequential}, + errors::BlockExecutionError, executor::BlockExecutor, proptest_types::{ baseline::BaselineOutput, @@ -20,7 +20,7 @@ use aptos_types::{ block_executor::config::BlockExecutorConfig, contract_event::TransactionEvent, executable::ExecutableTestType, }; -use claims::assert_ok; +use claims::{assert_matches, assert_ok}; use num_cpus; use proptest::{ collection::vec, @@ -86,16 +86,12 @@ fn run_transactions( .execute_transactions_parallel((), &transactions, &data_view); if module_access.0 && module_access.1 { - assert_eq!( - output.unwrap_err(), - BlockExecutionError::FallbackToSequential(PanicOr::Or( - IntentionalFallbackToSequential::ModulePathReadWrite - )) - ); + assert_matches!(output, Err(PanicOr::Or(_))); continue; } - BaselineOutput::generate(&transactions, maybe_block_gas_limit).assert_output(&output); + BaselineOutput::generate(&transactions, maybe_block_gas_limit) + .assert_output(&output.map_err(BlockExecutionError::FallbackToSequential)); } } @@ -224,7 +220,8 @@ fn deltas_writes_mixed_with_block_gas_limit(num_txns: usize, maybe_block_gas_lim ) .execute_transactions_parallel((), &transactions, &data_view); - BaselineOutput::generate(&transactions, maybe_block_gas_limit).assert_output(&output); + BaselineOutput::generate(&transactions, maybe_block_gas_limit) + .assert_output(&output.map_err(BlockExecutionError::FallbackToSequential)); } } @@ -274,7 +271,8 @@ fn deltas_resolver_with_block_gas_limit(num_txns: usize, maybe_block_gas_limit: ) .execute_transactions_parallel((), &transactions, &data_view); - BaselineOutput::generate(&transactions, maybe_block_gas_limit).assert_output(&output); + BaselineOutput::generate(&transactions, maybe_block_gas_limit) + .assert_output(&output.map_err(BlockExecutionError::FallbackToSequential)); } } @@ -474,12 +472,7 @@ fn publishing_fixed_params_with_block_gas_limit( ) // Ensure enough gas limit to commit the module txns (4 is maximum gas per txn) .execute_transactions_parallel((), &transactions, &data_view); - assert_eq!( - output.unwrap_err(), - BlockExecutionError::FallbackToSequential(PanicOr::Or( - IntentionalFallbackToSequential::ModulePathReadWrite - )) - ); + assert_matches!(output, Err(PanicOr::Or(_))); } } @@ -558,7 +551,8 @@ fn non_empty_group( ) .execute_transactions_parallel((), &transactions, &data_view); - BaselineOutput::generate(&transactions, None).assert_output(&output); + BaselineOutput::generate(&transactions, None) + .assert_output(&output.map_err(BlockExecutionError::FallbackToSequential)); } for _ in 0..num_repeat_sequential { diff --git a/aptos-move/block-executor/src/scheduler.rs b/aptos-move/block-executor/src/scheduler.rs index 3e154c37616cd..c4316a31088be 100644 --- a/aptos-move/block-executor/src/scheduler.rs +++ b/aptos-move/block-executor/src/scheduler.rs @@ -581,17 +581,21 @@ impl Scheduler { } /// This function can halt the BlockSTM early, even if there are unfinished tasks. - /// It will set the done_marker to be true, resolve all pending dependencies. + /// It will set the done_marker to be true, and resolve all pending dependencies. /// - /// Currently there are 4 scenarios to early halt the BlockSTM execution. - /// 1. There is a module publishing txn that has read/write intersection with any txns even during speculative execution. - /// 2. There is a txn with VM execution status Abort. - /// 3. There is a txn with VM execution status SkipRest. - /// 4. The committed txns have exceeded the PER_BLOCK_GAS_LIMIT. + /// Currently, the reasons for halting the scheduler are as follows: + /// 1. There is a module publishing txn that has read/write intersection with any txns + /// even during speculative execution. + /// 2. There is a resource group serialization error. + /// 3. There is a txn with VM execution status Abort. + /// 4. There is a txn with VM execution status SkipRest. + /// 5. The committed txns have exceeded the PER_BLOCK_GAS_LIMIT. + /// 6. All transactions have been committed. /// - /// For scenarios 1 and 2, only the error will be returned as the output of the block execution. - /// For scenarios 3 and 4, the execution outputs of the committed txn prefix will be returned. - pub fn halt(&self) -> bool { + /// For scenarios 1, 2 & 3, the output of the block execution will be an error, leading + /// to a fallback with sequential execution. For scenarios 4, 5 & 6, execution outputs + /// of the committed txn prefix will be returned from block execution. + pub(crate) fn halt(&self) -> bool { // The first thread that sets done_marker to be true will be responsible for // resolving the conditional variables, to help other theads that may be pending // on the read dependency. See the comment of the function halt_transaction_execution(). @@ -926,3 +930,17 @@ impl Scheduler { self.done_marker.load(Ordering::Acquire) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn scheduler_halt() { + let s = Scheduler::new(5); + assert!(!s.done()); + assert!(s.halt()); + assert!(s.done()); + assert!(!s.halt()); + } +} diff --git a/aptos-move/block-executor/src/txn_last_input_output.rs b/aptos-move/block-executor/src/txn_last_input_output.rs index d00efb903816a..d204ae73b24aa 100644 --- a/aptos-move/block-executor/src/txn_last_input_output.rs +++ b/aptos-move/block-executor/src/txn_last_input_output.rs @@ -8,7 +8,8 @@ use crate::{ task::{ExecutionStatus, TransactionOutput}, types::{InputOutputKey, ReadWriteSummary}, }; -use aptos_aggregator::types::PanicOr; +use aptos_aggregator::types::{code_invariant_error, PanicOr}; +use aptos_logger::warn; use aptos_mvhashmap::types::{TxnIndex, ValueWithLayout}; use aptos_types::{ fee_statement::FeeStatement, transaction::BlockExecutableTransaction as Transaction, @@ -22,10 +23,7 @@ use std::{ collections::{BTreeMap, HashSet}, fmt::Debug, iter::{empty, Iterator}, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, + sync::Arc, }; type TxnInput = CapturedReads; @@ -70,8 +68,6 @@ pub struct TxnLastInputOutput, E: // Move-VM loader cache - see 'record' function comment for more information. module_writes: DashSet, module_reads: DashSet, - - module_read_write_intersection: AtomicBool, } impl, E: Debug + Send + Clone> @@ -90,7 +86,6 @@ impl, E: Debug + Send + Clone> .collect(), module_writes: DashSet::new(), module_reads: DashSet::new(), - module_read_write_intersection: AtomicBool::new(false), } } @@ -154,19 +149,9 @@ impl, E: Debug + Send + Clone> module_reads_keys: impl Iterator, module_writes_keys: impl Iterator, ) -> bool { - if self.module_read_write_intersection.load(Ordering::Relaxed) { - return true; - } - // Check if adding new read & write modules leads to intersections. - if Self::append_and_check(module_reads_keys, &self.module_reads, &self.module_writes) + Self::append_and_check(module_reads_keys, &self.module_reads, &self.module_writes) || Self::append_and_check(module_writes_keys, &self.module_writes, &self.module_reads) - { - self.module_read_write_intersection - .store(true, Ordering::Release); - return true; - } - false } pub(crate) fn read_set(&self, txn_idx: TxnIndex) -> Option>> { @@ -211,33 +196,35 @@ impl, E: Debug + Send + Clone> ) } - pub(crate) fn module_rw_intersection_ok( + pub(crate) fn check_execution_status_during_commit( &self, + txn_idx: TxnIndex, ) -> Result<(), PanicOr> { - if self.module_read_write_intersection.load(Ordering::Acquire) { - Err(PanicOr::Or( - IntentionalFallbackToSequential::ModulePathReadWrite, - )) + if let Some(status) = self.outputs[txn_idx as usize].load_full() { + match &status.output_status { + ExecutionStatus::Success(_) | ExecutionStatus::SkipRest(_) => Ok(()), + // Transaction cannot be committed with below statuses, as: + // - Speculative error must have failed validation. + // - Execution w. delayed field code error propagates the error directly, + // does not finish execution. Similar for FatalVMError / abort. + ExecutionStatus::Abort(_) => { + Err(code_invariant_error("Abort status cannot be committed").into()) + }, + ExecutionStatus::SpeculativeExecutionAbortError(_) => { + Err(code_invariant_error("Speculative error status cannot be committed").into()) + }, + ExecutionStatus::DelayedFieldsCodeInvariantError(_) => Err(code_invariant_error( + "Delayed field invariant error cannot be committed", + ) + .into()), + } } else { + // TODO: check carefully if such a case is possible due to early halts. + warn!("Possible to not find committed output (halted?)"); Ok(()) } } - pub(crate) fn aborted_execution_status( - &self, - txn_idx: TxnIndex, - ) -> Option> { - if let ExecutionStatus::Abort(err) = &self.outputs[txn_idx as usize] - .load_full() - .expect("[BlockSTM]: Execution output must be recorded after execution") - .output_status - { - Some(err.clone()) - } else { - None - } - } - pub(crate) fn update_to_skip_rest(&self, txn_idx: TxnIndex) { if let ExecutionStatus::Success(output) = self.take_output(txn_idx) { self.outputs[txn_idx as usize].store(Some(Arc::new(TxnOutput { diff --git a/aptos-move/block-executor/src/unit_tests/mod.rs b/aptos-move/block-executor/src/unit_tests/mod.rs index 91c41c36cc752..abe2104498969 100644 --- a/aptos-move/block-executor/src/unit_tests/mod.rs +++ b/aptos-move/block-executor/src/unit_tests/mod.rs @@ -3,6 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ + errors::{BlockExecutionError, IntentionalFallbackToSequential}, executor::BlockExecutor, proptest_types::{ baseline::BaselineOutput, @@ -20,6 +21,7 @@ use aptos_aggregator::{ bounded_math::SignedU128, delta_change_set::{delta_add, delta_sub, DeltaOp}, delta_math::DeltaHistory, + types::PanicOr, }; use aptos_mvhashmap::types::TxnIndex; use aptos_types::{ @@ -28,11 +30,64 @@ use aptos_types::{ executable::{ExecutableTestType, ModulePath}, }; use claims::assert_matches; +use fail::FailScenario; use rand::{prelude::*, random}; use std::{ cmp::min, collections::BTreeMap, fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc, }; +#[test] +fn block_output_err_precedence() { + let incarnation: MockIncarnation, MockEvent> = MockIncarnation::new( + vec![KeyType::(1, false)], + vec![( + KeyType::(2, false), + ValueType::from_value(vec![5], true), + )], + vec![], + vec![], + 10, + ); + let txn = MockTransaction::from_behavior(incarnation); + let transactions = Vec::from([txn.clone(), txn]); + + let data_view = DeltaDataView::> { + phantom: PhantomData, + }; + let executor_thread_pool = Arc::new( + rayon::ThreadPoolBuilder::new() + .num_threads(num_cpus::get()) + .build() + .unwrap(), + ); + let block_executor = BlockExecutor::< + MockTransaction, MockEvent>, + MockTask, MockEvent>, + DeltaDataView>, + NoOpTransactionCommitHook, MockEvent>, usize>, + ExecutableTestType, + >::new( + BlockExecutorConfig::new_no_block_limit(num_cpus::get()), + executor_thread_pool, + None, + ); + + let scenario = FailScenario::setup(); + assert!(fail::has_failpoints()); + fail::cfg("commit-all-halt-err", "return()").unwrap(); + assert!(!fail::list().is_empty()); + // Pause the thread that processes the aborting txn1, so txn2 can halt the scheduler first. + // Confirm that the fatal VM error is still detected and sequential fallback triggered. + let output = block_executor.execute_transactions_parallel((), &transactions, &data_view); + assert_matches!( + output, + Err(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + )) + ); + scenario.teardown(); +} + // TODO: add unit test for block gas limit! fn run_and_assert(transactions: Vec>) where @@ -64,7 +119,7 @@ where .execute_transactions_parallel((), &transactions, &data_view); let baseline = BaselineOutput::generate(&transactions, None); - baseline.assert_output(&output); + baseline.assert_output(&output.map_err(BlockExecutionError::FallbackToSequential)); } fn random_value(delete_value: bool) -> ValueType { From a5483226373e1677042d486529a3cc9157e27f03 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:09:50 -0800 Subject: [PATCH 026/328] add aggregator test to continuous single node performance (#11926) and measure conflicts --- .../src/publishing/module_simple.rs | 15 ++++++++++++--- execution/executor-benchmark/src/lib.rs | 15 ++++++++++++++- testsuite/single_node_performance.py | 6 +++--- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/crates/transaction-generator-lib/src/publishing/module_simple.rs b/crates/transaction-generator-lib/src/publishing/module_simple.rs index 469d5e361c61e..57981b3d1b340 100644 --- a/crates/transaction-generator-lib/src/publishing/module_simple.rs +++ b/crates/transaction-generator-lib/src/publishing/module_simple.rs @@ -9,7 +9,10 @@ use aptos_sdk::{ account_address::AccountAddress, ident_str, identifier::Identifier, language_storage::ModuleId, }, - types::transaction::{EntryFunction, TransactionPayload}, + types::{ + serde_helper::bcs_utils::bcs_size_of_byte_array, + transaction::{EntryFunction, TransactionPayload}, + }, }; use move_binary_format::{ file_format::{FunctionHandleIndex, IdentifierIndex, SignatureToken}, @@ -727,10 +730,16 @@ fn mint_new_token(module_id: ModuleId, other: AccountAddress) -> TransactionPayl } fn rand_string(rng: &mut StdRng, len: usize) -> String { - rng.sample_iter(&Alphanumeric) + let res = rng + .sample_iter(&Alphanumeric) .take(len) .map(char::from) - .collect() + .collect(); + assert_eq!( + bcs::serialized_size(&res).unwrap(), + bcs_size_of_byte_array(len) + ); + res } fn make_or_change( diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index c72988bfaae29..b237ff23e0583 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -415,6 +415,8 @@ struct GasMeasurement { pub approx_block_output: f64, pub gas_count: u64, + + pub speculative_abort_count: u64, } impl GasMeasurement { @@ -453,6 +455,8 @@ impl GasMeasurement { .with_label_values(&[block_executor_counters::Mode::PARALLEL]) .get_sample_sum(); + let speculative_abort_count = block_executor_counters::SPECULATIVE_ABORT_COUNT.get(); + Self { gas, effective_block_gas, @@ -460,6 +464,7 @@ impl GasMeasurement { execution_gas, approx_block_output, gas_count, + speculative_abort_count, } } @@ -473,6 +478,7 @@ impl GasMeasurement { execution_gas: end.execution_gas - self.execution_gas, approx_block_output: end.approx_block_output - self.approx_block_output, gas_count: end.gas_count - self.gas_count, + speculative_abort_count: end.speculative_abort_count - self.speculative_abort_count, } } } @@ -602,6 +608,13 @@ impl OverallMeasuring { delta_gas.effective_block_gas, elapsed ); + info!( + "{} speculative aborts: {} aborts/txn ({} aborts over {} txns)", + prefix, + delta_gas.speculative_abort_count as f64 / num_txns, + delta_gas.speculative_abort_count, + num_txns + ); info!("{} ioGPS: {} gas/s", prefix, delta_gas.io_gas / elapsed); info!( "{} executionGPS: {} gas/s", @@ -746,7 +759,7 @@ mod tests { AptosVM::set_processed_transactions_detailed_counters(); NativeExecutor::set_concurrency_level_once(4); test_generic_benchmark::( - Some(TransactionTypeArg::ModifyGlobalResourceAggV2), + Some(TransactionTypeArg::ResourceGroupsGlobalWriteTag1KB), true, ); } diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 55fdb4d6b74b8..4f5670df6a133 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -115,11 +115,11 @@ class RunGroupConfig: # RunGroupConfig(expected_tps=5, key=RunGroupKey("smart-table-picture1-b-with1-k-change"), included_in=Flow(0), waived=True), # RunGroupConfig(expected_tps=10, key=RunGroupKey("smart-table-picture1-b-with1-k-change", module_working_set_size=20), included_in=Flow(0), waived=True), - RunGroupConfig(expected_tps=4050, key=RunGroupKey("modify-global-resource-agg-v2"), included_in=Flow.AGG_V2), + RunGroupConfig(expected_tps=4400, key=RunGroupKey("modify-global-resource-agg-v2"), included_in=Flow.AGG_V2 | LAND_BLOCKING_AND_C), RunGroupConfig(expected_tps=12500, key=RunGroupKey("modify-global-resource-agg-v2", module_working_set_size=50), included_in=Flow.AGG_V2), - RunGroupConfig(expected_tps=4050, key=RunGroupKey("modify-global-flag-agg-v2"), included_in=Flow.AGG_V2), + RunGroupConfig(expected_tps=4900, key=RunGroupKey("modify-global-flag-agg-v2"), included_in=Flow.AGG_V2 | Flow.CONTINUOUS), RunGroupConfig(expected_tps=12500, key=RunGroupKey("modify-global-flag-agg-v2", module_working_set_size=50), included_in=Flow.AGG_V2), - RunGroupConfig(expected_tps=4050, key=RunGroupKey("modify-global-bounded-agg-v2"), included_in=Flow.AGG_V2), + RunGroupConfig(expected_tps=4500, key=RunGroupKey("modify-global-bounded-agg-v2"), included_in=Flow.AGG_V2 | Flow.CONTINUOUS), RunGroupConfig(expected_tps=12500, key=RunGroupKey("modify-global-bounded-agg-v2", module_working_set_size=50), included_in=Flow.AGG_V2), RunGroupConfig(expected_tps=3800, key=RunGroupKey("resource-groups-global-write-tag1-kb"), included_in=LAND_BLOCKING_AND_C | Flow.RESOURCE_GROUPS), From 43c82c1d65587303ff2d254255c0abf27c2a1d89 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:46:25 -0800 Subject: [PATCH 027/328] Enable CONCURRENT_TOKEN_V2 flag (#11932) --- aptos-move/vm-genesis/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index de1792bacbd59..7eeff81dc20dd 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -438,6 +438,7 @@ pub fn default_features() -> Vec { FeatureFlag::SINGLE_SENDER_AUTHENTICATOR, FeatureFlag::SPONSORED_AUTOMATIC_ACCOUNT_V1_CREATION, FeatureFlag::FEE_PAYER_ACCOUNT_OPTIONAL, + FeatureFlag::CONCURRENT_TOKEN_V2, FeatureFlag::LIMIT_MAX_IDENTIFIER_LENGTH, FeatureFlag::OPERATOR_BENEFICIARY_CHANGE, FeatureFlag::BN254_STRUCTURES, From 9a45f0844a82a331f27bc692de8e81ed5c5b8c06 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Wed, 7 Feb 2024 00:38:42 -0800 Subject: [PATCH 028/328] [agg_v2] Enable AIP-43/AIP-47 in genesis (i.e. tests and devnet) (#11912) --- aptos-move/aptos-vm/src/move_vm_ext/write_op_converter.rs | 4 ++-- aptos-move/vm-genesis/src/lib.rs | 2 ++ testsuite/single_node_performance.py | 8 ++++---- 3 files changed, 8 insertions(+), 6 deletions(-) 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 31d3d74d52a3a..033abf23b6515 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 @@ -115,7 +115,7 @@ fn check_size_and_existence_match( if exists { if size.get() == 0 { Err( - PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR).with_message( + PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR).with_message( format!( "Group tag count/size shouldn't be 0 for an existing group: {:?}", state_key @@ -127,7 +127,7 @@ fn check_size_and_existence_match( } } else if size.get() > 0 { Err( - PartialVMError::new(StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR).with_message( + PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR).with_message( format!( "Group tag count/size should be 0 for a new group: {:?}", state_key diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 7eeff81dc20dd..382807e67aaa5 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -438,10 +438,12 @@ pub fn default_features() -> Vec { FeatureFlag::SINGLE_SENDER_AUTHENTICATOR, FeatureFlag::SPONSORED_AUTOMATIC_ACCOUNT_V1_CREATION, FeatureFlag::FEE_PAYER_ACCOUNT_OPTIONAL, + FeatureFlag::AGGREGATOR_V2_DELAYED_FIELDS, FeatureFlag::CONCURRENT_TOKEN_V2, FeatureFlag::LIMIT_MAX_IDENTIFIER_LENGTH, FeatureFlag::OPERATOR_BENEFICIARY_CHANGE, FeatureFlag::BN254_STRUCTURES, + FeatureFlag::RESOURCE_GROUPS_CHARGE_AS_SIZE_SUM, FeatureFlag::COMMISSION_CHANGE_DELEGATION_POOL, FeatureFlag::WEBAUTHN_SIGNATURE, // FeatureFlag::RECONFIGURE_WITH_DKG, //TODO: re-enable once randomness is ready. diff --git a/testsuite/single_node_performance.py b/testsuite/single_node_performance.py index 4f5670df6a133..fdddf959140f0 100755 --- a/testsuite/single_node_performance.py +++ b/testsuite/single_node_performance.py @@ -115,11 +115,11 @@ class RunGroupConfig: # RunGroupConfig(expected_tps=5, key=RunGroupKey("smart-table-picture1-b-with1-k-change"), included_in=Flow(0), waived=True), # RunGroupConfig(expected_tps=10, key=RunGroupKey("smart-table-picture1-b-with1-k-change", module_working_set_size=20), included_in=Flow(0), waived=True), - RunGroupConfig(expected_tps=4400, key=RunGroupKey("modify-global-resource-agg-v2"), included_in=Flow.AGG_V2 | LAND_BLOCKING_AND_C), + RunGroupConfig(expected_tps=19500, key=RunGroupKey("modify-global-resource-agg-v2"), included_in=Flow.AGG_V2 | LAND_BLOCKING_AND_C), RunGroupConfig(expected_tps=12500, key=RunGroupKey("modify-global-resource-agg-v2", module_working_set_size=50), included_in=Flow.AGG_V2), - RunGroupConfig(expected_tps=4900, key=RunGroupKey("modify-global-flag-agg-v2"), included_in=Flow.AGG_V2 | Flow.CONTINUOUS), + RunGroupConfig(expected_tps=7650, key=RunGroupKey("modify-global-flag-agg-v2"), included_in=Flow.AGG_V2 | Flow.CONTINUOUS), RunGroupConfig(expected_tps=12500, key=RunGroupKey("modify-global-flag-agg-v2", module_working_set_size=50), included_in=Flow.AGG_V2), - RunGroupConfig(expected_tps=4500, key=RunGroupKey("modify-global-bounded-agg-v2"), included_in=Flow.AGG_V2 | Flow.CONTINUOUS), + RunGroupConfig(expected_tps=13000, key=RunGroupKey("modify-global-bounded-agg-v2"), included_in=Flow.AGG_V2 | Flow.CONTINUOUS), RunGroupConfig(expected_tps=12500, key=RunGroupKey("modify-global-bounded-agg-v2", module_working_set_size=50), included_in=Flow.AGG_V2), RunGroupConfig(expected_tps=3800, key=RunGroupKey("resource-groups-global-write-tag1-kb"), included_in=LAND_BLOCKING_AND_C | Flow.RESOURCE_GROUPS), @@ -144,7 +144,7 @@ class RunGroupConfig: RunGroupConfig(expected_tps=23500, key=RunGroupKey("no-op5-signers"), included_in=Flow.CONTINUOUS), - RunGroupConfig(expected_tps=1610, key=RunGroupKey("token-v2-ambassador-mint"), included_in=LAND_BLOCKING_AND_C | Flow.REPRESENTATIVE), + RunGroupConfig(expected_tps=6800, key=RunGroupKey("token-v2-ambassador-mint"), included_in=LAND_BLOCKING_AND_C | Flow.REPRESENTATIVE), RunGroupConfig(expected_tps=6800, key=RunGroupKey("token-v2-ambassador-mint", module_working_set_size=20), included_in=LAND_BLOCKING_AND_C | Flow.REPRESENTATIVE), RunGroupConfig(expected_tps=50000, key=RunGroupKey("coin_transfer_connected_components", executor_type="sharded", sharding_traffic_flags="--connected-tx-grps 5000", transaction_type_override=""), included_in=Flow.REPRESENTATIVE), From 4bc003314c63aa757ed5ba704e54c4308714aced Mon Sep 17 00:00:00 2001 From: Satya Vusirikala Date: Thu, 8 Feb 2024 00:22:08 +0530 Subject: [PATCH 029/328] Update indexer version to latest version (#11937) * Update indexer version * Fixing errors --- Cargo.lock | 24 ++++++++++++------- crates/aptos/Cargo.toml | 4 ++-- .../src/node/local_testnet/processors.rs | 6 +++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ee8635c683a0..4bd0898ea09cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2094,7 +2094,7 @@ dependencies = [ "aptos-indexer-grpc-server-framework", "aptos-indexer-grpc-utils", "aptos-metrics-core", - "aptos-moving-average", + "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "aptos-protos 1.1.2", "aptos-runtimes", "async-trait", @@ -2167,7 +2167,7 @@ dependencies = [ "aptos-indexer-grpc-utils", "aptos-logger", "aptos-metrics-core", - "aptos-moving-average", + "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "aptos-protos 1.1.2", "aptos-runtimes", "async-trait", @@ -2196,7 +2196,7 @@ dependencies = [ "aptos-indexer-grpc-server-framework", "aptos-indexer-grpc-utils", "aptos-metrics-core", - "aptos-moving-average", + "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "aptos-protos 1.1.2", "aptos-runtimes", "async-trait", @@ -2236,7 +2236,7 @@ dependencies = [ "aptos-mempool", "aptos-mempool-notifications", "aptos-metrics-core", - "aptos-moving-average", + "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "aptos-proptest-helpers", "aptos-protos 1.1.2", "aptos-runtimes", @@ -2359,7 +2359,7 @@ dependencies = [ "aptos-mempool", "aptos-mempool-notifications", "aptos-metrics-core", - "aptos-moving-average", + "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", "aptos-proptest-helpers", "aptos-protos 1.1.2", "aptos-rocksdb-options", @@ -2814,6 +2814,14 @@ dependencies = [ "chrono", ] +[[package]] +name = "aptos-moving-average" +version = "0.1.0" +source = "git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=68424a2b721cbd4a6b8c1e7c951f5d4f665473d3#68424a2b721cbd4a6b8c1e7c951f5d4f665473d3" +dependencies = [ + "chrono", +] + [[package]] name = "aptos-mvhashmap" version = "0.1.0" @@ -12951,10 +12959,10 @@ dependencies = [ [[package]] name = "processor" version = "1.0.0" -source = "git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf#4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf" +source = "git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=68424a2b721cbd4a6b8c1e7c951f5d4f665473d3#68424a2b721cbd4a6b8c1e7c951f5d4f665473d3" dependencies = [ "anyhow", - "aptos-moving-average", + "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=68424a2b721cbd4a6b8c1e7c951f5d4f665473d3)", "aptos-protos 1.1.2 (git+https://github.com/aptos-labs/aptos-core.git?rev=af0dcea7144225a709e4f595e58f8026b99e901c)", "async-trait", "base64 0.13.1", @@ -14534,7 +14542,7 @@ dependencies = [ [[package]] name = "server-framework" version = "1.0.0" -source = "git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf#4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf" +source = "git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=68424a2b721cbd4a6b8c1e7c951f5d4f665473d3#68424a2b721cbd4a6b8c1e7c951f5d4f665473d3" dependencies = [ "anyhow", "async-trait", diff --git a/crates/aptos/Cargo.toml b/crates/aptos/Cargo.toml index 24942e39c0d7c..064755118698f 100644 --- a/crates/aptos/Cargo.toml +++ b/crates/aptos/Cargo.toml @@ -79,7 +79,7 @@ move-unit-test = { workspace = true, features = [ "debugging" ] } move-vm-runtime = { workspace = true, features = [ "testing" ] } once_cell = { workspace = true } poem = { workspace = true } -processor = { git = "https://github.com/aptos-labs/aptos-indexer-processors.git", rev = "4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf" } +processor = { git = "https://github.com/aptos-labs/aptos-indexer-processors.git", rev = "68424a2b721cbd4a6b8c1e7c951f5d4f665473d3" } rand = { workspace = true } regex = { workspace = true } reqwest = { workspace = true } @@ -87,7 +87,7 @@ self_update = { version = "0.38.0", features = ["archive-zip", "compression-zip- serde = { workspace = true } serde_json = { workspace = true } serde_yaml = { workspace = true } -server-framework = { git = "https://github.com/aptos-labs/aptos-indexer-processors.git", rev = "4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf" } +server-framework = { git = "https://github.com/aptos-labs/aptos-indexer-processors.git", rev = "68424a2b721cbd4a6b8c1e7c951f5d4f665473d3" } tempfile = { workspace = true } termcolor = { workspace = true } thiserror = { workspace = true } diff --git a/crates/aptos/src/node/local_testnet/processors.rs b/crates/aptos/src/node/local_testnet/processors.rs index 7359514de1f88..0b94c9d1c6b13 100644 --- a/crates/aptos/src/node/local_testnet/processors.rs +++ b/crates/aptos/src/node/local_testnet/processors.rs @@ -82,6 +82,12 @@ impl ProcessorManager { }, ProcessorName::TokenV2Processor => ProcessorConfig::TokenV2Processor, ProcessorName::UserTransactionProcessor => ProcessorConfig::UserTransactionProcessor, + ProcessorName::MonitoringProcessor => { + bail!("Monitoring processor is not supported in the local testnet") + }, + ProcessorName::ObjectsProcessor => { + bail!("Objects processor is not supported in the local testnet") + }, }; let config = IndexerGrpcProcessorConfig { processor_config, From 1bdcfa67f9461bd28d62392664f0736014f037b0 Mon Sep 17 00:00:00 2001 From: Bo Wu Date: Tue, 6 Feb 2024 13:09:24 -0800 Subject: [PATCH 030/328] expire a range of transactions --- testsuite/replay_verify.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/replay_verify.py b/testsuite/replay_verify.py index ba1e3424998a3..9fc0b319ea079 100755 --- a/testsuite/replay_verify.py +++ b/testsuite/replay_verify.py @@ -51,7 +51,6 @@ ] MAINNET_RANGES = [ - [0, 45_000_000], [45_000_001, 100_000_000], [100_000_001, 116_000_000], [116_000_001, 155_000_000], @@ -67,7 +66,8 @@ [295_000_001, 321_000_000], [321_000_001, 331_000_000], [331_000_001, 354_000_000], - [354_000_001, sys.maxsize], + [354_000_001, 400_000_000], + [400_000_001, sys.maxsize], ] From a3477908210e50f2ea20b2a6f45f1d3401ea7fbb Mon Sep 17 00:00:00 2001 From: Justin Chang <37165464+just-in-chang@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:21:27 -0800 Subject: [PATCH 031/328] [NFT Metadata Crawler] Optimize code + loosen do_not_parse constraint (#11930) * Remove clones, update do_not_parse logic * Update log * lint * llint --- .../nft-metadata-crawler-parser/src/config.rs | 76 ++++++++++-------- .../nft-metadata-crawler-parser/src/lib.rs | 2 +- .../src/models/nft_metadata_crawler_uris.rs | 4 +- .../models/nft_metadata_crawler_uris_query.rs | 22 +++--- .../src/utils/database.rs | 2 +- .../src/utils/gcs.rs | 12 +-- .../src/utils/image_optimizer.rs | 4 +- .../src/utils/json_parser.rs | 4 +- .../src/utils/uri_parser.rs | 51 ++++-------- .../nft-metadata-crawler-parser/src/worker.rs | 79 ++++++++----------- 10 files changed, 119 insertions(+), 137 deletions(-) diff --git a/ecosystem/nft-metadata-crawler-parser/src/config.rs b/ecosystem/nft-metadata-crawler-parser/src/config.rs index 75a33c479a478..3c7e67b3062ba 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/config.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/config.rs @@ -50,14 +50,17 @@ impl RunnableConfig for ParserConfig { ); info!("[NFT Metadata Crawler] Connecting to database"); - let pool = establish_connection_pool(self.database_url.clone()); + let pool = establish_connection_pool(&self.database_url); info!("[NFT Metadata Crawler] Database connection successful"); info!("[NFT Metadata Crawler] Running migrations"); run_migrations(&pool); info!("[NFT Metadata Crawler] Finished migrations"); - if let Some(google_application_credentials) = self.google_application_credentials.clone() { + if let Some(google_application_credentials) = &self.google_application_credentials { + info!( + "[NFT Metadata Crawler] Google Application Credentials path found, setting env var" + ); std::env::set_var( "GOOGLE_APPLICATION_CREDENTIALS", google_application_credentials, @@ -78,9 +81,9 @@ impl RunnableConfig for ParserConfig { // Create request context let context = Arc::new(ServerContext { - parser_config: self.clone(), + parser_config: Arc::new(self.clone()), pool, - gcs_client: GCSClient::new(gcs_config), + gcs_client: Arc::new(GCSClient::new(gcs_config)), }); // Create web server @@ -103,17 +106,17 @@ impl RunnableConfig for ParserConfig { /// Struct to hold context required for parsing #[derive(Clone)] pub struct ServerContext { - pub parser_config: ParserConfig, + pub parser_config: Arc, pub pool: Pool>, - pub gcs_client: GCSClient, + pub gcs_client: Arc, } /// Repeatedly pulls workers from Channel and perform parsing operations async fn spawn_parser( - parser_config: ParserConfig, + parser_config: Arc, msg_base64: Bytes, pool: Pool>, - gcs_client: GCSClient, + gcs_client: Arc, ) { PARSER_INVOCATIONS_COUNT.inc(); let pubsub_message = String::from_utf8(msg_base64.to_vec()).unwrap_or_else(|e| { @@ -132,7 +135,10 @@ async fn spawn_parser( // Skips message if it does not have 5 commas (likely malformed URI) if pubsub_message.matches(',').count() != 5 { // Sends ack to PubSub only if ack_parsed_uris flag is true - info!("[NFT Metadata Crawler] More than 5 commas, skipping message"); + info!( + pubsub_message = pubsub_message, + "[NFT Metadata Crawler] Number of commans != 5, skipping message" + ); SKIP_URI_COUNT.with_label_values(&["invalid"]).inc(); return; } @@ -164,33 +170,35 @@ async fn spawn_parser( check_or_update_chain_id(&mut conn, grpc_chain_id as i64).expect("Chain id should match"); // Spawn worker + let last_transaction_version = parts[2].to_string().parse().unwrap_or_else(|e| { + error!( + error = ?e, + "[NFT Metadata Crawler] Failed to parse last transaction version from PubSub message" + ); + panic!(); + }); + let last_transaction_timestamp = + chrono::NaiveDateTime::parse_from_str(parts[3], "%Y-%m-%d %H:%M:%S %Z").unwrap_or( + chrono::NaiveDateTime::parse_from_str(parts[3], "%Y-%m-%d %H:%M:%S%.f %Z") + .unwrap_or_else(|e| { + error!( + error = ?e, + "[NFT Metadata Crawler] Failed to parse timestamp from PubSub message" + ); + panic!(); + }), + ); let mut worker = Worker::new( - parser_config.clone(), - conn, + parser_config.clone(), + conn, gcs_client.clone(), - pubsub_message.clone(), - parts[0].to_string(), - parts[1].to_string(), - parts[2].to_string().parse().unwrap_or_else(|e|{ - error!( - error = ?e, - "[NFT Metadata Crawler] Failed to parse last transaction version from PubSub message" - ); - panic!(); - }), - chrono::NaiveDateTime::parse_from_str(parts[3], "%Y-%m-%d %H:%M:%S %Z").unwrap_or( - chrono::NaiveDateTime::parse_from_str(parts[3], "%Y-%m-%d %H:%M:%S%.f %Z").unwrap_or_else( - |e| { - error!( - error = ?e, - "[NFT Metadata Crawler] Failed to parse timestamp from PubSub message" - ); - panic!(); - }, - ), - ), - parts[5].parse::().unwrap_or(false), - ); + &pubsub_message, + parts[0], + parts[1], + last_transaction_version, + last_transaction_timestamp, + parts[5].parse::().unwrap_or(false), + ); info!( pubsub_message = pubsub_message, diff --git a/ecosystem/nft-metadata-crawler-parser/src/lib.rs b/ecosystem/nft-metadata-crawler-parser/src/lib.rs index a3372bb673229..dd09816431ce0 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/lib.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/lib.rs @@ -12,7 +12,7 @@ use std::time::Duration; use utils::constants::MAX_HEAD_REQUEST_RETRY_SECONDS; /// HEAD request to get MIME type and size of content -pub async fn get_uri_metadata(url: String) -> anyhow::Result<(String, u32)> { +pub async fn get_uri_metadata(url: &str) -> anyhow::Result<(String, u32)> { let client = Client::builder() .timeout(Duration::from_secs(MAX_HEAD_REQUEST_RETRY_SECONDS)) .build() diff --git a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs index 898e4f3a69eb8..a630b53d150ec 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs @@ -26,9 +26,9 @@ pub struct NFTMetadataCrawlerURIs { } impl NFTMetadataCrawlerURIs { - pub fn new(asset_uri: String) -> Self { + pub fn new(asset_uri: &str) -> Self { Self { - asset_uri, + asset_uri: asset_uri.to_string(), raw_image_uri: None, raw_animation_uri: None, cdn_json_uri: None, diff --git a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs index 11bb7b0ab99f2..0ea8a1a250b9a 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs @@ -31,12 +31,12 @@ pub struct NFTMetadataCrawlerURIsQuery { impl NFTMetadataCrawlerURIsQuery { pub fn get_by_asset_uri( - asset_uri: String, + asset_uri: &str, conn: &mut PooledConnection>, ) -> Option { let mut op = || { parsed_asset_uris::table - .find(asset_uri.clone()) + .find(asset_uri) .first::(conn) .optional() .map_err(Into::into) @@ -54,14 +54,15 @@ impl NFTMetadataCrawlerURIsQuery { } pub fn get_by_raw_image_uri( - asset_uri: String, - raw_image_uri: String, + asset_uri: &str, + raw_image_uri: &str, conn: &mut PooledConnection>, ) -> Option { let mut op = || { parsed_asset_uris::table - .filter(parsed_asset_uris::raw_image_uri.eq(raw_image_uri.clone())) - .filter(parsed_asset_uris::asset_uri.ne(asset_uri.clone())) + .filter(parsed_asset_uris::raw_image_uri.eq(raw_image_uri)) + .filter(parsed_asset_uris::asset_uri.ne(asset_uri)) + .filter(parsed_asset_uris::cdn_image_uri.is_not_null()) .first::(conn) .optional() .map_err(Into::into) @@ -79,14 +80,15 @@ impl NFTMetadataCrawlerURIsQuery { } pub fn get_by_raw_animation_uri( - asset_uri: String, - raw_animation_uri: String, + asset_uri: &str, + raw_animation_uri: &str, conn: &mut PooledConnection>, ) -> Option { let mut op = || { parsed_asset_uris::table - .filter(parsed_asset_uris::raw_animation_uri.eq(raw_animation_uri.clone())) - .filter(parsed_asset_uris::asset_uri.ne(asset_uri.clone())) + .filter(parsed_asset_uris::raw_animation_uri.eq(raw_animation_uri)) + .filter(parsed_asset_uris::asset_uri.ne(asset_uri)) + .filter(parsed_asset_uris::cdn_animation_uri.is_not_null()) .first::(conn) .optional() .map_err(Into::into) diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs index 57fe8ff2cbcb8..84214131f6c11 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs @@ -16,7 +16,7 @@ use tracing::{debug, info}; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!(); /// Establishes a connection pool to Postgres -pub fn establish_connection_pool(database_url: String) -> Pool> { +pub fn establish_connection_pool(database_url: &str) -> Pool> { let manager = ConnectionManager::::new(database_url); Pool::builder() .build(manager) diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs index 2c605e49c572f..e69b40beb0633 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs @@ -20,8 +20,8 @@ use std::time::Duration; /// Writes JSON Value to GCS pub async fn write_json_to_gcs( - bucket: String, - id: String, + bucket: &str, + id: &str, json: &Value, client: &Client, ) -> anyhow::Result { @@ -41,7 +41,7 @@ pub async fn write_json_to_gcs( Ok(client .upload_object( &UploadObjectRequest { - bucket: bucket.clone(), + bucket: bucket.to_string(), ..Default::default() }, json_bytes.clone(), @@ -73,8 +73,8 @@ pub async fn write_json_to_gcs( /// Infers file type and writes image to GCS pub async fn write_image_to_gcs( img_format: ImageFormat, - bucket: String, - id: String, + bucket: &str, + id: &str, buffer: Vec, client: &Client, ) -> anyhow::Result { @@ -100,7 +100,7 @@ pub async fn write_image_to_gcs( Ok(client .upload_object( &UploadObjectRequest { - bucket: bucket.clone(), + bucket: bucket.to_string(), ..Default::default() }, buffer.clone(), diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/image_optimizer.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/image_optimizer.rs index 9d22bdf5a961a..e9e48fd2b6b8e 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/image_optimizer.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/image_optimizer.rs @@ -31,13 +31,13 @@ impl ImageOptimizer { /// Resizes and optimizes image from input URI. /// Returns new image as a byte array and its format. pub async fn optimize( - uri: String, + uri: &str, max_file_size_bytes: u32, image_quality: u8, max_image_dimensions: u32, ) -> anyhow::Result<(Vec, ImageFormat)> { OPTIMIZE_IMAGE_INVOCATION_COUNT.inc(); - let (_, size) = get_uri_metadata(uri.clone()).await?; + let (_, size) = get_uri_metadata(uri).await?; if size > max_file_size_bytes { FAILED_TO_OPTIMIZE_IMAGE_COUNT .with_label_values(&["Image file too large"]) diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/json_parser.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/json_parser.rs index fa5952fc74cc4..234db7a0aa4de 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/json_parser.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/json_parser.rs @@ -28,8 +28,8 @@ impl JSONParser { max_file_size_bytes: u32, ) -> anyhow::Result<(Option, Option, Value)> { PARSE_JSON_INVOCATION_COUNT.inc(); - let (mime, size) = get_uri_metadata(uri.clone()).await?; - if ImageFormat::from_mime_type(mime.clone()).is_some() { + let (mime, size) = get_uri_metadata(&uri).await?; + if ImageFormat::from_mime_type(&mime).is_some() { FAILED_TO_PARSE_JSON_COUNT .with_label_values(&["found image instead"]) .inc(); diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/uri_parser.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/uri_parser.rs index 81d5431fd8c0a..f4e0c84da829d 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/uri_parser.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/uri_parser.rs @@ -13,20 +13,20 @@ impl URIParser { /// Attempts to parse IPFS URI to use dedicated gateway. /// Returns the original URI if parsing fails. pub fn parse( - ipfs_prefix: String, - uri: String, - ipfs_auth_key: Option, + ipfs_prefix: &str, + uri: &str, + ipfs_auth_key: Option<&str>, ) -> anyhow::Result { PARSE_URI_INVOCATION_COUNT.inc(); if uri.contains("arweave.net") { PARSE_URI_TYPE_COUNT.with_label_values(&["arweave"]).inc(); - return Ok(uri); + return Ok(uri.to_string()); } let modified_uri = if uri.starts_with("ipfs://") { uri.replace("ipfs://", "https://ipfs.com/ipfs/") } else { - uri + uri.to_string() }; let ipfs_auth_param = if ipfs_auth_key.is_some() { @@ -57,7 +57,7 @@ impl URIParser { /// Formats a capture group into a URI. fn format_capture( captures: Captures<'_>, - ipfs_prefix: String, + ipfs_prefix: &str, ipfs_auth_param: Option, ) -> anyhow::Result { let cid = captures["cid"].to_string(); @@ -86,12 +86,7 @@ mod tests { #[test] fn test_parse_ipfs_uri() { let test_ipfs_uri = format!("ipfs://{}/{}", CID, PATH); - let parsed_uri = URIParser::parse( - IPFS_PREFIX.to_string(), - test_ipfs_uri, - Some(IPFS_AUTH.to_string()), - ) - .unwrap(); + let parsed_uri = URIParser::parse(IPFS_PREFIX, &test_ipfs_uri, Some(IPFS_AUTH)).unwrap(); assert_eq!( parsed_uri, format!("{IPFS_PREFIX}{CID}/{PATH}?{IPFS_AUTH_KEY}={IPFS_AUTH}") @@ -99,25 +94,20 @@ mod tests { // Path is optional for IPFS URIs let test_ipfs_uri_no_path = format!("ipfs://{}/{}", CID, ""); - let parsed_uri = - URIParser::parse(IPFS_PREFIX.to_string(), test_ipfs_uri_no_path, None).unwrap(); + let parsed_uri = URIParser::parse(IPFS_PREFIX, &test_ipfs_uri_no_path, None).unwrap(); assert_eq!(parsed_uri, format!("{}{}/{}", IPFS_PREFIX, CID, "")); // IPFS URIs must contain a CID, expect error here let test_ipfs_uri_no_cid = format!("ipfs://{}/{}", "", PATH); - let parsed_uri = URIParser::parse(IPFS_PREFIX.to_string(), test_ipfs_uri_no_cid, None); + let parsed_uri = URIParser::parse(IPFS_PREFIX, &test_ipfs_uri_no_cid, None); assert!(parsed_uri.is_err()); } #[test] fn test_parse_public_gateway_uri() { let test_public_gateway_uri = format!("https://ipfs.io/ipfs/{}/{}", CID, PATH); - let parsed_uri = URIParser::parse( - IPFS_PREFIX.to_string(), - test_public_gateway_uri, - Some(IPFS_AUTH.to_string()), - ) - .unwrap(); + let parsed_uri = + URIParser::parse(IPFS_PREFIX, &test_public_gateway_uri, Some(IPFS_AUTH)).unwrap(); assert_eq!( parsed_uri, format!("{IPFS_PREFIX}{CID}/{PATH}?{IPFS_AUTH_KEY}={IPFS_AUTH}") @@ -125,27 +115,18 @@ mod tests { // Path is optional for public gateway URIs let test_public_gateway_uri_no_path = format!("https://ipfs.io/ipfs/{}/{}", CID, ""); - let parsed_uri = URIParser::parse( - IPFS_PREFIX.to_string(), - test_public_gateway_uri_no_path, - None, - ) - .unwrap(); + let parsed_uri = + URIParser::parse(IPFS_PREFIX, &test_public_gateway_uri_no_path, None).unwrap(); assert_eq!(parsed_uri, format!("{}{}/{}", IPFS_PREFIX, CID, "")); // Some submitted URIs are in the redirected format let test_ipfs_redirect = format!("https://{}.ipfs.re.dir.io/{}", CID, PATH); - let parsed_uri = - URIParser::parse(IPFS_PREFIX.to_string(), test_ipfs_redirect, None).unwrap(); + let parsed_uri = URIParser::parse(IPFS_PREFIX, &test_ipfs_redirect, None).unwrap(); assert_eq!(parsed_uri, format!("{IPFS_PREFIX}{CID}/{PATH}")); // Public gateway URIs must contain a CID, expect error here let test_public_gateway_uri_no_cid = format!("https://ipfs.io/ipfs/{}/{}", "", PATH); - let parsed_uri = URIParser::parse( - IPFS_PREFIX.to_string(), - test_public_gateway_uri_no_cid, - None, - ); + let parsed_uri = URIParser::parse(IPFS_PREFIX, &test_public_gateway_uri_no_cid, None); assert!(parsed_uri.is_err()); } @@ -153,7 +134,7 @@ mod tests { fn test_parse_non_ipfs_uri_fail() { // Expects an error if parsing a non-IPFS URI let test_non_ipfs_uri = "https://tesetnotipfsuri.com/notipfspath.json".to_string(); - let parsed_uri = URIParser::parse(IPFS_PREFIX.to_string(), test_non_ipfs_uri, None); + let parsed_uri = URIParser::parse(IPFS_PREFIX, &test_non_ipfs_uri, None); assert!(parsed_uri.is_err()); } } diff --git a/ecosystem/nft-metadata-crawler-parser/src/worker.rs b/ecosystem/nft-metadata-crawler-parser/src/worker.rs index d2e4eb63d47dd..3899f55de62a4 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/worker.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/worker.rs @@ -30,14 +30,15 @@ use diesel::{ use google_cloud_storage::client::Client as GCSClient; use image::ImageFormat; use serde_json::Value; +use std::sync::Arc; use tracing::{error, info, warn}; use url::Url; /// Stuct that represents a parser for a single entry from queue pub struct Worker { - config: ParserConfig, + config: Arc, conn: PooledConnection>, - gcs_client: GCSClient, + gcs_client: Arc, pubsub_message: String, model: NFTMetadataCrawlerURIs, asset_data_id: String, @@ -49,12 +50,12 @@ pub struct Worker { impl Worker { pub fn new( - config: ParserConfig, + config: Arc, conn: PooledConnection>, - gcs_client: GCSClient, - pubsub_message: String, - asset_data_id: String, - asset_uri: String, + gcs_client: Arc, + pubsub_message: &str, + asset_data_id: &str, + asset_uri: &str, last_transaction_version: i32, last_transaction_timestamp: chrono::NaiveDateTime, force: bool, @@ -63,10 +64,10 @@ impl Worker { config, conn, gcs_client, - pubsub_message, - model: NFTMetadataCrawlerURIs::new(asset_uri.clone()), - asset_data_id, - asset_uri, + pubsub_message: pubsub_message.to_string(), + model: NFTMetadataCrawlerURIs::new(asset_uri), + asset_data_id: asset_data_id.to_string(), + asset_uri: asset_uri.to_string(), last_transaction_version, last_transaction_timestamp, force, @@ -80,7 +81,7 @@ impl Worker { // Deduplicate asset_uri // Exit if not force or if asset_uri has already been parsed let prev_model = - NFTMetadataCrawlerURIsQuery::get_by_asset_uri(self.asset_uri.clone(), &mut self.conn); + NFTMetadataCrawlerURIsQuery::get_by_asset_uri(&self.asset_uri, &mut self.conn); if let Some(pm) = prev_model { DUPLICATE_ASSET_URI_COUNT.inc(); if !self.force && pm.do_not_parse { @@ -92,7 +93,7 @@ impl Worker { } // Skip if asset_uri contains any of the uris in URI_SKIP_LIST - if let Some(blacklist) = self.config.uri_blacklist.clone() { + if let Some(blacklist) = &self.config.uri_blacklist { if blacklist.iter().any(|uri| self.asset_uri.contains(uri)) { self.log_info("Found match in URI skip list, skipping parse"); SKIP_URI_COUNT.with_label_values(&["blacklist"]).inc(); @@ -115,9 +116,9 @@ impl Worker { // Parse asset_uri self.log_info("Parsing asset_uri"); let json_uri = URIParser::parse( - self.config.ipfs_prefix.clone(), - self.model.get_asset_uri(), - self.config.ipfs_auth_key.clone(), + &self.config.ipfs_prefix, + &self.model.get_asset_uri(), + self.config.ipfs_auth_key.as_deref(), ) .unwrap_or_else(|_| { self.log_warn("Failed to parse asset_uri", None); @@ -148,8 +149,8 @@ impl Worker { if json != Value::Null { self.log_info("Writing JSON to GCS"); let cdn_json_uri_result = write_json_to_gcs( - self.config.bucket.clone(), - self.asset_data_id.clone(), + &self.config.bucket, + &self.asset_data_id, &json, &self.gcs_client, ) @@ -182,8 +183,8 @@ impl Worker { && (self.model.get_cdn_image_uri().is_some() || self.model.get_raw_image_uri().map_or(true, |uri_option| { match NFTMetadataCrawlerURIsQuery::get_by_raw_image_uri( - self.asset_uri.clone(), - uri_option, + &self.asset_uri, + &uri_option, &mut self.conn, ) { Some(uris) => { @@ -203,9 +204,9 @@ impl Worker { .get_raw_image_uri() .unwrap_or(self.model.get_asset_uri()); let img_uri = URIParser::parse( - self.config.ipfs_prefix.clone(), - raw_image_uri.clone(), - self.config.ipfs_auth_key.clone(), + &self.config.ipfs_prefix, + &raw_image_uri, + self.config.ipfs_auth_key.as_deref(), ) .unwrap_or_else(|_| { self.log_warn("Failed to parse raw_image_uri", None); @@ -219,7 +220,7 @@ impl Worker { .with_label_values(&["image"]) .inc(); let (image, format) = ImageOptimizer::optimize( - img_uri, + &img_uri, self.config .max_file_size_bytes .unwrap_or(DEFAULT_MAX_FILE_SIZE_BYTES), @@ -236,23 +237,13 @@ impl Worker { (vec![], ImageFormat::Png) }); - if image.is_empty() { - self.log_info("Image is empty, skipping parse"); - self.model.set_do_not_parse(true); - SKIP_URI_COUNT.with_label_values(&["empty"]).inc(); - if let Err(e) = upsert_uris(&mut self.conn, &self.model) { - self.log_error("Commit to Postgres failed", &e); - } - return Ok(()); - } - // Save resized and optimized image to GCS if !image.is_empty() { self.log_info("Writing image to GCS"); let cdn_image_uri_result = write_image_to_gcs( format, - self.config.bucket.clone(), - self.asset_data_id.clone(), + &self.config.bucket, + &self.asset_data_id, image, &self.gcs_client, ) @@ -285,8 +276,8 @@ impl Worker { || !self.force && raw_animation_uri_option.clone().map_or(true, |uri| { match NFTMetadataCrawlerURIsQuery::get_by_raw_animation_uri( - self.asset_uri.clone(), - uri, + &self.asset_uri, + &uri, &mut self.conn, ) { Some(uris) => { @@ -306,9 +297,9 @@ impl Worker { if let Some(raw_animation_uri) = raw_animation_uri_option { self.log_info("Starting animation optimization"); let animation_uri = URIParser::parse( - self.config.ipfs_prefix.clone(), - raw_animation_uri.clone(), - self.config.ipfs_auth_key.clone(), + &self.config.ipfs_prefix, + &raw_animation_uri, + self.config.ipfs_auth_key.as_deref(), ) .unwrap_or_else(|_| { self.log_warn("Failed to parse raw_animation_uri", None); @@ -322,7 +313,7 @@ impl Worker { .with_label_values(&["animation"]) .inc(); let (animation, format) = ImageOptimizer::optimize( - animation_uri, + &animation_uri, self.config .max_file_size_bytes .unwrap_or(DEFAULT_MAX_FILE_SIZE_BYTES), @@ -344,8 +335,8 @@ impl Worker { self.log_info("Writing animation to GCS"); let cdn_animation_uri_result = write_image_to_gcs( format, - self.config.bucket.clone(), - self.asset_data_id.clone(), + &self.config.bucket, + &self.asset_data_id, animation, &self.gcs_client, ) From eb221f5e843d4270a778f19be3cfaf170a35e8a7 Mon Sep 17 00:00:00 2001 From: alnoki <43892045+alnoki@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:31:34 -0800 Subject: [PATCH 032/328] [Framework] Fix typo in state storage module (#11507) --- aptos-move/framework/aptos-framework/doc/state_storage.md | 2 +- aptos-move/framework/aptos-framework/sources/state_storage.move | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aptos-move/framework/aptos-framework/doc/state_storage.md b/aptos-move/framework/aptos-framework/doc/state_storage.md index f7a73a4b7083d..b12e25959ca59 100644 --- a/aptos-move/framework/aptos-framework/doc/state_storage.md +++ b/aptos-move/framework/aptos-framework/doc/state_storage.md @@ -67,7 +67,7 @@ ## Resource `StateStorageUsage` -This is updated at the beginning of each opoch, reflecting the storage +This is updated at the beginning of each epoch, reflecting the storage usage after the last txn of the previous epoch is committed. diff --git a/aptos-move/framework/aptos-framework/sources/state_storage.move b/aptos-move/framework/aptos-framework/sources/state_storage.move index 216e1fe305af5..af9d749615ec6 100644 --- a/aptos-move/framework/aptos-framework/sources/state_storage.move +++ b/aptos-move/framework/aptos-framework/sources/state_storage.move @@ -14,7 +14,7 @@ module aptos_framework::state_storage { bytes: u64, } - /// This is updated at the beginning of each opoch, reflecting the storage + /// This is updated at the beginning of each epoch, reflecting the storage /// usage after the last txn of the previous epoch is committed. struct StateStorageUsage has key, store { epoch: u64, From 6020c61871b0925fae4ecd0a03e56c93fdc77f28 Mon Sep 17 00:00:00 2001 From: alnoki <43892045+alnoki@users.noreply.github.com> Date: Wed, 7 Feb 2024 12:44:43 -0800 Subject: [PATCH 033/328] Add GCD algorithm to math library (#11919) * Add GCD algorithm to math library * Optimize algorithm, update for GCD(a, 0) = a * Incorporate algorithm, test in u128 library * Rebuild DocGen --- .../framework/aptos-stdlib/doc/math128.md | 32 +++++++++++++++++++ .../framework/aptos-stdlib/doc/math64.md | 32 +++++++++++++++++++ .../aptos-stdlib/sources/math128.move | 32 +++++++++++++++++++ .../aptos-stdlib/sources/math64.move | 31 ++++++++++++++++++ 4 files changed, 127 insertions(+) diff --git a/aptos-move/framework/aptos-stdlib/doc/math128.md b/aptos-move/framework/aptos-stdlib/doc/math128.md index ffbb7b483c8de..0160568fc30b7 100644 --- a/aptos-move/framework/aptos-stdlib/doc/math128.md +++ b/aptos-move/framework/aptos-stdlib/doc/math128.md @@ -10,6 +10,7 @@ Standard math utilities missing in the Move Language. - [Function `max`](#0x1_math128_max) - [Function `min`](#0x1_math128_min) - [Function `average`](#0x1_math128_average) +- [Function `gcd`](#0x1_math128_gcd) - [Function `mul_div`](#0x1_math128_mul_div) - [Function `clamp`](#0x1_math128_clamp) - [Function `pow`](#0x1_math128_pow) @@ -127,6 +128,37 @@ Return the average of two. + + + + +## Function `gcd` + +Return greatest common divisor of a & b, via the Euclidean algorithm. + + +

public fun gcd(a: u128, b: u128): u128
+
+ + + +
+Implementation + + +
public inline fun gcd(a: u128, b: u128): u128 {
+    let (large, small) = if (a > b) (a, b) else (b, a);
+    while (small != 0) {
+        let tmp = small;
+        small = large % small;
+        large = tmp;
+    };
+    large
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-stdlib/doc/math64.md b/aptos-move/framework/aptos-stdlib/doc/math64.md index 6e51c4f82c409..b40a67a25860f 100644 --- a/aptos-move/framework/aptos-stdlib/doc/math64.md +++ b/aptos-move/framework/aptos-stdlib/doc/math64.md @@ -10,6 +10,7 @@ Standard math utilities missing in the Move Language. - [Function `max`](#0x1_math64_max) - [Function `min`](#0x1_math64_min) - [Function `average`](#0x1_math64_average) +- [Function `gcd`](#0x1_math64_gcd) - [Function `mul_div`](#0x1_math64_mul_div) - [Function `clamp`](#0x1_math64_clamp) - [Function `pow`](#0x1_math64_pow) @@ -125,6 +126,37 @@ Return the average of two. + + + + +## Function `gcd` + +Return greatest common divisor of a & b, via the Euclidean algorithm. + + +
public fun gcd(a: u64, b: u64): u64
+
+ + + +
+Implementation + + +
public inline fun gcd(a: u64, b: u64): u64 {
+    let (large, small) = if (a > b) (a, b) else (b, a);
+    while (small != 0) {
+        let tmp = small;
+        small = large % small;
+        large = tmp;
+    };
+    large
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-stdlib/sources/math128.move b/aptos-move/framework/aptos-stdlib/sources/math128.move index 9e72ceeb9694b..6528153699fb4 100644 --- a/aptos-move/framework/aptos-stdlib/sources/math128.move +++ b/aptos-move/framework/aptos-stdlib/sources/math128.move @@ -28,6 +28,17 @@ module aptos_std::math128 { } } + /// Return greatest common divisor of `a` & `b`, via the Euclidean algorithm. + public inline fun gcd(a: u128, b: u128): u128 { + let (large, small) = if (a > b) (a, b) else (b, a); + while (small != 0) { + let tmp = small; + small = large % small; + large = tmp; + }; + large + } + /// Returns a * b / c going through u256 to prevent intermediate overflow public inline fun mul_div(a: u128, b: u128, c: u128): u128 { // Inline functions cannot take constants, as then every module using it needs the constant @@ -161,6 +172,27 @@ module aptos_std::math128 { // No overflow assert!(ceil_div((((1u256<<128) - 9) as u128), 11) == 30934760629176223951215873402888019223, 0); } + + #[test] + fun test_gcd() { + assert!(gcd(20, 8) == 4, 0); + assert!(gcd(8, 20) == 4, 0); + assert!(gcd(1, 100) == 1, 0); + assert!(gcd(100, 1) == 1, 0); + assert!(gcd(210, 45) == 15, 0); + assert!(gcd(45, 210) == 15, 0); + assert!(gcd(0, 0) == 0, 0); + assert!(gcd(1, 0) == 1, 0); + assert!(gcd(50, 0) == 50, 0); + assert!(gcd(0, 1) == 1, 0); + assert!(gcd(0, 50) == 50, 0); + assert!(gcd(54, 24) == 6, 0); + assert!(gcd(24, 54) == 6, 0); + assert!(gcd(10, 10) == 10, 0); + assert!(gcd(1071, 462) == 21, 0); + assert!(gcd(462, 1071) == 21, 0); + } + #[test] public entry fun test_max() { let result = max(3u128, 6u128); diff --git a/aptos-move/framework/aptos-stdlib/sources/math64.move b/aptos-move/framework/aptos-stdlib/sources/math64.move index 71d855318230d..50fd38ed3f6ab 100644 --- a/aptos-move/framework/aptos-stdlib/sources/math64.move +++ b/aptos-move/framework/aptos-stdlib/sources/math64.move @@ -26,6 +26,17 @@ module aptos_std::math64 { } } + /// Return greatest common divisor of `a` & `b`, via the Euclidean algorithm. + public inline fun gcd(a: u64, b: u64): u64 { + let (large, small) = if (a > b) (a, b) else (b, a); + while (small != 0) { + let tmp = small; + small = large % small; + large = tmp; + }; + large + } + /// Returns a * b / c going through u128 to prevent intermediate overflow public inline fun mul_div(a: u64, b: u64, c: u64): u64 { // Inline functions cannot take constants, as then every module using it needs the constant @@ -136,6 +147,26 @@ module aptos_std::math64 { assert!(ceil_div((((1u128<<64) - 9) as u64), 11) == 1676976733973595601, 0); } + #[test] + fun test_gcd() { + assert!(gcd(20, 8) == 4, 0); + assert!(gcd(8, 20) == 4, 0); + assert!(gcd(1, 100) == 1, 0); + assert!(gcd(100, 1) == 1, 0); + assert!(gcd(210, 45) == 15, 0); + assert!(gcd(45, 210) == 15, 0); + assert!(gcd(0, 0) == 0, 0); + assert!(gcd(1, 0) == 1, 0); + assert!(gcd(50, 0) == 50, 0); + assert!(gcd(0, 1) == 1, 0); + assert!(gcd(0, 50) == 50, 0); + assert!(gcd(54, 24) == 6, 0); + assert!(gcd(24, 54) == 6, 0); + assert!(gcd(10, 10) == 10, 0); + assert!(gcd(1071, 462) == 21, 0); + assert!(gcd(462, 1071) == 21, 0); + } + #[test] public entry fun test_max_64() { let result = max(3u64, 6u64); From 02381a21f7954c595cc60e84441c86e35ae88a6d Mon Sep 17 00:00:00 2001 From: Satya Vusirikala Date: Thu, 8 Feb 2024 03:16:33 +0530 Subject: [PATCH 034/328] end-to-end tests for resource groups (#11909) * E2E tests for resource groups * Cleaning up and adding check method * Add another proptest * Updating comments * Addressing PR comments --- aptos-move/e2e-move-tests/src/lib.rs | 1 + .../e2e-move-tests/src/resource_groups.rs | 245 ++++++++++++++++++ .../e2e-move-tests/src/tests/aggregator_v2.rs | 3 +- .../tests/resource_groups.data/pack/Move.toml | 6 + .../pack/sources/resource_groups_test.move | 238 +++++++++++++++++ .../src/tests/resource_groups.rs | 143 +++++++++- 6 files changed, 633 insertions(+), 3 deletions(-) create mode 100644 aptos-move/e2e-move-tests/src/resource_groups.rs create mode 100644 aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/Move.toml create mode 100644 aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/sources/resource_groups_test.move diff --git a/aptos-move/e2e-move-tests/src/lib.rs b/aptos-move/e2e-move-tests/src/lib.rs index cc953f076e6a1..60e981d417daa 100644 --- a/aptos-move/e2e-move-tests/src/lib.rs +++ b/aptos-move/e2e-move-tests/src/lib.rs @@ -5,6 +5,7 @@ pub mod aggregator; pub mod aggregator_v2; pub mod aptos_governance; pub mod harness; +pub mod resource_groups; pub mod stake; pub mod transaction_fee; diff --git a/aptos-move/e2e-move-tests/src/resource_groups.rs b/aptos-move/e2e-move-tests/src/resource_groups.rs new file mode 100644 index 0000000000000..9e151d104609d --- /dev/null +++ b/aptos-move/e2e-move-tests/src/resource_groups.rs @@ -0,0 +1,245 @@ +// Copyright © Aptos Foundation + +use crate::{assert_success, harness::MoveHarness, BlockSplit}; +use aptos_language_e2e_tests::{ + account::Account, + executor::{assert_outputs_equal, ExecutorMode, FakeExecutor}, +}; +use aptos_types::{ + account_address::AccountAddress, on_chain_config::FeatureFlag, transaction::SignedTransaction, +}; +use std::path::PathBuf; + +pub fn initialize( + path: PathBuf, + mode: ExecutorMode, + resource_group_charge_as_sum_enabled: bool, + txns: usize, +) -> ResourceGroupsTestHarness { + let (harness, account) = initialize_harness(mode, resource_group_charge_as_sum_enabled, path); + + let mut rg_harness = ResourceGroupsTestHarness { + harness, + comparison_harnesses: vec![], + account, + txn_accounts: vec![], + txn_index: 0, + }; + + rg_harness.initialize_issuer_accounts(txns); + rg_harness +} + +pub fn initialize_enabled_disabled_comparison( + path: PathBuf, + mode: ExecutorMode, + txns: usize, +) -> ResourceGroupsTestHarness { + let (harness_base, account_base) = initialize_harness(mode, false, path.clone()); + let (harness_comp, _account_comp) = initialize_harness(mode, true, path); + + let mut rg_harness = ResourceGroupsTestHarness { + harness: harness_base, + comparison_harnesses: vec![harness_comp], + account: account_base, + txn_accounts: vec![], + txn_index: 0, + }; + + rg_harness.initialize_issuer_accounts(txns); + rg_harness +} + +fn initialize_harness( + mode: ExecutorMode, + resource_group_charge_as_sum_enabled: bool, + path: PathBuf, +) -> (MoveHarness, Account) { + let executor = FakeExecutor::from_head_genesis().set_executor_mode(mode); + + let mut harness = MoveHarness::new_with_executor(executor); + // Reduce gas scaling, so that smaller differences in gas are caught in comparison testing. + harness.modify_gas_scaling(1000); + if resource_group_charge_as_sum_enabled { + harness.enable_features( + vec![FeatureFlag::RESOURCE_GROUPS_CHARGE_AS_SIZE_SUM], + vec![], + ); + } else { + harness.enable_features(vec![], vec![ + FeatureFlag::RESOURCE_GROUPS_CHARGE_AS_SIZE_SUM, + ]); + } + let account = harness.new_account_at(AccountAddress::ONE); + assert_success!(harness.publish_package_cache_building(&account, &path)); + (harness, account) +} + +pub struct ResourceGroupsTestHarness { + pub harness: MoveHarness, + pub comparison_harnesses: Vec, + pub account: Account, + pub txn_accounts: Vec, + pub txn_index: usize, +} + +impl ResourceGroupsTestHarness { + // TODO[agg_v2](cleanup): These 3 functions are common with aggregator_v2 tests. + // Should I create struct PropTestHarness with these 3 functions, and set + // ResourceGroupsTestHarness { harness: PropTestHarness }? + pub fn run_block_in_parts_and_check( + &mut self, + block_split: BlockSplit, + txn_block: Vec<(u64, SignedTransaction)>, + ) { + let result = self + .harness + .run_block_in_parts_and_check(block_split, txn_block.clone()); + + for (idx, h) in self.comparison_harnesses.iter_mut().enumerate() { + let new_result = h.run_block_in_parts_and_check(block_split, txn_block.clone()); + assert_outputs_equal( + &result, + "baseline", + &new_result, + &format!("comparison {}", idx), + ); + } + } + + pub fn initialize_issuer_accounts(&mut self, num_accounts: usize) { + self.txn_accounts = (0..num_accounts) + .map(|_i| self.new_account_with_key_pair()) + .collect(); + } + + pub fn new_account_with_key_pair(&mut self) -> Account { + let acc = Account::new(); + let seq_num = 0; + // Mint the account 10M Aptos coins (with 8 decimals). + let balance = 1_000_000_000_000_000; + + let result = self.harness.store_and_fund_account(&acc, balance, seq_num); + + for h in self.comparison_harnesses.iter_mut() { + h.store_and_fund_account(&acc, balance, seq_num); + } + + result + } + + pub fn init_signer(&mut self, seed: Vec) -> SignedTransaction { + self.harness.create_entry_function( + &self.account, + str::parse("0x1::resource_groups_test::init_signer").unwrap(), + vec![], + vec![bcs::to_bytes(&seed).unwrap()], + ) + } + + pub fn set_resource(&mut self, index: u32, name: String, value: u32) -> SignedTransaction { + self.txn_index += 1; + self.harness.create_entry_function( + &self.txn_accounts[self.txn_index % self.txn_accounts.len()], + str::parse("0x1::resource_groups_test::set_resource").unwrap(), + vec![], + vec![ + bcs::to_bytes(self.account.address()).unwrap(), + bcs::to_bytes(&index).unwrap(), + bcs::to_bytes(&name).unwrap(), + bcs::to_bytes(&value).unwrap(), + ], + ) + } + + pub fn unset_resource(&mut self, index: u32) -> SignedTransaction { + self.txn_index += 1; + self.harness.create_entry_function( + &self.txn_accounts[self.txn_index % self.txn_accounts.len()], + str::parse("0x1::resource_groups_test::unset_resource").unwrap(), + vec![], + vec![ + bcs::to_bytes(self.account.address()).unwrap(), + bcs::to_bytes(&index).unwrap(), + ], + ) + } + + pub fn read_or_init(&mut self, index: u32) -> SignedTransaction { + self.txn_index += 1; + self.harness.create_entry_function( + &self.txn_accounts[self.txn_index % self.txn_accounts.len()], + str::parse("0x1::resource_groups_test::read_or_init").unwrap(), + vec![], + vec![ + bcs::to_bytes(self.account.address()).unwrap(), + bcs::to_bytes(&index).unwrap(), + ], + ) + } + + pub fn set_3_group_members( + &mut self, + index1: u32, + index2: u32, + index3: u32, + name: String, + value: u32, + ) -> SignedTransaction { + self.txn_index += 1; + self.harness.create_entry_function( + &self.txn_accounts[self.txn_index % self.txn_accounts.len()], + str::parse("0x1::resource_groups_test::set_3_group_members").unwrap(), + vec![], + vec![ + bcs::to_bytes(self.account.address()).unwrap(), + bcs::to_bytes(&index1).unwrap(), + bcs::to_bytes(&index2).unwrap(), + bcs::to_bytes(&index3).unwrap(), + bcs::to_bytes(&name).unwrap(), + bcs::to_bytes(&value).unwrap(), + ], + ) + } + + pub fn check(&mut self, index: u32, name: String, value: u32) -> SignedTransaction { + self.txn_index += 1; + self.harness.create_entry_function( + &self.txn_accounts[self.txn_index % self.txn_accounts.len()], + str::parse("0x1::resource_groups_test::check").unwrap(), + vec![], + vec![ + bcs::to_bytes(self.account.address()).unwrap(), + bcs::to_bytes(&index).unwrap(), + bcs::to_bytes(&name).unwrap(), + bcs::to_bytes(&value).unwrap(), + ], + ) + } + + pub fn set_and_check( + &mut self, + index1: u32, + index2: u32, + name1: String, + value1: u32, + name2: String, + value2: u32, + ) -> SignedTransaction { + self.txn_index += 1; + self.harness.create_entry_function( + &self.txn_accounts[self.txn_index % self.txn_accounts.len()], + str::parse("0x1::resource_groups_test::set_and_check").unwrap(), + vec![], + vec![ + bcs::to_bytes(self.account.address()).unwrap(), + bcs::to_bytes(&index1).unwrap(), + bcs::to_bytes(&index2).unwrap(), + bcs::to_bytes(&name1).unwrap(), + bcs::to_bytes(&value1).unwrap(), + bcs::to_bytes(&name2).unwrap(), + bcs::to_bytes(&value2).unwrap(), + ], + ) + } +} diff --git a/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs b/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs index ac106efd5f895..b9d831586efe8 100644 --- a/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs +++ b/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs @@ -116,8 +116,7 @@ mod test_cases { } } -#[allow(dead_code)] -fn arb_block_split(len: usize) -> BoxedStrategy { +pub fn arb_block_split(len: usize) -> BoxedStrategy { (0..3) .prop_flat_map(move |enum_type| { // making running a test with a full block likely diff --git a/aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/Move.toml b/aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/Move.toml new file mode 100644 index 0000000000000..379bba0bfe864 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/Move.toml @@ -0,0 +1,6 @@ +[package] +name = "resource_groups_test" +version = "0.0.0" + +[dependencies] +AptosFramework = { local = "../../../../../framework/aptos-framework" } diff --git a/aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/sources/resource_groups_test.move b/aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/sources/resource_groups_test.move new file mode 100644 index 0000000000000..3844ce5700426 --- /dev/null +++ b/aptos-move/e2e-move-tests/src/tests/resource_groups.data/pack/sources/resource_groups_test.move @@ -0,0 +1,238 @@ +module 0x1::resource_groups_test { + use std::string::{Self, String}; + use aptos_framework::account; + use std::signer; + + const ENOT_EQUAL: u64 = 17; + const EINVALID_ARG: u64 = 18; + const ERESOURCE_DOESNT_EXIST: u64 = 19; + + #[resource_group(scope = global)] + struct MyGroup {} + + #[resource_group_member(group = 0x1::resource_groups_test::MyGroup)] + struct MyResource1 has key, drop { + name: String, + value: u32, + } + + #[resource_group_member(group = 0x1::resource_groups_test::MyGroup)] + struct MyResource2 has key, drop { + name: String, + value: u32, + } + + #[resource_group_member(group = 0x1::resource_groups_test::MyGroup)] + struct MyResource3 has key, drop { + name: String, + value: u32, + } + + #[resource_group_member(group = 0x1::resource_groups_test::MyGroup)] + struct MyResource4 has key, drop { + name: String, + value: u32, + } + + struct MainResource has key { + signer_cap: account::SignerCapability + } + + public entry fun init_signer(main_account: &signer, seed: vector) { + let (_resource_account_signer, signer_cap) = account::create_resource_account(main_account, seed); + let main_resource = MainResource { + signer_cap, + }; + move_to(main_account, main_resource); + } + + public entry fun set_resource(main_account: address, index: u32, name: String, value: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + let main_resource = borrow_global_mut(main_account); + let owner = account::create_signer_with_capability(&main_resource.signer_cap); + let owner_address = signer::address_of(&owner); + + if (index == 1) { + if (exists(owner_address)) { + let resource = borrow_global_mut(owner_address); + resource.name = name; + resource.value = value; + } else { + let resource = MyResource1 { + name, + value, + }; + move_to(&owner, resource); + } + } else if (index == 2) { + if (exists(owner_address)) { + let resource = borrow_global_mut(owner_address); + resource.name = name; + resource.value = value; + } else { + let resource = MyResource2 { + name, + value, + }; + move_to(&owner, resource); + } + } else if (index == 3) { + if (exists(owner_address)) { + let resource = borrow_global_mut(owner_address); + resource.name = name; + resource.value = value; + } else { + let resource = MyResource3 { + name, + value, + }; + move_to(&owner, resource); + } + } else if (index == 4) { + if (exists(owner_address)) { + let resource = borrow_global_mut(owner_address); + resource.name = name; + resource.value = value; + } else { + let resource = MyResource4 { + name, + value, + }; + move_to(&owner, resource); + } + } else { + assert!(false, EINVALID_ARG); + } + } + + public entry fun check(main_account: address, index: u32, name: String, value: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + let main_resource = borrow_global_mut(main_account); + let owner_address = account::get_signer_capability_address(&main_resource.signer_cap); + + if (index == 1) { + if (exists(owner_address)) { + let resource = borrow_global(owner_address); + assert!(resource.name == name, ENOT_EQUAL); + assert!(resource.value == value, ENOT_EQUAL); + } else { + assert!(false, ERESOURCE_DOESNT_EXIST); + } + } else if (index == 2) { + if (exists(owner_address)) { + let resource = borrow_global(owner_address); + assert!(resource.name == name, ENOT_EQUAL); + assert!(resource.value == value, ENOT_EQUAL); + } else { + assert!(false, ERESOURCE_DOESNT_EXIST); + } + } else if (index == 3) { + if (exists(owner_address)) { + let resource = borrow_global(owner_address); + assert!(resource.name == name, ENOT_EQUAL); + assert!(resource.value == value, ENOT_EQUAL); + } else { + assert!(false, ERESOURCE_DOESNT_EXIST); + } + } else if (index == 4) { + if (exists(owner_address)) { + let resource = borrow_global(owner_address); + assert!(resource.name == name, ENOT_EQUAL); + assert!(resource.value == value, ENOT_EQUAL); + } else { + assert!(false, ERESOURCE_DOESNT_EXIST); + } + } else { + assert!(false, EINVALID_ARG); + } + } + + public entry fun unset_resource(main_account: address, index: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + let main_resource = borrow_global_mut(main_account); + let owner_address = account::get_signer_capability_address(&main_resource.signer_cap); + // TODO: Is this how we unset a resource? + if (index == 1) { + if (exists(owner_address)) { + move_from(owner_address); + } + } else if (index == 2) { + if (exists(owner_address)) { + move_from(owner_address); + } + } else if (index == 3) { + if (exists(owner_address)) { + move_from(owner_address); + } + } else if (index == 4) { + if (exists(owner_address)) { + move_from(owner_address); + } + } else { + assert!(false, EINVALID_ARG); + } + } + + public entry fun read_or_init(main_account: address, index: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + let main_resource = borrow_global_mut(main_account); + let owner = account::create_signer_with_capability(&main_resource.signer_cap); + let owner_address = signer::address_of(&owner); + + if (index == 1) { + if (exists(owner_address)) { + let _resource = borrow_global_mut(owner_address); + } else { + let resource = MyResource1 { + name: string::utf8(b"init_name"), + value: 5, + }; + move_to(&owner, resource); + } + } else if (index == 2) { + if (exists(owner_address)) { + let _resource = borrow_global_mut(owner_address); + } else { + let resource = MyResource2 { + name: string::utf8(b"init_name"), + value: 5, + }; + move_to(&owner, resource); + } + } else if (index == 3) { + if (exists(owner_address)) { + let _resource = borrow_global_mut(owner_address); + } else { + let resource = MyResource3 { + name: string::utf8(b"init_name"), + value: 5, + }; + move_to(&owner, resource); + } + } else if (index == 4) { + if (exists(owner_address)) { + let _resource = borrow_global_mut(owner_address); + } else { + let resource = MyResource4 { + name: string::utf8(b"init_name"), + value: 5, + }; + move_to(&owner, resource); + } + } else { + assert!(false, EINVALID_ARG); + } + } + + public entry fun set_3_group_members(main_account: address, index1: u32, index2: u32, index3: u32, name: String, value: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + set_resource(main_account, index1, name, value); + set_resource(main_account, index2, name, value); + set_resource(main_account, index3, name, value); + } + + public entry fun set_resource_and_read(main_account: address, set_index: u32, read_index: u32, name: String, value: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + set_resource(main_account, set_index, name, value); + read_or_init(main_account, read_index); + } + + public entry fun set_and_check(main_account: address, set_index: u32, check_index: u32, name1: String, value1: u32, name2: String, value2: u32) acquires MainResource, MyResource1, MyResource2, MyResource3, MyResource4 { + set_resource(main_account, set_index, name1, value1); + check(main_account, check_index, name2, value2); + } +} diff --git a/aptos-move/e2e-move-tests/src/tests/resource_groups.rs b/aptos-move/e2e-move-tests/src/tests/resource_groups.rs index 54415eab9e4c2..dba7574128620 100644 --- a/aptos-move/e2e-move-tests/src/tests/resource_groups.rs +++ b/aptos-move/e2e-move-tests/src/tests/resource_groups.rs @@ -1,13 +1,154 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::{assert_success, assert_vm_status, tests::common, MoveHarness}; +use crate::{ + assert_success, assert_vm_status, + resource_groups::{ + initialize, initialize_enabled_disabled_comparison, ResourceGroupsTestHarness, + }, + tests::{aggregator_v2::arb_block_split, common}, + BlockSplit, MoveHarness, SUCCESS, +}; +use aptos_language_e2e_tests::executor::ExecutorMode; use aptos_package_builder::PackageBuilder; use aptos_types::{account_address::AccountAddress, on_chain_config::FeatureFlag}; use move_core_types::{identifier::Identifier, language_storage::StructTag, vm_status::StatusCode}; +use proptest::prelude::*; use serde::Deserialize; use test_case::test_case; +// This mode describes whether to enable or disable RESOURCE_GROUPS_CHARGE_AS_SIZE_SUM flag +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum ResourceGroupMode { + EnabledOnly, + DisabledOnly, + BothComparison, +} + +const STRESSTEST_MODE: bool = false; +const ENOT_EQUAL: u64 = 17; +const EINVALID_ARG: u64 = 18; +const ERESOURCE_DOESNT_EXIST: u64 = 19; + +// TODO[agg_v2](cleanup): This interface looks similar to aggregator v2 test harness. +// Could cleanup later on. +fn setup( + executor_mode: ExecutorMode, + // This mode describes whether to enable or disable RESOURCE_GROUPS_CHARGE_AS_SIZE_SUM flag + resource_group_mode: ResourceGroupMode, + txns: usize, +) -> ResourceGroupsTestHarness { + let path = common::test_dir_path("resource_groups.data/pack"); + match resource_group_mode { + ResourceGroupMode::EnabledOnly => initialize(path, executor_mode, true, txns), + ResourceGroupMode::DisabledOnly => initialize(path, executor_mode, false, txns), + ResourceGroupMode::BothComparison => { + initialize_enabled_disabled_comparison(path, executor_mode, txns) + }, + } +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub struct TestEnvConfig { + pub executor_mode: ExecutorMode, + pub resource_group_mode: ResourceGroupMode, + pub block_split: BlockSplit, +} + +#[allow(clippy::arc_with_non_send_sync)] // I think this is noise, don't see an issue, and tests run fine +fn arb_test_env(num_txns: usize) -> BoxedStrategy { + prop_oneof![ + arb_block_split(num_txns).prop_map(|block_split| TestEnvConfig { + executor_mode: ExecutorMode::BothComparison, + resource_group_mode: ResourceGroupMode::BothComparison, + block_split + }), + ] + .boxed() +} + +#[allow(clippy::arc_with_non_send_sync)] // I think this is noise, don't see an issue, and tests run fine +fn arb_test_env_non_equivalent(num_txns: usize) -> BoxedStrategy { + prop_oneof![ + arb_block_split(num_txns).prop_map(|block_split| TestEnvConfig { + executor_mode: ExecutorMode::BothComparison, + resource_group_mode: ResourceGroupMode::DisabledOnly, + block_split + }), + arb_block_split(num_txns).prop_map(|block_split| TestEnvConfig { + executor_mode: ExecutorMode::BothComparison, + resource_group_mode: ResourceGroupMode::EnabledOnly, + block_split + }), + ] + .boxed() +} + +proptest! { + #![proptest_config(ProptestConfig { + // Cases are expensive, few cases is enough. + // We will test a few more comprehensive tests more times, and the rest even fewer. + cases: if STRESSTEST_MODE { 1000 } else { 20 }, + result_cache: if STRESSTEST_MODE { prop::test_runner::noop_result_cache } else {prop::test_runner::basic_result_cache }, + .. ProptestConfig::default() + })] + + #[test] + fn proptest_resource_groups_1(test_env in arb_test_env(17)) { + println!("Testing test_aggregator_lifetime {:?}", test_env); + let mut h = setup(test_env.executor_mode, test_env.resource_group_mode, 17); + + let txns = vec![ + (SUCCESS, h.init_signer(vec![5,2,3])), + (SUCCESS, h.set_resource(4, "ABC".to_string(), 10)), + (SUCCESS, h.set_resource(2, "DEFG".to_string(), 20)), + (SUCCESS, h.unset_resource(3)), + (SUCCESS, h.set_resource(3, "GH".to_string(), 30)), + (SUCCESS, h.set_resource(4, "JKLMNO".to_string(), 40)), + (SUCCESS, h.set_and_check(2, 4, "MNOP".to_string(), 50, "JKLMNO".to_string(), 40)), + (SUCCESS, h.read_or_init(1)), + (SUCCESS, h.check(2, "MNOP".to_string(), 50)), + (SUCCESS, h.check(1, "init_name".to_string(), 5)), + (SUCCESS, h.unset_resource(1)), + (SUCCESS, h.set_3_group_members(1, 2, 3, "L".to_string(), 25)), + (SUCCESS, h.check(1, "L".to_string(), 25)), + (SUCCESS, h.unset_resource(3)), + (ENOT_EQUAL, h.check(2, "MNOP".to_string(), 50)), + (EINVALID_ARG, h.set_resource(5, "JKLI".to_string(), 40)), + (ERESOURCE_DOESNT_EXIST, h.check(3, "L".to_string(), 25)), + ]; + h.run_block_in_parts_and_check( + test_env.block_split, + txns, + ); + } + + #[test] + fn proptest_resource_groups_2(test_env in arb_test_env_non_equivalent(12)) { + println!("Testing test_aggregator_lifetime {:?}", test_env); + let mut h = setup(test_env.executor_mode, test_env.resource_group_mode, 12); + + let txns = vec![ + (SUCCESS, h.init_signer(vec![5,2,3])), + (SUCCESS, h.set_resource(4, "ABCDEF".to_string(), 10)), + (SUCCESS, h.set_resource(2, "DEF".to_string(), 20)), + (SUCCESS, h.read_or_init(4)), + (SUCCESS, h.set_resource(2, "XYZK".to_string(), 25)), + (ENOT_EQUAL, h.check(2, "DEF".to_string(), 20)), + (SUCCESS, h.check(2, "XYZK".to_string(), 25)), + (SUCCESS, h.set_resource(3, "GH".to_string(), 30)), + (SUCCESS, h.unset_resource(3)), + (ERESOURCE_DOESNT_EXIST, h.check(3, "LJH".to_string(), 25)), + (ERESOURCE_DOESNT_EXIST, h.set_and_check(2, 1, "MNO".to_string(), 50, "GH".to_string(), 30)), + (SUCCESS, h.check(2, "XYZK".to_string(), 25)), + ]; + h.run_block_in_parts_and_check( + test_env.block_split, + txns, + ); + } +} + #[derive(Debug, Deserialize, Eq, PartialEq)] struct Primary { value: u64, From 4e55d252605a2fe43464efb6dd8dffdfb9da43cf Mon Sep 17 00:00:00 2001 From: Guoteng Rao <3603304+grao1991@users.noreply.github.com> Date: Wed, 7 Feb 2024 14:01:05 -0800 Subject: [PATCH 035/328] [Fix] Only create parent dir when it doesn't exist. (#11942) --- .../indexer-grpc-utils/src/file_store_operator/local.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs b/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs index c3dfd359acb25..65245733935a9 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-utils/src/file_store_operator/local.rs @@ -171,8 +171,10 @@ impl FileStoreOperator for LocalFileStoreOperator { let file_entry_key = FileEntry::build_key(starting_version, self.storage_format).to_string(); let txns_path = self.path.join(file_entry_key.as_str()); - if !txns_path.exists() { - tokio::fs::create_dir_all(txns_path.clone()).await?; + let parent_dir = txns_path.parent().unwrap(); + if !parent_dir.exists() { + tracing::debug!("Creating parent dir: {parent_dir:?}."); + tokio::fs::create_dir_all(parent_dir).await?; } tracing::debug!( From 637180090eb5f7e4935b2f80b436b1d7514429bb Mon Sep 17 00:00:00 2001 From: Alin Tomescu Date: Wed, 7 Feb 2024 14:35:52 -0800 Subject: [PATCH 036/328] [randomness] print average/best/worst-case aggregation subset information (#11946) --- .../aptos-dkg/tests/secret_sharing_config.rs | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 crates/aptos-dkg/tests/secret_sharing_config.rs diff --git a/crates/aptos-dkg/tests/secret_sharing_config.rs b/crates/aptos-dkg/tests/secret_sharing_config.rs new file mode 100644 index 0000000000000..1c7d4da04056a --- /dev/null +++ b/crates/aptos-dkg/tests/secret_sharing_config.rs @@ -0,0 +1,49 @@ +#![allow(clippy::ptr_arg)] +#![allow(clippy::needless_borrow)] + +// Copyright © Aptos Foundation + +use aptos_dkg::pvss::{ + test_utils::get_weighted_configs_for_benchmarking, traits::SecretSharingConfig, +}; +use rand::thread_rng; + +#[ignore] +#[test] +fn print_best_worst_avg_case_subsets() { + let wcs = get_weighted_configs_for_benchmarking(); + + let mut rng = thread_rng(); + + for wc in wcs { + println!("{wc}"); + for i in 0..wc.get_total_num_players() { + print!("p[{i}]: {}, ", wc.get_player_weight(&wc.get_player(i))); + } + println!(); + + println!( + "Average case subset size: {}", + wc.get_average_size_of_eligible_subset(1000, &mut rng) + ); + + let worst_case = wc.get_worst_case_eligible_subset_of_players(&mut rng); + println!( + "Worst case subset is of size {}. Player IDs are {:?}", + worst_case.len(), + worst_case + .iter() + .map(|p| p.get_id()) + .collect::>() + ); + + let best_case = wc.get_best_case_eligible_subset_of_players(&mut rng); + println!( + "Best case subset is of size {}. Player IDs are {:?}", + best_case.len(), + best_case.iter().map(|p| p.get_id()).collect::>() + ); + + println!(); + } +} From e230ba17fa01a3935b7c3002e1b7a52bc8d99c04 Mon Sep 17 00:00:00 2001 From: Manu Dhundi Date: Wed, 7 Feb 2024 19:12:44 -0800 Subject: [PATCH 037/328] Allow 'pipeline_backpressure' to truncate num_txns included in a block to lower value (potentially < batch size) (#11830) * Allow 'pipeline_backpressure' to truncate num_txns included in a block to lower value (potentially < batch size) To go into effect, all validators will have to upgrade to this change, and we need to set the desired config value at ConsensusConfig * Address review comments * Add smoke test, address review comments * Rename the counter to 'MAX_TXNS_FROM_BLOCK_TO_EXECUTE' --- config/src/config/consensus_config.rs | 10 + consensus/consensus-types/src/block.rs | 3 +- consensus/consensus-types/src/common.rs | 91 +++++++- consensus/src/block_preparer.rs | 16 +- consensus/src/counters.rs | 10 + consensus/src/liveness/proposal_generator.rs | 25 ++- consensus/src/payload_manager.rs | 203 +++++++++++------- .../quorum_store/tests/proof_manager_test.rs | 67 +++++- .../src/test_utils/mock_state_computer.rs | 3 +- consensus/src/util/db_tool.rs | 36 ++-- .../tests/staged/consensus.yaml | 10 + testsuite/smoke-test/src/txn_emitter.rs | 41 +++- 12 files changed, 394 insertions(+), 121 deletions(-) diff --git a/config/src/config/consensus_config.rs b/config/src/config/consensus_config.rs index 83564f58cd6d0..781a8c66979c1 100644 --- a/config/src/config/consensus_config.rs +++ b/config/src/config/consensus_config.rs @@ -123,6 +123,7 @@ pub struct PipelineBackpressureValues { // If we want to dynamically increase it beyond quorum_store_poll_time, // we need to adjust timeouts other nodes use for the backpressured round. pub backpressure_proposal_delay_ms: u64, + pub max_txns_from_block_to_execute: Option, } #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] @@ -180,36 +181,42 @@ impl Default for ConsensusConfig { max_sending_block_txns_override: 10000, max_sending_block_bytes_override: 5 * 1024 * 1024, backpressure_proposal_delay_ms: 100, + max_txns_from_block_to_execute: None, }, PipelineBackpressureValues { back_pressure_pipeline_latency_limit_ms: 1100, max_sending_block_txns_override: 10000, max_sending_block_bytes_override: 5 * 1024 * 1024, backpressure_proposal_delay_ms: 200, + max_txns_from_block_to_execute: None, }, PipelineBackpressureValues { back_pressure_pipeline_latency_limit_ms: 1400, max_sending_block_txns_override: 2000, max_sending_block_bytes_override: 1024 * 1024 + BATCH_PADDING_BYTES as u64, backpressure_proposal_delay_ms: 300, + max_txns_from_block_to_execute: None, }, PipelineBackpressureValues { back_pressure_pipeline_latency_limit_ms: 1700, max_sending_block_txns_override: 1000, max_sending_block_bytes_override: 1024 * 1024 + BATCH_PADDING_BYTES as u64, backpressure_proposal_delay_ms: 400, + max_txns_from_block_to_execute: None, }, PipelineBackpressureValues { back_pressure_pipeline_latency_limit_ms: 2000, max_sending_block_txns_override: 600, max_sending_block_bytes_override: 1024 * 1024 + BATCH_PADDING_BYTES as u64, backpressure_proposal_delay_ms: 500, + max_txns_from_block_to_execute: None, }, PipelineBackpressureValues { back_pressure_pipeline_latency_limit_ms: 2300, max_sending_block_txns_override: 400, max_sending_block_bytes_override: 1024 * 1024 + BATCH_PADDING_BYTES as u64, backpressure_proposal_delay_ms: 500, + max_txns_from_block_to_execute: None, }, PipelineBackpressureValues { back_pressure_pipeline_latency_limit_ms: 2600, @@ -222,6 +229,7 @@ impl Default for ConsensusConfig { // stop reducing size, so 1MB transactions can still go through max_sending_block_bytes_override: 1024 * 1024 + BATCH_PADDING_BYTES as u64, backpressure_proposal_delay_ms: 500, + max_txns_from_block_to_execute: None, }, ], window_for_chain_health: 100, @@ -583,6 +591,7 @@ mod test { max_sending_block_txns_override: 350, max_sending_block_bytes_override: 0, backpressure_proposal_delay_ms: 0, + max_txns_from_block_to_execute: None, }], quorum_store: QuorumStoreConfig { receiver_max_batch_txns: 250, @@ -613,6 +622,7 @@ mod test { max_sending_block_txns_override: 251, max_sending_block_bytes_override: 100, backpressure_proposal_delay_ms: 0, + max_txns_from_block_to_execute: None, }], quorum_store: QuorumStoreConfig { receiver_max_batch_bytes: 2_000_000, diff --git a/consensus/consensus-types/src/block.rs b/consensus/consensus-types/src/block.rs index 54fd0fcd7fd68..c83cd05197ff6 100644 --- a/consensus/consensus-types/src/block.rs +++ b/consensus/consensus-types/src/block.rs @@ -111,7 +111,8 @@ impl Block { None => 0, Some(payload) => match payload { Payload::InQuorumStore(pos) => pos.proofs.len(), - Payload::DirectMempool(txns) => txns.len(), + Payload::DirectMempool(_txns) => 0, + Payload::InQuorumStoreWithLimit(pos) => pos.proof_with_data.proofs.len(), }, } } diff --git a/consensus/consensus-types/src/common.rs b/consensus/consensus-types/src/common.rs index 987a339b038bd..180edeb342b84 100644 --- a/consensus/consensus-types/src/common.rs +++ b/consensus/consensus-types/src/common.rs @@ -12,7 +12,7 @@ use aptos_types::{ }; use rayon::prelude::*; use serde::{Deserialize, Serialize}; -use std::{collections::HashSet, fmt, fmt::Write, sync::Arc}; +use std::{cmp::min, collections::HashSet, fmt, fmt::Write, sync::Arc}; use tokio::sync::oneshot; /// The round of a block is a consensus-internal counter, which starts with 0 and increases @@ -139,14 +139,61 @@ impl ProofWithData { } } +#[derive(Deserialize, Serialize, Clone, Debug)] +pub struct ProofWithDataWithTxnLimit { + pub proof_with_data: ProofWithData, + pub max_txns_to_execute: Option, +} + +impl PartialEq for ProofWithDataWithTxnLimit { + fn eq(&self, other: &Self) -> bool { + self.proof_with_data == other.proof_with_data + && self.max_txns_to_execute == other.max_txns_to_execute + } +} + +impl Eq for ProofWithDataWithTxnLimit {} + +impl ProofWithDataWithTxnLimit { + pub fn new(proof_with_data: ProofWithData, max_txns_to_execute: Option) -> Self { + Self { + proof_with_data, + max_txns_to_execute, + } + } + + pub fn extend(&mut self, other: ProofWithDataWithTxnLimit) { + self.proof_with_data.extend(other.proof_with_data); + // InQuorumStoreWithLimit TODO: what is the right logic here ??? + if self.max_txns_to_execute.is_none() { + self.max_txns_to_execute = other.max_txns_to_execute; + } + } +} + /// The payload in block. #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)] pub enum Payload { DirectMempool(Vec), InQuorumStore(ProofWithData), + InQuorumStoreWithLimit(ProofWithDataWithTxnLimit), } impl Payload { + pub fn transform_to_quorum_store_v2(self, max_txns_to_execute: Option) -> Self { + match self { + Payload::InQuorumStore(proof_with_status) => Payload::InQuorumStoreWithLimit( + ProofWithDataWithTxnLimit::new(proof_with_status, max_txns_to_execute), + ), + Payload::InQuorumStoreWithLimit(_) => { + panic!("Payload is already in quorumStoreV2 format"); + }, + Payload::DirectMempool(_) => { + panic!("Payload is in direct mempool format"); + }, + } + } + pub fn empty(quorum_store_enabled: bool) -> Self { if quorum_store_enabled { Payload::InQuorumStore(ProofWithData::new(Vec::new())) @@ -163,6 +210,19 @@ impl Payload { .iter() .map(|proof| proof.num_txns() as usize) .sum(), + Payload::InQuorumStoreWithLimit(proof_with_status) => { + let num_txns = proof_with_status + .proof_with_data + .proofs + .iter() + .map(|proof| proof.num_txns() as usize) + .sum(); + if proof_with_status.max_txns_to_execute.is_some() { + min(proof_with_status.max_txns_to_execute.unwrap(), num_txns) + } else { + num_txns + } + }, } } @@ -170,6 +230,11 @@ impl Payload { match self { Payload::DirectMempool(txns) => txns.is_empty(), Payload::InQuorumStore(proof_with_status) => proof_with_status.proofs.is_empty(), + Payload::InQuorumStoreWithLimit(proof_with_status) => { + proof_with_status.proof_with_data.proofs.is_empty() + || (proof_with_status.max_txns_to_execute.is_some() + && proof_with_status.max_txns_to_execute.unwrap() == 0) + }, } } @@ -177,6 +242,9 @@ impl Payload { match (self, other) { (Payload::DirectMempool(v1), Payload::DirectMempool(v2)) => v1.extend(v2), (Payload::InQuorumStore(p1), Payload::InQuorumStore(p2)) => p1.extend(p2), + (Payload::InQuorumStoreWithLimit(p1), Payload::InQuorumStoreWithLimit(p2)) => { + p1.extend(p2) + }, (_, _) => unreachable!(), } } @@ -198,6 +266,14 @@ impl Payload { .iter() .map(|proof| proof.num_bytes() as usize) .sum(), + // We dedeup, shuffle and finally truncate the txns in the payload to the length == 'max_txns_to_execute'. + // Hence, it makes sense to pass the full size of the payload here. + Payload::InQuorumStoreWithLimit(proof_with_status) => proof_with_status + .proof_with_data + .proofs + .iter() + .map(|proof| proof.num_bytes() as usize) + .sum(), } } @@ -214,6 +290,12 @@ impl Payload { } Ok(()) }, + (true, Payload::InQuorumStoreWithLimit(proof_with_status)) => { + for proof in proof_with_status.proof_with_data.proofs.iter() { + proof.verify(validator)?; + } + Ok(()) + }, (_, _) => Err(anyhow::anyhow!( "Wrong payload type. Expected Payload::InQuorumStore {} got {} ", quorum_store_enabled, @@ -232,6 +314,13 @@ impl fmt::Display for Payload { Payload::InQuorumStore(proof_with_status) => { write!(f, "InMemory proofs: {}", proof_with_status.proofs.len()) }, + Payload::InQuorumStoreWithLimit(proof_with_status) => { + write!( + f, + "InMemory proofs: {}", + proof_with_status.proof_with_data.proofs.len() + ) + }, } } } diff --git a/consensus/src/block_preparer.rs b/consensus/src/block_preparer.rs index 51168e1656019..ce052ddbef276 100644 --- a/consensus/src/block_preparer.rs +++ b/consensus/src/block_preparer.rs @@ -2,8 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - payload_manager::PayloadManager, transaction_deduper::TransactionDeduper, - transaction_filter::TransactionFilter, transaction_shuffler::TransactionShuffler, + counters::MAX_TXNS_FROM_BLOCK_TO_EXECUTE, payload_manager::PayloadManager, + transaction_deduper::TransactionDeduper, transaction_filter::TransactionFilter, + transaction_shuffler::TransactionShuffler, }; use aptos_consensus_types::block::Block; use aptos_executor_types::ExecutorResult; @@ -33,7 +34,8 @@ impl BlockPreparer { } pub async fn prepare_block(&self, block: &Block) -> ExecutorResult> { - let txns = self.payload_manager.get_transactions(block).await?; + let (txns, max_txns_from_block_to_execute) = + self.payload_manager.get_transactions(block).await?; let txn_filter = self.txn_filter.clone(); let txn_deduper = self.txn_deduper.clone(); let txn_shuffler = self.txn_shuffler.clone(); @@ -43,7 +45,13 @@ impl BlockPreparer { tokio::task::spawn_blocking(move || { let filtered_txns = txn_filter.filter(block_id, block_timestamp_usecs, txns); let deduped_txns = txn_deduper.dedup(filtered_txns); - Ok(txn_shuffler.shuffle(deduped_txns)) + let mut shuffled_txns = txn_shuffler.shuffle(deduped_txns); + + if let Some(max_txns_from_block_to_execute) = max_txns_from_block_to_execute { + shuffled_txns.truncate(max_txns_from_block_to_execute); + } + MAX_TXNS_FROM_BLOCK_TO_EXECUTE.observe(shuffled_txns.len() as f64); + Ok(shuffled_txns) }) .await .expect("Failed to spawn blocking task for transaction generation") diff --git a/consensus/src/counters.rs b/consensus/src/counters.rs index 7ed9f6ae4d037..208f3d5e78322 100644 --- a/consensus/src/counters.rs +++ b/consensus/src/counters.rs @@ -843,6 +843,16 @@ pub static UNEXPECTED_PROPOSAL_EXT_COUNT: Lazy = Lazy::new(|| { .unwrap() }); +/// Histogram for the number of txns to be executed in a block. +pub static MAX_TXNS_FROM_BLOCK_TO_EXECUTE: Lazy = Lazy::new(|| { + register_histogram!( + "max_txns_from_block_to_execute", + "Histogram for the number of txns to be executed in a block.", + exponential_buckets(/*start=*/ 1.5, /*factor=*/ 1.5, /*count=*/ 25).unwrap(), + ) + .unwrap() +}); + /// Update various counters for committed blocks pub fn update_counters_for_committed_blocks(blocks_to_commit: &[Arc]) { for block in blocks_to_commit { diff --git a/consensus/src/liveness/proposal_generator.rs b/consensus/src/liveness/proposal_generator.rs index bebef30cd24e0..cd74bfe0bfbeb 100644 --- a/consensus/src/liveness/proposal_generator.rs +++ b/consensus/src/liveness/proposal_generator.rs @@ -296,9 +296,9 @@ impl ProposalGenerator { let voting_power_ratio = proposer_election.get_voting_power_participation_ratio(round); - let (max_block_txns, max_block_bytes, proposal_delay) = self - .calculate_max_block_sizes(voting_power_ratio, timestamp, round) - .await; + let (max_block_txns, max_block_bytes, max_txns_from_block_to_execute, proposal_delay) = + self.calculate_max_block_sizes(voting_power_ratio, timestamp, round) + .await; PROPOSER_DELAY_PROPOSAL.set(proposal_delay.as_secs_f64()); if !proposal_delay.is_zero() { @@ -329,7 +329,7 @@ impl ProposalGenerator { .collect(); let validator_txn_filter = vtxn_pool::TransactionFilter::PendingTxnHashSet(pending_validator_txn_hashes); - let (validator_txns, payload) = self + let (validator_txns, mut payload) = self .payload_client .pull_payload( self.quorum_store_poll_time.saturating_sub(proposal_delay), @@ -345,6 +345,12 @@ impl ProposalGenerator { .await .context("Fail to retrieve payload")?; + if !payload.is_direct() + && max_txns_from_block_to_execute.is_some() + && payload.len() > max_txns_from_block_to_execute.unwrap() + { + payload = payload.transform_to_quorum_store_v2(max_txns_from_block_to_execute); + } (validator_txns, payload, timestamp.as_micros() as u64) }; @@ -385,10 +391,11 @@ impl ProposalGenerator { voting_power_ratio: f64, timestamp: Duration, round: Round, - ) -> (u64, u64, Duration) { + ) -> (u64, u64, Option, Duration) { let mut values_max_block_txns = vec![self.max_block_txns]; let mut values_max_block_bytes = vec![self.max_block_bytes]; let mut values_proposal_delay = vec![Duration::ZERO]; + let mut max_txns_from_block_to_execute = None; let chain_health_backoff = self .chain_health_backoff_config @@ -408,6 +415,7 @@ impl ProposalGenerator { if let Some(value) = pipeline_backpressure { values_max_block_txns.push(value.max_sending_block_txns_override); values_max_block_bytes.push(value.max_sending_block_bytes_override); + max_txns_from_block_to_execute = value.max_txns_from_block_to_execute; values_proposal_delay.push(Duration::from_millis(value.backpressure_proposal_delay_ms)); PIPELINE_BACKPRESSURE_ON_PROPOSAL_TRIGGERED.observe(1.0); } else { @@ -429,7 +437,12 @@ impl ProposalGenerator { round, ); } - (max_block_txns, max_block_bytes, proposal_delay) + ( + max_block_txns, + max_block_bytes, + max_txns_from_block_to_execute, + proposal_delay, + ) } fn ensure_highest_quorum_cert(&self, round: Round) -> anyhow::Result> { diff --git a/consensus/src/payload_manager.rs b/consensus/src/payload_manager.rs index b9c4de86b0ef2..7f331ff89bf95 100644 --- a/consensus/src/payload_manager.rs +++ b/consensus/src/payload_manager.rs @@ -7,7 +7,7 @@ use crate::{ }; use aptos_consensus_types::{ block::Block, - common::{DataStatus, Payload}, + common::{DataStatus, Payload, ProofWithData}, proof_of_store::ProofOfStore, }; use aptos_crypto::HashValue; @@ -75,6 +75,9 @@ impl PayloadManager { unreachable!("InQuorumStore should be used"); }, Payload::InQuorumStore(proof_with_status) => proof_with_status.proofs, + Payload::InQuorumStoreWithLimit(proof_with_status) => { + proof_with_status.proof_with_data.proofs + }, }) .map(|proof| proof.info().clone()) .collect(); @@ -96,21 +99,30 @@ impl PayloadManager { /// Called from consensus to pre-fetch the transaction behind the batches in the block. pub fn prefetch_payload_data(&self, payload: &Payload, timestamp: u64) { + let request_txns_and_update_status = + move |proof_with_status: &ProofWithData, batch_reader: Arc| { + let receivers = PayloadManager::request_transactions( + proof_with_status.proofs.clone(), + timestamp, + batch_reader.clone(), + ); + proof_with_status + .status + .lock() + .replace(DataStatus::Requested(receivers)); + }; + match self { PayloadManager::DirectMempool => {}, PayloadManager::InQuorumStore(batch_reader, _) => match payload { Payload::InQuorumStore(proof_with_status) => { - if proof_with_status.status.lock().is_none() { - let receivers = PayloadManager::request_transactions( - proof_with_status.proofs.clone(), - timestamp, - batch_reader.clone(), - ); - proof_with_status - .status - .lock() - .replace(DataStatus::Requested(receivers)); - } + request_txns_and_update_status(proof_with_status, batch_reader.clone()); + }, + Payload::InQuorumStoreWithLimit(proof_with_data) => { + request_txns_and_update_status( + &proof_with_data.proof_with_data, + batch_reader.clone(), + ); }, Payload::DirectMempool(_) => { unreachable!() @@ -121,83 +133,112 @@ impl PayloadManager { /// Extract transaction from a given block /// Assumes it is never called for the same block concurrently. Otherwise status can be None. - pub async fn get_transactions(&self, block: &Block) -> ExecutorResult> { + pub async fn get_transactions( + &self, + block: &Block, + ) -> ExecutorResult<(Vec, Option)> { let payload = match block.payload() { Some(p) => p, - None => return Ok(Vec::new()), + None => return Ok((Vec::new(), None)), }; + async fn process_payload( + proof_with_data: &ProofWithData, + batch_reader: Arc, + block: &Block, + ) -> ExecutorResult> { + let status = proof_with_data.status.lock().take(); + match status.expect("Should have been updated before.") { + DataStatus::Cached(data) => { + counters::QUORUM_BATCH_READY_COUNT.inc(); + proof_with_data + .status + .lock() + .replace(DataStatus::Cached(data.clone())); + Ok(data) + }, + DataStatus::Requested(receivers) => { + let _timer = counters::BATCH_WAIT_DURATION.start_timer(); + let mut vec_ret = Vec::new(); + if !receivers.is_empty() { + debug!( + "QSE: waiting for data on {} receivers, block_round {}", + receivers.len(), + block.round() + ); + } + for (digest, rx) in receivers { + match rx.await { + Err(e) => { + // We probably advanced epoch already. + warn!( + "Oneshot channel to get a batch was dropped with error {:?}", + e + ); + let new_receivers = PayloadManager::request_transactions( + proof_with_data.proofs.clone(), + block.timestamp_usecs(), + batch_reader.clone(), + ); + // Could not get all data so requested again + proof_with_data + .status + .lock() + .replace(DataStatus::Requested(new_receivers)); + return Err(DataNotFound(digest)); + }, + Ok(Ok(data)) => { + vec_ret.push(data); + }, + Ok(Err(e)) => { + let new_receivers = PayloadManager::request_transactions( + proof_with_data.proofs.clone(), + block.timestamp_usecs(), + batch_reader.clone(), + ); + // Could not get all data so requested again + proof_with_data + .status + .lock() + .replace(DataStatus::Requested(new_receivers)); + return Err(e); + }, + } + } + let ret: Vec = vec_ret.into_iter().flatten().collect(); + // execution asks for the data twice, so data is cached here for the second time. + proof_with_data + .status + .lock() + .replace(DataStatus::Cached(ret.clone())); + Ok(ret) + }, + } + } + match (self, payload) { - (PayloadManager::DirectMempool, Payload::DirectMempool(txns)) => Ok(txns.clone()), + (PayloadManager::DirectMempool, Payload::DirectMempool(txns)) => { + Ok((txns.clone(), None)) + }, ( PayloadManager::InQuorumStore(batch_reader, _), Payload::InQuorumStore(proof_with_data), - ) => { - let status = proof_with_data.status.lock().take(); - match status.expect("Should have been updated before.") { - DataStatus::Cached(data) => { - counters::QUORUM_BATCH_READY_COUNT.inc(); - proof_with_data - .status - .lock() - .replace(DataStatus::Cached(data.clone())); - Ok(data) - }, - DataStatus::Requested(receivers) => { - let _timer = counters::BATCH_WAIT_DURATION.start_timer(); - let mut vec_ret = Vec::new(); - if !receivers.is_empty() { - debug!( - "QSE: waiting for data on {} receivers, block_round {}", - receivers.len(), - block.round() - ); - } - for (digest, rx) in receivers { - match rx.await { - Err(e) => { - // We probably advanced epoch already. - warn!("Oneshot channel to get a batch was dropped with error {:?}", e); - let new_receivers = PayloadManager::request_transactions( - proof_with_data.proofs.clone(), - block.timestamp_usecs(), - batch_reader.clone(), - ); - // Could not get all data so requested again - proof_with_data - .status - .lock() - .replace(DataStatus::Requested(new_receivers)); - return Err(DataNotFound(digest)); - }, - Ok(Ok(data)) => { - vec_ret.push(data); - }, - Ok(Err(e)) => { - let new_receivers = PayloadManager::request_transactions( - proof_with_data.proofs.clone(), - block.timestamp_usecs(), - batch_reader.clone(), - ); - // Could not get all data so requested again - proof_with_data - .status - .lock() - .replace(DataStatus::Requested(new_receivers)); - return Err(e); - }, - } - } - let ret: Vec = vec_ret.into_iter().flatten().collect(); - // execution asks for the data twice, so data is cached here for the second time. - proof_with_data - .status - .lock() - .replace(DataStatus::Cached(ret.clone())); - Ok(ret) - }, - } - }, + ) => Ok(( + process_payload(proof_with_data, batch_reader.clone(), block).await?, + None, + )), + ( + PayloadManager::InQuorumStore(batch_reader, _), + Payload::InQuorumStoreWithLimit(proof_with_data), + ) => Ok(( + process_payload( + &proof_with_data.proof_with_data, + batch_reader.clone(), + block, + ) + .await?, + proof_with_data.max_txns_to_execute, + )), (_, _) => unreachable!( "Wrong payload {} epoch {}, round {}, id {}", payload, diff --git a/consensus/src/quorum_store/tests/proof_manager_test.rs b/consensus/src/quorum_store/tests/proof_manager_test.rs index e02040c01ffa0..44bd51e9b4e10 100644 --- a/consensus/src/quorum_store/tests/proof_manager_test.rs +++ b/consensus/src/quorum_store/tests/proof_manager_test.rs @@ -43,12 +43,11 @@ fn create_proof_with_gas( ) } -async fn get_proposal_and_assert( +async fn get_proposal( proof_manager: &mut ProofManager, max_txns: u64, filter: &[BatchInfo], - expected: &[ProofOfStore], -) { +) -> Payload { let (callback_tx, callback_rx) = oneshot::channel(); let filter_set = HashSet::from_iter(filter.iter().cloned()); let req = GetPayloadCommand::GetPayloadRequest( @@ -60,16 +59,45 @@ async fn get_proposal_and_assert( ); proof_manager.handle_proposal_request(req); let GetPayloadResponse::GetPayloadResponse(payload) = callback_rx.await.unwrap().unwrap(); - if let Payload::InQuorumStore(proofs) = payload { - assert_eq!(proofs.proofs.len(), expected.len()); - for proof in proofs.proofs { - assert!(expected.contains(&proof)); - } - } else { - panic!("Unexpected variant") + payload +} + +fn assert_payload_response( + payload: Payload, + expected: &[ProofOfStore], + max_txns_from_block_to_execute: Option, +) { + match payload { + Payload::InQuorumStore(proofs) => { + assert_eq!(proofs.proofs.len(), expected.len()); + for proof in proofs.proofs { + assert!(expected.contains(&proof)); + } + }, + Payload::InQuorumStoreWithLimit(proofs) => { + assert_eq!(proofs.proof_with_data.proofs.len(), expected.len()); + for proof in proofs.proof_with_data.proofs { + assert!(expected.contains(&proof)); + } + assert_eq!(proofs.max_txns_to_execute, max_txns_from_block_to_execute); + }, + _ => panic!("Unexpected variant"), } } +async fn get_proposal_and_assert( + proof_manager: &mut ProofManager, + max_txns: u64, + filter: &[BatchInfo], + expected: &[ProofOfStore], +) { + assert_payload_response( + get_proposal(proof_manager, max_txns, filter).await, + expected, + None, + ); +} + #[tokio::test] async fn test_block_request() { let mut proof_manager = create_proof_manager(); @@ -77,7 +105,24 @@ async fn test_block_request() { let proof = create_proof(PeerId::random(), 10, 1); proof_manager.receive_proofs(vec![proof.clone()]); - get_proposal_and_assert(&mut proof_manager, 100, &[], &vec![proof.clone()]).await; + get_proposal_and_assert(&mut proof_manager, 100, &[], &vec![proof]).await; +} + +#[tokio::test] +async fn test_max_txns_from_block_to_execute() { + let mut proof_manager = create_proof_manager(); + + let proof = create_proof(PeerId::random(), 10, 1); + proof_manager.receive_proofs(vec![proof.clone()]); + + let payload = get_proposal(&mut proof_manager, 100, &[]).await; + // convert payload to v2 format and assert + let max_txns_from_block_to_execute = 10; + assert_payload_response( + payload.transform_to_quorum_store_v2(Some(max_txns_from_block_to_execute)), + &vec![proof], + Some(max_txns_from_block_to_execute), + ); } #[tokio::test] diff --git a/consensus/src/test_utils/mock_state_computer.rs b/consensus/src/test_utils/mock_state_computer.rs index f3003979742ba..3c3d6b5e1446a 100644 --- a/consensus/src/test_utils/mock_state_computer.rs +++ b/consensus/src/test_utils/mock_state_computer.rs @@ -65,7 +65,8 @@ impl MockStateComputer { .lock() .remove(&block.id()) .ok_or_else(|| format_err!("Cannot find block"))?; - let mut payload_txns = self.payload_manager.get_transactions(block.block()).await?; + let (mut payload_txns, _max_txns_from_block_to_execute) = + self.payload_manager.get_transactions(block.block()).await?; txns.append(&mut payload_txns); } // they may fail during shutdown diff --git a/consensus/src/util/db_tool.rs b/consensus/src/util/db_tool.rs index 82369167d84f5..1de1dc8f2e2e7 100644 --- a/consensus/src/util/db_tool.rs +++ b/consensus/src/util/db_tool.rs @@ -9,7 +9,7 @@ use crate::{ }, }; use anyhow::{bail, Result}; -use aptos_consensus_types::{block::Block, common::Payload}; +use aptos_consensus_types::{block::Block, common::Payload, proof_of_store::ProofOfStore}; use aptos_crypto::HashValue; use aptos_types::transaction::{SignedTransaction, Transaction}; use clap::Parser; @@ -65,26 +65,34 @@ pub fn extract_txns_from_block<'a>( match block.payload().as_ref() { Some(payload) => { let mut block_txns = Vec::new(); + + let extract_txns_from_proof_stores = move |proofs: &Vec| { + for proof in proofs { + let digest = proof.digest(); + if let Some(batch) = all_batches.get(digest) { + if let Some(txns) = batch.payload() { + block_txns.extend(txns); + } else { + bail!("Payload is not found for batch ({digest})."); + } + } else { + bail!("Batch ({digest}) is not found."); + } + } + Ok(block_txns) + }; + match payload { Payload::DirectMempool(_) => { bail!("DirectMempool is not supported."); }, Payload::InQuorumStore(proof_with_data) => { - for proof in &proof_with_data.proofs { - let digest = proof.digest(); - if let Some(batch) = all_batches.get(digest) { - if let Some(txns) = batch.payload() { - block_txns.extend(txns); - } else { - bail!("Payload is not found for batch ({digest})."); - } - } else { - bail!("Batch ({digest}) is not found."); - } - } + extract_txns_from_proof_stores(&proof_with_data.proofs) + }, + Payload::InQuorumStoreWithLimit(proof_with_data) => { + extract_txns_from_proof_stores(&proof_with_data.proof_with_data.proofs) }, } - Ok(block_txns) }, None => Ok(vec![]), } diff --git a/testsuite/generate-format/tests/staged/consensus.yaml b/testsuite/generate-format/tests/staged/consensus.yaml index 3d69260096c87..38fee8400bd97 100644 --- a/testsuite/generate-format/tests/staged/consensus.yaml +++ b/testsuite/generate-format/tests/staged/consensus.yaml @@ -600,6 +600,10 @@ Payload: InQuorumStore: NEWTYPE: TYPENAME: ProofWithData + 2: + InQuorumStoreWithLimit: + NEWTYPE: + TYPENAME: ProofWithDataWithTxnLimit Pepper: NEWTYPESTRUCT: TUPLEARRAY: @@ -621,6 +625,12 @@ ProofWithData: - proofs: SEQ: TYPENAME: ProofOfStore +ProofWithDataWithTxnLimit: + STRUCT: + - proof_with_data: + TYPENAME: ProofWithData + - max_txns_to_execute: + OPTION: U64 ProposalExt: ENUM: 0: diff --git a/testsuite/smoke-test/src/txn_emitter.rs b/testsuite/smoke-test/src/txn_emitter.rs index 9d00b913454f9..a7e0ec02580cf 100644 --- a/testsuite/smoke-test/src/txn_emitter.rs +++ b/testsuite/smoke-test/src/txn_emitter.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::smoke_test_environment::new_local_swarm_with_aptos; +use crate::smoke_test_environment::{new_local_swarm_with_aptos, SwarmBuilder}; use anyhow::ensure; use aptos_forge::{ args::TransactionTypeArg, EmitJobMode, EmitJobRequest, EntryPoints, NodeExt, Result, Swarm, @@ -9,7 +9,7 @@ use aptos_forge::{ }; use aptos_sdk::{transaction_builder::TransactionFactory, types::PeerId}; use rand::{rngs::OsRng, SeedableRng}; -use std::time::Duration; +use std::{sync::Arc, time::Duration}; pub async fn generate_traffic( swarm: &mut dyn Swarm, @@ -123,3 +123,40 @@ async fn test_txn_emmitter() { assert!(txn_stat.submitted > 30); assert!(txn_stat.committed > 30); } + +#[tokio::test] +async fn test_txn_emmitter_with_high_pending_latency() { + let mut swarm = SwarmBuilder::new_local(1) + .with_aptos() + .with_init_config(Arc::new(|_, conf, _| { + conf.api.failpoints_enabled = true; + conf.consensus.pipeline_backpressure.truncate(1); + conf.consensus.pipeline_backpressure[0].max_txns_from_block_to_execute = Some(2); + conf.consensus.pipeline_backpressure[0].back_pressure_pipeline_latency_limit_ms = 0; + })) + .build() + .await; + + let all_validators = swarm.validators().map(|v| v.peer_id()).collect::>(); + + let txn_stat = generate_traffic( + &mut swarm, + &all_validators, + Duration::from_secs(20), + 100, + vec![vec![( + TransactionType::CallCustomModules { + entry_point: EntryPoints::SmartTablePicture { + length: 128 * 1024, + num_points_per_txn: 256, + }, + num_modules: 1, + use_account_pool: false, + }, + 1, + )]], + ) + .await + .unwrap(); + assert!(txn_stat.submitted > 30); +} From 78dd9431a2f398ee26c2ce9a74c2f181a208f752 Mon Sep 17 00:00:00 2001 From: Sital Kedia Date: Wed, 7 Feb 2024 19:28:08 -0800 Subject: [PATCH 038/328] [Txn Emitter] Various improvements to the transaction emitter (#11907) --- crates/transaction-emitter-lib/src/args.rs | 9 +- .../src/emitter/account_minter.rs | 201 ++++++++------- .../src/emitter/mod.rs | 236 +++++++++++------- .../src/emitter/transaction_executor.rs | 33 ++- .../transaction-emitter-lib/src/wrappers.rs | 16 +- 5 files changed, 288 insertions(+), 207 deletions(-) diff --git a/crates/transaction-emitter-lib/src/args.rs b/crates/transaction-emitter-lib/src/args.rs index 2087ac0347619..822a6054c85dd 100644 --- a/crates/transaction-emitter-lib/src/args.rs +++ b/crates/transaction-emitter-lib/src/args.rs @@ -176,9 +176,16 @@ pub struct EmitArgs { #[clap(long)] pub expected_gas_per_txn: Option, - #[clap(long)] + #[clap(long, conflicts_with = "num_accounts")] pub max_transactions_per_account: Option, + #[clap(long, conflicts_with = "max_transactions_per_account")] + pub num_accounts: Option, + + #[clap(long, default_value = "false")] + /// Skip minting account during initialization + pub skip_minting_accounts: bool, + #[clap(long)] pub latency_polling_interval_s: Option, diff --git a/crates/transaction-emitter-lib/src/emitter/account_minter.rs b/crates/transaction-emitter-lib/src/emitter/account_minter.rs index 8af17d6484de8..da0a2ac8d24c7 100644 --- a/crates/transaction-emitter-lib/src/emitter/account_minter.rs +++ b/crates/transaction-emitter-lib/src/emitter/account_minter.rs @@ -20,10 +20,11 @@ use core::{ cmp::min, result::Result::{Err, Ok}, }; -use futures::StreamExt; +use futures::{future::try_join_all, StreamExt}; use rand::{rngs::StdRng, Rng, SeedableRng}; use std::{ path::Path, + sync::Arc, time::{Duration, Instant}, }; @@ -47,6 +48,22 @@ impl<'t> AccountMinter<'t> { } } + pub fn get_needed_balance_per_account(&self, req: &EmitJobRequest, num_accounts: usize) -> u64 { + if let Some(val) = req.coins_per_account_override { + val + } else { + (req.expected_max_txns / num_accounts as u64) + .checked_mul(SEND_AMOUNT + req.expected_gas_per_txn * req.gas_price) + .unwrap() + .checked_add( + req.max_gas_per_txn * req.gas_price + // for module publishing + + 2 * req.max_gas_per_txn * req.gas_price * req.init_gas_price_multiplier, + ) + .unwrap() // extra coins for secure to pay none zero gas price + } + } + /// workflow of create accounts: /// 1. Use given source_account as the money source /// 1a. Optionally, and if it is root account, mint balance to that account @@ -57,30 +74,17 @@ impl<'t> AccountMinter<'t> { /// example: /// requested totally 100 new accounts with 10 endpoints /// will create 10 seed accounts, each seed account create 10 new accounts - pub async fn create_accounts( + pub async fn create_and_fund_accounts( &mut self, txn_executor: &dyn ReliableTransactionSubmitter, req: &EmitJobRequest, max_submit_batch_size: usize, - total_requested_accounts: usize, - ) -> Result> { - let mut accounts = vec![]; - let expected_num_seed_accounts = (total_requested_accounts / 50) - .clamp(1, (total_requested_accounts as f32).sqrt() as usize + 1); - let num_accounts = total_requested_accounts - accounts.len(); // Only minting extra accounts - let coins_per_account = if let Some(val) = req.coins_per_account_override { - val - } else { - (req.expected_max_txns / total_requested_accounts as u64) - .checked_mul(SEND_AMOUNT + req.expected_gas_per_txn * req.gas_price) - .unwrap() - .checked_add( - req.max_gas_per_txn * req.gas_price - // for module publishing - + 2 * req.max_gas_per_txn * req.gas_price * req.init_gas_price_multiplier, - ) - .unwrap() // extra coins for secure to pay none zero gas price - }; + local_accounts: Vec>, + ) -> Result<()> { + let num_accounts = local_accounts.len(); + let expected_num_seed_accounts = + (num_accounts / 50).clamp(1, (num_accounts as f32).sqrt() as usize + 1); + let coins_per_account = self.get_needed_balance_per_account(req, num_accounts); let txn_factory = self.txn_factory.clone(); let expected_children_per_seed_account = (num_accounts + expected_num_seed_accounts - 1) / expected_num_seed_accounts; @@ -214,8 +218,7 @@ impl<'t> AccountMinter<'t> { ) .await?; let actual_num_seed_accounts = seed_accounts.len(); - let num_new_child_accounts = - (num_accounts + actual_num_seed_accounts - 1) / actual_num_seed_accounts; + info!( "Completed creating {} seed accounts in {}s, each with {} coins, request stats: {}", seed_accounts.len(), @@ -233,48 +236,50 @@ impl<'t> AccountMinter<'t> { let start = Instant::now(); let request_counters = txn_executor.create_counter_state(); + let approx_accounts_per_seed = + (num_accounts + actual_num_seed_accounts - 1) / actual_num_seed_accounts; + + let local_accounts_by_seed: Vec>> = local_accounts + .chunks(approx_accounts_per_seed) + .map(|chunk| chunk.to_vec()) + .collect(); + // For each seed account, create a future and transfer coins from that seed account to new accounts - let account_futures = seed_accounts.into_iter().map(|seed_account| { - // Spawn new threads - create_and_fund_new_accounts( - seed_account, - num_new_child_accounts, - coins_per_account, - max_submit_batch_size, - txn_executor, - &txn_factory, - StdRng::from_rng(self.rng()).unwrap(), - &request_counters, - ) - }); + let account_futures = seed_accounts + .into_iter() + .zip(local_accounts_by_seed.into_iter()) + .map(|(seed_account, accounts)| { + // Spawn new threads + create_and_fund_new_accounts( + seed_account, + accounts, + coins_per_account, + max_submit_batch_size, + txn_executor, + &txn_factory, + &request_counters, + ) + }); // Each future creates 10 accounts, limit concurrency to 1000. let stream = futures::stream::iter(account_futures).buffer_unordered(CREATION_PARALLELISM); // wait for all futures to complete - let mut created_accounts = stream + let _: Vec<_> = stream .collect::>() .await .into_iter() .collect::>>() .map_err(|e| format_err!("Failed to create accounts: {:?}", e))? .into_iter() - .flatten() .collect(); - accounts.append(&mut created_accounts); - assert!( - accounts.len() >= num_accounts, - "Something wrong in create_accounts, wanted to create {}, only have {}", - total_requested_accounts, - accounts.len() - ); info!( "Successfully completed creating {} accounts in {}s, request stats: {}", - actual_num_seed_accounts * num_new_child_accounts, + local_accounts.len(), start.elapsed().as_secs(), request_counters.show_simple(), ); - Ok(accounts) + Ok(()) } pub async fn mint_to_root( @@ -430,54 +435,41 @@ impl<'t> AccountMinter<'t> { /// Create `num_new_accounts` by transferring coins from `source_account`. Return Vec of created /// accounts -async fn create_and_fund_new_accounts( +async fn create_and_fund_new_accounts( mut source_account: LocalAccount, - num_new_accounts: usize, + accounts: Vec>, coins_per_new_account: u64, max_num_accounts_per_batch: usize, txn_executor: &dyn ReliableTransactionSubmitter, txn_factory: &TransactionFactory, - mut rng: R, counters: &CounterState, -) -> Result> -where - R: ::rand_core::RngCore + ::rand_core::CryptoRng, -{ - let mut i = 0; - let mut accounts = vec![]; - - while i < num_new_accounts { - let batch_size = min(max_num_accounts_per_batch, num_new_accounts - i); - let mut batch = { - let batch = gen_reusable_accounts(txn_executor, batch_size, &mut rng).await?; - let creation_requests: Vec<_> = batch - .as_slice() - .iter() - .map(|account| { - create_and_fund_account_request( - &mut source_account, - coins_per_new_account, - account.public_key(), - txn_factory, - ) - }) - .collect(); - - txn_executor - .execute_transactions_with_counter(&creation_requests, counters) - .await - .with_context(|| format!("Account {} couldn't mint", source_account.address()))?; - - batch - }; +) -> Result<()> { + let accounts_by_batch = accounts + .chunks(max_num_accounts_per_batch) + .map(|chunk| chunk.to_vec()) + .collect::>(); + for batch in accounts_by_batch { + let creation_requests: Vec<_> = batch + .iter() + .map(|account| { + create_and_fund_account_request( + &mut source_account, + coins_per_new_account, + account.public_key(), + txn_factory, + ) + }) + .collect(); - i += batch.len(); - accounts.append(&mut batch); + txn_executor + .execute_transactions_with_counter(&creation_requests, counters) + .await + .with_context(|| format!("Account {} couldn't mint", source_account.address()))?; } - Ok(accounts) + Ok(()) } -async fn gen_reusable_accounts( +pub async fn gen_reusable_accounts( txn_executor: &dyn ReliableTransactionSubmitter, num_accounts: usize, rng: &mut R, @@ -485,26 +477,33 @@ async fn gen_reusable_accounts( where R: rand_core::RngCore + ::rand_core::CryptoRng, { - let mut vasp_accounts = vec![]; + let mut account_keys = vec![]; + let mut addresses = vec![]; let mut i = 0; while i < num_accounts { - vasp_accounts.push(gen_reusable_account(txn_executor, rng).await?); + let account_key = AccountKey::generate(rng); + addresses.push(account_key.authentication_key().account_address()); + account_keys.push(account_key); i += 1; } - Ok(vasp_accounts) -} - -async fn gen_reusable_account( - txn_executor: &dyn ReliableTransactionSubmitter, - rng: &mut R, -) -> Result -where - R: ::rand_core::RngCore + ::rand_core::CryptoRng, -{ - let account_key = AccountKey::generate(rng); - let address = account_key.authentication_key().account_address(); - let sequence_number = txn_executor.query_sequence_number(address).await?; - Ok(LocalAccount::new(address, account_key, sequence_number)) + let result_futures = addresses + .iter() + .map(|address| txn_executor.query_sequence_number(*address)) + .collect::>(); + let seq_nums: Vec<_> = try_join_all(result_futures).await?.into_iter().collect(); + + let accounts = account_keys + .into_iter() + .zip(seq_nums.into_iter()) + .map(|(account_key, sequence_number)| { + LocalAccount::new( + account_key.authentication_key().account_address(), + account_key, + sequence_number, + ) + }) + .collect(); + Ok(accounts) } pub fn create_and_fund_account_request( diff --git a/crates/transaction-emitter-lib/src/emitter/mod.rs b/crates/transaction-emitter-lib/src/emitter/mod.rs index ab7adfe6d275c..54b343f204949 100644 --- a/crates/transaction-emitter-lib/src/emitter/mod.rs +++ b/crates/transaction-emitter-lib/src/emitter/mod.rs @@ -7,7 +7,7 @@ pub mod submission_worker; pub mod transaction_executor; use crate::emitter::{ - account_minter::AccountMinter, + account_minter::{gen_reusable_accounts, AccountMinter}, stats::{DynamicStatsTracking, TxnStats}, submission_worker::SubmissionWorker, transaction_executor::RestApiReliableTransactionSubmitter, @@ -22,7 +22,9 @@ use aptos_sdk::{ transaction_builder::{aptos_stdlib, TransactionFactory}, types::{transaction::SignedTransaction, LocalAccount}, }; -use aptos_transaction_generator_lib::{create_txn_generator_creator, TransactionType}; +use aptos_transaction_generator_lib::{ + create_txn_generator_creator, ReliableTransactionSubmitter, TransactionType, +}; use futures::future::{try_join_all, FutureExt}; use once_cell::sync::Lazy; use rand::{rngs::StdRng, seq::IteratorRandom, Rng}; @@ -60,9 +62,7 @@ pub struct EmitModeParams { pub txn_expiration_time_secs: u64, pub endpoints: usize, - pub workers_per_endpoint: usize, - pub accounts_per_worker: usize, - + pub num_accounts: usize, /// Max transactions per account in mempool pub transactions_per_account: usize, pub max_submit_batch_size: usize, @@ -113,6 +113,26 @@ impl EmitJobMode { } } +#[derive(Clone, Debug)] +pub enum NumAccountsMode { + NumAccounts(usize), + TransactionsPerAccount(usize), +} + +impl NumAccountsMode { + pub fn create(num_accounts: Option, transactions_per_account: Option) -> Self { + match (num_accounts, transactions_per_account) { + (Some(num_accounts), None) => Self::NumAccounts(num_accounts), + (None, Some(transactions_per_account)) => { + Self::TransactionsPerAccount(transactions_per_account) + }, + _ => panic!( + "Either num_accounts or transactions_per_account should be set, but not both" + ), + } + } +} + /// total coins consumed are less than 2 * max_txns * expected_gas_per_txn * gas_price, /// which is by default 100000000000 * 100000, but can be overriden. #[derive(Clone, Debug)] @@ -128,14 +148,13 @@ pub struct EmitJobRequest { init_gas_price_multiplier: u64, mint_to_root: bool, + skip_minting_accounts: bool, txn_expiration_time_secs: u64, init_expiration_multiplier: f64, init_retry_interval: Duration, - - max_transactions_per_account: usize, - + num_accounts_mode: NumAccountsMode, expected_max_txns: u64, expected_gas_per_txn: u64, prompt_before_spending: bool, @@ -161,10 +180,11 @@ impl Default for EmitJobRequest { init_max_gas_per_txn: aptos_global_constants::MAX_GAS_AMOUNT, init_gas_price_multiplier: 10, mint_to_root: false, + skip_minting_accounts: false, txn_expiration_time_secs: 60, init_expiration_multiplier: 3.0, init_retry_interval: Duration::from_secs(10), - max_transactions_per_account: 20, + num_accounts_mode: NumAccountsMode::TransactionsPerAccount(20), expected_max_txns: MAX_TXNS, expected_gas_per_txn: aptos_global_constants::MAX_GAS_AMOUNT, prompt_before_spending: false, @@ -253,8 +273,8 @@ impl EmitJobRequest { self } - pub fn max_transactions_per_account(mut self, max_transactions_per_account: usize) -> Self { - self.max_transactions_per_account = max_transactions_per_account; + pub fn num_accounts_mode(mut self, num_accounts: NumAccountsMode) -> Self { + self.num_accounts_mode = num_accounts; self } @@ -286,6 +306,11 @@ impl EmitJobRequest { self } + pub fn skip_minting_accounts(mut self) -> Self { + self.skip_minting_accounts = true; + self + } + pub fn calculate_mode_params(&self) -> EmitModeParams { let clients_count = self.rest_clients.len(); @@ -294,11 +319,20 @@ impl EmitJobRequest { // The target mempool backlog is set to be 3x of the target TPS because of the on an average, // we can ~3 blocks in consensus queue. As long as we have 3x the target TPS as backlog, // it should be enough to produce the target TPS. - let transactions_per_account = self.max_transactions_per_account; - let num_workers_per_endpoint = max( - mempool_backlog / (clients_count * transactions_per_account), - 1, - ); + let (transactions_per_account, num_accounts) = match self.num_accounts_mode { + NumAccountsMode::NumAccounts(num_accounts) => { + assert_eq!( + mempool_backlog % num_accounts, + 0, + "mempool_backlog should be a multiple of num_accounts" + ); + (mempool_backlog / num_accounts, num_accounts) + }, + NumAccountsMode::TransactionsPerAccount(transactions_per_account) => ( + transactions_per_account, + mempool_backlog / transactions_per_account, + ), + }; info!( " Transaction emitter target mempool backlog is {}", @@ -306,21 +340,19 @@ impl EmitJobRequest { ); info!( - " Will use {} clients and {} workers per client", - clients_count, num_workers_per_endpoint + " Will use {} clients and {} total number of accounts", + clients_count, num_accounts ); EmitModeParams { wait_millis: 0, txn_expiration_time_secs: self.txn_expiration_time_secs, - transactions_per_account: transactions_per_account - .min(num_workers_per_endpoint * clients_count), + num_accounts, + transactions_per_account, max_submit_batch_size: DEFAULT_MAX_SUBMIT_TRANSACTION_BATCH_SIZE, worker_offset_mode: WorkerOffsetMode::Jitter { jitter_millis: 5000, }, - accounts_per_worker: 1, - workers_per_endpoint: num_workers_per_endpoint, endpoints: clients_count, check_account_sequence_only_once_fraction: 0.0, check_account_sequence_sleep: self.latency_polling_interval, @@ -349,27 +381,32 @@ impl EmitJobRequest { // In case we set a very low TPS, we need to still be able to spread out // transactions, at least to the seconds granularity, so we reduce transactions_per_account // if needed. - let transactions_per_account = min(self.max_transactions_per_account, tps); + let transactions_per_account = match self.num_accounts_mode { + NumAccountsMode::TransactionsPerAccount(transactions_per_account) => { + transactions_per_account + }, + _ => 10, + }; + let transactions_per_account = min(transactions_per_account, tps); assert!( transactions_per_account > 0, "TPS ({}) needs to be larger than 0", tps, ); - - // compute num_workers_per_endpoint, so that target_tps is achieved. - let num_workers_per_endpoint = - (tps * wait_seconds as usize) / clients_count / transactions_per_account; - assert!( - num_workers_per_endpoint > 0, - "Requested too small TPS: {}", - tps - ); + let num_accounts = match self.num_accounts_mode { + NumAccountsMode::NumAccounts(num_accounts) => num_accounts, + NumAccountsMode::TransactionsPerAccount(_) => { + let total_txns = tps * wait_seconds as usize; + let num_accounts = total_txns / transactions_per_account; + assert!(num_accounts > 0, "Requested too small TPS: {}", tps); + num_accounts + }, + }; info!( " Transaction emitter targetting {} TPS, expecting {} TPS", tps, - clients_count * num_workers_per_endpoint * transactions_per_account - / wait_seconds as usize + num_accounts * transactions_per_account / wait_seconds as usize ); info!( @@ -378,20 +415,18 @@ impl EmitJobRequest { ); // sample latency on 2% of requests, or at least once every 5s. - let sample_latency_fraction = 1.0_f32.min(0.02_f32.max( - wait_seconds as f32 - / (clients_count * num_workers_per_endpoint) as f32 - / 5.0_f32, - )); + let sample_latency_fraction = + 1.0_f32.min(0.02_f32.max(wait_seconds as f32 / num_accounts as f32 / 5.0_f32)); info!( - " Will use {} clients and {} workers per client, sampling latency on {}", - clients_count, num_workers_per_endpoint, sample_latency_fraction + " Will use {} clients and {} accounts, sampling latency on {}", + clients_count, num_accounts, sample_latency_fraction ); EmitModeParams { wait_millis: wait_seconds * 1000, txn_expiration_time_secs: self.txn_expiration_time_secs, + num_accounts, transactions_per_account, max_submit_batch_size: DEFAULT_MAX_SUBMIT_TRANSACTION_BATCH_SIZE, worker_offset_mode: if let EmitJobMode::WaveTps { @@ -407,8 +442,6 @@ impl EmitJobRequest { } else { WorkerOffsetMode::Spread }, - accounts_per_worker: 1, - workers_per_endpoint: num_workers_per_endpoint, endpoints: clients_count, check_account_sequence_only_once_fraction: 1.0 - sample_latency_fraction, check_account_sequence_sleep: self.latency_polling_interval, @@ -420,7 +453,7 @@ impl EmitJobRequest { impl EmitModeParams { pub fn get_all_start_sleep_durations(&self, mut rng: ::rand::rngs::StdRng) -> Vec { - let index_range = 0..self.endpoints * self.workers_per_endpoint; + let index_range = 0..self.num_accounts; match self.worker_offset_mode { WorkerOffsetMode::NoOffset => index_range.map(|_i| 0).collect(), WorkerOffsetMode::Jitter { jitter_millis } => index_range @@ -434,8 +467,8 @@ impl EmitModeParams { .collect(), WorkerOffsetMode::Spread => index_range .map(|i| { - let start_offset_multiplier_millis = self.wait_millis as f64 - / (self.workers_per_endpoint * self.endpoints) as f64; + let start_offset_multiplier_millis = + self.wait_millis as f64 / (self.num_accounts) as f64; (start_offset_multiplier_millis * i as f64) as u64 }) .collect(), @@ -455,7 +488,7 @@ impl EmitModeParams { / time_scale }; - let workers = self.endpoints * self.workers_per_endpoint; + let workers = self.num_accounts; let multiplier = workers as f64 / integral(self.wait_millis as f64); let mut result = Vec::new(); @@ -587,12 +620,11 @@ impl TxnEmitter { ensure!(req.gas_price > 0, "gas_price is required to be non zero"); let mode_params = req.calculate_mode_params(); - let workers_per_endpoint = mode_params.workers_per_endpoint; - let num_workers = req.rest_clients.len() * workers_per_endpoint; - let num_accounts = num_workers * mode_params.accounts_per_worker; + let num_accounts = mode_params.num_accounts; + info!( - "Will use {} workers per endpoint for a total of {} endpoint clients and {} accounts", - workers_per_endpoint, num_workers, num_accounts + "Will use total of {} endpoint clients and {} accounts", + num_accounts, num_accounts ); let txn_factory = self @@ -617,6 +649,7 @@ impl TxnEmitter { &init_txn_factory, &req, mode_params.max_submit_batch_size, + req.skip_minting_accounts, seed, num_accounts, init_retries, @@ -651,12 +684,10 @@ impl TxnEmitter { tokio::time::sleep(req.coordination_delay_between_instances).await; } - let total_workers = req.rest_clients.len() * workers_per_endpoint; - - let check_account_sequence_only_once_for = (0..total_workers) + let check_account_sequence_only_once_for = (0..num_accounts) .choose_multiple( &mut self.from_rng(), - (mode_params.check_account_sequence_only_once_fraction * total_workers as f32) + (mode_params.check_account_sequence_only_once_fraction * num_accounts as f32) as usize, ) .into_iter() @@ -664,8 +695,8 @@ impl TxnEmitter { info!( "Checking account sequence and counting latency for {} out of {} total_workers", - total_workers - check_account_sequence_only_once_for.len(), - total_workers + num_accounts - check_account_sequence_only_once_for.len(), + num_accounts ); let all_start_sleep_durations = mode_params.get_all_start_sleep_durations(self.from_rng()); @@ -674,32 +705,27 @@ impl TxnEmitter { // so we create them all first, before starting them - so they start at the right time for // traffic pattern to be correct. info!("Tx emitter creating workers"); - let mut submission_workers = - Vec::with_capacity(workers_per_endpoint * req.rest_clients.len()); - for _ in 0..workers_per_endpoint { - for client in &req.rest_clients { - let accounts = - all_accounts.split_off(all_accounts.len() - mode_params.accounts_per_worker); - assert!(accounts.len() == mode_params.accounts_per_worker); - - let stop = stop.clone(); - let stats = Arc::clone(&stats); - let txn_generator = txn_generator_creator.create_transaction_generator(); - let worker_index = submission_workers.len(); - - let worker = SubmissionWorker::new( - accounts, - client.clone(), - stop, - mode_params.clone(), - stats, - txn_generator, - all_start_sleep_durations[worker_index], - check_account_sequence_only_once_for.contains(&worker_index), - self.from_rng(), - ); - submission_workers.push(worker); - } + let mut submission_workers = Vec::with_capacity(num_accounts); + for index in 0..num_accounts { + let client = &req.rest_clients[index % req.rest_clients.len()]; + let accounts = all_accounts.split_off(all_accounts.len() - 1); + let stop = stop.clone(); + let stats = Arc::clone(&stats); + let txn_generator = txn_generator_creator.create_transaction_generator(); + let worker_index = submission_workers.len(); + + let worker = SubmissionWorker::new( + accounts, + client.clone(), + stop, + mode_params.clone(), + stats, + txn_generator, + all_start_sleep_durations[worker_index], + check_account_sequence_only_once_for.contains(&worker_index), + self.from_rng(), + ); + submission_workers.push(worker); } info!("Tx emitter workers created"); @@ -1037,6 +1063,7 @@ pub async fn create_accounts( txn_factory: &TransactionFactory, req: &EmitJobRequest, max_submit_batch_size: usize, + skip_minting_accounts: bool, seed: [u8; 32], num_accounts: usize, retries: usize, @@ -1058,7 +1085,42 @@ pub async fn create_accounts( max_retries: retries, retry_after: req.init_retry_interval, }; - account_minter - .create_accounts(&txn_executor, req, max_submit_batch_size, num_accounts) - .await + let mut rng = StdRng::from_seed(seed); + + let accounts = gen_reusable_accounts(&txn_executor, num_accounts, &mut rng).await?; + info!("Generated re-usable accounts for seed {:?}", seed); + + if !skip_minting_accounts { + let accounts: Vec<_> = accounts.into_iter().map(Arc::new).collect(); + account_minter + .create_and_fund_accounts(&txn_executor, req, max_submit_batch_size, accounts.clone()) + .await?; + let accounts: Vec<_> = accounts + .into_iter() + .map(|a| Arc::try_unwrap(a).unwrap()) + .collect(); + info!("Accounts created and funded"); + Ok(accounts) + } else { + let needed_min_balance = account_minter.get_needed_balance_per_account(req, accounts.len()); + let balance_futures = accounts + .iter() + .map(|account| txn_executor.get_account_balance(account.address())); + let balances: Vec<_> = try_join_all(balance_futures).await?; + accounts + .iter() + .zip(balances) + .for_each(|(account, balance)| { + assert!( + balance >= needed_min_balance, + "Account {} has balance {} < needed_min_balance {}", + account.address(), + balance, + needed_min_balance + ); + }); + + info!("Skipping minting accounts"); + Ok(accounts) + } } diff --git a/crates/transaction-emitter-lib/src/emitter/transaction_executor.rs b/crates/transaction-emitter-lib/src/emitter/transaction_executor.rs index 502a31fba1f7e..b00ccd35ab011 100644 --- a/crates/transaction-emitter-lib/src/emitter/transaction_executor.rs +++ b/crates/transaction-emitter-lib/src/emitter/transaction_executor.rs @@ -252,6 +252,25 @@ async fn submit_and_check( Ok(()) } +pub async fn query_sequence_number_with_client( + rest_client: &RestClient, + account_address: AccountAddress, +) -> Result { + let result = RETRY_POLICY + .retry_if( + move || rest_client.get_account_bcs(account_address), + |error: &RestError| !is_account_not_found(error), + ) + .await; + match result { + Ok(account) => Ok(account.into_inner().sequence_number()), + Err(error) => match is_account_not_found(&error) { + true => Ok(0), + false => Err(error.into()), + }, + } +} + fn is_account_not_found(error: &RestError) -> bool { match error { RestError::Api(error) => matches!(error.error.error_code, AptosErrorCode::AccountNotFound), @@ -273,19 +292,7 @@ impl ReliableTransactionSubmitter for RestApiReliableTransactionSubmitter { } async fn query_sequence_number(&self, account_address: AccountAddress) -> Result { - let result = RETRY_POLICY - .retry_if( - move || self.random_rest_client().get_account_bcs(account_address), - |error: &RestError| !is_account_not_found(error), - ) - .await; - match result { - Ok(account) => Ok(account.into_inner().sequence_number()), - Err(error) => match is_account_not_found(&error) { - true => Ok(0), - false => Err(error.into()), - }, - } + query_sequence_number_with_client(self.random_rest_client(), account_address).await } async fn execute_transactions_with_counter( diff --git a/crates/transaction-emitter-lib/src/wrappers.rs b/crates/transaction-emitter-lib/src/wrappers.rs index 41aa83c5e4ab7..1947d83c15fc3 100644 --- a/crates/transaction-emitter-lib/src/wrappers.rs +++ b/crates/transaction-emitter-lib/src/wrappers.rs @@ -5,7 +5,8 @@ use crate::{ args::{ClusterArgs, EmitArgs}, cluster::Cluster, emitter::{ - create_accounts, parse_seed, stats::TxnStats, EmitJobMode, EmitJobRequest, TxnEmitter, + create_accounts, parse_seed, stats::TxnStats, EmitJobMode, EmitJobRequest, NumAccountsMode, + TxnEmitter, }, instance::Instance, CreateAccountsArgs, @@ -97,10 +98,10 @@ pub async fn emit_transactions_with_cluster( args.coordination_delay_between_instances.unwrap_or(0), )); - if let Some(max_transactions_per_account) = args.max_transactions_per_account { - emit_job_request = - emit_job_request.max_transactions_per_account(max_transactions_per_account); - } + let num_accounts = + NumAccountsMode::create(args.num_accounts, args.max_transactions_per_account); + + emit_job_request = emit_job_request.num_accounts_mode(num_accounts); if let Some(gas_price) = args.gas_price { emit_job_request = emit_job_request.gas_price(gas_price); @@ -143,6 +144,10 @@ pub async fn emit_transactions_with_cluster( .latency_polling_interval(Duration::from_secs_f32(latency_polling_interval_s)); } + if args.skip_minting_accounts { + emit_job_request = emit_job_request.skip_minting_accounts(); + } + let stats = emitter .emit_txn_for_with_stats( &mut coin_source_account, @@ -183,6 +188,7 @@ pub async fn create_accounts_command( &txn_factory, &emit_job_request, DEFAULT_MAX_SUBMIT_TRANSACTION_BATCH_SIZE, + false, seed, create_accounts_args.count, 4, From 2d7288fb9f63f703af0513b0c3e343591124628b Mon Sep 17 00:00:00 2001 From: Alin Tomescu Date: Wed, 7 Feb 2024 21:27:14 -0800 Subject: [PATCH 039/328] Fetch the zkID Groth16 VK from on-chain (#11895) Co-authored-by: Oliver --- api/src/tests/accounts_test.rs | 13 +- api/types/src/transaction.rs | 15 +- aptos-move/aptos-vm/src/aptos_vm.rs | 6 +- aptos-move/aptos-vm/src/zkid_validation.rs | 123 +++- .../framework/aptos-framework/doc/genesis.md | 2 + .../framework/aptos-framework/doc/overview.md | 1 + .../framework/aptos-framework/doc/zkid.md | 492 ++++++++++++++++ .../aptos-framework/sources/genesis.move | 4 +- .../aptos-framework/sources/zkid.move | 194 +++++++ .../aptos-crypto/src/ed25519/ed25519_keys.rs | 5 +- .../aptos-crypto/src/ed25519/ed25519_sigs.rs | 2 +- crates/aptos-crypto/src/poseidon_bn254.rs | 4 +- scripts/authenticator_regenerate.sh | 54 ++ .../generate-format/tests/staged/api.yaml | 17 +- .../generate-format/tests/staged/aptos.yaml | 17 +- .../tests/staged/consensus.yaml | 17 +- testsuite/smoke-test/src/zkid.rs | 96 ++- types/src/bn254_circom.rs | 222 +++++-- types/src/jwks/rsa/mod.rs | 21 +- types/src/transaction/authenticator.rs | 480 +++------------ types/src/zkid.rs | 549 ++++++++++++++---- 21 files changed, 1669 insertions(+), 665 deletions(-) create mode 100644 aptos-move/framework/aptos-framework/doc/zkid.md create mode 100644 aptos-move/framework/aptos-framework/sources/zkid.move create mode 100755 scripts/authenticator_regenerate.sh diff --git a/api/src/tests/accounts_test.rs b/api/src/tests/accounts_test.rs index eb9e7c3c12c2c..ceb6ee8def93f 100644 --- a/api/src/tests/accounts_test.rs +++ b/api/src/tests/accounts_test.rs @@ -4,7 +4,7 @@ use super::new_test_context; use aptos_api_test_context::{current_function_name, find_value}; -use aptos_api_types::{MoveModuleBytecode, MoveResource, StateKeyWrapper}; +use aptos_api_types::{MoveModuleBytecode, MoveResource, MoveStructTag, StateKeyWrapper}; use aptos_cached_packages::aptos_stdlib; use serde_json::json; use std::str::FromStr; @@ -217,9 +217,10 @@ async fn test_get_account_resources_with_pagination() { // Make a request, assert we get a cursor back in the header for the next // page of results. Assert we can deserialize the string representation // of the cursor returned in the header. + // FIXME: Pagination seems to be off by one (change 4 to 5 below and see what happens). let req = warp::test::request() .method("GET") - .path(&format!("/v1{}?limit=5", account_resources(address))); + .path(&format!("/v1{}?limit=4", account_resources(address))); let resp = context.reply(req).await; assert_eq!(resp.status(), 200); let cursor_header = resp @@ -228,6 +229,14 @@ async fn test_get_account_resources_with_pagination() { .expect("Cursor header was missing"); let cursor_header = StateKeyWrapper::from_str(cursor_header.to_str().unwrap()).unwrap(); let resources: Vec = serde_json::from_slice(resp.body()).unwrap(); + println!("Returned {} resources:", resources.len()); + for r in resources + .iter() + .map(|mvr| &mvr.typ) + .collect::>() + { + println!("0x1::{}::{}", r.module, r.name); + } assert_eq!(resources.len(), 5); assert_eq!(resources, all_resources[0..5].to_vec()); diff --git a/api/types/src/transaction.rs b/api/types/src/transaction.rs index c82017aa4a473..9ec1dde2c07ad 100755 --- a/api/types/src/transaction.rs +++ b/api/types/src/transaction.rs @@ -28,7 +28,7 @@ use aptos_types::{ webauthn::PartialAuthenticatorAssertionResponse, Script, SignedTransaction, TransactionOutput, TransactionWithProof, }, - zkid::{MAX_ZK_PUBLIC_KEY_BYTES, MAX_ZK_SIGNATURE_BYTES}, + zkid, }; use once_cell::sync::Lazy; use poem_openapi::{Object, Union}; @@ -1205,18 +1205,17 @@ impl VerifyInput for ZkIdSignature { fn verify(&self) -> anyhow::Result<()> { let public_key_len = self.public_key.inner().len(); let signature_len = self.signature.inner().len(); - if public_key_len > MAX_ZK_PUBLIC_KEY_BYTES { + if public_key_len > zkid::ZkIdPublicKey::MAX_LEN { bail!( - "ZKID public key length is greater than the maximum number of {} bytes: found {} bytes", - MAX_ZK_PUBLIC_KEY_BYTES, public_key_len + "zkID public key length is greater than the maximum number of {} bytes: found {} bytes", + zkid::ZkIdPublicKey::MAX_LEN, public_key_len ) - } else if signature_len > MAX_ZK_SIGNATURE_BYTES { + } else if signature_len > zkid::ZkIdSignature::MAX_LEN { bail!( - "ZKID signature length is greater than the maximum number of {} bytes: found {} bytes", - MAX_ZK_SIGNATURE_BYTES, signature_len + "zkID signature length is greater than the maximum number of {} bytes: found {} bytes", + zkid::ZkIdSignature::MAX_LEN, signature_len ) } else { - // TODO(zkid): Any other checks we can do here? Ok(()) } } diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index e3bb0fbe552ae..f0162c8b1ff8c 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -1408,11 +1408,7 @@ impl AptosVM { }, } - zkid_validation::validate_zkid_authenticators( - &authenticators.unwrap(), - resolver, - self.move_vm.get_chain_id(), - )?; + zkid_validation::validate_zkid_authenticators(&authenticators.unwrap(), resolver)?; // The prologue MUST be run AFTER any validation. Otherwise you may run prologue and hit // SEQUENCE_NUMBER_TOO_NEW if there is more than one transaction from the same sender and diff --git a/aptos-move/aptos-vm/src/zkid_validation.rs b/aptos-move/aptos-vm/src/zkid_validation.rs index 019bcf082e611..d449f7ebe0c29 100644 --- a/aptos-move/aptos-vm/src/zkid_validation.rs +++ b/aptos-move/aptos-vm/src/zkid_validation.rs @@ -3,20 +3,26 @@ // SPDX-License-Identifier: Apache-2.0 use crate::move_vm_ext::AptosMoveResolver; +use aptos_crypto::ed25519::Ed25519PublicKey; use aptos_types::{ - bn254_circom::get_public_inputs_hash, - chain_id::ChainId, + bn254_circom::{get_public_inputs_hash, Groth16VerificationKey}, + invalid_signature, jwks::{jwk::JWK, PatchedJWKs}, on_chain_config::{CurrentTimeMicroseconds, OnChainConfig}, + transaction::authenticator::EphemeralPublicKey, vm_status::{StatusCode, VMStatus}, - zkid::{ZkIdPublicKey, ZkIdSignature, ZkpOrOpenIdSig, MAX_ZK_ID_AUTHENTICATORS_ALLOWED}, + zkid, + zkid::{Configuration, ZkIdPublicKey, ZkIdSignature, ZkpOrOpenIdSig}, }; use move_binary_format::errors::Location; use move_core_types::{language_storage::CORE_CODE_ADDRESS, move_resource::MoveStructType}; -macro_rules! invalid_signature { +macro_rules! value_deserialization_error { ($message:expr) => { - VMStatus::error(StatusCode::INVALID_SIGNATURE, Some($message.to_owned())) + VMStatus::error( + StatusCode::VALUE_DESERIALIZATION_ERROR, + Some($message.to_owned()), + ) }; } @@ -24,53 +30,77 @@ fn get_current_time_onchain( resolver: &impl AptosMoveResolver, ) -> anyhow::Result { CurrentTimeMicroseconds::fetch_config(resolver).ok_or_else(|| { - VMStatus::error( - StatusCode::VALUE_DESERIALIZATION_ERROR, - Some("could not fetch CurrentTimeMicroseconds on-chain config".to_string()), - ) + value_deserialization_error!("could not fetch CurrentTimeMicroseconds on-chain config") }) } fn get_jwks_onchain(resolver: &impl AptosMoveResolver) -> anyhow::Result { - let error_status = VMStatus::error( - StatusCode::VALUE_DESERIALIZATION_ERROR, - Some("could not fetch PatchedJWKs".to_string()), - ); let bytes = resolver .get_resource(&CORE_CODE_ADDRESS, &PatchedJWKs::struct_tag()) .map_err(|e| e.finish(Location::Undefined).into_vm_status())? - .ok_or_else(|| error_status.clone())?; - let jwks = bcs::from_bytes::(&bytes).map_err(|_| error_status.clone())?; + .ok_or_else(|| value_deserialization_error!("get_resource failed on PatchedJWKs"))?; + let jwks = bcs::from_bytes::(&bytes) + .map_err(|_| value_deserialization_error!("could not deserialize PatchedJWKs"))?; Ok(jwks) } +fn get_groth16_vk_onchain( + resolver: &impl AptosMoveResolver, +) -> anyhow::Result { + let bytes = resolver + .get_resource(&CORE_CODE_ADDRESS, &Groth16VerificationKey::struct_tag()) + .map_err(|e| e.finish(Location::Undefined).into_vm_status())? + .ok_or_else(|| value_deserialization_error!("get_resource failed on Groth16 VK"))?; + let vk = bcs::from_bytes::(&bytes) + .map_err(|_| value_deserialization_error!("could not deserialize Groth16 VK"))?; + Ok(vk) +} + +fn get_configs_onchain( + resolver: &impl AptosMoveResolver, +) -> anyhow::Result { + let bytes = resolver + .get_resource(&CORE_CODE_ADDRESS, &Configuration::struct_tag()) + .map_err(|e| e.finish(Location::Undefined).into_vm_status())? + .ok_or_else(|| value_deserialization_error!("get_resource failed on zkID configuration"))?; + let configs = bcs::from_bytes::(&bytes) + .map_err(|_| value_deserialization_error!("could not deserialize zkID configuration"))?; + Ok(configs) +} + fn get_jwk_for_zkid_authenticator( jwks: &PatchedJWKs, zkid_pub_key: &ZkIdPublicKey, zkid_sig: &ZkIdSignature, ) -> Result { - let jwt_header_parsed = zkid_sig + let jwt_header = zkid_sig .parse_jwt_header() - .map_err(|_| invalid_signature!("Failed to get JWT header"))?; + .map_err(|_| invalid_signature!("Failed to parse JWT header"))?; let jwk_move_struct = jwks - .get_jwk(&zkid_pub_key.iss, &jwt_header_parsed.kid) - .map_err(|_| invalid_signature!("JWK not found"))?; + .get_jwk(&zkid_pub_key.iss, &jwt_header.kid) + .map_err(|_| { + invalid_signature!(format!( + "JWK for {} with KID {} was not found", + zkid_pub_key.iss, jwt_header.kid + )) + })?; - let jwk = - JWK::try_from(jwk_move_struct).map_err(|_| invalid_signature!("Could not parse JWK"))?; + let jwk = JWK::try_from(jwk_move_struct) + .map_err(|_| invalid_signature!("Could not unpack Any in JWK Move struct"))?; Ok(jwk) } pub fn validate_zkid_authenticators( authenticators: &Vec<(ZkIdPublicKey, ZkIdSignature)>, resolver: &impl AptosMoveResolver, - chain_id: ChainId, ) -> Result<(), VMStatus> { if authenticators.is_empty() { return Ok(()); } - if authenticators.len() > MAX_ZK_ID_AUTHENTICATORS_ALLOWED { + let config = &get_configs_onchain(resolver)?; + + if authenticators.len() > config.max_zkid_signatures_per_txn as usize { return Err(invalid_signature!("Too many zkID authenticators")); } @@ -83,6 +113,18 @@ pub fn validate_zkid_authenticators( } let patched_jwks = get_jwks_onchain(resolver)?; + let pvk = &get_groth16_vk_onchain(resolver)? + .try_into() + .map_err(|_| invalid_signature!("Could not deserialize on-chain Groth16 VK"))?; + + let training_wheels_pk = match &config.training_wheels_pubkey { + None => None, + Some(bytes) => Some(EphemeralPublicKey::ed25519( + Ed25519PublicKey::try_from(bytes.as_slice()).map_err(|_| { + invalid_signature!("The training wheels PK set on chain is not a valid PK") + })?, + )), + }; for (zkid_pub_key, zkid_sig) in authenticators { let jwk = get_jwk_for_zkid_authenticator(&patched_jwks, zkid_pub_key, zkid_sig)?; @@ -90,12 +132,30 @@ pub fn validate_zkid_authenticators( match &zkid_sig.sig { ZkpOrOpenIdSig::Groth16Zkp(proof) => match jwk { JWK::RSA(rsa_jwk) => { + // If an `aud` override was set for account recovery purposes, check that it is + // in the allow-list on-chain. + if proof.override_aud_val.is_some() { + zkid::is_allowed_override_aud( + config, + proof.override_aud_val.as_ref().unwrap(), + )?; + } + + // The training wheels signature is only checked if a training wheels PK is set on chain + if training_wheels_pk.is_some() { + proof + .verify_training_wheels_sig(training_wheels_pk.as_ref().unwrap()) + .map_err(|_| { + invalid_signature!("Could not verify training wheels signature") + })?; + } + let public_inputs_hash = - get_public_inputs_hash(zkid_sig, zkid_pub_key, &rsa_jwk).map_err(|_| { - invalid_signature!("Could not compute public inputs hash") - })?; + get_public_inputs_hash(zkid_sig, zkid_pub_key, &rsa_jwk, config).map_err( + |_| invalid_signature!("Could not compute public inputs hash"), + )?; proof - .verify_proof(public_inputs_hash, chain_id) + .verify_proof(public_inputs_hash, pvk) .map_err(|_| invalid_signature!("Proof verification failed"))?; }, JWK::Unsupported(_) => return Err(invalid_signature!("JWK is not supported")), @@ -103,6 +163,15 @@ pub fn validate_zkid_authenticators( ZkpOrOpenIdSig::OpenIdSig(openid_sig) => { match jwk { JWK::RSA(rsa_jwk) => { + openid_sig + .verify_jwt_claims( + zkid_sig.exp_timestamp_secs, + &zkid_sig.ephemeral_pubkey, + zkid_pub_key, + config, + ) + .map_err(|_| invalid_signature!("OpenID claim verification failed"))?; + // TODO(OpenIdSig): Implement batch verification for all RSA signatures in // one TXN. // Note: Individual OpenID RSA signature verification will be fast when the diff --git a/aptos-move/framework/aptos-framework/doc/genesis.md b/aptos-move/framework/aptos-framework/doc/genesis.md index fcc8afa9f61b1..8683381ac43b1 100644 --- a/aptos-move/framework/aptos-framework/doc/genesis.md +++ b/aptos-move/framework/aptos-framework/doc/genesis.md @@ -63,6 +63,7 @@ use 0x1::vector; use 0x1::version; use 0x1::vesting; +use 0x1::zkid;
@@ -366,6 +367,7 @@ Genesis step 1: Initialize aptos framework account and core modules on chain. state_storage::initialize(&aptos_framework_account); timestamp::set_time_has_started(&aptos_framework_account); jwks::initialize(&aptos_framework_account); + zkid::initialize(&aptos_framework_account, zkid::devnet_groth16_vk(), zkid::default_devnet_configuration()); }
diff --git a/aptos-move/framework/aptos-framework/doc/overview.md b/aptos-move/framework/aptos-framework/doc/overview.md index da4ecbae09b09..015d6289e1436 100644 --- a/aptos-move/framework/aptos-framework/doc/overview.md +++ b/aptos-move/framework/aptos-framework/doc/overview.md @@ -57,6 +57,7 @@ This is the reference documentation of the Aptos framework. - [`0x1::version`](version.md#0x1_version) - [`0x1::vesting`](vesting.md#0x1_vesting) - [`0x1::voting`](voting.md#0x1_voting) +- [`0x1::zkid`](zkid.md#0x1_zkid) [move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/doc/zkid.md b/aptos-move/framework/aptos-framework/doc/zkid.md new file mode 100644 index 0000000000000..ddbff02c95c41 --- /dev/null +++ b/aptos-move/framework/aptos-framework/doc/zkid.md @@ -0,0 +1,492 @@ + + + +# Module `0x1::zkid` + + + +- [Struct `Group`](#0x1_zkid_Group) +- [Resource `Groth16VerificationKey`](#0x1_zkid_Groth16VerificationKey) +- [Resource `Configuration`](#0x1_zkid_Configuration) +- [Constants](#@Constants_0) +- [Function `initialize`](#0x1_zkid_initialize) +- [Function `new_groth16_verification_key`](#0x1_zkid_new_groth16_verification_key) +- [Function `new_configuration`](#0x1_zkid_new_configuration) +- [Function `devnet_groth16_vk`](#0x1_zkid_devnet_groth16_vk) +- [Function `default_devnet_configuration`](#0x1_zkid_default_devnet_configuration) +- [Function `update_groth16_verification_key`](#0x1_zkid_update_groth16_verification_key) +- [Function `update_configuration`](#0x1_zkid_update_configuration) +- [Function `update_training_wheels`](#0x1_zkid_update_training_wheels) + + +
use 0x1::option;
+use 0x1::signer;
+use 0x1::string;
+use 0x1::system_addresses;
+
+ + + + + +## Struct `Group` + + + +
#[resource_group(#[scope = global])]
+struct Group
+
+ + + +
+Fields + + +
+
+dummy_field: bool +
+
+ +
+
+ + +
+ + + +## Resource `Groth16VerificationKey` + +The 288-byte Groth16 verification key (VK) for the zkID relation. + + +
#[resource_group_member(#[group = 0x1::zkid::Group])]
+struct Groth16VerificationKey has store, key
+
+ + + +
+Fields + + +
+
+alpha_g1: vector<u8> +
+
+ 32-byte serialization of alpha * G, where G is the generator of G1. +
+
+beta_g2: vector<u8> +
+
+ 64-byte serialization of alpha * H, where H is the generator of G2. +
+
+gamma_g2: vector<u8> +
+
+ 64-byte serialization of gamma * H, where H is the generator of G2. +
+
+delta_g2: vector<u8> +
+
+ 64-byte serialization of delta * H, where H is the generator of G2. +
+
+gamma_abc_g1: vector<vector<u8>> +
+
+ \forall i \in {0, ..., \ell}, 64-byte serialization of gamma^{-1} * (beta * a_i + alpha * b_i + c_i) * H, where + H is the generator of G1 and \ell is 1 for the zkID relation. +
+
+ + +
+ + + +## Resource `Configuration` + + + +
#[resource_group_member(#[group = 0x1::zkid::Group])]
+struct Configuration has store, key
+
+ + + +
+Fields + + +
+
+override_aud_vals: vector<string::String> +
+
+ An override aud for the identity of a recovery service, which will help users recover their zkID accounts + associated with dapps or wallets that have disappeared. + IMPORTANT: This recovery service **cannot** on its own take over user accounts; a user must first sign in + via OAuth in the recovery service in order to allow it to rotate any of that user's zkID accounts. +
+
+max_zkid_signatures_per_txn: u16 +
+
+ No transaction can have more than this many zkID signatures. +
+
+max_exp_horizon_secs: u64 +
+
+ How far in the future from the JWT issued at time the EPK expiry can be set. +
+
+training_wheels_pubkey: option::Option<vector<u8>> +
+
+ The training wheels PK, if training wheels are on +
+
+nonce_commitment_num_bytes: u16 +
+
+ The size of the "nonce commitment (to the EPK and expiration date)" stored in the JWT's nonce field. +
+
+max_commited_epk_bytes: u16 +
+
+ The max length of an ephemeral public key supported in our circuit (93 bytes) +
+
+max_iss_field_bytes: u16 +
+
+ The max length of the field name and value of the JWT's iss field supported in our circuit (e.g., "iss":"aptos.com") +
+
+max_extra_field_bytes: u16 +
+
+ The max length of the JWT field name and value (e.g., "max_age":"18") supported in our circuit +
+
+max_jwt_header_b64_bytes: u32 +
+
+ The max length of the base64url-encoded JWT header in bytes supported in our circuit +
+
+ + +
+ + + +## Constants + + + + +The training wheels PK needs to be 32 bytes long. + + +
const E_TRAINING_WHEELS_PK_WRONG_SIZE: u64 = 1;
+
+ + + + + +## Function `initialize` + + + +
public(friend) fun initialize(fx: &signer, vk: zkid::Groth16VerificationKey, constants: zkid::Configuration)
+
+ + + +
+Implementation + + +
public(friend) fun initialize(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) {
+    system_addresses::assert_aptos_framework(fx);
+
+    move_to(fx, vk);
+    move_to(fx, constants);
+}
+
+ + + +
+ + + +## Function `new_groth16_verification_key` + + + +
public fun new_groth16_verification_key(alpha_g1: vector<u8>, beta_g2: vector<u8>, gamma_g2: vector<u8>, delta_g2: vector<u8>, gamma_abc_g1: vector<vector<u8>>): zkid::Groth16VerificationKey
+
+ + + +
+Implementation + + +
public fun new_groth16_verification_key(alpha_g1: vector<u8>, beta_g2: vector<u8>, gamma_g2: vector<u8>, delta_g2: vector<u8>, gamma_abc_g1: vector<vector<u8>>): Groth16VerificationKey {
+    Groth16VerificationKey {
+        alpha_g1,
+        beta_g2,
+        gamma_g2,
+        delta_g2,
+        gamma_abc_g1,
+    }
+}
+
+ + + +
+ + + +## Function `new_configuration` + + + +
public fun new_configuration(override_aud_val: vector<string::String>, max_zkid_signatures_per_txn: u16, max_exp_horizon_secs: u64, training_wheels_pubkey: option::Option<vector<u8>>, nonce_commitment_num_bytes: u16, max_commited_epk_bytes: u16, max_iss_field_bytes: u16, max_extra_field_bytes: u16, max_jwt_header_b64_bytes: u32): zkid::Configuration
+
+ + + +
+Implementation + + +
public fun new_configuration(
+    override_aud_val: vector<String>,
+    max_zkid_signatures_per_txn: u16,
+    max_exp_horizon_secs: u64,
+    training_wheels_pubkey: Option<vector<u8>>,
+    nonce_commitment_num_bytes: u16,
+    max_commited_epk_bytes: u16,
+    max_iss_field_bytes: u16,
+    max_extra_field_bytes: u16,
+    max_jwt_header_b64_bytes: u32
+): Configuration {
+    Configuration {
+        override_aud_vals: override_aud_val,
+        max_zkid_signatures_per_txn,
+        max_exp_horizon_secs,
+        training_wheels_pubkey,
+        nonce_commitment_num_bytes,
+        max_commited_epk_bytes,
+        max_iss_field_bytes,
+        max_extra_field_bytes,
+        max_jwt_header_b64_bytes,
+    }
+}
+
+ + + +
+ + + +## Function `devnet_groth16_vk` + +Returns the Groth16 VK for our devnet deployment. + + +
public fun devnet_groth16_vk(): zkid::Groth16VerificationKey
+
+ + + +
+Implementation + + +
public fun devnet_groth16_vk(): Groth16VerificationKey {
+    Groth16VerificationKey {
+        alpha_g1: x"6d1c152d2705e35fe7a07a66eb8a10a7f42f1e38c412fbbc3ac7f9affc25dc24",
+        beta_g2: x"e20a834c55ae6e2fcbd66636e09322727f317aff8957dd342afa11f936ef7c02cfdc8c9862849a0442bcaa4e03f45343e8bf261ef4ab58cead2efc17100a3b16",
+        gamma_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19",
+        delta_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19",
+        gamma_abc_g1: vector[
+            x"9aae6580d6040e77969d70e748e861664228e3567e77aa99822f8a4a19c29101",
+            x"e38ad8b845e3ef599232b43af2a64a73ada04d5f0e73f1848e6631e17a247415",
+        ],
+    }
+}
+
+ + + +
+ + + +## Function `default_devnet_configuration` + +Returns the configuration for our devnet deployment. + + +
public fun default_devnet_configuration(): zkid::Configuration
+
+ + + +
+Implementation + + +
public fun default_devnet_configuration(): Configuration {
+    // TODO(zkid): Put reasonable defaults & circuit-specific constants here.
+    Configuration {
+        override_aud_vals: vector[],
+        max_zkid_signatures_per_txn: 3,
+        max_exp_horizon_secs: 100_255_944, // ~1160 days
+        training_wheels_pubkey: option::some(x"aa"),
+        // The commitment is using the Poseidon-BN254 hash function, hence the 254-bit (32 byte) size.
+        nonce_commitment_num_bytes: 32,
+        max_commited_epk_bytes: 3 * 31,
+        max_iss_field_bytes: 126,
+        max_extra_field_bytes:  350,
+        max_jwt_header_b64_bytes: 300,
+    }
+}
+
+ + + +
+ + + +## Function `update_groth16_verification_key` + + + +
public fun update_groth16_verification_key(fx: &signer, alpha_g1: vector<u8>, beta_g2: vector<u8>, gamma_g2: vector<u8>, delta_g2: vector<u8>, gamma_abc_g1: vector<vector<u8>>)
+
+ + + +
+Implementation + + +
public fun update_groth16_verification_key(fx: &signer,
+                                           alpha_g1: vector<u8>,
+                                           beta_g2: vector<u8>,
+                                           gamma_g2: vector<u8>,
+                                           delta_g2: vector<u8>,
+                                           gamma_abc_g1: vector<vector<u8>>,
+) acquires Groth16VerificationKey {
+    system_addresses::assert_aptos_framework(fx);
+
+    if (exists<Groth16VerificationKey>(signer::address_of(fx))) {
+        let Groth16VerificationKey {
+            alpha_g1: _,
+            beta_g2: _,
+            gamma_g2: _,
+            delta_g2: _,
+            gamma_abc_g1: _
+        } = move_from<Groth16VerificationKey>(signer::address_of(fx));
+    };
+
+    let vk = new_groth16_verification_key(alpha_g1, beta_g2, gamma_g2, delta_g2, gamma_abc_g1);
+    move_to(fx, vk);
+}
+
+ + + +
+ + + +## Function `update_configuration` + + + +
public fun update_configuration(fx: &signer, config: zkid::Configuration)
+
+ + + +
+Implementation + + +
public fun update_configuration(fx: &signer, config: Configuration) acquires Configuration {
+    system_addresses::assert_aptos_framework(fx);
+
+    if (exists<Configuration>(signer::address_of(fx))) {
+        let Configuration {
+            override_aud_vals: _,
+            max_zkid_signatures_per_txn: _,
+            max_exp_horizon_secs: _,
+            training_wheels_pubkey: _,
+            nonce_commitment_num_bytes: _,
+            max_commited_epk_bytes: _,
+            max_iss_field_bytes: _,
+            max_extra_field_bytes: _,
+            max_jwt_header_b64_bytes: _,
+        } = move_from<Configuration>(signer::address_of(fx));
+    };
+
+    move_to(fx, config);
+}
+
+ + + +
+ + + +## Function `update_training_wheels` + + + +
public fun update_training_wheels(fx: &signer, pk: option::Option<vector<u8>>)
+
+ + + +
+Implementation + + +
public fun update_training_wheels(fx: &signer, pk: Option<vector<u8>>) acquires Configuration {
+    system_addresses::assert_aptos_framework(fx);
+    if (option::is_some(&pk)) {
+        assert!(vector::length(option::borrow(&pk)) == 32, E_TRAINING_WHEELS_PK_WRONG_SIZE)
+    };
+
+    let config = borrow_global_mut<Configuration>(signer::address_of(fx));
+    config.training_wheels_pubkey = pk;
+}
+
+ + + +
+ + +[move-book]: https://aptos.dev/move/book/SUMMARY diff --git a/aptos-move/framework/aptos-framework/sources/genesis.move b/aptos-move/framework/aptos-framework/sources/genesis.move index eacfb41b93b55..682f568ed2c62 100644 --- a/aptos-move/framework/aptos-framework/sources/genesis.move +++ b/aptos-move/framework/aptos-framework/sources/genesis.move @@ -17,6 +17,7 @@ module aptos_framework::genesis { use aptos_framework::execution_config; use aptos_framework::create_signer::create_signer; use aptos_framework::gas_schedule; + use aptos_framework::jwks; use aptos_framework::reconfiguration; use aptos_framework::stake; use aptos_framework::staking_contract; @@ -28,6 +29,7 @@ module aptos_framework::genesis { use aptos_framework::transaction_validation; use aptos_framework::version; use aptos_framework::vesting; + use aptos_framework::zkid; const EDUPLICATE_ACCOUNT: u64 = 1; const EACCOUNT_DOES_NOT_EXIST: u64 = 2; @@ -131,6 +133,7 @@ module aptos_framework::genesis { state_storage::initialize(&aptos_framework_account); timestamp::set_time_has_started(&aptos_framework_account); jwks::initialize(&aptos_framework_account); + zkid::initialize(&aptos_framework_account, zkid::devnet_groth16_vk(), zkid::default_devnet_configuration()); } /// Genesis step 2: Initialize Aptos coin. @@ -382,7 +385,6 @@ module aptos_framework::genesis { #[verify_only] use std::features; - use aptos_framework::jwks; #[verify_only] fun initialize_for_verification( diff --git a/aptos-move/framework/aptos-framework/sources/zkid.move b/aptos-move/framework/aptos-framework/sources/zkid.move new file mode 100644 index 0000000000000..97b7b9d32f240 --- /dev/null +++ b/aptos-move/framework/aptos-framework/sources/zkid.move @@ -0,0 +1,194 @@ +module aptos_framework::zkid { + use std::option; + use std::option::Option; + use std::signer; + use std::string::String; + use std::vector; + use aptos_framework::system_addresses; + + /// The training wheels PK needs to be 32 bytes long. + const E_TRAINING_WHEELS_PK_WRONG_SIZE : u64 = 1; + + #[resource_group(scope = global)] + struct Group {} + + #[resource_group_member(group = aptos_framework::zkid::Group)] + /// The 288-byte Groth16 verification key (VK) for the zkID relation. + struct Groth16VerificationKey has key, store { + /// 32-byte serialization of `alpha * G`, where `G` is the generator of `G1`. + alpha_g1: vector, + /// 64-byte serialization of `alpha * H`, where `H` is the generator of `G2`. + beta_g2: vector, + /// 64-byte serialization of `gamma * H`, where `H` is the generator of `G2`. + gamma_g2: vector, + /// 64-byte serialization of `delta * H`, where `H` is the generator of `G2`. + delta_g2: vector, + /// `\forall i \in {0, ..., \ell}, 64-byte serialization of gamma^{-1} * (beta * a_i + alpha * b_i + c_i) * H`, where + /// `H` is the generator of `G1` and `\ell` is 1 for the zkID relation. + gamma_abc_g1: vector>, + } + + #[resource_group_member(group = aptos_framework::zkid::Group)] + struct Configuration has key, store { + /// An override `aud` for the identity of a recovery service, which will help users recover their zkID accounts + /// associated with dapps or wallets that have disappeared. + /// IMPORTANT: This recovery service **cannot** on its own take over user accounts; a user must first sign in + /// via OAuth in the recovery service in order to allow it to rotate any of that user's zkID accounts. + override_aud_vals: vector, + /// No transaction can have more than this many zkID signatures. + max_zkid_signatures_per_txn: u16, + /// How far in the future from the JWT issued at time the EPK expiry can be set. + max_exp_horizon_secs: u64, + /// The training wheels PK, if training wheels are on + training_wheels_pubkey: Option>, + /// The size of the "nonce commitment (to the EPK and expiration date)" stored in the JWT's `nonce` field. + nonce_commitment_num_bytes: u16, + /// The max length of an ephemeral public key supported in our circuit (93 bytes) + max_commited_epk_bytes: u16, + /// The max length of the field name and value of the JWT's `iss` field supported in our circuit (e.g., `"iss":"aptos.com"`) + max_iss_field_bytes: u16, + /// The max length of the JWT field name and value (e.g., `"max_age":"18"`) supported in our circuit + max_extra_field_bytes: u16, + /// The max length of the base64url-encoded JWT header in bytes supported in our circuit + max_jwt_header_b64_bytes: u32, + } + + // genesis.move needs to initialize the devnet VK + friend aptos_framework::genesis; + + public(friend) fun initialize(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) { + system_addresses::assert_aptos_framework(fx); + + move_to(fx, vk); + move_to(fx, constants); + } + + #[test_only] + public fun initialize_for_test(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) { + initialize(fx, vk, constants) + } + + public fun new_groth16_verification_key(alpha_g1: vector, beta_g2: vector, gamma_g2: vector, delta_g2: vector, gamma_abc_g1: vector>): Groth16VerificationKey { + Groth16VerificationKey { + alpha_g1, + beta_g2, + gamma_g2, + delta_g2, + gamma_abc_g1, + } + } + + public fun new_configuration( + override_aud_val: vector, + max_zkid_signatures_per_txn: u16, + max_exp_horizon_secs: u64, + training_wheels_pubkey: Option>, + nonce_commitment_num_bytes: u16, + max_commited_epk_bytes: u16, + max_iss_field_bytes: u16, + max_extra_field_bytes: u16, + max_jwt_header_b64_bytes: u32 + ): Configuration { + Configuration { + override_aud_vals: override_aud_val, + max_zkid_signatures_per_txn, + max_exp_horizon_secs, + training_wheels_pubkey, + nonce_commitment_num_bytes, + max_commited_epk_bytes, + max_iss_field_bytes, + max_extra_field_bytes, + max_jwt_header_b64_bytes, + } + } + + /// Returns the Groth16 VK for our devnet deployment. + public fun devnet_groth16_vk(): Groth16VerificationKey { + Groth16VerificationKey { + alpha_g1: x"6d1c152d2705e35fe7a07a66eb8a10a7f42f1e38c412fbbc3ac7f9affc25dc24", + beta_g2: x"e20a834c55ae6e2fcbd66636e09322727f317aff8957dd342afa11f936ef7c02cfdc8c9862849a0442bcaa4e03f45343e8bf261ef4ab58cead2efc17100a3b16", + gamma_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19", + delta_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19", + gamma_abc_g1: vector[ + x"9aae6580d6040e77969d70e748e861664228e3567e77aa99822f8a4a19c29101", + x"e38ad8b845e3ef599232b43af2a64a73ada04d5f0e73f1848e6631e17a247415", + ], + } + } + + /// Returns the configuration for our devnet deployment. + public fun default_devnet_configuration(): Configuration { + // TODO(zkid): Put reasonable defaults & circuit-specific constants here. + Configuration { + override_aud_vals: vector[], + max_zkid_signatures_per_txn: 3, + max_exp_horizon_secs: 100_255_944, // ~1160 days + training_wheels_pubkey: option::some(x"aa"), + // The commitment is using the Poseidon-BN254 hash function, hence the 254-bit (32 byte) size. + nonce_commitment_num_bytes: 32, + max_commited_epk_bytes: 3 * 31, + max_iss_field_bytes: 126, + max_extra_field_bytes: 350, + max_jwt_header_b64_bytes: 300, + } + } + + // Sets the zkID Groth16 verification key, only callable via governance proposal. + // WARNING: If a malicious key is set, this would lead to stolen funds. + public fun update_groth16_verification_key(fx: &signer, + alpha_g1: vector, + beta_g2: vector, + gamma_g2: vector, + delta_g2: vector, + gamma_abc_g1: vector>, + ) acquires Groth16VerificationKey { + system_addresses::assert_aptos_framework(fx); + + if (exists(signer::address_of(fx))) { + let Groth16VerificationKey { + alpha_g1: _, + beta_g2: _, + gamma_g2: _, + delta_g2: _, + gamma_abc_g1: _ + } = move_from(signer::address_of(fx)); + }; + + let vk = new_groth16_verification_key(alpha_g1, beta_g2, gamma_g2, delta_g2, gamma_abc_g1); + move_to(fx, vk); + } + + // Sets the zkID configuration, only callable via governance proposal. + // WARNING: If a malicious key is set, this would lead to stolen funds. + public fun update_configuration(fx: &signer, config: Configuration) acquires Configuration { + system_addresses::assert_aptos_framework(fx); + + if (exists(signer::address_of(fx))) { + let Configuration { + override_aud_vals: _, + max_zkid_signatures_per_txn: _, + max_exp_horizon_secs: _, + training_wheels_pubkey: _, + nonce_commitment_num_bytes: _, + max_commited_epk_bytes: _, + max_iss_field_bytes: _, + max_extra_field_bytes: _, + max_jwt_header_b64_bytes: _, + } = move_from(signer::address_of(fx)); + }; + + move_to(fx, config); + } + + // Convenience method to set the zkID training wheels, only callable via governance proposal. + // WARNING: If a malicious key is set, this would lead to stolen funds. + public fun update_training_wheels(fx: &signer, pk: Option>) acquires Configuration { + system_addresses::assert_aptos_framework(fx); + if (option::is_some(&pk)) { + assert!(vector::length(option::borrow(&pk)) == 32, E_TRAINING_WHEELS_PK_WRONG_SIZE) + }; + + let config = borrow_global_mut(signer::address_of(fx)); + config.training_wheels_pubkey = pk; + } +} diff --git a/crates/aptos-crypto/src/ed25519/ed25519_keys.rs b/crates/aptos-crypto/src/ed25519/ed25519_keys.rs index 72a94b531d8b3..fc32132590f7e 100644 --- a/crates/aptos-crypto/src/ed25519/ed25519_keys.rs +++ b/crates/aptos-crypto/src/ed25519/ed25519_keys.rs @@ -38,7 +38,7 @@ pub struct Ed25519PublicKey(pub(crate) ed25519_dalek::PublicKey); impl Ed25519PrivateKey { /// The length of the Ed25519PrivateKey - pub const LENGTH: usize = ed25519_dalek::SECRET_KEY_LENGTH; + pub const LENGTH: usize = ED25519_PRIVATE_KEY_LENGTH; /// Serialize an Ed25519PrivateKey. pub fn to_bytes(&self) -> [u8; ED25519_PRIVATE_KEY_LENGTH] { @@ -68,6 +68,9 @@ impl Ed25519PrivateKey { } impl Ed25519PublicKey { + /// The maximum size in bytes. + pub const LENGTH: usize = ED25519_PUBLIC_KEY_LENGTH; + /// Serialize an Ed25519PublicKey. pub fn to_bytes(&self) -> [u8; ED25519_PUBLIC_KEY_LENGTH] { self.0.to_bytes() diff --git a/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs b/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs index 8330102896480..4c1d9438c83a0 100644 --- a/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs +++ b/crates/aptos-crypto/src/ed25519/ed25519_sigs.rs @@ -20,7 +20,7 @@ pub struct Ed25519Signature(pub(crate) ed25519_dalek::Signature); impl Ed25519Signature { /// The length of the Ed25519Signature - pub const LENGTH: usize = ed25519_dalek::SIGNATURE_LENGTH; + pub const LENGTH: usize = ED25519_SIGNATURE_LENGTH; /// Serialize an Ed25519Signature. pub fn to_bytes(&self) -> [u8; ED25519_SIGNATURE_LENGTH] { diff --git a/crates/aptos-crypto/src/poseidon_bn254.rs b/crates/aptos-crypto/src/poseidon_bn254.rs index 3ee067a40ceff..219122719c80e 100644 --- a/crates/aptos-crypto/src/poseidon_bn254.rs +++ b/crates/aptos-crypto/src/poseidon_bn254.rs @@ -243,8 +243,8 @@ mod test { #[test] fn test_poseidon_bn254_pad_and_hash_bytes() { let aud = "google"; - const MAX_AUD_VAL_BYTES: usize = 248; - let aud_val_hash = poseidon_bn254::pad_and_hash_string(aud, MAX_AUD_VAL_BYTES).unwrap(); + const LEN: usize = 248; + let aud_val_hash = poseidon_bn254::pad_and_hash_string(aud, LEN).unwrap(); assert_eq!( aud_val_hash.to_string(), "4022319167392179362271493931675371567039199401695470709241660273812313544045" diff --git a/scripts/authenticator_regenerate.sh b/scripts/authenticator_regenerate.sh new file mode 100755 index 0000000000000..350851b0f29d0 --- /dev/null +++ b/scripts/authenticator_regenerate.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -x +set -e + +scriptdir="$(cd "$(dirname "$0")" >/dev/null 2>&1 && pwd)" + +echo "Executing from directory: $scriptdir" + +repodir=$scriptdir/.. + +cd $repodir + +( + echo + echo "Regenerating serde-reflection to track type changes over time (in `pwd`)" + cargo run -p generate-format -- --corpus api --record + cargo run -p generate-format -- --corpus aptos --record + cargo run -p generate-format -- --corpus consensus --record + cargo run -p generate-format -- --corpus network --record + cargo run -p generate-format -- --corpus move-abi --record +) + +( + echo + echo "Regenerating protobufs (in `pwd`)" + echo "See https://github.com/aptos-labs/aptos-core-private/tree/main/protos/README.md if you're having troubles" + cd protos/ + ./scripts/build_protos.sh +) + +( + echo + echo "Regenerating Aptos Node APIs (in `pwd`)" + # Aptos Node API + cargo run -p aptos-openapi-spec-generator -- -f yaml -o api/doc/spec.yaml + cargo run -p aptos-openapi-spec-generator -- -f json -o api/doc/spec.json + + echo + echo "Regenerating Typescript SDK (in `pwd`)" + # Typescript SDK client files + cd ecosystem/typescript/sdk + pnpm install + pnpm generate-client + + # Typescript SDK docs + pnpm generate-ts-docs + cd .. +) + +echo +echo "WARNING: If you are adding a new transaction authenticator..." +echo " 1. Check out https://github.com/aptos-labs/aptos-core/blob/main/testsuite/generate-format/README.md" +echo " 2. ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs must be manually updated" +echo diff --git a/testsuite/generate-format/tests/staged/api.yaml b/testsuite/generate-format/tests/staged/api.yaml index 063d1bdaafc7b..782ded3e31a22 100644 --- a/testsuite/generate-format/tests/staged/api.yaml +++ b/testsuite/generate-format/tests/staged/api.yaml @@ -292,10 +292,7 @@ HashValue: CONTENT: U8 SIZE: 32 IdCommitment: - NEWTYPESTRUCT: - TUPLEARRAY: - CONTENT: U8 - SIZE: 32 + NEWTYPESTRUCT: BYTES Identifier: NEWTYPESTRUCT: STR JWKMoveStruct: @@ -353,12 +350,11 @@ OpenIdSig: - jwt_sig: STR - jwt_payload: STR - uid_key: STR - - epk_blinder: - TUPLEARRAY: - CONTENT: U8 - SIZE: 31 + - epk_blinder: BYTES - pepper: TYPENAME: Pepper + - idc_aud_val: + OPTION: STR PartialAuthenticatorAssertionResponse: STRUCT: - signature: @@ -458,6 +454,11 @@ SignedGroth16Zkp: TYPENAME: Groth16Zkp - non_malleability_signature: TYPENAME: EphemeralSignature + - training_wheels_signature: + TYPENAME: EphemeralSignature + - extra_field: STR + - override_aud_val: + OPTION: STR SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/generate-format/tests/staged/aptos.yaml b/testsuite/generate-format/tests/staged/aptos.yaml index 65ae950be420f..a9b1a2432a886 100644 --- a/testsuite/generate-format/tests/staged/aptos.yaml +++ b/testsuite/generate-format/tests/staged/aptos.yaml @@ -238,10 +238,7 @@ HashValue: CONTENT: U8 SIZE: 32 IdCommitment: - NEWTYPESTRUCT: - TUPLEARRAY: - CONTENT: U8 - SIZE: 32 + NEWTYPESTRUCT: BYTES Identifier: NEWTYPESTRUCT: STR JWKMoveStruct: @@ -299,12 +296,11 @@ OpenIdSig: - jwt_sig: STR - jwt_payload: STR - uid_key: STR - - epk_blinder: - TUPLEARRAY: - CONTENT: U8 - SIZE: 31 + - epk_blinder: BYTES - pepper: TYPENAME: Pepper + - idc_aud_val: + OPTION: STR PartialAuthenticatorAssertionResponse: STRUCT: - signature: @@ -390,6 +386,11 @@ SignedGroth16Zkp: TYPENAME: Groth16Zkp - non_malleability_signature: TYPENAME: EphemeralSignature + - training_wheels_signature: + TYPENAME: EphemeralSignature + - extra_field: STR + - override_aud_val: + OPTION: STR SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/generate-format/tests/staged/consensus.yaml b/testsuite/generate-format/tests/staged/consensus.yaml index 38fee8400bd97..c33b28ac42223 100644 --- a/testsuite/generate-format/tests/staged/consensus.yaml +++ b/testsuite/generate-format/tests/staged/consensus.yaml @@ -498,10 +498,7 @@ HashValue: CONTENT: U8 SIZE: 32 IdCommitment: - NEWTYPESTRUCT: - TUPLEARRAY: - CONTENT: U8 - SIZE: 32 + NEWTYPESTRUCT: BYTES Identifier: NEWTYPESTRUCT: STR JWKMoveStruct: @@ -577,12 +574,11 @@ OpenIdSig: - jwt_sig: STR - jwt_payload: STR - uid_key: STR - - epk_blinder: - TUPLEARRAY: - CONTENT: U8 - SIZE: 31 + - epk_blinder: BYTES - pepper: TYPENAME: Pepper + - idc_aud_val: + OPTION: STR PartialAuthenticatorAssertionResponse: STRUCT: - signature: @@ -749,6 +745,11 @@ SignedGroth16Zkp: TYPENAME: Groth16Zkp - non_malleability_signature: TYPENAME: EphemeralSignature + - training_wheels_signature: + TYPENAME: EphemeralSignature + - extra_field: STR + - override_aud_val: + OPTION: STR SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/smoke-test/src/zkid.rs b/testsuite/smoke-test/src/zkid.rs index d3be06aed3329..bb2bc12e236ed 100644 --- a/testsuite/smoke-test/src/zkid.rs +++ b/testsuite/smoke-test/src/zkid.rs @@ -3,7 +3,11 @@ use crate::smoke_test_environment::SwarmBuilder; use aptos::test::CliTestFramework; use aptos_cached_packages::aptos_stdlib; -use aptos_crypto::{ed25519::Ed25519PrivateKey, encoding_type::EncodingType, SigningKey}; +use aptos_crypto::{ + ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, + encoding_type::EncodingType, + SigningKey, Uniform, +}; use aptos_forge::{LocalSwarm, NodeExt, Swarm, SwarmExt}; use aptos_logger::{debug, info}; use aptos_rest_client::Client; @@ -25,15 +29,19 @@ use aptos_types::{ }, }; use move_core_types::account_address::AccountAddress; +use rand::thread_rng; use std::time::Duration; +// TODO(zkid): test the override aud_val path +// TODO(zkid): These tests are not modular and they lack instructions for how to regenerate the proofs. + #[tokio::test] -async fn test_openid_signature_transaction_submission() { +async fn test_zkid_oidc_signature_transaction_submission() { let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) .with_aptos() .build_with_cli(0) .await; - test_setup(&mut swarm, &mut cli).await; + let _ = test_setup(&mut swarm, &mut cli).await; let mut info = swarm.aptos_public_info(); @@ -81,7 +89,7 @@ async fn test_openid_signature_transaction_submission() { let sender_sig = ephemeral_account.private_key().sign(&raw_txn).unwrap(); let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); - let epk_blinder: [u8; 31] = [0u8; 31]; + let epk_blinder = vec![0u8; 31]; let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiIxYlFsNF9YYzUtSXBDcFViS19BZVhwZ2Q2R1o0MGxVVjN1YjN5b19FTHhrIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcwNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); let jwt_sig = "oBdOiIUc-ioG2-sHV1hWDLjgk4NrVf3z6V-HmgbOrVAz3PV1CwdfyTXsmVaCqLzOHzcbFB6ZRDxShs3aR7PsqdlhI0Dh8WrfU8kBkyk1FAmx2nST4SoSJROXsnusaOpNFpgSl96Rq3SXgr-yPBE9dEwTfD00vq2gH_fH1JAIeJJhc6WicMcsEZ7iONT1RZOid_9FlDrg1GxlGtNmpn4nEAmIxqnT0JrCESiRvzmuuXUibwx9xvHgIxhyVuAA9amlzaD1DL6jEc5B_0YnGKN7DO_l2Hkj9MbQZvU0beR-Lfcz8jxCjojODTYmWgbtu5E7YWIyC6dsjiBnTxc-svCsmQ".to_string(); @@ -92,6 +100,7 @@ async fn test_openid_signature_transaction_submission() { uid_key: "sub".to_string(), epk_blinder, pepper, + idc_aud_val: None, }; let zk_sig = ZkIdSignature { @@ -112,12 +121,12 @@ async fn test_openid_signature_transaction_submission() { } #[tokio::test] -async fn test_openid_signature_transaction_submission_fails_jwt_verification() { +async fn test_zkid_oidc_signature_transaction_submission_fails_jwt_verification() { let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) .with_aptos() .build_with_cli(0) .await; - test_setup(&mut swarm, &mut cli).await; + let _ = test_setup(&mut swarm, &mut cli).await; let mut info = swarm.aptos_public_info(); let pepper = Pepper::new([0u8; 31]); @@ -164,7 +173,7 @@ async fn test_openid_signature_transaction_submission_fails_jwt_verification() { let sender_sig = ephemeral_account.private_key().sign(&raw_txn).unwrap(); let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); - let epk_blinder: [u8; 31] = [0u8; 31]; + let epk_blinder = vec![0u8; 31]; let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiIxYlFsNF9YYzUtSXBDcFViS19BZVhwZ2Q2R1o0MGxVVjN1YjN5b19FTHhrIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcwNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); let jwt_sig = "bad_signature".to_string(); @@ -175,6 +184,7 @@ async fn test_openid_signature_transaction_submission_fails_jwt_verification() { uid_key: "sub".to_string(), epk_blinder, pepper, + idc_aud_val: None, }; let zk_sig = ZkIdSignature { @@ -196,12 +206,12 @@ async fn test_openid_signature_transaction_submission_fails_jwt_verification() { } #[tokio::test] -async fn test_openid_signature_transaction_submission_epk_expired() { +async fn test_zkid_oidc_signature_transaction_submission_epk_expired() { let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) .with_aptos() .build_with_cli(0) .await; - test_setup(&mut swarm, &mut cli).await; + let _ = test_setup(&mut swarm, &mut cli).await; let mut info = swarm.aptos_public_info(); let pepper = Pepper::new([0u8; 31]); @@ -248,7 +258,7 @@ async fn test_openid_signature_transaction_submission_epk_expired() { let sender_sig = ephemeral_account.private_key().sign(&raw_txn).unwrap(); let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); - let epk_blinder: [u8; 31] = [0u8; 31]; + let epk_blinder = vec![0u8; 31]; let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiIxYlFsNF9YYzUtSXBDcFViS19BZVhwZ2Q2R1o0MGxVVjN1YjN5b19FTHhrIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcwNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); let jwt_sig = "oBdOiIUc-ioG2-sHV1hWDLjgk4NrVf3z6V-HmgbOrVAz3PV1CwdfyTXsmVaCqLzOHzcbFB6ZRDxShs3aR7PsqdlhI0Dh8WrfU8kBkyk1FAmx2nST4SoSJROXsnusaOpNFpgSl96Rq3SXgr-yPBE9dEwTfD00vq2gH_fH1JAIeJJhc6WicMcsEZ7iONT1RZOid_9FlDrg1GxlGtNmpn4nEAmIxqnT0JrCESiRvzmuuXUibwx9xvHgIxhyVuAA9amlzaD1DL6jEc5B_0YnGKN7DO_l2Hkj9MbQZvU0beR-Lfcz8jxCjojODTYmWgbtu5E7YWIyC6dsjiBnTxc-svCsmQ".to_string(); @@ -259,6 +269,7 @@ async fn test_openid_signature_transaction_submission_epk_expired() { uid_key: "sub".to_string(), epk_blinder, pepper, + idc_aud_val: None, }; let zk_sig = ZkIdSignature { @@ -280,12 +291,12 @@ async fn test_openid_signature_transaction_submission_epk_expired() { } #[tokio::test] -async fn test_groth16_signature_transaction_submission() { +async fn test_zkid_groth16_verifies() { let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) .with_aptos() .build_with_cli(0) .await; - test_setup(&mut swarm, &mut cli).await; + let tw_sk = test_setup(&mut swarm, &mut cli).await; let mut info = swarm.aptos_public_info(); let pepper = Pepper::from_number(76); @@ -338,24 +349,24 @@ async fn test_groth16_signature_transaction_submission() { let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); let a = G1Bytes::new_unchecked( - "11685701338011120485255682535216931952523490513574344095859176729155974193429", - "19570000702948951151001315672614758851000529478920585316943681012227747910337", + "20534193224874816823038374805971256353897254359389549519579800571198905682623", + "3128047629776327625062258700337193014005673411952335683536865294076478098678", ) .unwrap(); let b = G2Bytes::new_unchecked( [ - "10039243553158378944380740968043887743081233734014916979736214569065002261361", - "4926621746570487391149084476602889692047252928870676314074045787488022393462", + "11831059544281359959902363827760224027191828999098259913907764686593049260801", + "14933419822301565783764657928814181728459886670248956535955133596731082875810", ], [ - "8151326214925440719229499872086146990795191649649968979609056373308460653969", - "12483309147304635788397060225283577172417980480151834869358925058077916828359", + "16616167200367085072660100259194052934821478809307596510515652443339946625933", + "1103855954970567341442645156173756328940907403537523212700521414512165362008", ], ) .unwrap(); let c = G1Bytes::new_unchecked( - "17509024307642709963307435885289611077932619305068428354097243520217914637634", - "17824783754604065652634030354434350582834434348663254057492956883323214722668", + "296457556259014920933232985275282694032456344171046224944953719399946325676", + "10314488872240559867545387237625153841351761679810222583912967187658678987385", ) .unwrap(); let proof = Groth16Zkp::new(a, b, c); @@ -365,10 +376,16 @@ async fn test_groth16_signature_transaction_submission() { let proof_sig = ephemeral_account.private_key().sign(&proof).unwrap(); let ephem_proof_sig = EphemeralSignature::ed25519(proof_sig); + // TODO(zkid): Refactor tests to be modular and add test for bad training wheels signature (commented out below). + //let bad_sk = Ed25519PrivateKey::generate(&mut thread_rng()); let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephem_proof_sig, + training_wheels_signature: EphemeralSignature::ed25519(tw_sk.sign(&proof).unwrap()), + //training_wheels_signature: EphemeralSignature::ed25519(bad_sk.sign(&proof).unwrap()), + extra_field: "\"family_name\":\"Straka\",".to_string(), + override_aud_val: None, }), jwt_header, exp_timestamp_secs: 1900255944, @@ -386,12 +403,12 @@ async fn test_groth16_signature_transaction_submission() { } #[tokio::test] -async fn test_groth16_signature_transaction_submission_proof_signature_check_fails() { +async fn test_zkid_groth16_signature_transaction_submission_proof_signature_check_fails() { let (mut swarm, mut cli, _faucet) = SwarmBuilder::new_local(4) .with_aptos() .build_with_cli(0) .await; - test_setup(&mut swarm, &mut cli).await; + let tw_sk = test_setup(&mut swarm, &mut cli).await; let mut info = swarm.aptos_public_info(); let pepper = Pepper::from_number(76); @@ -444,24 +461,24 @@ async fn test_groth16_signature_transaction_submission_proof_signature_check_fai let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); let a = G1Bytes::new_unchecked( - "11685701338011120485255682535216931952523490513574344095859176729155974193429", - "19570000702948951151001315672614758851000529478920585316943681012227747910337", + "20534193224874816823038374805971256353897254359389549519579800571198905682623", + "3128047629776327625062258700337193014005673411952335683536865294076478098678", ) .unwrap(); let b = G2Bytes::new_unchecked( [ - "10039243553158378944380740968043887743081233734014916979736214569065002261361", - "4926621746570487391149084476602889692047252928870676314074045787488022393462", + "11831059544281359959902363827760224027191828999098259913907764686593049260801", + "14933419822301565783764657928814181728459886670248956535955133596731082875810", ], [ - "8151326214925440719229499872086146990795191649649968979609056373308460653969", - "12483309147304635788397060225283577172417980480151834869358925058077916828359", + "16616167200367085072660100259194052934821478809307596510515652443339946625933", + "1103855954970567341442645156173756328940907403537523212700521414512165362008", ], ) .unwrap(); let c = G1Bytes::new_unchecked( - "17509024307642709963307435885289611077932619305068428354097243520217914637634", - "17824783754604065652634030354434350582834434348663254057492956883323214722668", + "296457556259014920933232985275282694032456344171046224944953719399946325676", + "10314488872240559867545387237625153841351761679810222583912967187658678987385", ) .unwrap(); let proof = Groth16Zkp::new(a, b, c); @@ -472,6 +489,9 @@ async fn test_groth16_signature_transaction_submission_proof_signature_check_fai sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephemeral_signature.clone(), // Wrong signature + training_wheels_signature: EphemeralSignature::ed25519(tw_sk.sign(&proof).unwrap()), + extra_field: "\"family_name\":\"Straka\",".to_string(), + override_aud_val: None, }), jwt_header, exp_timestamp_secs: 1900255944, @@ -488,7 +508,7 @@ async fn test_groth16_signature_transaction_submission_proof_signature_check_fai .unwrap_err(); } -async fn test_setup(swarm: &mut LocalSwarm, cli: &mut CliTestFramework) { +async fn test_setup(swarm: &mut LocalSwarm, cli: &mut CliTestFramework) -> Ed25519PrivateKey { let client = swarm.validators().next().unwrap().rest_client(); let root_idx = cli.add_account_with_address_to_cli( swarm.root_key(), @@ -508,13 +528,18 @@ async fn test_setup(swarm: &mut LocalSwarm, cli: &mut CliTestFramework) { n:"6S7asUuzq5Q_3U9rbs-PkDVIdjgmtgWreG5qWPsC9xXZKiMV1AiV9LXyqQsAYpCqEDM3XbfmZqGb48yLhb_XqZaKgSYaC_h2DjM7lgrIQAp9902Rr8fUmLN2ivr5tnLxUUOnMOc2SQtr9dgzTONYW5Zu3PwyvAWk5D6ueIUhLtYzpcB-etoNdL3Ir2746KIy_VUsDwAM7dhrqSK8U2xFCGlau4ikOTtvzDownAMHMrfE7q1B6WZQDAQlBmxRQsyKln5DIsKv6xauNsHRgBAKctUxZG8M4QJIx3S6Aughd3RZC4Ca5Ae9fd8L8mlNYBCrQhOZ7dS0f4at4arlLcajtw".to_owned(), }; + let training_wheels_sk = Ed25519PrivateKey::generate(&mut thread_rng()); + let training_wheels_pk = Ed25519PublicKey::from(&training_wheels_sk); + info!("Insert a JWK."); let jwk_patch_script = format!( r#" script {{ use aptos_framework::jwks; +use aptos_framework::zkid; use aptos_framework::aptos_governance; use std::string::utf8; +use std::option; fun main(core_resources: &signer) {{ let framework_signer = aptos_governance::get_signer_testnet_only(core_resources, @0000000000000000000000000000000000000000000000000000000000000001); let google_jwk_0 = jwks::new_rsa_jwk( @@ -528,10 +553,15 @@ fun main(core_resources: &signer) {{ jwks::new_patch_upsert_jwk(b"{}", google_jwk_0), ]; jwks::set_patches(&framework_signer, patches); + + zkid::update_training_wheels(&framework_signer, option::some(x"{}")); }} }} "#, - jwk.kid, jwk.n, iss + jwk.kid, + jwk.n, + iss, + hex::encode(training_wheels_pk.to_bytes()) ); let txn_summary = cli.run_script(root_idx, &jwk_patch_script).await.unwrap(); @@ -554,6 +584,8 @@ fun main(core_resources: &signer) {{ // Increment sequence number since we patched a JWK info.root_account().increment_sequence_number(); + + training_wheels_sk } async fn get_latest_jwkset(rest_client: &Client) -> PatchedJWKs { diff --git a/types/src/bn254_circom.rs b/types/src/bn254_circom.rs index 4505ad7edc3dc..34d98c404c0b3 100644 --- a/types/src/bn254_circom.rs +++ b/types/src/bn254_circom.rs @@ -2,42 +2,136 @@ use crate::{ jwks::rsa::RSA_JWK, - zkid::{ - ZkIdPublicKey, ZkIdSignature, MAX_EPK_BYTES, MAX_EXPIRY_HORIZON_SECS, MAX_ISS_BYTES, - MAX_JWT_HEADER_BYTES, - }, + zkid::{Configuration, IdCommitment, ZkIdPublicKey, ZkIdSignature, ZkpOrOpenIdSig}, }; use anyhow::bail; use aptos_crypto::{poseidon_bn254, CryptoMaterialError}; -use ark_bn254::{Fq, Fq2}; +use ark_bn254::{Bn254, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projective}; use ark_ff::PrimeField; use ark_groth16::{PreparedVerifyingKey, VerifyingKey}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use move_core_types::{ident_str, identifier::IdentStr, move_resource::MoveStructType}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use serde_big_array::BigArray; +use std::fmt::{Display, Formatter}; // TODO(zkid): Some of this stuff, if not all, belongs to the aptos-crypto crate pub const G1_PROJECTIVE_COMPRESSED_NUM_BYTES: usize = 32; pub const G2_PROJECTIVE_COMPRESSED_NUM_BYTES: usize = 64; -pub static DEVNET_VERIFYING_KEY: Lazy> = - Lazy::new(devnet_pvk); +/// Useful macro for arkworks serialization! +macro_rules! serialize { + ($obj:expr) => {{ + let mut buf = vec![]; + $obj.serialize_compressed(&mut buf).unwrap(); + buf + }}; +} + +/// Reflection of aptos_framework::zkid::Groth16PreparedVerificationKey +#[derive(Serialize, Deserialize, Debug)] +pub struct Groth16VerificationKey { + alpha_g1: Vec, + beta_g2: Vec, + gamma_g2: Vec, + delta_g2: Vec, + gamma_abc_g1: Vec>, +} + +impl MoveStructType for Groth16VerificationKey { + const MODULE_NAME: &'static IdentStr = ident_str!("zkid"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Groth16VerificationKey"); +} + +impl TryFrom for PreparedVerifyingKey { + type Error = CryptoMaterialError; + + fn try_from(vk: Groth16VerificationKey) -> Result { + if vk.gamma_abc_g1.len() != 2 { + return Err(CryptoMaterialError::DeserializationError); + } + + Ok(Self::from(VerifyingKey { + alpha_g1: G1Affine::deserialize_compressed(vk.alpha_g1.as_slice()) + .map_err(|_| CryptoMaterialError::DeserializationError)?, + beta_g2: G2Affine::deserialize_compressed(vk.beta_g2.as_slice()) + .map_err(|_| CryptoMaterialError::DeserializationError)?, + gamma_g2: G2Affine::deserialize_compressed(vk.gamma_g2.as_slice()) + .map_err(|_| CryptoMaterialError::DeserializationError)?, + delta_g2: G2Affine::deserialize_compressed(vk.delta_g2.as_slice()) + .map_err(|_| CryptoMaterialError::DeserializationError)?, + gamma_abc_g1: vec![ + G1Affine::deserialize_compressed(vk.gamma_abc_g1[0].as_slice()) + .map_err(|_| CryptoMaterialError::DeserializationError)?, + G1Affine::deserialize_compressed(vk.gamma_abc_g1[1].as_slice()) + .map_err(|_| CryptoMaterialError::DeserializationError)?, + ], + })) + } +} + +impl From> for Groth16VerificationKey { + fn from(pvk: PreparedVerifyingKey) -> Self { + let PreparedVerifyingKey { + vk: + VerifyingKey { + alpha_g1, + beta_g2, + gamma_g2, + delta_g2, + gamma_abc_g1, + }, + alpha_g1_beta_g2: _alpha_g1_beta_g2, // unnecessary for Move + gamma_g2_neg_pc: _gamma_g2_neg_pc, // unnecessary for Move + delta_g2_neg_pc: _delta_g2_neg_pc, // unnecessary for Move + } = pvk; + + let mut gamma_abc_g1_bytes = Vec::with_capacity(gamma_abc_g1.len()); + for e in gamma_abc_g1.iter() { + gamma_abc_g1_bytes.push(serialize!(e)); + } + + Groth16VerificationKey { + alpha_g1: serialize!(alpha_g1), + beta_g2: serialize!(beta_g2), + gamma_g2: serialize!(gamma_g2), + delta_g2: serialize!(delta_g2), + gamma_abc_g1: gamma_abc_g1_bytes, + } + } +} + +impl Display for Groth16VerificationKey { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "alpha_g1: {}", hex::encode(&self.alpha_g1))?; + write!(f, "beta_g2: {}", hex::encode(&self.beta_g2))?; + write!(f, "gamma_g2: {}", hex::encode(&self.gamma_g2))?; + write!(f, "delta_g2: {}", hex::encode(&self.delta_g2))?; + for (i, e) in self.gamma_abc_g1.iter().enumerate() { + write!(f, "gamma_abc_g1[{i}]: {}", hex::encode(serialize!(e)))?; + } + Ok(()) + } +} + +pub static DEVNET_VERIFYING_KEY: Lazy> = Lazy::new(devnet_pvk); /// This will do the proper subgroup membership checks. -fn g1_projective_str_to_affine(x: &str, y: &str) -> anyhow::Result { +fn g1_projective_str_to_affine(x: &str, y: &str) -> anyhow::Result { let g1_affine = G1Bytes::new_unchecked(x, y)?.deserialize_into_affine()?; Ok(g1_affine) } /// This will do the proper subgroup membership checks. -fn g2_projective_str_to_affine(x: [&str; 2], y: [&str; 2]) -> anyhow::Result { +fn g2_projective_str_to_affine(x: [&str; 2], y: [&str; 2]) -> anyhow::Result { let g2_affine = G2Bytes::new_unchecked(x, y)?.to_affine()?; Ok(g2_affine) } -fn devnet_pvk() -> PreparedVerifyingKey { +/// This function uses the decimal uncompressed point serialization which is outputted by circom. +fn devnet_pvk() -> PreparedVerifyingKey { // Convert the projective points to affine. let alpha_g1 = g1_projective_str_to_affine( "16672231080302629756836614130913173861541009360974119524782950408048375831661", @@ -71,12 +165,12 @@ fn devnet_pvk() -> PreparedVerifyingKey { let delta_g2 = g2_projective_str_to_affine( [ - "19799867077440075892798570892827678991452882191483986973420950266983588147526", - "7261406229996412667156189606964369006242293247396567701023787052439810543589", + "10857046999023057135944570762232829481370756359578518086990519993285655852781", + "11559732032986387107991004021392285783925812861821192530917403151452391805634", ], [ - "15618356441847575237880159451782511420373837463064250522093342825487687558812", - "20490123502151072560031041764173142979409281632225526952209676367033524880945", + "8495653923123431417604973247489272438418190587263600148770280649306958101930", + "4082367875863433681332203403145435568316851327593401208105741076214120093531", ], ) .unwrap(); @@ -84,13 +178,13 @@ fn devnet_pvk() -> PreparedVerifyingKey { let mut gamma_abc_g1 = Vec::new(); for points in [ g1_projective_str_to_affine( - "16119992548622948701752093197035559180088659648245261797962160821523395857787", - "10895012769720065848112628781322097989082134121307195027616506940584635557433", + "709845293616032000883655261014820428774807602111296273992483611119383326362", + "645961711055726048875381920095150798755926517220714963239815637182963128467", ) .unwrap(), g1_projective_str_to_affine( - "12743680909720798417558674763081930985009983383780261525309863653205478749832", - "10808093222645961212778297519773755506856954740368509958745099866520706196565", + "9703775855460452449287141941638080366156266996878046656846622159120386001635", + "1903615495723998350630869740881559921229604803173196414121492346747062004184", ) .unwrap(), ] { @@ -126,7 +220,7 @@ pub struct G1Bytes(pub(crate) [u8; G1_PROJECTIVE_COMPRESSED_NUM_BYTES]); impl G1Bytes { pub fn new_unchecked(x: &str, y: &str) -> anyhow::Result { - let g1 = ark_bn254::G1Projective::new_unchecked( + let g1 = G1Projective::new_unchecked( parse_field_element(x)?, parse_field_element(y)?, parse_field_element("1")?, @@ -136,6 +230,7 @@ impl G1Bytes { Self::new_from_vec(bytes) } + /// Used internall or for testing. pub fn new_from_vec(vec: Vec) -> anyhow::Result { if vec.len() == G1_PROJECTIVE_COMPRESSED_NUM_BYTES { let mut bytes = [0; G1_PROJECTIVE_COMPRESSED_NUM_BYTES]; @@ -149,25 +244,25 @@ impl G1Bytes { } } - pub fn deserialize_into_affine(&self) -> Result { + pub fn deserialize_into_affine(&self) -> Result { self.try_into() } } -impl TryInto for &G1Bytes { +impl TryInto for &G1Bytes { type Error = CryptoMaterialError; - fn try_into(self) -> Result { - ark_bn254::G1Projective::deserialize_compressed(self.0.as_slice()) + fn try_into(self) -> Result { + G1Projective::deserialize_compressed(self.0.as_slice()) .map_err(|_| CryptoMaterialError::DeserializationError) } } -impl TryInto for &G1Bytes { +impl TryInto for &G1Bytes { type Error = CryptoMaterialError; - fn try_into(self) -> Result { - let g1_projective: ark_bn254::G1Projective = self.try_into()?; + fn try_into(self) -> Result { + let g1_projective: G1Projective = self.try_into()?; Ok(g1_projective.into()) } } @@ -177,7 +272,7 @@ pub struct G2Bytes(#[serde(with = "BigArray")] pub(crate) [u8; G2_PROJECTIVE_COM impl G2Bytes { pub fn new_unchecked(x: [&str; 2], y: [&str; 2]) -> anyhow::Result { - let g2 = ark_bn254::G2Projective::new_unchecked( + let g2 = G2Projective::new_unchecked( Fq2::new(parse_field_element(x[0])?, parse_field_element(x[1])?), Fq2::new(parse_field_element(y[0])?, parse_field_element(y[1])?), Fq2::new(parse_field_element("1")?, parse_field_element("0")?), @@ -200,25 +295,25 @@ impl G2Bytes { } } - pub fn to_affine(&self) -> Result { + pub fn to_affine(&self) -> Result { self.try_into() } } -impl TryInto for &G2Bytes { +impl TryInto for &G2Bytes { type Error = CryptoMaterialError; - fn try_into(self) -> Result { - ark_bn254::G2Projective::deserialize_compressed(self.0.as_slice()) + fn try_into(self) -> Result { + G2Projective::deserialize_compressed(self.0.as_slice()) .map_err(|_| CryptoMaterialError::DeserializationError) } } -impl TryInto for &G2Bytes { +impl TryInto for &G2Bytes { type Error = CryptoMaterialError; - fn try_into(self) -> Result { - let g2_projective: ark_bn254::G2Projective = self.try_into()?; + fn try_into(self) -> Result { + let g2_projective: G2Projective = self.try_into()?; Ok(g2_projective.into()) } } @@ -227,46 +322,79 @@ pub fn get_public_inputs_hash( sig: &ZkIdSignature, pk: &ZkIdPublicKey, jwk: &RSA_JWK, -) -> anyhow::Result { + config: &Configuration, +) -> anyhow::Result { + let extra_field_hashed; + let override_aud_val_hashed; + let use_override_aud; + if let ZkpOrOpenIdSig::Groth16Zkp(proof) = &sig.sig { + extra_field_hashed = poseidon_bn254::pad_and_hash_string( + &proof.extra_field, + config.max_extra_field_bytes as usize, + )?; + if let Some(override_aud_val) = &proof.override_aud_val { + use_override_aud = ark_bn254::Fr::from(1); + override_aud_val_hashed = poseidon_bn254::pad_and_hash_string( + override_aud_val, + IdCommitment::MAX_AUD_VAL_BYTES, + )?; + } else { + use_override_aud = ark_bn254::Fr::from(0); + override_aud_val_hashed = + poseidon_bn254::pad_and_hash_string("", IdCommitment::MAX_AUD_VAL_BYTES)?; + } + } else { + bail!("Cannot get_public_inputs_hash for ZkIdSignature") + } + // Add the epk as padded and packed scalars let mut frs = poseidon_bn254::pad_and_pack_bytes_to_scalars_with_len( sig.ephemeral_pubkey.to_bytes().as_slice(), - MAX_EPK_BYTES, + config.max_commited_epk_bytes as usize, )?; // Add the id_commitment as a scalar - frs.push(ark_bn254::Fr::from_le_bytes_mod_order(&pk.idc.0)); + frs.push(Fr::from_le_bytes_mod_order(&pk.idc.0)); // Add the exp_timestamp_secs as a scalar - frs.push(ark_bn254::Fr::from(sig.exp_timestamp_secs)); + frs.push(Fr::from(sig.exp_timestamp_secs)); // Add the epk lifespan as a scalar - frs.push(ark_bn254::Fr::from(MAX_EXPIRY_HORIZON_SECS)); + frs.push(Fr::from(config.max_exp_horizon_secs)); // Add the hash of the iss (formatted key-value pair string). let formatted_iss = format!("\"iss\":\"{}\",", pk.iss); frs.push(poseidon_bn254::pad_and_hash_string( &formatted_iss, - MAX_ISS_BYTES, + config.max_iss_field_bytes as usize, )?); + frs.push(extra_field_hashed); + // Add the hash of the jwt_header with the "." separator appended let jwt_header_with_separator = format!("{}.", sig.jwt_header); frs.push(poseidon_bn254::pad_and_hash_string( &jwt_header_with_separator, - MAX_JWT_HEADER_BYTES, + config.max_jwt_header_b64_bytes as usize, )?); frs.push(jwk.to_poseidon_scalar()?); + frs.push(override_aud_val_hashed); + + frs.push(use_override_aud); + poseidon_bn254::hash_scalars(frs) } #[cfg(test)] mod test { use crate::bn254_circom::{ - G1Bytes, G2Bytes, G1_PROJECTIVE_COMPRESSED_NUM_BYTES, G2_PROJECTIVE_COMPRESSED_NUM_BYTES, + devnet_pvk, G1Bytes, G2Bytes, Groth16VerificationKey, G1_PROJECTIVE_COMPRESSED_NUM_BYTES, + G2_PROJECTIVE_COMPRESSED_NUM_BYTES, }; + use ark_bn254::Bn254; + use ark_groth16::PreparedVerifyingKey; #[test] pub fn test_bn254_serialized_sizes() { @@ -294,4 +422,14 @@ mod test { let g2_bytes = bcs::to_bytes(&g2).unwrap(); assert_eq!(g2_bytes.len(), G2_PROJECTIVE_COMPRESSED_NUM_BYTES); } + + #[test] + // Tests conversion between the devnet ark_groth16::PreparedVerificationKey and our Move + // representation of it. + fn print_groth16_pvk() { + let groth16_vk: Groth16VerificationKey = devnet_pvk().into(); + let same_pvk: PreparedVerifyingKey = groth16_vk.try_into().unwrap(); + + assert_eq!(same_pvk, devnet_pvk()); + } } diff --git a/types/src/jwks/rsa/mod.rs b/types/src/jwks/rsa/mod.rs index d3fd836f5c8b6..40d15f68b641c 100644 --- a/types/src/jwks/rsa/mod.rs +++ b/types/src/jwks/rsa/mod.rs @@ -8,8 +8,6 @@ use jsonwebtoken::{Algorithm, DecodingKey, TokenData, Validation}; use move_core_types::value::{MoveStruct, MoveValue}; use serde::{Deserialize, Serialize}; -pub const RSA_MODULUS_BYTES: usize = 256; - /// Move type `0x1::jwks::RSA_JWK` in rust. /// See its doc in Move for more details. #[allow(non_camel_case_types)] @@ -23,6 +21,9 @@ pub struct RSA_JWK { } impl RSA_JWK { + /// The circuit-supported RSA modulus size. + pub const RSA_MODULUS_BYTES: usize = 256; + /// Make an `RSA_JWK` from `kty="RSA", alg="RS256", e="AQAB"` (a popular setting) /// and caller-specified `kid` and `n`. pub fn new_256_aqab(kid: &str, n: &str) -> Self { @@ -61,18 +62,24 @@ impl RSA_JWK { pub fn to_poseidon_scalar(&self) -> Result { let mut modulus = base64::decode_config(&self.n, URL_SAFE_NO_PAD)?; // The circuit only supports RSA256 - if modulus.len() != RSA_MODULUS_BYTES { - bail!("Wrong modulus size, must be {} bytes", RSA_MODULUS_BYTES); + if modulus.len() != Self::RSA_MODULUS_BYTES { + bail!( + "Wrong modulus size, must be {} bytes", + Self::RSA_MODULUS_BYTES + ); } - modulus.reverse(); // This is done to match the circuit, which requires the modulus in a verify specific format due to how RSA verification is implemented - // TODO(zkid): finalize the jwk hashing scheme. + + // This is done to match the circuit, which requires the modulus in a verify specific format + // due to how RSA verification is implemented + modulus.reverse(); + let mut scalars = modulus .chunks(24) // Pack 3 64 bit limbs per scalar, so chunk into 24 bytes per scalar .map(|chunk| { poseidon_bn254::pack_bytes_to_one_scalar(chunk).expect("chunk converts to scalar") }) .collect::>(); - scalars.push(ark_bn254::Fr::from(RSA_MODULUS_BYTES as i32)); + scalars.push(ark_bn254::Fr::from(Self::RSA_MODULUS_BYTES as i32)); poseidon_bn254::hash_scalars(scalars) } } diff --git a/types/src/transaction/authenticator.rs b/types/src/transaction/authenticator.rs index ca146f6650b38..cb354f032a08d 100644 --- a/types/src/transaction/authenticator.rs +++ b/types/src/transaction/authenticator.rs @@ -1004,16 +1004,12 @@ impl AnySignature { signature.verify(message, public_key) }, (Self::WebAuthn { signature }, _) => signature.verify(message, public_key), - (Self::ZkId { signature }, AnyPublicKey::ZkId { public_key }) => { + (Self::ZkId { signature }, AnyPublicKey::ZkId { public_key: _ }) => { match &signature.sig { ZkpOrOpenIdSig::Groth16Zkp(proof) => { - proof.verify_non_malleability(&signature.ephemeral_pubkey)? + proof.verify_non_malleability_sig(&signature.ephemeral_pubkey)? }, - ZkpOrOpenIdSig::OpenIdSig(oidc_sig) => oidc_sig.verify_jwt_claims( - signature.exp_timestamp_secs, - &signature.ephemeral_pubkey, - public_key, - )?, + ZkpOrOpenIdSig::OpenIdSig(_) => {}, } // Verify the ephemeral signature on the TXN. The rest of the verification, // i.e., [ZKPoK of] OpenID signature verification will be done in `AptosVM::run_prologue`. @@ -1068,7 +1064,6 @@ impl AnyPublicKey { bcs::to_bytes(self).expect("Only unhandleable errors happen here.") } } - #[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] pub enum EphemeralSignature { Ed25519 { signature: Ed25519Signature }, @@ -1131,9 +1126,7 @@ mod tests { use crate::{ bn254_circom::{G1Bytes, G2Bytes}, transaction::{webauthn::AssertionSignature, SignedTransaction}, - zkid::{ - Groth16Zkp, IdCommitment, OpenIdSig, Pepper, SignedGroth16Zkp, EPK_BLINDER_NUM_BYTES, - }, + zkid::{Groth16Zkp, IdCommitment, OpenIdSig, Pepper, SignedGroth16Zkp}, }; use aptos_crypto::{ ed25519::Ed25519PrivateKey, @@ -1141,9 +1134,8 @@ mod tests { secp256r1_ecdsa::{PublicKey, Signature}, PrivateKey, SigningKey, Uniform, }; - use base64::URL_SAFE_NO_PAD; use hex::FromHex; - use rand::{rngs::StdRng, SeedableRng}; + use rand::thread_rng; #[test] fn test_from_str_should_not_panic_by_given_empty_string() { @@ -1672,252 +1664,7 @@ mod tests { } #[test] - fn verify_zkid_open_id_single_key_auth() { - let iss = "https://server.example.com"; - let aud = "s6BhdRkqt3"; - let uid_key = "sub"; - let uid_val = "248289761001"; - let pepper = 76; - let exp_timestamp_secs = 1311281970; - let jwt_header_json = r#"{ - "alg": "RS256", - "typ": "JWT" - }"#; - let jwt_payload_json = format!( - r#"{{ - "iss": "{}", - "{}": "{}", - "aud": "{}", - "nonce": "uxxgjhTml_fhiFwyWCyExJTD3J2YK3MoVDOYdnxieiE", - "exp": 1311281970, - "iat": 1311280970, - "name": "Jane Doe", - "given_name": "Jane", - "family_name": "Doe", - "gender": "female", - "birthdate": "0000-10-31", - "email": "janedoe@example.com", - "picture": "http://example.com/janedoe/me.jpg" - }}"#, - iss, uid_key, uid_val, aud - ); - let idc = - IdCommitment::new_from_preimage(&Pepper::from_number(pepper), aud, uid_key, uid_val) - .unwrap(); - let zkid_pubkey = ZkIdPublicKey { - iss: iss.to_owned(), - idc, - }; - let signed_txn = zkid_test_setup( - zkid_pubkey, - uid_key, - pepper, - exp_timestamp_secs, - jwt_header_json, - &jwt_payload_json, - ); - let verification_result = signed_txn.verify_signature(); - verification_result.unwrap(); - } - - #[test] - fn verify_zkid_open_id_single_key_auth_fails_with_different_pepper() { - let iss = "https://server.example.com"; - let aud = "s6BhdRkqt3"; - let uid_key = "sub"; - let uid_val = "248289761001"; - let pepper = 76; - let bad_pepper = 123; - let exp_timestamp_secs = 1311281970; - let jwt_header_json = r#"{ - "alg": "RS256", - "typ": "JWT" - }"#; - let jwt_payload_json = format!( - r#"{{ - "iss": "{}", - "{}": "{}", - "aud": "{}", - "nonce": "uxxgjhTml_fhiFwyWCyExJTD3J2YK3MoVDOYdnxieiE", - "exp": 1311281970, - "iat": 1311280970, - "name": "Jane Doe", - "given_name": "Jane", - "family_name": "Doe", - "gender": "female", - "birthdate": "0000-10-31", - "email": "janedoe@example.com", - "picture": "http://example.com/janedoe/me.jpg" - }}"#, - iss, uid_key, uid_val, aud - ); - let idc = - IdCommitment::new_from_preimage(&Pepper::from_number(pepper), aud, uid_key, uid_val) - .unwrap(); - let zkid_pubkey = ZkIdPublicKey { - iss: iss.to_owned(), - idc, - }; - let signed_txn = zkid_test_setup( - zkid_pubkey, - uid_key, - bad_pepper, // Pepper does not match - exp_timestamp_secs, - jwt_header_json, - &jwt_payload_json, - ); - let verification_result = signed_txn.verify_signature(); - assert!(verification_result.is_err()); - } - - #[test] - fn verify_zkid_open_id_single_key_auth_fails_with_expiry_past_horizon() { - let iss = "https://server.example.com"; - let aud = "s6BhdRkqt3"; - let uid_key = "sub"; - let uid_val = "248289761001"; - let pepper = 76; - let jwt_header_json = r#"{ - "alg": "RS256", - "typ": "JWT" - }"#; - let jwt_payload_json = format!( - r#"{{ - "iss": "{}", - "{}": "{}", - "aud": "{}", - "nonce": "uxxgjhTml_fhiFwyWCyExJTD3J2YK3MoVDOYdnxieiE", - "exp": 1311281970, - "iat": 1311280970, - "name": "Jane Doe", - "given_name": "Jane", - "family_name": "Doe", - "gender": "female", - "birthdate": "0000-10-31", - "email": "janedoe@example.com", - "picture": "http://example.com/janedoe/me.jpg" - }}"#, - iss, uid_key, uid_val, aud - ); - let idc = - IdCommitment::new_from_preimage(&Pepper::from_number(pepper), aud, uid_key, uid_val) - .unwrap(); - let zkid_pubkey = ZkIdPublicKey { - iss: iss.to_owned(), - idc, - }; - let signed_txn = zkid_test_setup( - zkid_pubkey, - uid_key, - pepper, - 1000000000000000000, - jwt_header_json, - &jwt_payload_json, - ); - let verification_result = signed_txn.verify_signature(); - assert!(verification_result.is_err()); - } - - #[test] - fn verify_zkid_open_id_single_key_auth_fails_with_different_uid_val() { - let iss = "https://server.example.com"; - let aud = "s6BhdRkqt3"; - let uid_key = "sub"; - let uid_val = "248289761001"; - let pepper = 76; - let exp_timestamp_secs = 1311281970; - let jwt_header_json = r#"{ - "alg": "RS256", - "typ": "JWT" - }"#; - let jwt_payload_json = format!( - r#"{{ - "iss": "{}", - "{}": "{}", - "aud": "{}", - "nonce": "uxxgjhTml_fhiFwyWCyExJTD3J2YK3MoVDOYdnxieiE", - "exp": {}, - "iat": 1311280970, - "name": "Jane Doe", - "given_name": "Jane", - "family_name": "Doe", - "gender": "female", - "birthdate": "0000-10-31", - "email": "janedoe@example.com", - "picture": "http://example.com/janedoe/me.jpg" - }}"#, - iss, uid_key, "bad_uid_val", aud, exp_timestamp_secs - ); - let idc = - IdCommitment::new_from_preimage(&Pepper::from_number(pepper), aud, uid_key, uid_val) - .unwrap(); - let zkid_pubkey = ZkIdPublicKey { - iss: iss.to_owned(), - idc, - }; - let signed_txn = zkid_test_setup( - zkid_pubkey, - uid_key, - pepper, - exp_timestamp_secs, - jwt_header_json, - &jwt_payload_json, - ); - let verification_result = signed_txn.verify_signature(); - assert!(verification_result.is_err()); - } - - #[test] - fn verify_zkid_open_id_single_key_auth_fails_with_bad_nonce() { - let iss = "https://server.example.com"; - let aud = "s6BhdRkqt3"; - let uid_key = "sub"; - let uid_val = "248289761001"; - let pepper = 76; - let exp_timestamp_secs = 1311281970; - let jwt_header_json = r#"{ - "alg": "RS256", - "typ": "JWT" - }"#; - let jwt_payload_json = format!( - r#"{{ - "iss": "{}", - "{}": "{}", - "aud": "{}", - "nonce": "bad nonce", - "exp": {}, - "iat": 1311280970, - "name": "Jane Doe", - "given_name": "Jane", - "family_name": "Doe", - "gender": "female", - "birthdate": "0000-10-31", - "email": "janedoe@example.com", - "picture": "http://example.com/janedoe/me.jpg" - }}"#, - iss, uid_key, uid_val, aud, exp_timestamp_secs - ); - let idc = - IdCommitment::new_from_preimage(&Pepper::from_number(pepper), aud, uid_key, uid_val) - .unwrap(); - let zkid_pubkey = ZkIdPublicKey { - iss: iss.to_owned(), - idc, - }; - let signed_txn = zkid_test_setup( - zkid_pubkey, - uid_key, - pepper, - exp_timestamp_secs, - jwt_header_json, - &jwt_payload_json, - ); - let verification_result = signed_txn.verify_signature(); - assert!(verification_result.is_err()); - } - - #[test] - fn verify_zkid_open_id_single_key_auth_fails_with_bad_ephemeral_signature() { + fn test_zkid_oidc_sig_fails_with_bad_ephemeral_signature() { let pepper = Pepper::from_number(76); let idc = IdCommitment::new_from_preimage(&pepper, "s6BhdRkqt3", "sub", "248289761001").unwrap(); @@ -1929,138 +1676,99 @@ mod tests { let sender_auth_key = AuthenticationKey::any_key(sender_any_public_key.clone()); let sender_addr = sender_auth_key.account_address(); - let ephemeral_private_key = Ed25519PrivateKey::generate_for_testing(); - let ephemeral_public_key = EphemeralPublicKey::ed25519(ephemeral_private_key.public_key()); + let esk = Ed25519PrivateKey::generate_for_testing(); + let epk = EphemeralPublicKey::ed25519(esk.public_key()); let raw_txn = crate::test_helpers::transaction_test_helpers::get_test_signed_transaction( sender_addr, 0, - &ephemeral_private_key, - ephemeral_private_key.public_key(), + &esk, + esk.public_key(), None, 0, 0, None, ) .into_raw_transaction(); + let ephemeral_sig = EphemeralSignature::ed25519(esk.sign(&raw_txn).unwrap()); + + let bad_esk = Ed25519PrivateKey::generate(&mut thread_rng()); // Wrong private key! + let bad_ephemeral_sig = EphemeralSignature::ed25519(bad_esk.sign(&raw_txn).unwrap()); - let mut rng: StdRng = SeedableRng::from_seed([1; 32]); - let bad_ephemeral_private_key = Ed25519PrivateKey::generate(&mut rng); // Wrong private key! - let sender_sig = bad_ephemeral_private_key.sign(&raw_txn).unwrap(); - let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); - - // This is the decoded json string the jwt_payload used below. - // - // { - // "iss": "https://server.example.com", - // "sub": "248289761001", - // "aud": "s6BhdRkqt3", - // "nonce": "7BgjE1MZgLKY_4NwVWoJKUKPgpBcB0espRwKYASGkgw", - // "exp": 1311281970, - // "iat": 1311280970, - // "name": "Jane Doe", - // "given_name": "Jane", - // "family_name": "Doe", - // "gender": "female", - // "birthdate": "0000-10-31", - // "email": "janedoe@example.com", - // "picture": "http://example.com/janedoe/me.jpg" - // } let openid_signature = OpenIdSig { jwt_sig: "jwt_sig is verified in the prologue".to_string(), - jwt_payload: "ewogImlzcyI6ICJodHRwczovL3NlcnZlci5leGFtcGxlLmNvbSIsCiAic3ViIjogIjI0ODI4OTc2MTAwMSIsCiAiYXVkIjogInM2QmhkUmtxdDMiLAogIm5vbmNlIjogIjdCZ2pFMU1aZ0xLWV80TndWV29KS1VLUGdwQmNCMGVzcFJ3S1lBU0drZ3ciLAogImV4cCI6IDEzMTEyODE5NzAsCiAiaWF0IjogMTMxMTI4MDk3MCwKICJuYW1lIjogIkphbmUgRG9lIiwKICJnaXZlbl9uYW1lIjogIkphbmUiLAogImZhbWlseV9uYW1lIjogIkRvZSIsCiAiZ2VuZGVyIjogImZlbWFsZSIsCiAiYmlydGhkYXRlIjogIjAwMDAtMTAtMzEiLAogImVtYWlsIjogImphbmVkb2VAZXhhbXBsZS5jb20iLAogInBpY3R1cmUiOiAiaHR0cDovL2V4YW1wbGUuY29tL2phbmVkb2UvbWUuanBnIgp9".to_string(), + jwt_payload: "JWT payload is now verified in prologue too".to_string(), uid_key: "sub".to_string(), - epk_blinder: [0u8; EPK_BLINDER_NUM_BYTES], + epk_blinder: vec![0u8; OpenIdSig::EPK_BLINDER_NUM_BYTES], pepper, + idc_aud_val: None, }; - let zk_sig = ZkIdSignature { - sig: ZkpOrOpenIdSig::OpenIdSig(openid_signature), - jwt_header: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.".to_owned(), - exp_timestamp_secs: 1311281970, - ephemeral_pubkey: ephemeral_public_key, - ephemeral_signature, - }; - - let sk_auth = - SingleKeyAuthenticator::new(sender_any_public_key, AnySignature::zkid(zk_sig)); - let account_auth = AccountAuthenticator::single_key(sk_auth); - let signed_txn = SignedTransaction::new_single_sender(raw_txn, account_auth); + let signed_txn = build_signature( + &sender_any_public_key, + &raw_txn, + &openid_signature, + &epk, + &ephemeral_sig, + ); + let badly_signed_txn = build_signature( + &sender_any_public_key, + &raw_txn, + &openid_signature, + &epk, + &bad_ephemeral_sig, + ); - let verification_result = signed_txn.verify_signature(); - assert!(verification_result.is_err()); + assert!(signed_txn.verify_signature().is_ok()); + assert!(badly_signed_txn.verify_signature().is_err()); } - #[test] - fn verify_zkid_open_id_single_key_auth_fails_with_different_iss() { - let iss = "https://server.example.com"; - let aud = "s6BhdRkqt3"; - let uid_key = "sub"; - let uid_val = "248289761001"; - let pepper = 76; - let exp_timestamp_secs = 1311281970; - let jwt_header_json = r#"{ - "alg": "RS256", - "typ": "JWT" - }"#; - let jwt_payload_json = format!( - r#"{{ - "iss": "{}", - "{}": "{}", - "aud": "{}", - "nonce": "7BgjE1MZgLKY_4NwVWoJKUKPgpBcB0espRwKYASGkgw", - "exp": {}, - "iat": 1311280970, - "name": "Jane Doe", - "given_name": "Jane", - "family_name": "Doe", - "gender": "female", - "birthdate": "0000-10-31", - "email": "janedoe@example.com", - "picture": "http://example.com/janedoe/me.jpg" - }}"#, - iss, uid_key, uid_val, aud, exp_timestamp_secs - ); - let idc = - IdCommitment::new_from_preimage(&Pepper::from_number(pepper), aud, uid_key, uid_val) - .unwrap(); - let zkid_pubkey = ZkIdPublicKey { - iss: "bad_iss".to_owned(), - idc, - }; - let signed_txn = zkid_test_setup( - zkid_pubkey, - uid_key, - pepper, + fn build_signature( + sender_any_public_key: &AnyPublicKey, + raw_txn: &RawTransaction, + oidc_sig: &OpenIdSig, + epk: &EphemeralPublicKey, + eph_sig: &EphemeralSignature, + ) -> SignedTransaction { + let exp_timestamp_secs = 100000000000; // does not matter + let zk_sig = ZkIdSignature { + sig: ZkpOrOpenIdSig::OpenIdSig(oidc_sig.clone()), + // {"alg":"RS256","typ":"JWT"} + jwt_header: "JWT header is verified during prologue too".to_owned(), exp_timestamp_secs, - jwt_header_json, - &jwt_payload_json, - ); - let verification_result = signed_txn.verify_signature(); - assert!(verification_result.is_err()); + ephemeral_pubkey: epk.clone(), + ephemeral_signature: eph_sig.clone(), + }; + + let account_auth = AccountAuthenticator::single_key(SingleKeyAuthenticator::new( + sender_any_public_key.clone(), + AnySignature::zkid(zk_sig), + )); + SignedTransaction::new_single_sender(raw_txn.clone(), account_auth) } + /// TODO(zkid): Redundancy; a similar test case is in types/src/zkid.rs #[test] - fn test_groth16_proof_verification() { + fn test_zkid_groth16_proof_verification() { let a = G1Bytes::new_unchecked( - "11685701338011120485255682535216931952523490513574344095859176729155974193429", - "19570000702948951151001315672614758851000529478920585316943681012227747910337", + "20534193224874816823038374805971256353897254359389549519579800571198905682623", + "3128047629776327625062258700337193014005673411952335683536865294076478098678", ) .unwrap(); let b = G2Bytes::new_unchecked( [ - "10039243553158378944380740968043887743081233734014916979736214569065002261361", - "4926621746570487391149084476602889692047252928870676314074045787488022393462", + "11831059544281359959902363827760224027191828999098259913907764686593049260801", + "14933419822301565783764657928814181728459886670248956535955133596731082875810", ], [ - "8151326214925440719229499872086146990795191649649968979609056373308460653969", - "12483309147304635788397060225283577172417980480151834869358925058077916828359", + "16616167200367085072660100259194052934821478809307596510515652443339946625933", + "1103855954970567341442645156173756328940907403537523212700521414512165362008", ], ) .unwrap(); let c = G1Bytes::new_unchecked( - "17509024307642709963307435885289611077932619305068428354097243520217914637634", - "17824783754604065652634030354434350582834434348663254057492956883323214722668", + "296457556259014920933232985275282694032456344171046224944953719399946325676", + "10314488872240559867545387237625153841351761679810222583912967187658678987385", ) .unwrap(); let proof = Groth16Zkp::new(a, b, c); @@ -2093,6 +1801,11 @@ mod tests { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephem_proof_sig, + training_wheels_signature: EphemeralSignature::ed25519( + Ed25519Signature::dummy_signature(), + ), + extra_field: "\"family_name\":\"Straka\",".to_string(), + override_aud_val: None, }), jwt_header: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_owned(), exp_timestamp_secs: 1900255944, @@ -2121,59 +1834,4 @@ mod tests { let verification_result = signed_txn.verify_signature(); verification_result.unwrap(); } - - fn zkid_test_setup( - zkid_pubkey: ZkIdPublicKey, - uid_key: &str, - pepper: u128, - exp_timestamp_secs: u64, - jwt_header_unencoded: &str, - jwt_payload_unencoded: &str, - ) -> SignedTransaction { - let sender_zkid_public_key = zkid_pubkey; - let sender_any_public_key = AnyPublicKey::zkid(sender_zkid_public_key); - let sender_auth_key = AuthenticationKey::any_key(sender_any_public_key.clone()); - let sender_addr = sender_auth_key.account_address(); - - let ephemeral_private_key = Ed25519PrivateKey::generate_for_testing(); - let ephemeral_public_key = EphemeralPublicKey::ed25519(ephemeral_private_key.public_key()); - - let raw_txn = crate::test_helpers::transaction_test_helpers::get_test_signed_transaction( - sender_addr, - 0, - &ephemeral_private_key, - ephemeral_private_key.public_key(), - None, - 0, - 0, - None, - ) - .into_raw_transaction(); - - let sender_sig = ephemeral_private_key.sign(&raw_txn).unwrap(); - let ephemeral_signature = EphemeralSignature::ed25519(sender_sig); - - let jwt_payload = base64::encode_config(jwt_payload_unencoded.as_bytes(), URL_SAFE_NO_PAD); - let openid_signature = OpenIdSig { - jwt_sig: "jwt_sig is verified in the prologue".to_string(), - jwt_payload, - uid_key: uid_key.to_owned(), - epk_blinder: [0u8; EPK_BLINDER_NUM_BYTES], - pepper: Pepper::from_number(pepper), - }; - - let jwt_header = base64::encode_config(jwt_header_unencoded.as_bytes(), URL_SAFE_NO_PAD); - let zk_sig = ZkIdSignature { - sig: ZkpOrOpenIdSig::OpenIdSig(openid_signature), - jwt_header, - exp_timestamp_secs, - ephemeral_pubkey: ephemeral_public_key, - ephemeral_signature, - }; - - let sk_auth = - SingleKeyAuthenticator::new(sender_any_public_key, AnySignature::zkid(zk_sig)); - let account_auth = AccountAuthenticator::single_key(sk_auth); - SignedTransaction::new_single_sender(raw_txn, account_auth) - } } diff --git a/types/src/zkid.rs b/types/src/zkid.rs index 180a19d6c2369..03ade9234cc0b 100644 --- a/types/src/zkid.rs +++ b/types/src/zkid.rs @@ -1,8 +1,7 @@ // Copyright © Aptos Foundation use crate::{ - bn254_circom::{G1Bytes, G2Bytes, DEVNET_VERIFYING_KEY}, - chain_id::ChainId, + bn254_circom::{G1Bytes, G2Bytes}, jwks::rsa::RSA_JWK, on_chain_config::CurrentTimeMicroseconds, transaction::{ @@ -15,10 +14,16 @@ use crate::{ use anyhow::{bail, ensure, Context, Result}; use aptos_crypto::{poseidon_bn254, CryptoMaterialError, ValidCryptoMaterial}; use aptos_crypto_derive::{BCSCryptoHash, CryptoHasher}; -use ark_bn254; -use ark_groth16::{Groth16, Proof}; +use ark_bn254::{self, Bn254, Fr}; +use ark_groth16::{Groth16, PreparedVerifyingKey, Proof}; use ark_serialize::CanonicalSerialize; -use base64::{URL_SAFE, URL_SAFE_NO_PAD}; +use base64::URL_SAFE_NO_PAD; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::MoveStructType, + vm_status::{StatusCode, VMStatus}, +}; use serde::{Deserialize, Serialize}; use serde_json::Value; use serde_with::skip_serializing_none; @@ -28,36 +33,58 @@ use std::{ time::{Duration, SystemTime, UNIX_EPOCH}, }; -pub const PEPPER_NUM_BYTES: usize = poseidon_bn254::BYTES_PACKED_PER_SCALAR; -pub const EPK_BLINDER_NUM_BYTES: usize = poseidon_bn254::BYTES_PACKED_PER_SCALAR; -pub const NONCE_NUM_BYTES: usize = 32; -pub const IDC_NUM_BYTES: usize = 32; - -// TODO(ZkIdGroth16Zkp): add some static asserts here that these don't exceed the MAX poseidon input sizes -// TODO(ZkIdGroth16Zkp): determine what our circuit will accept - -/// We support ephemeral public key lengths of up to 93 bytes. -pub const MAX_EPK_BYTES: usize = 3 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; -// The values here are consistent with our public inputs hashing scheme. -// Everything is a multiple of `poseidon_bn254::BYTES_PACKED_PER_SCALAR` to maximize the input -// sizes that can be hashed. -pub const MAX_ISS_BYTES: usize = 5 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; -pub const MAX_AUD_VAL_BYTES: usize = 4 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; -pub const MAX_UID_KEY_BYTES: usize = 2 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; -pub const MAX_UID_VAL_BYTES: usize = 4 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; -pub const MAX_JWT_HEADER_BYTES: usize = 8 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; +#[macro_export] +macro_rules! invalid_signature { + ($message:expr) => { + VMStatus::error(StatusCode::INVALID_SIGNATURE, Some($message.to_owned())) + }; +} -pub const MAX_ZK_PUBLIC_KEY_BYTES: usize = MAX_ISS_BYTES + MAX_EPK_BYTES; +/// The size of the pepper used to create a _hiding_ identity commitment (IDC) when deriving a zkID +/// address. This value should **NOT* be changed since on-chain addresses are based on it (e.g., +/// hashing with a larger pepper would lead to a different address). +pub const PEPPER_NUM_BYTES: usize = poseidon_bn254::BYTES_PACKED_PER_SCALAR; -// TODO(ZkIdGroth16Zkp): determine max length of zkSNARK + OIDC overhead + ephemeral pubkey and signature -pub const MAX_ZK_SIGNATURE_BYTES: usize = 2048; +/// Reflection of aptos_framework::zkid::Configs +#[derive(Serialize, Deserialize, Debug)] +pub struct Configuration { + pub override_aud_vals: Vec, + pub max_zkid_signatures_per_txn: u16, + pub max_exp_horizon_secs: u64, + pub training_wheels_pubkey: Option>, + pub nonce_commitment_num_bytes: u16, + pub max_commited_epk_bytes: u16, + pub max_iss_field_bytes: u16, + pub max_extra_field_bytes: u16, + pub max_jwt_header_b64_bytes: u32, +} -// TODO(ZkIdGroth16Zkp): each zkID Groth16 proof will take ~2 ms to verify, or so. We cannot verify too many due to DoS. -// Figure out what this should be. -pub const MAX_ZK_ID_AUTHENTICATORS_ALLOWED: usize = 10; +impl MoveStructType for Configuration { + const MODULE_NAME: &'static IdentStr = ident_str!("zkid"); + const STRUCT_NAME: &'static IdentStr = ident_str!("Configuration"); +} -// How far in the future from the JWT issued at time the EPK expiry can be set. -pub const MAX_EXPIRY_HORIZON_SECS: u64 = 100255944; // 1159.55 days TODO(zkid): finalize this value +impl Configuration { + #[cfg(test)] + const OVERRIDE_AUD_FOR_TESTING: &'static str = "some_override_aud"; + + #[cfg(test)] + pub fn new_for_testing() -> Configuration { + const POSEIDON_BYTES_PACKED_PER_SCALAR: u16 = 31; + + Configuration { + override_aud_vals: vec![Self::OVERRIDE_AUD_FOR_TESTING.to_owned()], + max_zkid_signatures_per_txn: 3, + max_exp_horizon_secs: 100_255_944, + training_wheels_pubkey: None, + nonce_commitment_num_bytes: 32, + max_commited_epk_bytes: 3 * POSEIDON_BYTES_PACKED_PER_SCALAR, + max_iss_field_bytes: 126, + max_extra_field_bytes: 350, + max_jwt_header_b64_bytes: 300, + } + } +} #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] pub struct JwkId { @@ -76,31 +103,41 @@ pub struct OpenIdSig { /// The name of the key in the claim that maps to the user identifier; e.g., "sub" or "email" pub uid_key: String, /// The random value used to obfuscate the EPK from OIDC providers in the nonce field - pub epk_blinder: [u8; EPK_BLINDER_NUM_BYTES], + #[serde(with = "serde_bytes")] + pub epk_blinder: Vec, /// The privacy-preserving value used to calculate the identity commitment. It is typically uniquely derived from `(iss, client_id, uid_key, uid_val)`. pub pepper: Pepper, + /// When an override aud_val is used, the signature needs to contain the aud_val committed in the + /// IDC, since the JWT will contain the override. + pub idc_aud_val: Option, } impl OpenIdSig { + /// The size of the blinding factor used to compute the nonce commitment to the EPK and expiration + /// date. This can be upgraded, if the OAuth nonce reconstruction is upgraded carefully. + pub const EPK_BLINDER_NUM_BYTES: usize = poseidon_bn254::BYTES_PACKED_PER_SCALAR; + /// Verifies an `OpenIdSig` by doing the following checks: /// 1. Check that the ephemeral public key lifespan is under MAX_EXPIRY_HORIZON_SECS /// 2. Check that the iss claim in the ZkIdPublicKey matches the one in the jwt_payload /// 3. Check that the identity commitment in the ZkIdPublicKey matches the one constructed from the jwt_payload /// 4. Check that the nonce constructed from the ephemeral public key, blinder, and exp_timestamp_secs matches the one in the jwt_payload + // TODO(zkid): Refactor to return a `Result<(), VMStatus>` because (1) this is now called in the + // VM and (2) is_override_aud_allowed does. pub fn verify_jwt_claims( &self, exp_timestamp_secs: u64, epk: &EphemeralPublicKey, pk: &ZkIdPublicKey, + config: &Configuration, ) -> Result<()> { - let jwt_payload_json = base64url_to_str(&self.jwt_payload)?; + let jwt_payload_json = base64url_decode_as_str(&self.jwt_payload)?; let claims: Claims = serde_json::from_str(&jwt_payload_json)?; - // TODO(zkid): Store MAX_EXPIRY_HORIZON_SECS in a resource in zkid.move. Then, move this check - // into the prologue for the ZK-less OpenID path. let max_expiration_date = - seconds_from_epoch(claims.oidc_claims.iat + MAX_EXPIRY_HORIZON_SECS); + seconds_from_epoch(claims.oidc_claims.iat + config.max_exp_horizon_secs); let expiration_date: SystemTime = seconds_from_epoch(exp_timestamp_secs); + ensure!( expiration_date < max_expiration_date, "The ephemeral public key's expiration date is too far into the future" @@ -117,21 +154,30 @@ impl OpenIdSig { "uid_key must be either 'sub' or 'email', was \"{}\"", self.uid_key ); - let uid_val = claims.get_uid_val(&self.uid_key)?; + // When an aud_val override is set, the IDC-committed `aud` is included next to the + // OpenID signature. + let idc_aud_val = match self.idc_aud_val.as_ref() { + None => &claims.oidc_claims.aud, + Some(idc_aud_val) => { + // If there's an override, check that the override `aud` from the JWT, is allow-listed + ensure!( + is_allowed_override_aud(config, &claims.oidc_claims.aud).is_ok(), + "{} is not an allow-listed override aud", + &claims.oidc_claims.aud + ); + idc_aud_val + }, + }; + let uid_val = claims.get_uid_val(&self.uid_key)?; ensure!( - IdCommitment::new_from_preimage( - &self.pepper, - &claims.oidc_claims.aud, - &self.uid_key, - &uid_val - )? - .eq(&pk.idc), + IdCommitment::new_from_preimage(&self.pepper, idc_aud_val, &self.uid_key, &uid_val)? + .eq(&pk.idc), "Address IDC verification failed" ); ensure!( - self.reconstruct_oauth_nonce(exp_timestamp_secs, epk)? + self.reconstruct_oauth_nonce(exp_timestamp_secs, epk, config)? .eq(&claims.oidc_claims.nonce), "'nonce' claim did not contain the expected EPK and expiration date commitment" ); @@ -151,22 +197,23 @@ impl OpenIdSig { &self, exp_timestamp_secs: u64, epk: &EphemeralPublicKey, + config: &Configuration, ) -> Result { let mut frs = poseidon_bn254::pad_and_pack_bytes_to_scalars_with_len( epk.to_bytes().as_slice(), - MAX_EPK_BYTES, + config.max_commited_epk_bytes as usize, )?; - frs.push(ark_bn254::Fr::from(exp_timestamp_secs)); + frs.push(Fr::from(exp_timestamp_secs)); frs.push(poseidon_bn254::pack_bytes_to_one_scalar( &self.epk_blinder[..], )?); let nonce_fr = poseidon_bn254::hash_scalars(frs)?; - let mut nonce_bytes = [0u8; NONCE_NUM_BYTES]; + let mut nonce_bytes = vec![0u8; config.nonce_commitment_num_bytes as usize]; nonce_fr.serialize_uncompressed(&mut nonce_bytes[..])?; - Ok(base64::encode_config(nonce_bytes, URL_SAFE_NO_PAD)) + Ok(base64url_encode(&nonce_bytes[..])) } } @@ -247,31 +294,26 @@ pub struct SignedGroth16Zkp { pub proof: Groth16Zkp, /// The signature of the proof signed by the private key of the `ephemeral_pubkey`. pub non_malleability_signature: EphemeralSignature, - // TODO: add training_wheels_signature: EphemeralSignature, + pub training_wheels_signature: EphemeralSignature, + pub extra_field: String, + pub override_aud_val: Option, } impl SignedGroth16Zkp { - pub fn verify_non_malleability(&self, pub_key: &EphemeralPublicKey) -> Result<()> { + pub fn verify_non_malleability_sig(&self, pub_key: &EphemeralPublicKey) -> Result<()> { self.non_malleability_signature.verify(&self.proof, pub_key) } - pub fn verify_proof(&self, public_inputs_hash: ark_bn254::Fr, chain_id: ChainId) -> Result<()> { - let vk = match chain_id.is_mainnet() { - true => { - bail!("verifying key for main net missing") - }, - false => &DEVNET_VERIFYING_KEY, - }; - let proof: Proof = Proof { - a: self.proof.a.deserialize_into_affine()?, - b: self.proof.b.to_affine()?, - c: self.proof.c.deserialize_into_affine()?, - }; - let result = Groth16::::verify_proof(vk, &proof, &[public_inputs_hash])?; - if !result { - bail!("groth16 proof verification failed") - } - Ok(()) + pub fn verify_training_wheels_sig(&self, pub_key: &EphemeralPublicKey) -> Result<()> { + self.training_wheels_signature.verify(&self.proof, pub_key) + } + + pub fn verify_proof( + &self, + public_inputs_hash: Fr, + pvk: &PreparedVerifyingKey, + ) -> Result<()> { + self.proof.verify_proof(public_inputs_hash, pvk) } } @@ -288,19 +330,17 @@ impl Groth16Zkp { Groth16Zkp { a, b, c } } - pub fn verify_proof(&self, public_inputs_hash: ark_bn254::Fr, chain_id: ChainId) -> Result<()> { - let vk = match chain_id.is_mainnet() { - true => { - bail!("verifying key for main net missing") - }, - false => &DEVNET_VERIFYING_KEY, - }; - let proof: Proof = Proof { + pub fn verify_proof( + &self, + public_inputs_hash: Fr, + pvk: &PreparedVerifyingKey, + ) -> Result<()> { + let proof: Proof = Proof { a: self.a.deserialize_into_affine()?, b: self.b.to_affine()?, c: self.c.deserialize_into_affine()?, }; - let result = Groth16::::verify_proof(vk, &proof, &[public_inputs_hash])?; + let result = Groth16::::verify_proof(pvk, &proof, &[public_inputs_hash])?; if !result { bail!("groth16 proof verification failed") } @@ -323,7 +363,7 @@ pub struct ZkIdSignature { /// `exp_timestamp_secs`. pub sig: ZkpOrOpenIdSig, - /// The header contains two relevant fields: + /// The base64url-encoded header, which contains two relevant fields: /// 1. `kid`, which indicates which of the OIDC provider's JWKs should be used to verify the /// \[ZKPoK of an\] OpenID signature., /// 2. `alg`, which indicates which type of signature scheme was used to sign the JWT @@ -360,8 +400,12 @@ pub struct JWTHeader { } impl ZkIdSignature { + /// A reasonable upper bound for the number of bytes we expect in a zkID public key. This is + /// enforced by our full nodes when they receive zkID TXNs. + pub const MAX_LEN: usize = 4000; + pub fn parse_jwt_header(&self) -> Result { - let jwt_header_json = base64url_to_str(&self.jwt_header)?; + let jwt_header_json = base64url_decode_as_str(&self.jwt_header)?; let header: JWTHeader = serde_json::from_str(&jwt_header_json)?; Ok(header) } @@ -401,18 +445,40 @@ impl Pepper { } #[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] -pub struct IdCommitment(pub(crate) [u8; IDC_NUM_BYTES]); +pub struct IdCommitment(#[serde(with = "serde_bytes")] pub(crate) Vec); + +impl IdCommitment { + /// The size of the identity commitment (IDC) used to derive a zkID address. This value should **NOT* + /// be changed since on-chain addresses are based on it (e.g., hashing a larger-sized IDC would lead + /// to a different address). + pub const NUM_BYTES: usize = 32; +} impl IdCommitment { + /// The max length of the value of the JWT's `aud` field supported in our circuit. zkID address + /// derivation depends on this, so it should not be changed. + pub const MAX_AUD_VAL_BYTES: usize = 115; + // 4 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; + /// The max length of the JWT field name that stores the user's ID (e.g., `sub`, `email`) which is + /// supported in our circuit. zkID address derivation depends on this, so it should not be changed. + pub const MAX_UID_KEY_BYTES: usize = 30; + // 2 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; + /// The max length of the value of the JWT's UID field (`sub`, `email`) that stores the user's ID + /// which is supported in our circuit. zkID address derivation depends on this, so it should not + /// be changed. + pub const MAX_UID_VAL_BYTES: usize = 330; + + // 4 * poseidon_bn254::BYTES_PACKED_PER_SCALAR; + pub fn new_from_preimage( pepper: &Pepper, aud: &str, uid_key: &str, uid_val: &str, ) -> Result { - let aud_val_hash = poseidon_bn254::pad_and_hash_string(aud, MAX_AUD_VAL_BYTES)?; - let uid_key_hash = poseidon_bn254::pad_and_hash_string(uid_key, MAX_UID_KEY_BYTES)?; - let uid_val_hash = poseidon_bn254::pad_and_hash_string(uid_val, MAX_UID_VAL_BYTES)?; + let aud_val_hash = poseidon_bn254::pad_and_hash_string(aud, Self::MAX_AUD_VAL_BYTES)?; + let uid_key_hash = poseidon_bn254::pad_and_hash_string(uid_key, Self::MAX_UID_KEY_BYTES)?; + let uid_val_hash = poseidon_bn254::pad_and_hash_string(uid_val, Self::MAX_UID_VAL_BYTES)?; let pepper_scalar = poseidon_bn254::pack_bytes_to_one_scalar(pepper.0.as_slice())?; let fr = poseidon_bn254::hash_scalars(vec![ @@ -422,7 +488,7 @@ impl IdCommitment { uid_key_hash, ])?; - let mut idc_bytes = [0u8; IDC_NUM_BYTES]; + let mut idc_bytes = vec![0u8; IdCommitment::NUM_BYTES]; fr.serialize_uncompressed(&mut idc_bytes[..])?; Ok(IdCommitment(idc_bytes)) } @@ -457,6 +523,10 @@ pub struct ZkIdPublicKey { } impl ZkIdPublicKey { + /// A reasonable upper bound for the number of bytes we expect in a zkID public key. This is + /// enforced by our full nodes when they receive zkID TXNs. + pub const MAX_LEN: usize = 200 + IdCommitment::NUM_BYTES; + pub fn to_bytes(&self) -> Vec { bcs::to_bytes(&self).expect("Only unhandleable errors happen here.") } @@ -489,8 +559,16 @@ pub fn get_zkid_authenticators( Ok(authenticators) } -fn base64url_to_str(b64: &str) -> Result { - let decoded_bytes = base64::decode_config(b64, URL_SAFE)?; +pub fn base64url_encode(data: &[u8]) -> String { + base64::encode_config(data, URL_SAFE_NO_PAD) +} + +pub fn base64url_encode_str(data: &str) -> String { + base64::encode_config(data.as_bytes(), URL_SAFE_NO_PAD) +} + +pub fn base64url_decode_as_str(b64: &str) -> Result { + let decoded_bytes = base64::decode_config(b64, URL_SAFE_NO_PAD)?; // Convert the decoded bytes to a UTF-8 string let str = String::from_utf8(decoded_bytes)?; Ok(str) @@ -500,41 +578,65 @@ fn seconds_from_epoch(secs: u64) -> SystemTime { UNIX_EPOCH + Duration::from_secs(secs) } +pub fn is_allowed_override_aud( + config: &Configuration, + override_aud_val: &String, +) -> Result<(), VMStatus> { + let matches = config + .override_aud_vals + .iter() + .filter(|&e| e.eq(override_aud_val)) + .count(); + + if matches == 0 { + Err(invalid_signature!( + "override aud is not allow-listed in 0x1::zkid" + )) + } else { + Ok(()) + } +} + #[cfg(test)] mod test { use crate::{ - bn254_circom::get_public_inputs_hash, - chain_id::ChainId, + bn254_circom::{get_public_inputs_hash, DEVNET_VERIFYING_KEY}, jwks::rsa::RSA_JWK, transaction::authenticator::{AuthenticationKey, EphemeralPublicKey, EphemeralSignature}, zkid::{ - G1Bytes, G2Bytes, Groth16Zkp, IdCommitment, Pepper, SignedGroth16Zkp, ZkIdPublicKey, - ZkIdSignature, ZkpOrOpenIdSig, + base64url_encode_str, Configuration, G1Bytes, G2Bytes, Groth16Zkp, IdCommitment, + OpenIdSig, Pepper, SignedGroth16Zkp, ZkIdPublicKey, ZkIdSignature, ZkpOrOpenIdSig, }, }; - use aptos_crypto::{ed25519::Ed25519PrivateKey, PrivateKey, SigningKey, Uniform}; + use aptos_crypto::{ + ed25519::{Ed25519PrivateKey, Ed25519Signature}, + PrivateKey, SigningKey, Uniform, + }; + use std::ops::Deref; + // TODO(zkid): This test case must be rewritten to be more modular and updatable. + // Right now, there are no instructions on how to produce this test case. #[test] - fn test_groth16_proof_verification() { + fn test_zkid_groth16_proof_verification() { let a = G1Bytes::new_unchecked( - "11685701338011120485255682535216931952523490513574344095859176729155974193429", - "19570000702948951151001315672614758851000529478920585316943681012227747910337", + "20534193224874816823038374805971256353897254359389549519579800571198905682623", + "3128047629776327625062258700337193014005673411952335683536865294076478098678", ) .unwrap(); let b = G2Bytes::new_unchecked( [ - "10039243553158378944380740968043887743081233734014916979736214569065002261361", - "4926621746570487391149084476602889692047252928870676314074045787488022393462", + "11831059544281359959902363827760224027191828999098259913907764686593049260801", + "14933419822301565783764657928814181728459886670248956535955133596731082875810", ], [ - "8151326214925440719229499872086146990795191649649968979609056373308460653969", - "12483309147304635788397060225283577172417980480151834869358925058077916828359", + "16616167200367085072660100259194052934821478809307596510515652443339946625933", + "1103855954970567341442645156173756328940907403537523212700521414512165362008", ], ) .unwrap(); let c = G1Bytes::new_unchecked( - "17509024307642709963307435885289611077932619305068428354097243520217914637634", - "17824783754604065652634030354434350582834434348663254057492956883323214722668", + "296457556259014920933232985275282694032456344171046224944953719399946325676", + "10314488872240559867545387237625153841351761679810222583912967187658678987385", ) .unwrap(); let proof = Groth16Zkp::new(a, b, c); @@ -566,6 +668,11 @@ mod test { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephem_proof_sig, + training_wheels_signature: EphemeralSignature::ed25519( + Ed25519Signature::dummy_signature(), + ), + extra_field: "\"family_name\":\"Straka\",".to_string(), + override_aud_val: None, }), jwt_header: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_owned(), exp_timestamp_secs: 1900255944, @@ -594,10 +701,248 @@ mod test { n:"6S7asUuzq5Q_3U9rbs-PkDVIdjgmtgWreG5qWPsC9xXZKiMV1AiV9LXyqQsAYpCqEDM3XbfmZqGb48yLhb_XqZaKgSYaC_h2DjM7lgrIQAp9902Rr8fUmLN2ivr5tnLxUUOnMOc2SQtr9dgzTONYW5Zu3PwyvAWk5D6ueIUhLtYzpcB-etoNdL3Ir2746KIy_VUsDwAM7dhrqSK8U2xFCGlau4ikOTtvzDownAMHMrfE7q1B6WZQDAQlBmxRQsyKln5DIsKv6xauNsHRgBAKctUxZG8M4QJIx3S6Aughd3RZC4Ca5Ae9fd8L8mlNYBCrQhOZ7dS0f4at4arlLcajtw".to_owned(), }; - let public_inputs_hash = get_public_inputs_hash(&zk_sig, &zk_pk, &jwk).unwrap(); + let public_inputs_hash = + get_public_inputs_hash(&zk_sig, &zk_pk, &jwk, &Configuration::new_for_testing()) + .unwrap(); proof - .verify_proof(public_inputs_hash, ChainId::test()) + .verify_proof(public_inputs_hash, DEVNET_VERIFYING_KEY.deref()) .unwrap(); } + + /// Returns frequently-used JSON in our test cases + fn get_jwt_payload_json( + iss: &str, + uid_key: &str, + uid_val: &str, + aud: &str, + nonce: Option, + ) -> String { + let nonce_str = match &nonce { + None => "uxxgjhTml_fhiFwyWCyExJTD3J2YK3MoVDOYdnxieiE", + Some(s) => s.as_str(), + }; + + format!( + r#"{{ + "iss": "{}", + "{}": "{}", + "aud": "{}", + "nonce": "{}", + "exp": 1311281970, + "iat": 1311280970, + "name": "Jane Doe", + "given_name": "Jane", + "family_name": "Doe", + "gender": "female", + "birthdate": "0000-10-31", + "email": "janedoe@example.com", + "picture": "http://example.com/janedoe/me.jpg" + }}"#, + iss, uid_key, uid_val, aud, nonce_str + ) + } + + fn get_jwt_default_values() -> ( + &'static str, + &'static str, + &'static str, + &'static str, + u64, + Configuration, + EphemeralPublicKey, + u128, + ZkIdPublicKey, + ) { + let iss = "https://server.example.com"; + let aud = "s6BhdRkqt3"; + let uid_key = "sub"; + let uid_val = "248289761001"; + let exp_timestamp_secs = 1311281970; + let config = Configuration::new_for_testing(); + let pepper = 76; + + let zkid_pk = ZkIdPublicKey { + iss: iss.to_owned(), + idc: IdCommitment::new_from_preimage( + &Pepper::from_number(pepper), + aud, + uid_key, + uid_val, + ) + .unwrap(), + }; + + let epk = + EphemeralPublicKey::ed25519(Ed25519PrivateKey::generate_for_testing().public_key()); + + ( + iss, + aud, + uid_key, + uid_val, + exp_timestamp_secs, + config, + epk, + pepper, + zkid_pk, + ) + } + + #[test] + fn test_zkid_oidc_sig_verifies() { + let (iss, aud, uid_key, uid_val, exp_timestamp_secs, config, epk, pepper, zkid_pk) = + get_jwt_default_values(); + + let oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + assert!(oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_ok()); + } + + #[test] + fn test_zkid_oidc_sig_fails_with_different_pepper() { + let (iss, aud, uid_key, uid_val, exp_timestamp_secs, config, epk, pepper, zkid_pk) = + get_jwt_default_values(); + let bad_pepper = pepper + 1; + + let oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + + assert!(oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_ok()); + + let bad_oidc_sig = zkid_simulate_oidc_signature( + uid_key, + bad_pepper, // Pepper does not match + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + + assert!(bad_oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_err()); + } + + #[test] + fn test_zkid_oidc_sig_fails_with_expiry_past_horizon() { + let (iss, aud, uid_key, uid_val, exp_timestamp_secs, config, epk, pepper, zkid_pk) = + get_jwt_default_values(); + let oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + + assert!(oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_ok()); + + let bad_exp_timestamp_secs = 1000000000000000000; + assert!(oidc_sig + .verify_jwt_claims(bad_exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_err()); + } + + #[test] + fn test_zkid_oidc_sig_fails_with_different_uid_val() { + let (iss, aud, uid_key, uid_val, exp_timestamp_secs, config, epk, pepper, zkid_pk) = + get_jwt_default_values(); + let oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + + assert!(oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_ok()); + + let bad_uid_val = format!("{}+1", uid_val); + let bad_oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, bad_uid_val.as_str(), aud, None), + ); + + assert!(bad_oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_err()); + } + + #[test] + fn test_zkid_oidc_sig_fails_with_bad_nonce() { + let (iss, aud, uid_key, uid_val, exp_timestamp_secs, config, epk, pepper, zkid_pk) = + get_jwt_default_values(); + let oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + + assert!(oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_ok()); + + let bad_nonce = "bad nonce".to_string(); + let bad_oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, Some(bad_nonce)), + ); + + assert!(bad_oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_err()); + } + + #[test] + fn test_zkid_oidc_sig_with_different_iss() { + let (iss, aud, uid_key, uid_val, exp_timestamp_secs, config, epk, pepper, zkid_pk) = + get_jwt_default_values(); + let oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(iss, uid_key, uid_val, aud, None), + ); + + assert!(oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_ok()); + + let bad_iss = format!("{}+1", iss); + let bad_oidc_sig = zkid_simulate_oidc_signature( + uid_key, + pepper, + &get_jwt_payload_json(bad_iss.as_str(), uid_key, uid_val, aud, None), + ); + + assert!(bad_oidc_sig + .verify_jwt_claims(exp_timestamp_secs, &epk, &zkid_pk, &config) + .is_err()); + } + + fn zkid_simulate_oidc_signature( + uid_key: &str, + pepper: u128, + jwt_payload_unencoded: &str, + ) -> OpenIdSig { + let jwt_payload = base64url_encode_str(jwt_payload_unencoded); + + OpenIdSig { + jwt_sig: "jwt_sig is verified in the prologue".to_string(), + jwt_payload, + uid_key: uid_key.to_owned(), + epk_blinder: vec![0u8; OpenIdSig::EPK_BLINDER_NUM_BYTES], + pepper: Pepper::from_number(pepper), + idc_aud_val: None, + } + } } From e9de3f3a77b71c50464be11cfe62a8ae5c6a7644 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Wed, 7 Feb 2024 23:24:59 -0800 Subject: [PATCH 040/328] fix transaction emitter balance requirements (#11947) --- .../src/emitter/account_minter.rs | 10 +++------- crates/transaction-emitter-lib/src/emitter/mod.rs | 5 ++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/crates/transaction-emitter-lib/src/emitter/account_minter.rs b/crates/transaction-emitter-lib/src/emitter/account_minter.rs index da0a2ac8d24c7..61bdab69db175 100644 --- a/crates/transaction-emitter-lib/src/emitter/account_minter.rs +++ b/crates/transaction-emitter-lib/src/emitter/account_minter.rs @@ -55,11 +55,7 @@ impl<'t> AccountMinter<'t> { (req.expected_max_txns / num_accounts as u64) .checked_mul(SEND_AMOUNT + req.expected_gas_per_txn * req.gas_price) .unwrap() - .checked_add( - req.max_gas_per_txn * req.gas_price - // for module publishing - + 2 * req.max_gas_per_txn * req.gas_price * req.init_gas_price_multiplier, - ) + .checked_add(req.max_gas_per_txn * req.gas_price) .unwrap() // extra coins for secure to pay none zero gas price } } @@ -99,14 +95,14 @@ impl<'t> AccountMinter<'t> { let coins_per_seed_account = (expected_children_per_seed_account as u64) .checked_mul( coins_per_account - + req.max_gas_per_txn * req.gas_price * req.init_gas_price_multiplier, + + req.init_max_gas_per_txn * req.gas_price * req.init_gas_price_multiplier, ) .unwrap_or_else(|| { panic!( "coins_per_seed_account exceeds u64: {} * ({} + {} * {} * {})", expected_children_per_seed_account, coins_per_account, - req.max_gas_per_txn, + req.init_max_gas_per_txn, req.gas_price, req.init_gas_price_multiplier ) diff --git a/crates/transaction-emitter-lib/src/emitter/mod.rs b/crates/transaction-emitter-lib/src/emitter/mod.rs index 54b343f204949..6d57efba356bb 100644 --- a/crates/transaction-emitter-lib/src/emitter/mod.rs +++ b/crates/transaction-emitter-lib/src/emitter/mod.rs @@ -955,7 +955,10 @@ fn update_seq_num_and_get_num_expired( .map( |(address, (start_seq_num, end_seq_num))| match latest_fetched_counts.get(address) { Some(count) => { - assert!(*count <= *end_seq_num); + assert!( + *count <= *end_seq_num, + "{address} :: {count} > {end_seq_num}" + ); if *count >= *start_seq_num { ( (*count - *start_seq_num) as usize, From 183c6c8339ae2a6009228d1f1f9abd55aca1b947 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Wed, 7 Feb 2024 23:27:56 -0800 Subject: [PATCH 041/328] cleaning up aggregators part 2 (#11939) --- aptos-move/aptos-aggregator/src/types.rs | 8 ++++-- aptos-move/aptos-vm-types/src/change_set.rs | 4 +-- aptos-move/aptos-vm-types/src/output.rs | 4 +-- .../src/resource_group_adapter.rs | 5 ++-- .../src/tests/test_change_set.rs | 3 +- aptos-move/aptos-vm/src/block_executor/mod.rs | 8 +++--- .../aptos-vm/src/block_executor/vm_wrapper.rs | 7 +++-- aptos-move/aptos-vm/src/data_cache.rs | 2 +- aptos-move/aptos-vm/src/errors.rs | 2 +- .../src/move_vm_ext/respawned_session.rs | 11 ++------ .../src/move_vm_ext/write_op_converter.rs | 8 +++--- .../block-executor/src/captured_reads.rs | 2 +- aptos-move/block-executor/src/executor.rs | 28 ++++++++++--------- .../src/proptest_types/types.rs | 4 ++- aptos-move/block-executor/src/task.rs | 6 ++-- .../src/txn_last_input_output.rs | 9 +++--- aptos-move/block-executor/src/view.rs | 2 +- .../mvhashmap/src/versioned_delayed_fields.rs | 2 +- .../move/move-core/types/src/vm_status.rs | 5 ++-- types/src/delayed_fields.rs | 18 ++++++------ 20 files changed, 71 insertions(+), 67 deletions(-) diff --git a/aptos-move/aptos-aggregator/src/types.rs b/aptos-move/aptos-aggregator/src/types.rs index 6276f1049e88d..e58495c7a6672 100644 --- a/aptos-move/aptos-aggregator/src/types.rs +++ b/aptos-move/aptos-aggregator/src/types.rs @@ -39,7 +39,7 @@ impl PanicOr { pub fn code_invariant_error(message: M) -> PanicError { let msg = format!( - "Delayed field / resource group code invariant broken (a bug in the code), {:?}", + "Delayed materialization code invariant broken (there is a bug in the code), {:?}", message ); error!("{}", msg); @@ -75,7 +75,9 @@ impl From for PartialVMError { impl From<&PanicOr> for StatusCode { fn from(err: &PanicOr) -> Self { match err { - PanicOr::CodeInvariantError(_) => StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + PanicOr::CodeInvariantError(_) => { + StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR + }, PanicOr::Or(_) => StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR, } } @@ -85,7 +87,7 @@ impl From> for PartialVMError { fn from(err: PanicOr) -> Self { match err { PanicOr::CodeInvariantError(msg) => { - PartialVMError::new(StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR) + PartialVMError::new(StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR) .with_message(msg) }, PanicOr::Or(err) => PartialVMError::new(StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR) diff --git a/aptos-move/aptos-vm-types/src/change_set.rs b/aptos-move/aptos-vm-types/src/change_set.rs index 13116ffa1d8f2..d2b0a5180c853 100644 --- a/aptos-move/aptos-vm-types/src/change_set.rs +++ b/aptos-move/aptos-vm-types/src/change_set.rs @@ -179,7 +179,7 @@ impl VMChangeSet { .write_len() .ok_or_else(|| { PartialVMError::new( - StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, ) .with_message( "Read with exchange cannot be a delete." @@ -211,7 +211,7 @@ impl VMChangeSet { let (key, value) = element?; if acc.insert(key, value).is_some() { Err(PartialVMError::new( - StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, ) .with_message( "Found duplicate key across resource change sets.".to_string(), diff --git a/aptos-move/aptos-vm-types/src/output.rs b/aptos-move/aptos-vm-types/src/output.rs index 56b22af00faac..22cbd301b971a 100644 --- a/aptos-move/aptos-vm-types/src/output.rs +++ b/aptos-move/aptos-vm-types/src/output.rs @@ -108,7 +108,7 @@ impl VMOutput { self.try_materialize(resolver)?; Self::convert_to_transaction_output(self).map_err(|e| { VMStatus::error( - StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, Some(e.to_string()), ) }) @@ -120,7 +120,7 @@ impl VMOutput { let output = VMOutput::new(change_set, fee_statement, status); Self::convert_to_transaction_output(output).map_err(|e| { VMStatus::error( - StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, Some(e.to_string()), ) }) diff --git a/aptos-move/aptos-vm-types/src/resource_group_adapter.rs b/aptos-move/aptos-vm-types/src/resource_group_adapter.rs index 0912b8dad2cce..e2d26be8028bc 100644 --- a/aptos-move/aptos-vm-types/src/resource_group_adapter.rs +++ b/aptos-move/aptos-vm-types/src/resource_group_adapter.rs @@ -124,10 +124,11 @@ impl<'r> ResourceGroupAdapter<'r> { gas_feature_version: u64, resource_group_charge_as_size_sum_enabled: bool, ) -> Self { - // TODO[agg_v2](fix) - when is_resource_group_split_in_change_set_capable is false, + // when is_resource_group_split_in_change_set_capable is false, // but resource_group_charge_as_size_sum_enabled is true, we still don't set // group_size_kind to GroupSizeKind::AsSum, meaning that - // is_resource_group_split_in_change_set_capable affects gas charging. make sure that is correct + // is_resource_group_split_in_change_set_capable affects gas charging. + // Onchain execution always needs to go through capable resolvers. let group_size_kind = GroupSizeKind::from_gas_feature_version( gas_feature_version, diff --git a/aptos-move/aptos-vm-types/src/tests/test_change_set.rs b/aptos-move/aptos-vm-types/src/tests/test_change_set.rs index 775850abcedc0..1869d0d911af5 100644 --- a/aptos-move/aptos-vm-types/src/tests/test_change_set.rs +++ b/aptos-move/aptos-vm-types/src/tests/test_change_set.rs @@ -253,7 +253,8 @@ macro_rules! assert_invariant_violation { // TODO[agg_v2](test): Uniformize errors for write op squashing. assert!( err.major_status() == StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR - || err.major_status() == StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR + || err.major_status() + == StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR ); }; diff --git a/aptos-move/aptos-vm/src/block_executor/mod.rs b/aptos-move/aptos-vm/src/block_executor/mod.rs index e1bb1cba256a0..72685fc95beb5 100644 --- a/aptos-move/aptos-vm/src/block_executor/mod.rs +++ b/aptos-move/aptos-vm/src/block_executor/mod.rs @@ -21,6 +21,7 @@ use aptos_infallible::Mutex; use aptos_types::{ block_executor::config::BlockExecutorConfig, contract_event::ContractEvent, + delayed_fields::PanicError, executable::ExecutableTestType, fee_statement::FeeStatement, state_store::{state_key::StateKey, StateView, StateViewId}, @@ -272,7 +273,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { aggregator_v1_writes: Vec<(StateKey, WriteOp)>, patched_resource_write_set: Vec<(StateKey, WriteOp)>, patched_events: Vec, - ) { + ) -> Result<(), PanicError> { assert!( self.committed_output .set( @@ -284,13 +285,12 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { aggregator_v1_writes, patched_resource_write_set, patched_events, - ) - // TODO[agg_v2](fix) - propagate issued to block executor. - .expect("Materialization must not fail"), + )?, ) .is_ok(), "Could not combine VMOutput with the patched resource and event data" ); + Ok(()) } fn set_txn_output_for_non_dynamic_change_set(&self) { diff --git a/aptos-move/aptos-vm/src/block_executor/vm_wrapper.rs b/aptos-move/aptos-vm/src/block_executor/vm_wrapper.rs index bfcd9716ecf0a..164ffc9e2b47c 100644 --- a/aptos-move/aptos-vm/src/block_executor/vm_wrapper.rs +++ b/aptos-move/aptos-vm/src/block_executor/vm_wrapper.rs @@ -78,7 +78,8 @@ impl<'a, S: 'a + StateView + Sync> ExecutorTask for AptosExecutorTask<'a, S> { ExecutionStatus::SpeculativeExecutionAbortError( vm_status.message().cloned().unwrap_or_default(), ) - } else if vm_status.status_code() == StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR + } else if vm_status.status_code() + == StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR { ExecutionStatus::DelayedFieldsCodeInvariantError( vm_status.message().cloned().unwrap_or_default(), @@ -104,7 +105,9 @@ impl<'a, S: 'a + StateView + Sync> ExecutorTask for AptosExecutorTask<'a, S> { ExecutionStatus::SpeculativeExecutionAbortError( err.message().cloned().unwrap_or_default(), ) - } else if err.status_code() == StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR { + } else if err.status_code() + == StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR + { ExecutionStatus::DelayedFieldsCodeInvariantError( err.message().cloned().unwrap_or_default(), ) diff --git a/aptos-move/aptos-vm/src/data_cache.rs b/aptos-move/aptos-vm/src/data_cache.rs index 9a3734163edbb..a41435432ae7c 100644 --- a/aptos-move/aptos-vm/src/data_cache.rs +++ b/aptos-move/aptos-vm/src/data_cache.rs @@ -381,7 +381,7 @@ pub(crate) mod tests { }; let group_adapter = ResourceGroupAdapter::new( - // TODO[agg_v2](fix) add a converter for StateView for tests that implements ResourceGroupView + // TODO[agg_v2](test) add a converter for StateView for tests that implements ResourceGroupView None, state_view, gas_feature_version, diff --git a/aptos-move/aptos-vm/src/errors.rs b/aptos-move/aptos-vm/src/errors.rs index 0f2377c41200e..968c1e8cd7110 100644 --- a/aptos-move/aptos-vm/src/errors.rs +++ b/aptos-move/aptos-vm/src/errors.rs @@ -212,7 +212,7 @@ pub fn expect_only_successful_execution( e @ VMStatus::Error { status_code: StatusCode::SPECULATIVE_EXECUTION_ABORT_ERROR - | StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + | StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, .. } => e, status => { diff --git a/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs b/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs index 98e5312aca03a..05ebdf21d6414 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs @@ -380,15 +380,8 @@ impl<'r> TResourceGroupView for ExecutorViewWithChangeSet<'r> { WriteResourceGroup(group_write) => Some(Ok(group_write)), ResourceGroupInPlaceDelayedFieldChange(_) => None, Write(_) | WriteWithDelayedFields(_) | InPlaceDelayedFieldChange(_) => { - // TODO[agg_v2](fix): Revisit this error whether it should be invariant violation - // or a panic/fallback. - Some(Err(PartialVMError::new( - StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, - ) - .with_message( - "Non-ResourceGroup write found for key in get_resource_from_group call" - .to_string(), - ))) + // There should be no colisions, we cannot have group key refer to a resource. + Some(Err(code_invariant_error(format!("Non-ResourceGroup write found for key in get_resource_from_group call for key {group_key:?}")))) }, }) .transpose()? 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 033abf23b6515..bfa5fd0b77635 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 @@ -416,7 +416,7 @@ mod tests { } } - // TODO[agg_v2](fix) make as_resolver_with_group_size_kind support AsSum + // TODO[agg_v2](test) make as_resolver_with_group_size_kind support AsSum // #[test] #[allow(unused)] fn size_computation_delete_modify_ops() { @@ -474,7 +474,7 @@ mod tests { ); } - // TODO[agg_v2](fix) make as_resolver_with_group_size_kind support AsSum + // TODO[agg_v2](test) make as_resolver_with_group_size_kind support AsSum // #[test] #[allow(unused)] fn size_computation_new_op() { @@ -515,7 +515,7 @@ mod tests { ); } - // TODO[agg_v2](fix) make as_resolver_with_group_size_kind support AsSum + // TODO[agg_v2](test) make as_resolver_with_group_size_kind support AsSum // #[test] #[allow(unused)] fn size_computation_new_group() { @@ -541,7 +541,7 @@ mod tests { ); } - // TODO[agg_v2](fix) make as_resolver_with_group_size_kind support AsSum + // TODO[agg_v2](test) make as_resolver_with_group_size_kind support AsSum // #[test] #[allow(unused)] fn size_computation_delete_group() { diff --git a/aptos-move/block-executor/src/captured_reads.rs b/aptos-move/block-executor/src/captured_reads.rs index f12c690b3abc9..1abb8df59d6d1 100644 --- a/aptos-move/block-executor/src/captured_reads.rs +++ b/aptos-move/block-executor/src/captured_reads.rs @@ -61,7 +61,7 @@ pub(crate) enum DataRead { // (version implies value equality, but not vice versa). TODO: when // comparing the instances of V is cheaper, compare those instead. #[derivative(PartialEq = "ignore", Debug = "ignore")] Arc, - Option>, + #[derivative(PartialEq = "ignore", Debug = "ignore")] Option>, ), Metadata(Option), Exists(bool), diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index 0dd958e01545d..2cf74ee4dfd19 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -887,7 +887,7 @@ where .chain(serialized_groups) .collect(), patched_events, - ); + )?; if let Some(txn_commit_listener) = &self.transaction_commit_hook { let txn_output = last_input_output.txn_output(txn_idx).unwrap(); let execution_status = txn_output.output_status(); @@ -1370,18 +1370,20 @@ where Self::serialize_groups(patched_finalized_groups, idx as TxnIndex) .map_err(BlockExecutionError::FallbackToSequential)?; - // TODO[agg_v2] patch resources in groups and provide explicitly - output.incorporate_materialized_txn_output( - // No aggregator v1 delta writes are needed for sequential execution. - // They are already handled because we passed materialize_deltas=true - // to execute_transaction. - vec![], - patched_resource_write_set - .into_iter() - .chain(serialized_groups.into_iter()) - .collect(), - patched_events, - ); + output + .incorporate_materialized_txn_output( + // No aggregator v1 delta writes are needed for sequential execution. + // They are already handled because we passed materialize_deltas=true + // to execute_transaction. + vec![], + patched_resource_write_set + .into_iter() + .chain(serialized_groups.into_iter()) + .collect(), + patched_events, + ) + .map_err(PanicOr::from) + .map_err(BlockExecutionError::FallbackToSequential)?; } // If dynamic change set is disabled, this can be used to assert nothing needs patching instead: // output.set_txn_output_for_non_dynamic_change_set(); diff --git a/aptos-move/block-executor/src/proptest_types/types.rs b/aptos-move/block-executor/src/proptest_types/types.rs index f3b011066cf79..00151ae4f85d1 100644 --- a/aptos-move/block-executor/src/proptest_types/types.rs +++ b/aptos-move/block-executor/src/proptest_types/types.rs @@ -17,6 +17,7 @@ use aptos_types::{ access_path::AccessPath, account_address::AccountAddress, contract_event::TransactionEvent, + delayed_fields::PanicError, executable::ModulePath, fee_statement::FeeStatement, on_chain_config::CurrentTimeMicroseconds, @@ -1114,10 +1115,11 @@ where ::Value, )>, _patched_events: Vec<::Event>, - ) { + ) -> Result<(), PanicError> { assert_ok!(self.materialized_delta_writes.set(aggregator_v1_writes)); // TODO[agg_v2](tests): Set the patched resource write set and events. But that requires the function // to take &mut self as input + Ok(()) } fn set_txn_output_for_non_dynamic_change_set(&self) { diff --git a/aptos-move/block-executor/src/task.rs b/aptos-move/block-executor/src/task.rs index 8c6e4b0ee23ec..127d37d3efb75 100644 --- a/aptos-move/block-executor/src/task.rs +++ b/aptos-move/block-executor/src/task.rs @@ -8,8 +8,8 @@ use aptos_aggregator::{ }; use aptos_mvhashmap::types::TxnIndex; use aptos_types::{ - fee_statement::FeeStatement, transaction::BlockExecutableTransaction as Transaction, - write_set::WriteOp, + delayed_fields::PanicError, fee_statement::FeeStatement, + transaction::BlockExecutableTransaction as Transaction, write_set::WriteOp, }; use aptos_vm_types::resolver::{TExecutorView, TResourceGroupView}; use move_core_types::value::MoveTypeLayout; @@ -179,7 +179,7 @@ pub trait TransactionOutput: Send + Sync + Debug { ::Value, )>, patched_events: Vec<::Event>, - ); + ) -> Result<(), PanicError>; fn set_txn_output_for_non_dynamic_change_set(&self); diff --git a/aptos-move/block-executor/src/txn_last_input_output.rs b/aptos-move/block-executor/src/txn_last_input_output.rs index d204ae73b24aa..693c27ec60919 100644 --- a/aptos-move/block-executor/src/txn_last_input_output.rs +++ b/aptos-move/block-executor/src/txn_last_input_output.rs @@ -12,8 +12,8 @@ use aptos_aggregator::types::{code_invariant_error, PanicOr}; use aptos_logger::warn; use aptos_mvhashmap::types::{TxnIndex, ValueWithLayout}; use aptos_types::{ - fee_statement::FeeStatement, transaction::BlockExecutableTransaction as Transaction, - write_set::WriteOp, + delayed_fields::PanicError, fee_statement::FeeStatement, + transaction::BlockExecutableTransaction as Transaction, write_set::WriteOp, }; use arc_swap::ArcSwapOption; use crossbeam::utils::CachePadded; @@ -411,7 +411,7 @@ impl, E: Debug + Send + Clone> delta_writes: Vec<(T::Key, WriteOp)>, patched_resource_write_set: Vec<(T::Key, T::Value)>, patched_events: Vec, - ) { + ) -> Result<(), PanicError> { match &self.outputs[txn_idx as usize] .load_full() .expect("Output must exist") @@ -422,12 +422,13 @@ impl, E: Debug + Send + Clone> delta_writes, patched_resource_write_set, patched_events, - ); + )?; }, ExecutionStatus::Abort(_) | ExecutionStatus::SpeculativeExecutionAbortError(_) | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => {}, }; + Ok(()) } pub(crate) fn get_txn_read_write_summary(&self, txn_idx: TxnIndex) -> ReadWriteSummary { diff --git a/aptos-move/block-executor/src/view.rs b/aptos-move/block-executor/src/view.rs index 3a429e4b0f572..b14973296e8ea 100644 --- a/aptos-move/block-executor/src/view.rs +++ b/aptos-move/block-executor/src/view.rs @@ -1050,7 +1050,7 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< ); self.mark_incorrect_use(); return Err(PartialVMError::new( - StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR, + StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, ) .with_message(format!("{}", err))); }, diff --git a/aptos-move/mvhashmap/src/versioned_delayed_fields.rs b/aptos-move/mvhashmap/src/versioned_delayed_fields.rs index 002bf21d1d809..3908c32ca2d91 100644 --- a/aptos-move/mvhashmap/src/versioned_delayed_fields.rs +++ b/aptos-move/mvhashmap/src/versioned_delayed_fields.rs @@ -167,7 +167,7 @@ impl VersionedValue { ))) }, } { - // TODO[agg_v2](fix): handle invalidation when we change read_estimate_deltas + // TODO[agg_v2](optimize): See if we want to invalidate, when we change read_estimate_deltas self.read_estimate_deltas = false; } o.insert(CachePadded::new(entry)); diff --git a/third_party/move/move-core/types/src/vm_status.rs b/third_party/move/move-core/types/src/vm_status.rs index 1983aaf3adf7b..e27ba2e28a3e9 100644 --- a/third_party/move/move-core/types/src/vm_status.rs +++ b/third_party/move/move-core/types/src/vm_status.rs @@ -729,11 +729,12 @@ pub enum StatusCode { // Failed to resolve type due to linking being broken after verification TYPE_RESOLUTION_FAILURE = 2021, DUPLICATE_NATIVE_FUNCTION = 2022, - // code invariant error while handling delayed fields, should never happen, + // code invariant error while handling delayed materialization, should never happen, // always indicates a code bug. + // Delayed materialization includes handling of Resource Groups and Delayed Fields. // Unlike regular CODE_INVARIANT_ERROR, this is a signal to BlockSTM, // which it might do something about (i.e. fallback to sequential execution) - DELAYED_FIELDS_CODE_INVARIANT_ERROR = 2023, + DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR = 2023, // Speculative error means that there was an issue because of speculative // reads provided to the transaction, and the transaction needs to // be re-executed. diff --git a/types/src/delayed_fields.rs b/types/src/delayed_fields.rs index 086ea3947bc6b..7ab6195558830 100644 --- a/types/src/delayed_fields.rs +++ b/types/src/delayed_fields.rs @@ -107,7 +107,7 @@ impl From for PartialVMError { fn from(err: PanicError) -> Self { match err { PanicError::CodeInvariantError(msg) => { - PartialVMError::new(StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR) + PartialVMError::new(StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR) .with_message(msg) }, } @@ -218,7 +218,7 @@ impl TryFromMoveValue for DelayedFieldID { fn code_invariant_error(message: M) -> PanicError { let msg = format!( - "Delayed logic code invariant broken (there is a bug in the code), {:?}", + "Delayed materialization code invariant broken (there is a bug in the code), {:?}", message ); println!("ERROR: {}", msg); @@ -333,12 +333,11 @@ pub fn derived_string_struct_to_bytes_and_length(value: Struct) -> PartialVMResu let mut fields = value.unpack()?.collect::>(); if fields.len() != 2 { return Err( - PartialVMError::new(StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR).with_message( - format!( + PartialVMError::new(StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR) + .with_message(format!( "DerivedStringSnapshot has wrong number of fields: {:?}", fields.len() - ), - ), + )), ); } let padding = fields.pop().unwrap().value_as::>()?; @@ -349,12 +348,11 @@ pub fn derived_string_struct_to_bytes_and_length(value: Struct) -> PartialVMResu string_bytes, u32::try_from(bcs_size_of_byte_array(string_len) + bcs_size_of_byte_array(padding.len())) .map_err(|_| { - PartialVMError::new(StatusCode::DELAYED_FIELDS_CODE_INVARIANT_ERROR).with_message( - format!( + PartialVMError::new(StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR) + .with_message(format!( "DerivedStringSnapshot size exceeds u32: string_len: {string_len}, padding_len: {}", padding.len() - ), - ) + )) })?, )) } From 47a2e457a72bbf912003de24aca4d2bb3cc76531 Mon Sep 17 00:00:00 2001 From: Vineeth Kashyap Date: Thu, 8 Feb 2024 10:36:22 -0500 Subject: [PATCH 042/328] [compiler-v2] Add Bytecode verification at the end of compilation (#11923) --- third_party/move/move-compiler-v2/Cargo.toml | 2 +- third_party/move/move-compiler-v2/src/lib.rs | 55 +- .../tests/ability-checker/assign.exp | 360 +++++ .../tests/ability-checker/assign.move | 28 + .../tests/ability-checker/failing/fields.exp | 924 +++++++++++ .../tests/ability-checker/failing/fields.move | 41 + .../ability-checker/failing/operators.exp | 1354 +++++++++++++++++ .../ability-checker/failing/operators.move | 25 + .../tests/ability-checker/globals.exp | 422 +++++ .../tests/ability-checker/globals.move | 23 + .../bytecode-verify-failure/equality.exp | 49 + .../bytecode-verify-failure/equality.move | 5 + .../tests/file-format-generator/assign.exp | 4 +- .../tests/file-format-generator/assign.move | 4 +- .../tests/file-format-generator/fields.exp | 4 +- .../tests/file-format-generator/fields.move | 4 +- .../tests/file-format-generator/globals.exp | 2 +- .../tests/file-format-generator/globals.move | 2 +- .../tests/file-format-generator/operators.exp | 4 +- .../file-format-generator/operators.move | 4 +- .../move/move-compiler-v2/tests/testsuite.rs | 51 +- third_party/move/move-model/src/lib.rs | 2 +- 22 files changed, 3319 insertions(+), 50 deletions(-) create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/assign.exp create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/assign.move create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.exp create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.move create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.exp create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.move create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/globals.exp create mode 100644 third_party/move/move-compiler-v2/tests/ability-checker/globals.move create mode 100644 third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp create mode 100644 third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.move diff --git a/third_party/move/move-compiler-v2/Cargo.toml b/third_party/move/move-compiler-v2/Cargo.toml index f34ed25bb930d..c46708cc3f468 100644 --- a/third_party/move/move-compiler-v2/Cargo.toml +++ b/third_party/move/move-compiler-v2/Cargo.toml @@ -18,6 +18,7 @@ move-command-line-common = { path = "../move-command-line-common" } #move-package = { path = "../tools/move-package" } move-compiler = { path = "../move-compiler" } move-core-types = { path = "../move-core/types" } +move-disassembler = { path = "../tools/move-disassembler" } move-ir-types = { path = "../move-ir/types" } move-model = { path = "../move-model" } move-stackless-bytecode = { path = "../move-model/bytecode" } @@ -42,7 +43,6 @@ serde = { version = "1.0.124", features = ["derive"] } anyhow = "1.0.52" datatest-stable = "0.1.1" move-command-line-common = { path = "../move-command-line-common" } -move-disassembler = { path = "../tools/move-disassembler" } move-ir-types = { path = "../move-ir/types" } move-prover-test-utils = { path = "../move-prover/test-utils" } move-stdlib = { path = "../move-stdlib" } diff --git a/third_party/move/move-compiler-v2/src/lib.rs b/third_party/move/move-compiler-v2/src/lib.rs index 0714725bff9a6..6455ee09da6d9 100644 --- a/third_party/move/move-compiler-v2/src/lib.rs +++ b/third_party/move/move-compiler-v2/src/lib.rs @@ -25,15 +25,19 @@ use anyhow::bail; use codespan_reporting::term::termcolor::{ColorChoice, StandardStream, WriteColor}; pub use experiments::*; use log::{debug, info, log_enabled, trace, Level}; +use move_binary_format::binary_views::BinaryIndexedView; +use move_command_line_common::files::FileHash; use move_compiler::{ compiled_unit::{ - AnnotatedCompiledModule, AnnotatedCompiledScript, AnnotatedCompiledUnit, CompiledUnit, - FunctionInfo, + verify_units, AnnotatedCompiledModule, AnnotatedCompiledScript, AnnotatedCompiledUnit, + CompiledUnit, FunctionInfo, }, diagnostics::FilesSourceText, shared::{known_attributes::KnownAttribute, unique_map::UniqueMap}, }; -use move_model::{model::GlobalEnv, PackageInfo}; +use move_disassembler::disassembler::Disassembler; +use move_ir_types::location; +use move_model::{add_move_lang_diagnostics, model::GlobalEnv, PackageInfo}; use move_stackless_bytecode::function_target_pipeline::{ FunctionTargetPipeline, FunctionTargetsHolder, FunctionVariant, }; @@ -60,7 +64,7 @@ pub fn run_move_compiler( let mut env = run_checker(options.clone())?; check_errors(&env, error_writer, "checking errors")?; - trace!("After context check, GlobalEnv={}", env.dump_env()); + trace!("After context check, GlobalEnv=\n{}", env.dump_env()); // Flow-insensitive checks on AST flow_insensitive_checkers::check_for_unused_vars_and_params(&mut env); @@ -69,7 +73,7 @@ pub fn run_move_compiler( check_errors(&env, error_writer, "checking errors")?; trace!( - "After flow-insensitive checks, GlobalEnv={}", + "After flow-insensitive checks, GlobalEnv=\n{}", env.dump_env() ); @@ -77,7 +81,7 @@ pub fn run_move_compiler( inliner::run_inlining(&mut env); check_errors(&env, error_writer, "inlining")?; - debug!("After inlining, GlobalEnv={}", env.dump_env()); + debug!("After inlining, GlobalEnv=\n{}", env.dump_env()); // Run code generator let mut targets = run_bytecode_gen(&env); @@ -110,8 +114,17 @@ pub fn run_move_compiler( let modules_and_scripts = run_file_format_gen(&env, &targets); check_errors(&env, error_writer, "assembling errors")?; - let annotated = annotate_units(modules_and_scripts); - Ok((env, annotated)) + + debug!( + "File format bytecode:\n{}", + disassemble_compiled_units(&modules_and_scripts)? + ); + + let annotated_units = annotate_units(modules_and_scripts); + run_bytecode_verifier(&annotated_units, &mut env); + check_errors(&env, error_writer, "bytecode verification errors")?; + + Ok((env, annotated_units)) } /// Run the type checker and return the global env (with errors if encountered). The result @@ -151,7 +164,7 @@ pub fn run_checker(options: Options) -> anyhow::Result { // compilation, create an entry in the functions target holder which encapsulate info // like the generated bytecode. pub fn run_bytecode_gen(env: &GlobalEnv) -> FunctionTargetsHolder { - info!("Bytecode Generation"); + info!("Stackless bytecode Generation"); let mut targets = FunctionTargetsHolder::default(); let mut todo = BTreeSet::new(); let mut done = BTreeSet::new(); @@ -232,6 +245,30 @@ fn add_default_optimization_pipeline(pipeline: &mut FunctionTargetPipeline) { pipeline.add_processor(Box::new(UnreachableCodeRemover {})); } +/// Disassemble the given compiled units and return the disassembled code as a string. +pub fn disassemble_compiled_units(units: &[CompiledUnit]) -> anyhow::Result { + let disassembled_units: anyhow::Result> = units + .iter() + .map(|unit| { + let view = match unit { + CompiledUnit::Module(module) => BinaryIndexedView::Module(&module.module), + CompiledUnit::Script(script) => BinaryIndexedView::Script(&script.script), + }; + Disassembler::from_view(view, location::Loc::new(FileHash::empty(), 0, 0)) + .and_then(|d| d.disassemble()) + }) + .collect(); + Ok(disassembled_units?.concat()) +} + +/// Run the bytecode verifier on the given compiled units and add any diagnostics to the global env. +pub fn run_bytecode_verifier(units: &[AnnotatedCompiledUnit], env: &mut GlobalEnv) { + let diags = verify_units(units); + if !diags.is_empty() { + add_move_lang_diagnostics(env, diags); + } +} + /// Report any diags in the env to the writer and fail if there are errors. pub fn check_errors( env: &GlobalEnv, diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/assign.exp b/third_party/move/move-compiler-v2/tests/ability-checker/assign.exp new file mode 100644 index 0000000000000..20abc4842e034 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/assign.exp @@ -0,0 +1,360 @@ +============ initial bytecode ================ + +[variant baseline] +fun assign::assign_field($t0: &mut assign::S, $t1: u64) { + var $t2: &mut u64 + 0: $t2 := borrow_field.f($t0) + 1: write_ref($t2, $t1) + 2: return () +} + + +[variant baseline] +fun assign::assign_int($t0: &mut u64) { + var $t1: u64 + 0: $t1 := 42 + 1: write_ref($t0, $t1) + 2: return () +} + + +[variant baseline] +fun assign::assign_pattern($t0: assign::S, $t1: u64, $t2: u64): u64 { + var $t3: u64 + var $t4: assign::T + 0: ($t1, $t4) := unpack assign::S($t0) + 1: $t2 := unpack assign::T($t4) + 2: $t3 := +($t1, $t2) + 3: return $t3 +} + + +[variant baseline] +fun assign::assign_struct($t0: &mut assign::S) { + var $t1: assign::S + var $t2: u64 + var $t3: assign::T + var $t4: u64 + 0: $t2 := 42 + 1: $t4 := 42 + 2: $t3 := pack assign::T($t4) + 3: $t1 := pack assign::S($t2, $t3) + 4: write_ref($t0, $t1) + 5: return () +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun assign::assign_field($t0: &mut assign::S, $t1: u64) { + var $t2: &mut u64 + # live vars: $t0, $t1 + 0: $t2 := borrow_field.f($t0) + # live vars: $t1, $t2 + 1: write_ref($t2, $t1) + # live vars: + 2: return () +} + + +[variant baseline] +fun assign::assign_int($t0: &mut u64) { + var $t1: u64 + # live vars: $t0 + 0: $t1 := 42 + # live vars: $t0, $t1 + 1: write_ref($t0, $t1) + # live vars: + 2: return () +} + + +[variant baseline] +fun assign::assign_pattern($t0: assign::S, $t1: u64, $t2: u64): u64 { + var $t3: u64 + var $t4: assign::T + # live vars: $t0 + 0: ($t1, $t4) := unpack assign::S($t0) + # live vars: $t1, $t4 + 1: $t2 := unpack assign::T($t4) + # live vars: $t1, $t2 + 2: $t3 := +($t1, $t2) + # live vars: $t3 + 3: return $t3 +} + + +[variant baseline] +fun assign::assign_struct($t0: &mut assign::S) { + var $t1: assign::S + var $t2: u64 + var $t3: assign::T + var $t4: u64 + # live vars: $t0 + 0: $t2 := 42 + # live vars: $t0, $t2 + 1: $t4 := 42 + # live vars: $t0, $t2, $t4 + 2: $t3 := pack assign::T($t4) + # live vars: $t0, $t2, $t3 + 3: $t1 := pack assign::S($t2, $t3) + # live vars: $t0, $t1 + 4: write_ref($t0, $t1) + # live vars: + 5: return () +} + +============ after MemorySafetyProcessor: ================ + +[variant baseline] +fun assign::assign_field($t0: &mut assign::S, $t1: u64) { + var $t2: &mut u64 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := borrow_field.f($t0) + # live vars: $t1, $t2 + # graph: {L0=local($t0)[borrow_field(true) -> L1],L1=local($t2)[]} + # local_to_label: {$t0=L0,$t2=L1} + # global_to_label: {} + # moved: {} + # + 1: write_ref($t2, $t1) + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 2: return () +} + + +[variant baseline] +fun assign::assign_int($t0: &mut u64) { + var $t1: u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t1 := 42 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: write_ref($t0, $t1) + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 2: return () +} + + +[variant baseline] +fun assign::assign_pattern($t0: assign::S, $t1: u64, $t2: u64): u64 { + var $t3: u64 + var $t4: assign::T + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: ($t1, $t4) := unpack assign::S($t0) + # live vars: $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0} + # + 1: $t2 := unpack assign::T($t4) + # live vars: $t1, $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t4} + # + 2: $t3 := +($t1, $t2) + # live vars: $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t2,$t4} + # + 3: return $t3 +} + + +[variant baseline] +fun assign::assign_struct($t0: &mut assign::S) { + var $t1: assign::S + var $t2: u64 + var $t3: assign::T + var $t4: u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := 42 + # live vars: $t0, $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: $t4 := 42 + # live vars: $t0, $t2, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 2: $t3 := pack assign::T($t4) + # live vars: $t0, $t2, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t4} + # + 3: $t1 := pack assign::S($t2, $t3) + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t2,$t3,$t4} + # + 4: write_ref($t0, $t1) + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t2,$t3,$t4} + # + 5: return () +} + +============ after ExplicitDrop: ================ + +[variant baseline] +fun assign::assign_field($t0: &mut assign::S, $t1: u64) { + var $t2: &mut u64 + 0: $t2 := borrow_field.f($t0) + 1: drop($t0) + 2: write_ref($t2, $t1) + 3: drop($t2) + 4: return () +} + + +[variant baseline] +fun assign::assign_int($t0: &mut u64) { + var $t1: u64 + 0: $t1 := 42 + 1: write_ref($t0, $t1) + 2: drop($t0) + 3: return () +} + + +[variant baseline] +fun assign::assign_pattern($t0: assign::S, $t1: u64, $t2: u64): u64 { + var $t3: u64 + var $t4: assign::T + 0: ($t1, $t4) := unpack assign::S($t0) + 1: $t2 := unpack assign::T($t4) + 2: $t3 := +($t1, $t2) + 3: return $t3 +} + + +[variant baseline] +fun assign::assign_struct($t0: &mut assign::S) { + var $t1: assign::S + var $t2: u64 + var $t3: assign::T + var $t4: u64 + 0: $t2 := 42 + 1: $t4 := 42 + 2: $t3 := pack assign::T($t4) + 3: $t1 := pack assign::S($t2, $t3) + 4: write_ref($t0, $t1) + 5: drop($t0) + 6: drop($t1) + 7: return () +} + + +Diagnostics: +error: cannot drop + ┌─ tests/ability-checker/assign.move:17:9 + │ +17 │ *s = S { f: 42, g: T { h: 42 } }; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: write_ref: cannot drop + ┌─ tests/ability-checker/assign.move:17:9 + │ +17 │ *s = S { f: 42, g: T { h: 42 } }; + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +============ after AbilityChecker: ================ + +[variant baseline] +fun assign::assign_field($t0: &mut assign::S, $t1: u64) { + var $t2: &mut u64 + 0: $t2 := borrow_field.f($t0) + 1: drop($t0) + 2: write_ref($t2, $t1) + 3: drop($t2) + 4: return () +} + + +[variant baseline] +fun assign::assign_int($t0: &mut u64) { + var $t1: u64 + 0: $t1 := 42 + 1: write_ref($t0, $t1) + 2: drop($t0) + 3: return () +} + + +[variant baseline] +fun assign::assign_pattern($t0: assign::S, $t1: u64, $t2: u64): u64 { + var $t3: u64 + var $t4: assign::T + 0: ($t1, $t4) := unpack assign::S($t0) + 1: $t2 := unpack assign::T($t4) + 2: $t3 := +($t1, $t2) + 3: return $t3 +} + + +[variant baseline] +fun assign::assign_struct($t0: &mut assign::S) { + var $t1: assign::S + var $t2: u64 + var $t3: assign::T + var $t4: u64 + 0: $t2 := 42 + 1: $t4 := 42 + 2: $t3 := pack assign::T($t4) + 3: $t1 := pack assign::S($t2, $t3) + 4: write_ref($t0, $t1) + 5: drop($t0) + 6: drop($t1) + 7: return () +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/assign.move b/third_party/move/move-compiler-v2/tests/ability-checker/assign.move new file mode 100644 index 0000000000000..2ea2fe8d33721 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/assign.move @@ -0,0 +1,28 @@ +module 0x42::assign { + + struct S { + f: u64, + g: T + } + + struct T { + h: u64 + } + + fun assign_int(x: &mut u64) { + *x = 42; + } + + fun assign_struct(s: &mut S) { + *s = S { f: 42, g: T { h: 42 } }; + } + + fun assign_pattern(s: S, f: u64, h: u64): u64 { + S { f, g: T { h } } = s; + f + h + } + + fun assign_field(s: &mut S, f: u64) { + s.f = f; + } +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.exp b/third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.exp new file mode 100644 index 0000000000000..985104073389f --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.exp @@ -0,0 +1,924 @@ +============ initial bytecode ================ + +[variant baseline] +fun fields::read_ref($t0: &fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &u64 + 0: $t2 := borrow_field.g($t0) + 1: $t3 := borrow_field.h($t2) + 2: $t1 := read_ref($t3) + 3: return $t1 +} + + +[variant baseline] +fun fields::read_val($t0: fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &fields::S + var $t4: &u64 + 0: $t3 := borrow_local($t0) + 1: $t2 := borrow_field.g($t3) + 2: $t4 := borrow_field.h($t2) + 3: $t1 := read_ref($t4) + 4: return $t1 +} + + +[variant baseline] +fun fields::write_local_direct(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut fields::T + var $t9: &mut fields::S + 0: $t3 := 0 + 1: $t5 := 0 + 2: $t4 := pack fields::T($t5) + 3: $t2 := pack fields::S($t3, $t4) + 4: $t1 := infer($t2) + 5: $t6 := 42 + 6: $t9 := borrow_local($t1) + 7: $t8 := borrow_field.g($t9) + 8: $t7 := borrow_field.h($t8) + 9: write_ref($t7, $t6) + 10: $t0 := infer($t1) + 11: return $t0 +} + + +[variant baseline] +fun fields::write_local_via_ref(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: &mut fields::S + var $t7: &mut fields::S + var $t8: u64 + var $t9: &mut u64 + var $t10: &mut fields::T + 0: $t3 := 0 + 1: $t5 := 0 + 2: $t4 := pack fields::T($t5) + 3: $t2 := pack fields::S($t3, $t4) + 4: $t1 := infer($t2) + 5: $t7 := borrow_local($t1) + 6: $t6 := infer($t7) + 7: $t8 := 42 + 8: $t10 := borrow_field.g($t6) + 9: $t9 := borrow_field.h($t10) + 10: write_ref($t9, $t8) + 11: $t0 := infer($t1) + 12: return $t0 +} + + +[variant baseline] +fun fields::write_param($t0: &mut fields::S) { + var $t1: u64 + var $t2: &mut u64 + var $t3: &mut fields::T + 0: $t1 := 42 + 1: $t3 := borrow_field.g($t0) + 2: $t2 := borrow_field.h($t3) + 3: write_ref($t2, $t1) + 4: return () +} + + +[variant baseline] +fun fields::write_val($t0: fields::S): fields::S { + var $t1: fields::S + var $t2: u64 + var $t3: &mut u64 + var $t4: &mut fields::T + var $t5: &mut fields::S + 0: $t2 := 42 + 1: $t5 := borrow_local($t0) + 2: $t4 := borrow_field.g($t5) + 3: $t3 := borrow_field.h($t4) + 4: write_ref($t3, $t2) + 5: $t1 := infer($t0) + 6: return $t1 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun fields::read_ref($t0: &fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &u64 + # live vars: $t0 + 0: $t2 := borrow_field.g($t0) + # live vars: $t2 + 1: $t3 := borrow_field.h($t2) + # live vars: $t3 + 2: $t1 := read_ref($t3) + # live vars: $t1 + 3: return $t1 +} + + +[variant baseline] +fun fields::read_val($t0: fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &fields::S + var $t4: &u64 + # live vars: $t0 + 0: $t3 := borrow_local($t0) + # live vars: $t3 + 1: $t2 := borrow_field.g($t3) + # live vars: $t2 + 2: $t4 := borrow_field.h($t2) + # live vars: $t4 + 3: $t1 := read_ref($t4) + # live vars: $t1 + 4: return $t1 +} + + +[variant baseline] +fun fields::write_local_direct(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut fields::T + var $t9: &mut fields::S + # live vars: + 0: $t3 := 0 + # live vars: $t3 + 1: $t5 := 0 + # live vars: $t3, $t5 + 2: $t4 := pack fields::T($t5) + # live vars: $t3, $t4 + 3: $t2 := pack fields::S($t3, $t4) + # live vars: $t2 + 4: $t1 := move($t2) + # live vars: $t1 + 5: $t6 := 42 + # live vars: $t1, $t6 + 6: $t9 := borrow_local($t1) + # live vars: $t1, $t6, $t9 + 7: $t8 := borrow_field.g($t9) + # live vars: $t1, $t6, $t8 + 8: $t7 := borrow_field.h($t8) + # live vars: $t1, $t6, $t7 + 9: write_ref($t7, $t6) + # live vars: $t1 + 10: $t0 := move($t1) + # live vars: $t0 + 11: return $t0 +} + + +[variant baseline] +fun fields::write_local_via_ref(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: &mut fields::S + var $t7: &mut fields::S + var $t8: u64 + var $t9: &mut u64 + var $t10: &mut fields::T + # live vars: + 0: $t3 := 0 + # live vars: $t3 + 1: $t5 := 0 + # live vars: $t3, $t5 + 2: $t4 := pack fields::T($t5) + # live vars: $t3, $t4 + 3: $t2 := pack fields::S($t3, $t4) + # live vars: $t2 + 4: $t1 := move($t2) + # live vars: $t1 + 5: $t7 := borrow_local($t1) + # live vars: $t1, $t7 + 6: $t6 := move($t7) + # live vars: $t1, $t6 + 7: $t8 := 42 + # live vars: $t1, $t6, $t8 + 8: $t10 := borrow_field.g($t6) + # live vars: $t1, $t8, $t10 + 9: $t9 := borrow_field.h($t10) + # live vars: $t1, $t8, $t9 + 10: write_ref($t9, $t8) + # live vars: $t1 + 11: $t0 := move($t1) + # live vars: $t0 + 12: return $t0 +} + + +[variant baseline] +fun fields::write_param($t0: &mut fields::S) { + var $t1: u64 + var $t2: &mut u64 + var $t3: &mut fields::T + # live vars: $t0 + 0: $t1 := 42 + # live vars: $t0, $t1 + 1: $t3 := borrow_field.g($t0) + # live vars: $t1, $t3 + 2: $t2 := borrow_field.h($t3) + # live vars: $t1, $t2 + 3: write_ref($t2, $t1) + # live vars: + 4: return () +} + + +[variant baseline] +fun fields::write_val($t0: fields::S): fields::S { + var $t1: fields::S + var $t2: u64 + var $t3: &mut u64 + var $t4: &mut fields::T + var $t5: &mut fields::S + # live vars: $t0 + 0: $t2 := 42 + # live vars: $t0, $t2 + 1: $t5 := borrow_local($t0) + # live vars: $t0, $t2, $t5 + 2: $t4 := borrow_field.g($t5) + # live vars: $t0, $t2, $t4 + 3: $t3 := borrow_field.h($t4) + # live vars: $t0, $t2, $t3 + 4: write_ref($t3, $t2) + # live vars: $t0 + 5: $t1 := move($t0) + # live vars: $t1 + 6: return $t1 +} + +============ after MemorySafetyProcessor: ================ + +[variant baseline] +fun fields::read_ref($t0: &fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := borrow_field.g($t0) + # live vars: $t2 + # graph: {L0=local($t0)[borrow_field(false) -> L1],L1=local($t2)[]} + # local_to_label: {$t0=L0,$t2=L1} + # global_to_label: {} + # moved: {} + # + 1: $t3 := borrow_field.h($t2) + # live vars: $t3 + # graph: {L0=local($t0)[borrow_field(false) -> L1],L1=local($t2)[borrow_field(false) -> L257],L257=local($t3)[]} + # local_to_label: {$t0=L0,$t2=L1,$t3=L257} + # global_to_label: {} + # moved: {} + # + 2: $t1 := read_ref($t3) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 3: return $t1 +} + + +[variant baseline] +fun fields::read_val($t0: fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &fields::S + var $t4: &u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t3 := borrow_local($t0) + # live vars: $t3 + # graph: {L0=local($t0)[borrow(false) -> L1],L1=local($t3)[]} + # local_to_label: {$t0=L0,$t3=L1} + # global_to_label: {} + # moved: {} + # + 1: $t2 := borrow_field.g($t3) + # live vars: $t2 + # graph: {L0=local($t0)[borrow(false) -> L1],L1=local($t3)[borrow_field(false) -> L257],L257=local($t2)[]} + # local_to_label: {$t0=L0,$t2=L257,$t3=L1} + # global_to_label: {} + # moved: {} + # + 2: $t4 := borrow_field.h($t2) + # live vars: $t4 + # graph: {L0=local($t0)[borrow(false) -> L1],L1=local($t3)[borrow_field(false) -> L257],L257=local($t2)[borrow_field(false) -> L513],L513=local($t4)[]} + # local_to_label: {$t0=L0,$t2=L257,$t3=L1,$t4=L513} + # global_to_label: {} + # moved: {} + # + 3: $t1 := read_ref($t4) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 4: return $t1 +} + + +[variant baseline] +fun fields::write_local_direct(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut fields::T + var $t9: &mut fields::S + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t3 := 0 + # live vars: $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: $t5 := 0 + # live vars: $t3, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 2: $t4 := pack fields::T($t5) + # live vars: $t3, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t5} + # + 3: $t2 := pack fields::S($t3, $t4) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t3,$t4,$t5} + # + 4: $t1 := move($t2) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 5: $t6 := 42 + # live vars: $t1, $t6 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 6: $t9 := borrow_local($t1) + # live vars: $t1, $t6, $t9 + # graph: {L1536=local($t1)[borrow(true) -> L1537],L1537=local($t9)[]} + # local_to_label: {$t1=L1536,$t9=L1537} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 7: $t8 := borrow_field.g($t9) + # live vars: $t1, $t6, $t8 + # graph: {L1536=local($t1)[borrow(true) -> L1537],L1537=local($t9)[borrow_field(true) -> L1793],L1793=local($t8)[]} + # local_to_label: {$t1=L1536,$t8=L1793,$t9=L1537} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 8: $t7 := borrow_field.h($t8) + # live vars: $t1, $t6, $t7 + # graph: {L1536=local($t1)[borrow(true) -> L1537],L1537=local($t9)[borrow_field(true) -> L1793],L1793=local($t8)[borrow_field(true) -> L2049],L2049=local($t7)[]} + # local_to_label: {$t1=L1536,$t7=L2049,$t8=L1793,$t9=L1537} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 9: write_ref($t7, $t6) + # live vars: $t1 + # graph: {L1536=local($t1)[]} + # local_to_label: {$t1=L1536} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 10: $t0 := move($t1) + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1,$t2,$t3,$t4,$t5} + # + 11: return $t0 +} + + +[variant baseline] +fun fields::write_local_via_ref(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: &mut fields::S + var $t7: &mut fields::S + var $t8: u64 + var $t9: &mut u64 + var $t10: &mut fields::T + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t3 := 0 + # live vars: $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: $t5 := 0 + # live vars: $t3, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 2: $t4 := pack fields::T($t5) + # live vars: $t3, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t5} + # + 3: $t2 := pack fields::S($t3, $t4) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t3,$t4,$t5} + # + 4: $t1 := move($t2) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 5: $t7 := borrow_local($t1) + # live vars: $t1, $t7 + # graph: {L1280=local($t1)[borrow(true) -> L1281],L1281=local($t7)[]} + # local_to_label: {$t1=L1280,$t7=L1281} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5} + # + 6: $t6 := move($t7) + # live vars: $t1, $t6 + # graph: {L1280=local($t1)[borrow(true) -> L1281],L1281=local($t7)[skip -> L1537],L1537=local($t6)[]} + # local_to_label: {$t1=L1280,$t6=L1537,$t7=L1281} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5,$t7} + # + 7: $t8 := 42 + # live vars: $t1, $t6, $t8 + # graph: {L1280=local($t1)[borrow(true) -> L1281],L1281=local($t7)[skip -> L1537],L1537=local($t6)[]} + # local_to_label: {$t1=L1280,$t6=L1537,$t7=L1281} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5,$t7} + # + 8: $t10 := borrow_field.g($t6) + # live vars: $t1, $t8, $t10 + # graph: {L1280=local($t1)[borrow(true) -> L1281],L1281=local($t7)[skip -> L1537],L1537=local($t6)[borrow_field(true) -> L2049],L2049=local($t10)[]} + # local_to_label: {$t1=L1280,$t6=L1537,$t7=L1281,$t10=L2049} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5,$t7} + # + 9: $t9 := borrow_field.h($t10) + # live vars: $t1, $t8, $t9 + # graph: {L1280=local($t1)[borrow(true) -> L1281],L1281=local($t7)[skip -> L1537],L1537=local($t6)[borrow_field(true) -> L2049],L2049=local($t10)[borrow_field(true) -> L2305],L2305=local($t9)[]} + # local_to_label: {$t1=L1280,$t6=L1537,$t7=L1281,$t9=L2305,$t10=L2049} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5,$t7} + # + 10: write_ref($t9, $t8) + # live vars: $t1 + # graph: {L1280=local($t1)[]} + # local_to_label: {$t1=L1280} + # global_to_label: {} + # moved: {$t2,$t3,$t4,$t5,$t7} + # + 11: $t0 := move($t1) + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1,$t2,$t3,$t4,$t5,$t7} + # + 12: return $t0 +} + + +[variant baseline] +fun fields::write_param($t0: &mut fields::S) { + var $t1: u64 + var $t2: &mut u64 + var $t3: &mut fields::T + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t1 := 42 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: $t3 := borrow_field.g($t0) + # live vars: $t1, $t3 + # graph: {L256=local($t0)[borrow_field(true) -> L257],L257=local($t3)[]} + # local_to_label: {$t0=L256,$t3=L257} + # global_to_label: {} + # moved: {} + # + 2: $t2 := borrow_field.h($t3) + # live vars: $t1, $t2 + # graph: {L256=local($t0)[borrow_field(true) -> L257],L257=local($t3)[borrow_field(true) -> L513],L513=local($t2)[]} + # local_to_label: {$t0=L256,$t2=L513,$t3=L257} + # global_to_label: {} + # moved: {} + # + 3: write_ref($t2, $t1) + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 4: return () +} + + +[variant baseline] +fun fields::write_val($t0: fields::S): fields::S { + var $t1: fields::S + var $t2: u64 + var $t3: &mut u64 + var $t4: &mut fields::T + var $t5: &mut fields::S + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := 42 + # live vars: $t0, $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: $t5 := borrow_local($t0) + # live vars: $t0, $t2, $t5 + # graph: {L256=local($t0)[borrow(true) -> L257],L257=local($t5)[]} + # local_to_label: {$t0=L256,$t5=L257} + # global_to_label: {} + # moved: {} + # + 2: $t4 := borrow_field.g($t5) + # live vars: $t0, $t2, $t4 + # graph: {L256=local($t0)[borrow(true) -> L257],L257=local($t5)[borrow_field(true) -> L513],L513=local($t4)[]} + # local_to_label: {$t0=L256,$t4=L513,$t5=L257} + # global_to_label: {} + # moved: {} + # + 3: $t3 := borrow_field.h($t4) + # live vars: $t0, $t2, $t3 + # graph: {L256=local($t0)[borrow(true) -> L257],L257=local($t5)[borrow_field(true) -> L513],L513=local($t4)[borrow_field(true) -> L769],L769=local($t3)[]} + # local_to_label: {$t0=L256,$t3=L769,$t4=L513,$t5=L257} + # global_to_label: {} + # moved: {} + # + 4: write_ref($t3, $t2) + # live vars: $t0 + # graph: {L256=local($t0)[]} + # local_to_label: {$t0=L256} + # global_to_label: {} + # moved: {} + # + 5: $t1 := move($t0) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0} + # + 6: return $t1 +} + +============ after ExplicitDrop: ================ + +[variant baseline] +fun fields::read_ref($t0: &fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &u64 + 0: $t2 := borrow_field.g($t0) + 1: drop($t0) + 2: $t3 := borrow_field.h($t2) + 3: drop($t2) + 4: $t1 := read_ref($t3) + 5: drop($t3) + 6: return $t1 +} + + +[variant baseline] +fun fields::read_val($t0: fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &fields::S + var $t4: &u64 + 0: $t3 := borrow_local($t0) + 1: $t2 := borrow_field.g($t3) + 2: drop($t3) + 3: $t4 := borrow_field.h($t2) + 4: drop($t2) + 5: $t1 := read_ref($t4) + 6: release($t0) + 7: drop($t4) + 8: return $t1 +} + + +[variant baseline] +fun fields::write_local_direct(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut fields::T + var $t9: &mut fields::S + 0: $t3 := 0 + 1: $t5 := 0 + 2: $t4 := pack fields::T($t5) + 3: $t2 := pack fields::S($t3, $t4) + 4: $t1 := move($t2) + 5: $t6 := 42 + 6: $t9 := borrow_local($t1) + 7: $t8 := borrow_field.g($t9) + 8: drop($t9) + 9: $t7 := borrow_field.h($t8) + 10: drop($t8) + 11: write_ref($t7, $t6) + 12: drop($t7) + 13: $t0 := move($t1) + 14: return $t0 +} + + +[variant baseline] +fun fields::write_local_via_ref(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: &mut fields::S + var $t7: &mut fields::S + var $t8: u64 + var $t9: &mut u64 + var $t10: &mut fields::T + 0: $t3 := 0 + 1: $t5 := 0 + 2: $t4 := pack fields::T($t5) + 3: $t2 := pack fields::S($t3, $t4) + 4: $t1 := move($t2) + 5: $t7 := borrow_local($t1) + 6: $t6 := move($t7) + 7: $t8 := 42 + 8: $t10 := borrow_field.g($t6) + 9: drop($t6) + 10: $t9 := borrow_field.h($t10) + 11: drop($t10) + 12: write_ref($t9, $t8) + 13: drop($t9) + 14: $t0 := move($t1) + 15: return $t0 +} + + +[variant baseline] +fun fields::write_param($t0: &mut fields::S) { + var $t1: u64 + var $t2: &mut u64 + var $t3: &mut fields::T + 0: $t1 := 42 + 1: $t3 := borrow_field.g($t0) + 2: drop($t0) + 3: $t2 := borrow_field.h($t3) + 4: drop($t3) + 5: write_ref($t2, $t1) + 6: drop($t2) + 7: return () +} + + +[variant baseline] +fun fields::write_val($t0: fields::S): fields::S { + var $t1: fields::S + var $t2: u64 + var $t3: &mut u64 + var $t4: &mut fields::T + var $t5: &mut fields::S + 0: $t2 := 42 + 1: $t5 := borrow_local($t0) + 2: $t4 := borrow_field.g($t5) + 3: drop($t5) + 4: $t3 := borrow_field.h($t4) + 5: drop($t4) + 6: write_ref($t3, $t2) + 7: drop($t3) + 8: $t1 := move($t0) + 9: return $t1 +} + +============ after AbilityChecker: ================ + +[variant baseline] +fun fields::read_ref($t0: &fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &u64 + 0: $t2 := borrow_field.g($t0) + 1: drop($t0) + 2: $t3 := borrow_field.h($t2) + 3: drop($t2) + 4: $t1 := read_ref($t3) + 5: drop($t3) + 6: return $t1 +} + + +[variant baseline] +fun fields::read_val($t0: fields::S): u64 { + var $t1: u64 + var $t2: &fields::T + var $t3: &fields::S + var $t4: &u64 + 0: $t3 := borrow_local($t0) + 1: $t2 := borrow_field.g($t3) + 2: drop($t3) + 3: $t4 := borrow_field.h($t2) + 4: drop($t2) + 5: $t1 := read_ref($t4) + 6: release($t0) + 7: drop($t4) + 8: return $t1 +} + + +[variant baseline] +fun fields::write_local_direct(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: u64 + var $t7: &mut u64 + var $t8: &mut fields::T + var $t9: &mut fields::S + 0: $t3 := 0 + 1: $t5 := 0 + 2: $t4 := pack fields::T($t5) + 3: $t2 := pack fields::S($t3, $t4) + 4: $t1 := move($t2) + 5: $t6 := 42 + 6: $t9 := borrow_local($t1) + 7: $t8 := borrow_field.g($t9) + 8: drop($t9) + 9: $t7 := borrow_field.h($t8) + 10: drop($t8) + 11: write_ref($t7, $t6) + 12: drop($t7) + 13: $t0 := move($t1) + 14: return $t0 +} + + +[variant baseline] +fun fields::write_local_via_ref(): fields::S { + var $t0: fields::S + var $t1: fields::S + var $t2: fields::S + var $t3: u64 + var $t4: fields::T + var $t5: u64 + var $t6: &mut fields::S + var $t7: &mut fields::S + var $t8: u64 + var $t9: &mut u64 + var $t10: &mut fields::T + 0: $t3 := 0 + 1: $t5 := 0 + 2: $t4 := pack fields::T($t5) + 3: $t2 := pack fields::S($t3, $t4) + 4: $t1 := move($t2) + 5: $t7 := borrow_local($t1) + 6: $t6 := move($t7) + 7: $t8 := 42 + 8: $t10 := borrow_field.g($t6) + 9: drop($t6) + 10: $t9 := borrow_field.h($t10) + 11: drop($t10) + 12: write_ref($t9, $t8) + 13: drop($t9) + 14: $t0 := move($t1) + 15: return $t0 +} + + +[variant baseline] +fun fields::write_param($t0: &mut fields::S) { + var $t1: u64 + var $t2: &mut u64 + var $t3: &mut fields::T + 0: $t1 := 42 + 1: $t3 := borrow_field.g($t0) + 2: drop($t0) + 3: $t2 := borrow_field.h($t3) + 4: drop($t3) + 5: write_ref($t2, $t1) + 6: drop($t2) + 7: return () +} + + +[variant baseline] +fun fields::write_val($t0: fields::S): fields::S { + var $t1: fields::S + var $t2: u64 + var $t3: &mut u64 + var $t4: &mut fields::T + var $t5: &mut fields::S + 0: $t2 := 42 + 1: $t5 := borrow_local($t0) + 2: $t4 := borrow_field.g($t5) + 3: drop($t5) + 4: $t3 := borrow_field.h($t4) + 5: drop($t4) + 6: write_ref($t3, $t2) + 7: drop($t3) + 8: $t1 := move($t0) + 9: return $t1 +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.move b/third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.move new file mode 100644 index 0000000000000..da6bea9d1d449 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/failing/fields.move @@ -0,0 +1,41 @@ +module 0x42::fields { + + struct S { + f: u64, + g: T + } + + struct T { + h: u64 + } + + fun read_val(x: S): u64 { + x.g.h + } + + fun read_ref(x: &S): u64 { + x.g.h + } + + fun write_val(x: S): S { + x.g.h = 42; + x + } + + fun write_param(x: &mut S) { + x.g.h = 42; + } + + fun write_local_via_ref(): S { + let x = S { f: 0, g: T { h: 0 } }; + let r = &mut x; + r.g.h = 42; + x + } + + fun write_local_direct(): S { + let x = S { f: 0, g: T { h: 0 } }; + x.g.h = 42; + x + } +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.exp b/third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.exp new file mode 100644 index 0000000000000..53c3cfa378102 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.exp @@ -0,0 +1,1354 @@ +============ initial bytecode ================ + +[variant baseline] +fun operators::arithm($t0: u64, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t6 := -($t0, $t1) + 1: $t5 := /($t1, $t6) + 2: $t4 := *($t5, $t1) + 3: $t3 := %($t4, $t0) + 4: $t2 := +($t0, $t3) + 5: return $t2 +} + + +[variant baseline] +fun operators::bits($t0: u64, $t1: u8): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t4 := <<($t0, $t1) + 1: $t3 := &($t4, $t0) + 2: $t6 := >>($t0, $t1) + 3: $t5 := ^($t6, $t0) + 4: $t2 := |($t3, $t5) + 5: return $t2 +} + + +[variant baseline] +fun operators::bools($t0: bool, $t1: bool): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t5 := infer($t1) + 3: goto 6 + 4: label L1 + 5: $t5 := false + 6: label L2 + 7: if ($t5) goto 8 else goto 11 + 8: label L3 + 9: $t4 := true + 10: goto 19 + 11: label L4 + 12: if ($t0) goto 13 else goto 16 + 13: label L6 + 14: $t4 := !($t1) + 15: goto 18 + 16: label L7 + 17: $t4 := false + 18: label L8 + 19: label L5 + 20: if ($t4) goto 21 else goto 24 + 21: label L9 + 22: $t3 := true + 23: goto 33 + 24: label L10 + 25: $t6 := !($t0) + 26: if ($t6) goto 27 else goto 30 + 27: label L12 + 28: $t3 := infer($t1) + 29: goto 32 + 30: label L13 + 31: $t3 := false + 32: label L14 + 33: label L11 + 34: if ($t3) goto 35 else goto 38 + 35: label L15 + 36: $t2 := true + 37: goto 47 + 38: label L16 + 39: $t7 := !($t0) + 40: if ($t7) goto 41 else goto 44 + 41: label L18 + 42: $t2 := !($t1) + 43: goto 46 + 44: label L19 + 45: $t2 := false + 46: label L20 + 47: label L17 + 48: return $t2 +} + + +[variant baseline] +fun operators::equality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + 0: $t2 := ==($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +fun operators::inequality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + 0: $t2 := !=($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +fun operators::order($t0: u64, $t1: u64): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + 0: $t5 := <($t0, $t1) + 1: if ($t5) goto 2 else goto 5 + 2: label L0 + 3: $t4 := <=($t0, $t1) + 4: goto 7 + 5: label L1 + 6: $t4 := false + 7: label L2 + 8: if ($t4) goto 9 else goto 13 + 9: label L3 + 10: $t6 := >($t0, $t1) + 11: $t3 := !($t6) + 12: goto 15 + 13: label L4 + 14: $t3 := false + 15: label L5 + 16: if ($t3) goto 17 else goto 21 + 17: label L6 + 18: $t7 := >=($t0, $t1) + 19: $t2 := !($t7) + 20: goto 23 + 21: label L7 + 22: $t2 := false + 23: label L8 + 24: return $t2 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun operators::arithm($t0: u64, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + # live vars: $t0, $t1 + 0: $t6 := -($t0, $t1) + # live vars: $t0, $t1, $t6 + 1: $t5 := /($t1, $t6) + # live vars: $t0, $t1, $t5 + 2: $t4 := *($t5, $t1) + # live vars: $t0, $t4 + 3: $t3 := %($t4, $t0) + # live vars: $t0, $t3 + 4: $t2 := +($t0, $t3) + # live vars: $t2 + 5: return $t2 +} + + +[variant baseline] +fun operators::bits($t0: u64, $t1: u8): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + # live vars: $t0, $t1 + 0: $t4 := <<($t0, $t1) + # live vars: $t0, $t1, $t4 + 1: $t3 := &($t4, $t0) + # live vars: $t0, $t1, $t3 + 2: $t6 := >>($t0, $t1) + # live vars: $t0, $t3, $t6 + 3: $t5 := ^($t6, $t0) + # live vars: $t3, $t5 + 4: $t2 := |($t3, $t5) + # live vars: $t2 + 5: return $t2 +} + + +[variant baseline] +fun operators::bools($t0: bool, $t1: bool): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + # live vars: $t0, $t1 + 0: if ($t0) goto 1 else goto 4 + # live vars: $t0, $t1 + 1: label L0 + # live vars: $t0, $t1 + 2: $t5 := copy($t1) + # live vars: $t0, $t1, $t5 + 3: goto 6 + # live vars: $t0, $t1 + 4: label L1 + # live vars: $t0, $t1 + 5: $t5 := false + # live vars: $t0, $t1, $t5 + 6: label L2 + # live vars: $t0, $t1, $t5 + 7: if ($t5) goto 8 else goto 11 + # live vars: $t0, $t1 + 8: label L3 + # live vars: $t0, $t1 + 9: $t4 := true + # live vars: $t0, $t1, $t4 + 10: goto 19 + # live vars: $t0, $t1 + 11: label L4 + # live vars: $t0, $t1 + 12: if ($t0) goto 13 else goto 16 + # live vars: $t0, $t1 + 13: label L6 + # live vars: $t0, $t1 + 14: $t4 := !($t1) + # live vars: $t0, $t1, $t4 + 15: goto 18 + # live vars: $t0, $t1 + 16: label L7 + # live vars: $t0, $t1 + 17: $t4 := false + # live vars: $t0, $t1, $t4 + 18: label L8 + # live vars: $t0, $t1, $t4 + 19: label L5 + # live vars: $t0, $t1, $t4 + 20: if ($t4) goto 21 else goto 24 + # live vars: $t0, $t1 + 21: label L9 + # live vars: $t0, $t1 + 22: $t3 := true + # live vars: $t0, $t1, $t3 + 23: goto 33 + # live vars: $t0, $t1 + 24: label L10 + # live vars: $t0, $t1 + 25: $t6 := !($t0) + # live vars: $t0, $t1, $t6 + 26: if ($t6) goto 27 else goto 30 + # live vars: $t0, $t1 + 27: label L12 + # live vars: $t0, $t1 + 28: $t3 := copy($t1) + # live vars: $t0, $t1, $t3 + 29: goto 32 + # live vars: $t0, $t1 + 30: label L13 + # live vars: $t0, $t1 + 31: $t3 := false + # live vars: $t0, $t1, $t3 + 32: label L14 + # live vars: $t0, $t1, $t3 + 33: label L11 + # live vars: $t0, $t1, $t3 + 34: if ($t3) goto 35 else goto 38 + # live vars: $t0, $t1 + 35: label L15 + # live vars: + 36: $t2 := true + # live vars: $t2 + 37: goto 47 + # live vars: $t0, $t1 + 38: label L16 + # live vars: $t0, $t1 + 39: $t7 := !($t0) + # live vars: $t1, $t7 + 40: if ($t7) goto 41 else goto 44 + # live vars: $t1 + 41: label L18 + # live vars: $t1 + 42: $t2 := !($t1) + # live vars: $t2 + 43: goto 46 + # live vars: $t1 + 44: label L19 + # live vars: + 45: $t2 := false + # live vars: $t2 + 46: label L20 + # live vars: $t2 + 47: label L17 + # live vars: $t2 + 48: return $t2 +} + + +[variant baseline] +fun operators::equality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + # live vars: $t0, $t1 + 0: $t2 := ==($t0, $t1) + # live vars: $t2 + 1: return $t2 +} + + +[variant baseline] +fun operators::inequality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + # live vars: $t0, $t1 + 0: $t2 := !=($t0, $t1) + # live vars: $t2 + 1: return $t2 +} + + +[variant baseline] +fun operators::order($t0: u64, $t1: u64): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + # live vars: $t0, $t1 + 0: $t5 := <($t0, $t1) + # live vars: $t0, $t1, $t5 + 1: if ($t5) goto 2 else goto 5 + # live vars: $t0, $t1 + 2: label L0 + # live vars: $t0, $t1 + 3: $t4 := <=($t0, $t1) + # live vars: $t0, $t1, $t4 + 4: goto 7 + # live vars: $t0, $t1 + 5: label L1 + # live vars: $t0, $t1 + 6: $t4 := false + # live vars: $t0, $t1, $t4 + 7: label L2 + # live vars: $t0, $t1, $t4 + 8: if ($t4) goto 9 else goto 13 + # live vars: $t0, $t1 + 9: label L3 + # live vars: $t0, $t1 + 10: $t6 := >($t0, $t1) + # live vars: $t0, $t1, $t6 + 11: $t3 := !($t6) + # live vars: $t0, $t1, $t3 + 12: goto 15 + # live vars: $t0, $t1 + 13: label L4 + # live vars: $t0, $t1 + 14: $t3 := false + # live vars: $t0, $t1, $t3 + 15: label L5 + # live vars: $t0, $t1, $t3 + 16: if ($t3) goto 17 else goto 21 + # live vars: $t0, $t1 + 17: label L6 + # live vars: $t0, $t1 + 18: $t7 := >=($t0, $t1) + # live vars: $t7 + 19: $t2 := !($t7) + # live vars: $t2 + 20: goto 23 + # live vars: $t0, $t1 + 21: label L7 + # live vars: + 22: $t2 := false + # live vars: $t2 + 23: label L8 + # live vars: $t2 + 24: return $t2 +} + +============ after MemorySafetyProcessor: ================ + +[variant baseline] +fun operators::arithm($t0: u64, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t6 := -($t0, $t1) + # live vars: $t0, $t1, $t6 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 1: $t5 := /($t1, $t6) + # live vars: $t0, $t1, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 2: $t4 := *($t5, $t1) + # live vars: $t0, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t5,$t6} + # + 3: $t3 := %($t4, $t0) + # live vars: $t0, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t4,$t5,$t6} + # + 4: $t2 := +($t0, $t3) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t3,$t4,$t5,$t6} + # + 5: return $t2 +} + + +[variant baseline] +fun operators::bits($t0: u64, $t1: u8): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t4 := <<($t0, $t1) + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 1: $t3 := &($t4, $t0) + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t4} + # + 2: $t6 := >>($t0, $t1) + # live vars: $t0, $t3, $t6 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t4} + # + 3: $t5 := ^($t6, $t0) + # live vars: $t3, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t4,$t6} + # + 4: $t2 := |($t3, $t5) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t3,$t4,$t5,$t6} + # + 5: return $t2 +} + + +[variant baseline] +fun operators::bools($t0: bool, $t1: bool): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: if ($t0) goto 1 else goto 4 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: label L0 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 2: $t5 := copy($t1) + # live vars: $t0, $t1, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 3: goto 6 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 4: label L1 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 5: $t5 := false + # live vars: $t0, $t1, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 6: label L2 + # live vars: $t0, $t1, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 7: if ($t5) goto 8 else goto 11 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 8: label L3 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 9: $t4 := true + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 10: goto 19 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 11: label L4 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 12: if ($t0) goto 13 else goto 16 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 13: label L6 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 14: $t4 := !($t1) + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 15: goto 18 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 16: label L7 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 17: $t4 := false + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 18: label L8 + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 19: label L5 + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 20: if ($t4) goto 21 else goto 24 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 21: label L9 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 22: $t3 := true + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 23: goto 33 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 24: label L10 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t1} + # + 25: $t6 := !($t0) + # live vars: $t0, $t1, $t6 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 26: if ($t6) goto 27 else goto 30 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 27: label L12 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 28: $t3 := copy($t1) + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 29: goto 32 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 30: label L13 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 31: $t3 := false + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 32: label L14 + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 33: label L11 + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 34: if ($t3) goto 35 else goto 38 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 35: label L15 + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 36: $t2 := true + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 37: goto 47 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 38: label L16 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 39: $t7 := !($t0) + # live vars: $t1, $t7 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 40: if ($t7) goto 41 else goto 44 + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 41: label L18 + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 42: $t2 := !($t1) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 43: goto 46 + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 44: label L19 + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 45: $t2 := false + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 46: label L20 + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 47: label L17 + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 48: return $t2 +} + + +[variant baseline] +fun operators::equality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := ==($t0, $t1) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 1: return $t2 +} + + +[variant baseline] +fun operators::inequality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := !=($t0, $t1) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 1: return $t2 +} + + +[variant baseline] +fun operators::order($t0: u64, $t1: u64): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t5 := <($t0, $t1) + # live vars: $t0, $t1, $t5 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 1: if ($t5) goto 2 else goto 5 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 2: label L0 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 3: $t4 := <=($t0, $t1) + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 4: goto 7 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 5: label L1 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 6: $t4 := false + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 7: label L2 + # live vars: $t0, $t1, $t4 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 8: if ($t4) goto 9 else goto 13 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 9: label L3 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 10: $t6 := >($t0, $t1) + # live vars: $t0, $t1, $t6 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 11: $t3 := !($t6) + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 12: goto 15 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 13: label L4 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1} + # + 14: $t3 := false + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 15: label L5 + # live vars: $t0, $t1, $t3 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 16: if ($t3) goto 17 else goto 21 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 17: label L6 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 18: $t7 := >=($t0, $t1) + # live vars: $t7 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 19: $t2 := !($t7) + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6,$t7} + # + 20: goto 23 + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 21: label L7 + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6} + # + 22: $t2 := false + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6,$t7} + # + 23: label L8 + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t6,$t7} + # + 24: return $t2 +} + +============ after ExplicitDrop: ================ + +[variant baseline] +fun operators::arithm($t0: u64, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t6 := -($t0, $t1) + 1: $t5 := /($t1, $t6) + 2: $t4 := *($t5, $t1) + 3: $t3 := %($t4, $t0) + 4: $t2 := +($t0, $t3) + 5: return $t2 +} + + +[variant baseline] +fun operators::bits($t0: u64, $t1: u8): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t4 := <<($t0, $t1) + 1: $t3 := &($t4, $t0) + 2: $t6 := >>($t0, $t1) + 3: $t5 := ^($t6, $t0) + 4: $t2 := |($t3, $t5) + 5: return $t2 +} + + +[variant baseline] +fun operators::bools($t0: bool, $t1: bool): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t5 := copy($t1) + 3: goto 6 + 4: label L1 + 5: $t5 := false + 6: label L2 + 7: if ($t5) goto 8 else goto 11 + 8: label L3 + 9: $t4 := true + 10: goto 19 + 11: label L4 + 12: if ($t0) goto 13 else goto 16 + 13: label L6 + 14: $t4 := !($t1) + 15: goto 18 + 16: label L7 + 17: $t4 := false + 18: label L8 + 19: label L5 + 20: if ($t4) goto 21 else goto 24 + 21: label L9 + 22: $t3 := true + 23: goto 33 + 24: label L10 + 25: $t6 := !($t0) + 26: if ($t6) goto 27 else goto 30 + 27: label L12 + 28: $t3 := copy($t1) + 29: goto 32 + 30: label L13 + 31: $t3 := false + 32: label L14 + 33: label L11 + 34: if ($t3) goto 35 else goto 38 + 35: label L15 + 36: $t2 := true + 37: goto 47 + 38: label L16 + 39: $t7 := !($t0) + 40: if ($t7) goto 41 else goto 44 + 41: label L18 + 42: $t2 := !($t1) + 43: goto 46 + 44: label L19 + 45: $t2 := false + 46: label L20 + 47: label L17 + 48: return $t2 +} + + +[variant baseline] +fun operators::equality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + 0: $t2 := ==($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +fun operators::inequality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + 0: $t2 := !=($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +fun operators::order($t0: u64, $t1: u64): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + 0: $t5 := <($t0, $t1) + 1: if ($t5) goto 2 else goto 5 + 2: label L0 + 3: $t4 := <=($t0, $t1) + 4: goto 7 + 5: label L1 + 6: $t4 := false + 7: label L2 + 8: if ($t4) goto 9 else goto 13 + 9: label L3 + 10: $t6 := >($t0, $t1) + 11: $t3 := !($t6) + 12: goto 15 + 13: label L4 + 14: $t3 := false + 15: label L5 + 16: if ($t3) goto 17 else goto 21 + 17: label L6 + 18: $t7 := >=($t0, $t1) + 19: $t2 := !($t7) + 20: goto 23 + 21: label L7 + 22: $t2 := false + 23: label L8 + 24: return $t2 +} + +============ after AbilityChecker: ================ + +[variant baseline] +fun operators::arithm($t0: u64, $t1: u64): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t6 := -($t0, $t1) + 1: $t5 := /($t1, $t6) + 2: $t4 := *($t5, $t1) + 3: $t3 := %($t4, $t0) + 4: $t2 := +($t0, $t3) + 5: return $t2 +} + + +[variant baseline] +fun operators::bits($t0: u64, $t1: u8): u64 { + var $t2: u64 + var $t3: u64 + var $t4: u64 + var $t5: u64 + var $t6: u64 + 0: $t4 := <<($t0, $t1) + 1: $t3 := &($t4, $t0) + 2: $t6 := >>($t0, $t1) + 3: $t5 := ^($t6, $t0) + 4: $t2 := |($t3, $t5) + 5: return $t2 +} + + +[variant baseline] +fun operators::bools($t0: bool, $t1: bool): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + 0: if ($t0) goto 1 else goto 4 + 1: label L0 + 2: $t5 := copy($t1) + 3: goto 6 + 4: label L1 + 5: $t5 := false + 6: label L2 + 7: if ($t5) goto 8 else goto 11 + 8: label L3 + 9: $t4 := true + 10: goto 19 + 11: label L4 + 12: if ($t0) goto 13 else goto 16 + 13: label L6 + 14: $t4 := !($t1) + 15: goto 18 + 16: label L7 + 17: $t4 := false + 18: label L8 + 19: label L5 + 20: if ($t4) goto 21 else goto 24 + 21: label L9 + 22: $t3 := true + 23: goto 33 + 24: label L10 + 25: $t6 := !($t0) + 26: if ($t6) goto 27 else goto 30 + 27: label L12 + 28: $t3 := copy($t1) + 29: goto 32 + 30: label L13 + 31: $t3 := false + 32: label L14 + 33: label L11 + 34: if ($t3) goto 35 else goto 38 + 35: label L15 + 36: $t2 := true + 37: goto 47 + 38: label L16 + 39: $t7 := !($t0) + 40: if ($t7) goto 41 else goto 44 + 41: label L18 + 42: $t2 := !($t1) + 43: goto 46 + 44: label L19 + 45: $t2 := false + 46: label L20 + 47: label L17 + 48: return $t2 +} + + +[variant baseline] +fun operators::equality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + 0: $t2 := ==($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +fun operators::inequality<#0>($t0: #0, $t1: #0): bool { + var $t2: bool + 0: $t2 := !=($t0, $t1) + 1: return $t2 +} + + +[variant baseline] +fun operators::order($t0: u64, $t1: u64): bool { + var $t2: bool + var $t3: bool + var $t4: bool + var $t5: bool + var $t6: bool + var $t7: bool + 0: $t5 := <($t0, $t1) + 1: if ($t5) goto 2 else goto 5 + 2: label L0 + 3: $t4 := <=($t0, $t1) + 4: goto 7 + 5: label L1 + 6: $t4 := false + 7: label L2 + 8: if ($t4) goto 9 else goto 13 + 9: label L3 + 10: $t6 := >($t0, $t1) + 11: $t3 := !($t6) + 12: goto 15 + 13: label L4 + 14: $t3 := false + 15: label L5 + 16: if ($t3) goto 17 else goto 21 + 17: label L6 + 18: $t7 := >=($t0, $t1) + 19: $t2 := !($t7) + 20: goto 23 + 21: label L7 + 22: $t2 := false + 23: label L8 + 24: return $t2 +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.move b/third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.move new file mode 100644 index 0000000000000..b06cebbbde997 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/failing/operators.move @@ -0,0 +1,25 @@ +module 0x42::operators { + fun arithm(x: u64, y: u64): u64 { + x + y / (x - y) * y % x + } + + fun bits(x: u64, y: u8): u64 { + x << y & x | x >> y ^ x + } + + fun bools(x: bool, y: bool): bool { + x && y || x && !y || !x && y || !x && !y + } + + fun equality(x: T, y: T): bool { + x == y + } + + fun inequality(x: T, y: T): bool { + x != y + } + + fun order(x: u64, y: u64): bool { + x < y && x <= y && !(x > y) && !(x >= y) + } +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/globals.exp b/third_party/move/move-compiler-v2/tests/ability-checker/globals.exp new file mode 100644 index 0000000000000..58aec4093351e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/globals.exp @@ -0,0 +1,422 @@ + +Diagnostics: +warning: Unused parameter `x`. Consider removing or prefixing with an underscore: `_x` + ┌─ tests/ability-checker/globals.move:18:27 + │ +18 │ fun write(a: address, x: u64): u64 { + │ ^ + +============ initial bytecode ================ + +[variant baseline] +fun globals::check($t0: address): bool { + var $t1: bool + 0: $t1 := exists($t0) + 1: return $t1 +} + + +[variant baseline] +fun globals::publish($t0: &signer) { + var $t1: globals::R + var $t2: u64 + 0: $t2 := 1 + 1: $t1 := pack globals::R($t2) + 2: move_to($t0, $t1) + 3: return () +} + + +[variant baseline] +fun globals::read($t0: address): u64 { + var $t1: u64 + var $t2: &globals::R + var $t3: &globals::R + var $t4: &u64 + 0: $t3 := borrow_global($t0) + 1: $t2 := infer($t3) + 2: $t4 := borrow_field.f($t2) + 3: $t1 := read_ref($t4) + 4: return $t1 +} + + +[variant baseline] +fun globals::write($t0: address, $t1: u64): u64 { + var $t2: u64 + var $t3: &mut globals::R + var $t4: &mut globals::R + var $t5: u64 + var $t6: &mut u64 + 0: $t4 := borrow_global($t0) + 1: $t3 := infer($t4) + 2: $t5 := 2 + 3: $t6 := borrow_field.f($t3) + 4: write_ref($t6, $t5) + 5: $t2 := 9 + 6: return $t2 +} + +============ after LiveVarAnalysisProcessor: ================ + +[variant baseline] +fun globals::check($t0: address): bool { + var $t1: bool + # live vars: $t0 + 0: $t1 := exists($t0) + # live vars: $t1 + 1: return $t1 +} + + +[variant baseline] +fun globals::publish($t0: &signer) { + var $t1: globals::R + var $t2: u64 + # live vars: $t0 + 0: $t2 := 1 + # live vars: $t0, $t2 + 1: $t1 := pack globals::R($t2) + # live vars: $t0, $t1 + 2: move_to($t0, $t1) + # live vars: + 3: return () +} + + +[variant baseline] +fun globals::read($t0: address): u64 { + var $t1: u64 + var $t2: &globals::R + var $t3: &globals::R + var $t4: &u64 + # live vars: $t0 + 0: $t3 := borrow_global($t0) + # live vars: $t3 + 1: $t2 := move($t3) + # live vars: $t2 + 2: $t4 := borrow_field.f($t2) + # live vars: $t4 + 3: $t1 := read_ref($t4) + # live vars: $t1 + 4: return $t1 +} + + +[variant baseline] +fun globals::write($t0: address, $t1: u64): u64 { + var $t2: u64 + var $t3: &mut globals::R + var $t4: &mut globals::R + var $t5: u64 + var $t6: &mut u64 + # live vars: $t0 + 0: $t4 := borrow_global($t0) + # live vars: $t4 + 1: $t3 := move($t4) + # live vars: $t3 + 2: $t5 := 2 + # live vars: $t3, $t5 + 3: $t6 := borrow_field.f($t3) + # live vars: $t5, $t6 + 4: write_ref($t6, $t5) + # live vars: + 5: $t2 := 9 + # live vars: $t2 + 6: return $t2 +} + +============ after MemorySafetyProcessor: ================ + +[variant baseline] +fun globals::check($t0: address): bool { + var $t1: bool + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t1 := exists($t0) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0} + # + 1: return $t1 +} + + +[variant baseline] +fun globals::publish($t0: &signer) { + var $t1: globals::R + var $t2: u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t2 := 1 + # live vars: $t0, $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 1: $t1 := pack globals::R($t2) + # live vars: $t0, $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t2} + # + 2: move_to($t0, $t1) + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t0,$t1,$t2} + # + 3: return () +} + + +[variant baseline] +fun globals::read($t0: address): u64 { + var $t1: u64 + var $t2: &globals::R + var $t3: &globals::R + var $t4: &u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t3 := borrow_global($t0) + # live vars: $t3 + # graph: {L0=global[borrow_global(false) -> L1],L1=local($t3)[]} + # local_to_label: {$t3=L1} + # global_to_label: {globals::R=L0} + # moved: {} + # + 1: $t2 := move($t3) + # live vars: $t2 + # graph: {L0=global[borrow_global(false) -> L1],L1=local($t3)[skip -> L257],L257=local($t2)[]} + # local_to_label: {$t2=L257,$t3=L1} + # global_to_label: {globals::R=L0} + # moved: {$t3} + # + 2: $t4 := borrow_field.f($t2) + # live vars: $t4 + # graph: {L0=global[borrow_global(false) -> L1],L1=local($t3)[skip -> L257],L257=local($t2)[borrow_field(false) -> L513],L513=local($t4)[]} + # local_to_label: {$t2=L257,$t3=L1,$t4=L513} + # global_to_label: {globals::R=L0} + # moved: {$t3} + # + 3: $t1 := read_ref($t4) + # live vars: $t1 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t3} + # + 4: return $t1 +} + + +[variant baseline] +fun globals::write($t0: address, $t1: u64): u64 { + var $t2: u64 + var $t3: &mut globals::R + var $t4: &mut globals::R + var $t5: u64 + var $t6: &mut u64 + # live vars: $t0 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {} + # + 0: $t4 := borrow_global($t0) + # live vars: $t4 + # graph: {L0=global[borrow_global(true) -> L1],L1=local($t4)[]} + # local_to_label: {$t4=L1} + # global_to_label: {globals::R=L0} + # moved: {} + # + 1: $t3 := move($t4) + # live vars: $t3 + # graph: {L0=global[borrow_global(true) -> L1],L1=local($t4)[skip -> L257],L257=local($t3)[]} + # local_to_label: {$t3=L257,$t4=L1} + # global_to_label: {globals::R=L0} + # moved: {$t4} + # + 2: $t5 := 2 + # live vars: $t3, $t5 + # graph: {L0=global[borrow_global(true) -> L1],L1=local($t4)[skip -> L257],L257=local($t3)[]} + # local_to_label: {$t3=L257,$t4=L1} + # global_to_label: {globals::R=L0} + # moved: {$t4} + # + 3: $t6 := borrow_field.f($t3) + # live vars: $t5, $t6 + # graph: {L0=global[borrow_global(true) -> L1],L1=local($t4)[skip -> L257],L257=local($t3)[borrow_field(true) -> L769],L769=local($t6)[]} + # local_to_label: {$t3=L257,$t4=L1,$t6=L769} + # global_to_label: {globals::R=L0} + # moved: {$t4} + # + 4: write_ref($t6, $t5) + # live vars: + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t4} + # + 5: $t2 := 9 + # live vars: $t2 + # graph: {} + # local_to_label: {} + # global_to_label: {} + # moved: {$t4} + # + 6: return $t2 +} + +============ after ExplicitDrop: ================ + +[variant baseline] +fun globals::check($t0: address): bool { + var $t1: bool + 0: $t1 := exists($t0) + 1: return $t1 +} + + +[variant baseline] +fun globals::publish($t0: &signer) { + var $t1: globals::R + var $t2: u64 + 0: $t2 := 1 + 1: $t1 := pack globals::R($t2) + 2: move_to($t0, $t1) + 3: return () +} + + +[variant baseline] +fun globals::read($t0: address): u64 { + var $t1: u64 + var $t2: &globals::R + var $t3: &globals::R + var $t4: &u64 + 0: $t3 := borrow_global($t0) + 1: $t2 := move($t3) + 2: $t4 := borrow_field.f($t2) + 3: drop($t2) + 4: $t1 := read_ref($t4) + 5: drop($t4) + 6: return $t1 +} + + +[variant baseline] +fun globals::write($t0: address, $t1: u64): u64 { + var $t2: u64 + var $t3: &mut globals::R + var $t4: &mut globals::R + var $t5: u64 + var $t6: &mut u64 + 0: $t4 := borrow_global($t0) + 1: $t3 := move($t4) + 2: $t5 := 2 + 3: $t6 := borrow_field.f($t3) + 4: drop($t3) + 5: write_ref($t6, $t5) + 6: drop($t6) + 7: $t2 := 9 + 8: return $t2 +} + + +Diagnostics: +error: no key ability + ┌─ tests/ability-checker/globals.move:6:9 + │ +6 │ move_to(s, R{f: 1}); + │ ^^^^^^^^^^^^^^^^^^^ + +error: no key ability + ┌─ tests/ability-checker/globals.move:10:9 + │ +10 │ exists(a) + │ ^^^^^^^^^^^^ + +error: no key ability + ┌─ tests/ability-checker/globals.move:14:17 + │ +14 │ let r = borrow_global(a); + │ ^^^^^^^^^^^^^^^^^^^ + +error: no key ability + ┌─ tests/ability-checker/globals.move:19:17 + │ +19 │ let r = borrow_global_mut(a); + │ ^^^^^^^^^^^^^^^^^^^^^^^ + +============ after AbilityChecker: ================ + +[variant baseline] +fun globals::check($t0: address): bool { + var $t1: bool + 0: $t1 := exists($t0) + 1: return $t1 +} + + +[variant baseline] +fun globals::publish($t0: &signer) { + var $t1: globals::R + var $t2: u64 + 0: $t2 := 1 + 1: $t1 := pack globals::R($t2) + 2: move_to($t0, $t1) + 3: return () +} + + +[variant baseline] +fun globals::read($t0: address): u64 { + var $t1: u64 + var $t2: &globals::R + var $t3: &globals::R + var $t4: &u64 + 0: $t3 := borrow_global($t0) + 1: $t2 := move($t3) + 2: $t4 := borrow_field.f($t2) + 3: drop($t2) + 4: $t1 := read_ref($t4) + 5: drop($t4) + 6: return $t1 +} + + +[variant baseline] +fun globals::write($t0: address, $t1: u64): u64 { + var $t2: u64 + var $t3: &mut globals::R + var $t4: &mut globals::R + var $t5: u64 + var $t6: &mut u64 + 0: $t4 := borrow_global($t0) + 1: $t3 := move($t4) + 2: $t5 := 2 + 3: $t6 := borrow_field.f($t3) + 4: drop($t3) + 5: write_ref($t6, $t5) + 6: drop($t6) + 7: $t2 := 9 + 8: return $t2 +} diff --git a/third_party/move/move-compiler-v2/tests/ability-checker/globals.move b/third_party/move/move-compiler-v2/tests/ability-checker/globals.move new file mode 100644 index 0000000000000..e2da286af777a --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/ability-checker/globals.move @@ -0,0 +1,23 @@ +module 0x42::globals { + + struct R has store { f: u64 } + + fun publish(s: &signer) { + move_to(s, R{f: 1}); + } + + fun check(a: address): bool { + exists(a) + } + + fun read(a: address): u64 { + let r = borrow_global(a); + r.f + } + + fun write(a: address, x: u64): u64 { + let r = borrow_global_mut(a); + r.f = 2; + 9 + } +} diff --git a/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp b/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp new file mode 100644 index 0000000000000..c6971722dbe49 --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.exp @@ -0,0 +1,49 @@ + +============ disassembled file-format ================== +// Move bytecode v7 +module c0ffee.m { + + +equality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 0 */ { +B0: + 0: MoveLoc[0](Arg0: Ty0) + 1: MoveLoc[1](Arg1: Ty0) + 2: Eq + 3: Ret +} +} +Diagnostics: +bug: BYTECODE VERIFICATION FAILED + ┌─ tests/bytecode-verify-failure/equality.move:1:1 + │ +1 │ ╭ module 0xc0ffee::m { +2 │ │ fun equality(x: T, y: T): bool { +3 │ │ x == y +4 │ │ } +5 │ │ } + │ ╰─^ ICE failed bytecode verifier: VMError { + major_status: EQUALITY_OP_TYPE_MISMATCH_ERROR, + sub_status: None, + message: None, + exec_state: None, + location: Module( + ModuleId { + address: 0000000000000000000000000000000000000000000000000000000000c0ffee, + name: Identifier( + "m", + ), + }, + ), + indices: [ + ( + FunctionDefinition, + 0, + ), + ], + offsets: [ + ( + FunctionDefinitionIndex(0), + 2, + ), + ], +} diff --git a/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.move b/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.move new file mode 100644 index 0000000000000..4764e4d4cad8e --- /dev/null +++ b/third_party/move/move-compiler-v2/tests/bytecode-verify-failure/equality.move @@ -0,0 +1,5 @@ +module 0xc0ffee::m { + fun equality(x: T, y: T): bool { + x == y + } +} diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp index cbbd99c02299a..7d114d1b2dadf 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.exp @@ -108,10 +108,10 @@ fun assign::assign_struct($t0: &mut assign::S) { ============ disassembled file-format ================== // Move bytecode v7 module 42.assign { -struct T { +struct T has drop { h: u64 } -struct S { +struct S has drop { f: u64, g: T } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.move b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.move index 2ea2fe8d33721..afa8188675dd0 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/assign.move +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/assign.move @@ -1,11 +1,11 @@ module 0x42::assign { - struct S { + struct S has drop { f: u64, g: T } - struct T { + struct T has drop { h: u64 } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp index 5918bfd282cbc..e38f7b731faa9 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.exp @@ -274,10 +274,10 @@ fun fields::write_val($t0: fields::S): fields::S { ============ disassembled file-format ================== // Move bytecode v7 module 42.fields { -struct T { +struct T has drop { h: u64 } -struct S { +struct S has drop { f: u64, g: T } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.move b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.move index da6bea9d1d449..1d43aae913f18 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/fields.move +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/fields.move @@ -1,11 +1,11 @@ module 0x42::fields { - struct S { + struct S has drop { f: u64, g: T } - struct T { + struct T has drop { h: u64 } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp index 0ad865102c8d2..18cf1c0cffec8 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.exp @@ -130,7 +130,7 @@ fun globals::write($t0: address, $t1: u64): u64 { ============ disassembled file-format ================== // Move bytecode v7 module 42.globals { -struct R has store { +struct R has store, key { f: u64 } diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.move b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.move index e2da286af777a..711bc02fb9701 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/globals.move +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/globals.move @@ -1,6 +1,6 @@ module 0x42::globals { - struct R has store { f: u64 } + struct R has key, store { f: u64 } fun publish(s: &signer) { move_to(s, R{f: 1}); diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp index db97c6526e6ce..ecc5a567b8c58 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.exp @@ -490,14 +490,14 @@ B18: 47: MoveLoc[5](loc3: bool) 48: Ret } -equality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 3 */ { +equality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 3 */ { B0: 0: MoveLoc[0](Arg0: Ty0) 1: MoveLoc[1](Arg1: Ty0) 2: Eq 3: Ret } -inequality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 4 */ { +inequality(Arg0: Ty0, Arg1: Ty0): bool /* def_idx: 4 */ { B0: 0: MoveLoc[0](Arg0: Ty0) 1: MoveLoc[1](Arg1: Ty0) diff --git a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.move b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.move index b06cebbbde997..19bae2370d574 100644 --- a/third_party/move/move-compiler-v2/tests/file-format-generator/operators.move +++ b/third_party/move/move-compiler-v2/tests/file-format-generator/operators.move @@ -11,11 +11,11 @@ module 0x42::operators { x && y || x && !y || !x && y || !x && !y } - fun equality(x: T, y: T): bool { + fun equality(x: T, y: T): bool { x == y } - fun inequality(x: T, y: T): bool { + fun inequality(x: T, y: T): bool { x != y } diff --git a/third_party/move/move-compiler-v2/tests/testsuite.rs b/third_party/move/move-compiler-v2/tests/testsuite.rs index 85278f36c1f11..f37efdb752be7 100644 --- a/third_party/move/move-compiler-v2/tests/testsuite.rs +++ b/third_party/move/move-compiler-v2/tests/testsuite.rs @@ -4,11 +4,9 @@ use codespan_reporting::{diagnostic::Severity, term::termcolor::Buffer}; use log::{debug, trace}; -use move_binary_format::binary_views::BinaryIndexedView; -use move_command_line_common::files::FileHash; -use move_compiler::compiled_unit::CompiledUnit; use move_compiler_v2::{ - flow_insensitive_checkers, function_checker, inliner, logging, pipeline, + annotate_units, disassemble_compiled_units, flow_insensitive_checkers, function_checker, + inliner, logging, pipeline, pipeline::{ ability_checker::AbilityChecker, avail_copies_analysis::AvailCopiesAnalysisProcessor, copy_propagation::CopyPropagation, dead_store_elimination::DeadStoreElimination, @@ -18,10 +16,8 @@ use move_compiler_v2::{ unreachable_code_analysis::UnreachableCodeProcessor, unreachable_code_remover::UnreachableCodeRemover, visibility_checker::VisibilityChecker, }, - run_file_format_gen, Options, + run_bytecode_verifier, run_file_format_gen, Options, }; -use move_disassembler::disassembler::Disassembler; -use move_ir_types::location; use move_model::model::GlobalEnv; use move_prover_test_utils::{baseline_test, extract_test_directives}; use move_stackless_bytecode::function_target_pipeline::FunctionTargetPipeline; @@ -286,6 +282,21 @@ impl TestConfig { dump_annotated_targets: true, dump_for_only_some_stages: None, } + } else if path.contains("/bytecode-verify-failure/") { + pipeline.add_processor(Box::new(LiveVarAnalysisProcessor { + with_copy_inference: true, + })); + // Note that we do not run ability checker here, as we want to induce + // a bytecode verification failure. The test in /bytecode-verify-failure/ + // has erroneous ability annotations. + Self { + type_check_only: false, + dump_ast: false, + pipeline, + generate_file_format: true, + dump_annotated_targets: false, + dump_for_only_some_stages: None, + } } else { panic!( "unexpected test path `{}`, cannot derive configuration", @@ -341,7 +352,7 @@ impl TestConfig { if ok && !self.type_check_only { // Run stackless bytecode generator let mut targets = move_compiler_v2::run_bytecode_gen(&env); - let ok = Self::check_diags(&mut test_output.borrow_mut(), &env); + ok = Self::check_diags(&mut test_output.borrow_mut(), &env); if ok { // Run the target pipeline. self.pipeline.run_with_hook( @@ -411,22 +422,17 @@ impl TestConfig { } }, ); - let ok = Self::check_diags(&mut test_output.borrow_mut(), &env); + ok = Self::check_diags(&mut test_output.borrow_mut(), &env); if ok && self.generate_file_format { let units = run_file_format_gen(&env, &targets); let out = &mut test_output.borrow_mut(); out.push_str("\n============ disassembled file-format ==================\n"); - Self::check_diags(out, &env); - for compiled_unit in units { - let disassembled = match compiled_unit { - CompiledUnit::Module(module) => { - Self::disassemble(BinaryIndexedView::Module(&module.module))? - }, - CompiledUnit::Script(script) => { - Self::disassemble(BinaryIndexedView::Script(&script.script))? - }, - }; - out.push_str(&disassembled); + ok = Self::check_diags(out, &env); + out.push_str(&disassemble_compiled_units(&units)?); + if ok { + let annotated_units = annotate_units(units); + run_bytecode_verifier(&annotated_units, &mut env); + Self::check_diags(out, &env); } } } @@ -450,11 +456,6 @@ impl TestConfig { env.clear_diag(); ok } - - fn disassemble(view: BinaryIndexedView) -> anyhow::Result { - let diss = Disassembler::from_view(view, location::Loc::new(FileHash::empty(), 0, 0))?; - diss.disassemble() - } } datatest_stable::harness!(test_runner, "tests", r".*\.move$"); diff --git a/third_party/move/move-model/src/lib.rs b/third_party/move/move-model/src/lib.rs index ad37b73f6c278..fbca4039901dc 100644 --- a/third_party/move/move-model/src/lib.rs +++ b/third_party/move/move-model/src/lib.rs @@ -496,7 +496,7 @@ fn collect_related_modules_recursive<'a>( } } -fn add_move_lang_diagnostics(env: &mut GlobalEnv, diags: Diagnostics) { +pub fn add_move_lang_diagnostics(env: &mut GlobalEnv, diags: Diagnostics) { let mk_label = |is_primary: bool, (loc, msg): (move_ir_types::location::Loc, String)| { let style = if is_primary { LabelStyle::Primary From 4318127b6848cbdf901834706258a42f7c3da414 Mon Sep 17 00:00:00 2001 From: Rati Gelashvili Date: Thu, 8 Feb 2024 15:18:08 -0500 Subject: [PATCH 043/328] [Block Executor] Fix committed status checks / skip rest (#11945) --- aptos-move/block-executor/src/executor.rs | 10 ++---- .../src/proptest_types/baseline.rs | 5 ++- .../src/proptest_types/tests.rs | 2 +- .../src/proptest_types/types.rs | 10 ++++-- .../src/txn_last_input_output.rs | 14 +++++--- .../block-executor/src/unit_tests/mod.rs | 33 ++++++++++++++++++- 6 files changed, 56 insertions(+), 18 deletions(-) diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index 2cf74ee4dfd19..f2db61b44f5fb 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -483,6 +483,9 @@ where scheduler.add_to_commit_queue(txn_idx); } + // An invariant check on the recorded outputs. + last_input_output.check_execution_status_during_commit(txn_idx)?; + if let Some(fee_statement) = last_input_output.fee_statement(txn_idx) { let approx_output_size = block_gas_limit_type.block_output_limit().and_then(|_| { last_input_output @@ -575,13 +578,6 @@ where } } - // Note that module read/write intersection would be detected on record, and directly - // propagated as an error. Similarly, an unrecoverable VM failure, would also be - // directly propagated as error even from a speculative transaction execution. - - // An additional invariant check on the recorded outputs. - last_input_output.check_execution_status_during_commit(txn_idx)?; - last_input_output.record_finalized_group(txn_idx, finalized_groups); // While the above propagate errors and lead to eventually halting parallel execution, diff --git a/aptos-move/block-executor/src/proptest_types/baseline.rs b/aptos-move/block-executor/src/proptest_types/baseline.rs index 6cafa4cc2f741..fe61de4386554 100644 --- a/aptos-move/block-executor/src/proptest_types/baseline.rs +++ b/aptos-move/block-executor/src/proptest_types/baseline.rs @@ -114,12 +114,15 @@ impl BaselineOutput { status = BaselineStatus::Aborted; break; }, - MockTransaction::SkipRest => { + MockTransaction::SkipRest(gas) => { // In executor, SkipRest skips from the next index. Test assumes it's an empty // transaction, so create a successful empty reads and deltas. read_values.push(Ok(vec![])); resolved_deltas.push(Ok(HashMap::new())); + // gas in SkipRest is used for unit tests for now (can generalize when needed). + assert_eq!(*gas, 0); + status = BaselineStatus::SkipRest; break; }, diff --git a/aptos-move/block-executor/src/proptest_types/tests.rs b/aptos-move/block-executor/src/proptest_types/tests.rs index 738bc32c78096..7f642919db2aa 100644 --- a/aptos-move/block-executor/src/proptest_types/tests.rs +++ b/aptos-move/block-executor/src/proptest_types/tests.rs @@ -57,7 +57,7 @@ fn run_transactions( *transactions.get_mut(i.index(length)).unwrap() = MockTransaction::Abort; } for i in skip_rest_transactions { - *transactions.get_mut(i.index(length)).unwrap() = MockTransaction::SkipRest; + *transactions.get_mut(i.index(length)).unwrap() = MockTransaction::SkipRest(0); } let data_view = EmptyDataView::> { diff --git a/aptos-move/block-executor/src/proptest_types/types.rs b/aptos-move/block-executor/src/proptest_types/types.rs index 00151ae4f85d1..a25015af51c31 100644 --- a/aptos-move/block-executor/src/proptest_types/types.rs +++ b/aptos-move/block-executor/src/proptest_types/types.rs @@ -413,7 +413,7 @@ pub(crate) enum MockTransaction { incarnation_behaviors: Vec>, }, /// Skip the execution of trailing transactions. - SkipRest, + SkipRest(u64), /// Abort the execution. Abort, } @@ -439,7 +439,7 @@ impl MockTransaction { incarnation_behaviors, .. } => incarnation_behaviors, - Self::SkipRest => unreachable!("SkipRest does not contain incarnation behaviors"), + Self::SkipRest(_) => unreachable!("SkipRest does not contain incarnation behaviors"), Self::Abort => unreachable!("Abort does not contain incarnation behaviors"), } } @@ -968,7 +968,11 @@ where total_gas: behavior.gas, }) }, - MockTransaction::SkipRest => ExecutionStatus::SkipRest(MockOutput::skip_output()), + MockTransaction::SkipRest(gas) => { + let mut mock_output = MockOutput::skip_output(); + mock_output.total_gas = *gas; + ExecutionStatus::SkipRest(mock_output) + }, MockTransaction::Abort => ExecutionStatus::Abort(txn_idx as usize), } } diff --git a/aptos-move/block-executor/src/txn_last_input_output.rs b/aptos-move/block-executor/src/txn_last_input_output.rs index 693c27ec60919..f524ee20607f6 100644 --- a/aptos-move/block-executor/src/txn_last_input_output.rs +++ b/aptos-move/block-executor/src/txn_last_input_output.rs @@ -9,7 +9,6 @@ use crate::{ types::{InputOutputKey, ReadWriteSummary}, }; use aptos_aggregator::types::{code_invariant_error, PanicOr}; -use aptos_logger::warn; use aptos_mvhashmap::types::{TxnIndex, ValueWithLayout}; use aptos_types::{ delayed_fields::PanicError, fee_statement::FeeStatement, @@ -219,19 +218,24 @@ impl, E: Debug + Send + Clone> .into()), } } else { - // TODO: check carefully if such a case is possible due to early halts. - warn!("Possible to not find committed output (halted?)"); - Ok(()) + Err(code_invariant_error("Recorded output not found during commit").into()) } } pub(crate) fn update_to_skip_rest(&self, txn_idx: TxnIndex) { + if self.block_skips_rest_at_idx(txn_idx) { + // Already skipping. + return; + } + + // check_execution_status_during_commit must be used for checks re:status. + // Hence, since the status is not SkipRest, it must be Success. if let ExecutionStatus::Success(output) = self.take_output(txn_idx) { self.outputs[txn_idx as usize].store(Some(Arc::new(TxnOutput { output_status: ExecutionStatus::SkipRest(output), }))); } else { - unreachable!(); + unreachable!("Unexpected status"); } } diff --git a/aptos-move/block-executor/src/unit_tests/mod.rs b/aptos-move/block-executor/src/unit_tests/mod.rs index abe2104498969..92d4c31c60d88 100644 --- a/aptos-move/block-executor/src/unit_tests/mod.rs +++ b/aptos-move/block-executor/src/unit_tests/mod.rs @@ -88,6 +88,37 @@ fn block_output_err_precedence() { scenario.teardown(); } +#[test] +fn skip_rest_gas_limit() { + // The contents of the second txn does not matter, as the first should hit the gas limit and + // also skip. But it ensures block is not finished at the first txn (different processing). + let transactions = Vec::from([MockTransaction::SkipRest(10), MockTransaction::SkipRest(10)]); + + let data_view = DeltaDataView::> { + phantom: PhantomData, + }; + let executor_thread_pool = Arc::new( + rayon::ThreadPoolBuilder::new() + .num_threads(num_cpus::get()) + .build() + .unwrap(), + ); + let block_executor = BlockExecutor::< + MockTransaction, MockEvent>, + MockTask, MockEvent>, + DeltaDataView>, + NoOpTransactionCommitHook, MockEvent>, usize>, + ExecutableTestType, + >::new( + BlockExecutorConfig::new_maybe_block_limit(num_cpus::get(), Some(5)), + executor_thread_pool, + None, + ); + + // Should hit block limit on the skip transaction. + let _ = block_executor.execute_transactions_parallel((), &transactions, &data_view); +} + // TODO: add unit test for block gas limit! fn run_and_assert(transactions: Vec>) where @@ -376,7 +407,7 @@ fn early_skips() { ))); } // One transaction that triggers an abort - transactions.push(MockTransaction::SkipRest) + transactions.push(MockTransaction::SkipRest(0)) } run_and_assert(transactions) } From 9ef872b9a268fb07ce812c38c30764b51e50441f Mon Sep 17 00:00:00 2001 From: Rati Gelashvili Date: Thu, 8 Feb 2024 18:28:47 -0500 Subject: [PATCH 044/328] [Block Executor] implement group serialization fallback, test, fix halt (#11891) --- aptos-move/block-executor/src/errors.rs | 4 + aptos-move/block-executor/src/executor.rs | 104 +++++++++++++-- .../src/proptest_types/baseline.rs | 5 +- .../src/proptest_types/tests.rs | 2 +- .../src/proptest_types/types.rs | 3 + .../block-executor/src/unit_tests/mod.rs | 124 +++++++++++++++++- aptos-move/mvhashmap/src/unsync_map.rs | 7 +- 7 files changed, 224 insertions(+), 25 deletions(-) diff --git a/aptos-move/block-executor/src/errors.rs b/aptos-move/block-executor/src/errors.rs index ecd50bcf06e5b..bb30270524bb8 100644 --- a/aptos-move/block-executor/src/errors.rs +++ b/aptos-move/block-executor/src/errors.rs @@ -19,6 +19,10 @@ pub enum IntentionalFallbackToSequential { // This is not PanicError because we need to match the error variant to provide a specialized // fallback logic if a resource group serialization error occurs. ResourceGroupSerializationError, + // If multiple workers encounter conditions that qualify for a sequential fallback during parallel + // execution, it is not clear what is the "right" one to fallback with. Instead, we use the + // variant below. TODO: pass a vector of all encountered conditions (mainly for tests). + FallbackFromParallel, } impl IntentionalFallbackToSequential { diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index f2db61b44f5fb..047b22dc6b4ed 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -776,6 +776,14 @@ where finalized_groups: Vec<(T::Key, T::Value, Vec<(T::Tag, Arc)>)>, txn_idx: TxnIndex, ) -> Result, PanicOr> { + fail_point!( + "fail-point-resource-group-serialization", + !finalized_groups.is_empty(), + |_| Err(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + )) + ); + finalized_groups .into_iter() .map(|(group_key, mut metadata_op, finalized_group)| { @@ -806,9 +814,6 @@ where if res.is_err() { alert!("Failed to serialize resource group"); - // Alert first, then log an error with actual btree, to make sure - // printing it can't possibly fail during alert. - error!("Failed to serialize resource group BTreeMap {:?}", btree); } res @@ -1114,11 +1119,7 @@ where (!shared_maybe_error.load(Ordering::SeqCst)) .then(|| BlockOutput::new(final_results.into_inner())) .ok_or(PanicOr::Or( - // All errors (if more than one) have been logged, and here any error - // leads to a sequential fallback. We use serialization error for now - // to be defensive and avoid any scenarios where the fallback would not - // have the specialized logic enabled. TODO: refactor. - IntentionalFallbackToSequential::ResourceGroupSerializationError, + IntentionalFallbackToSequential::FallbackFromParallel, )) } @@ -1205,6 +1206,7 @@ where executor_arguments: E::Argument, signature_verified_block: &[T], base_view: &S, + resource_group_bcs_fallback: bool, ) -> BlockExecutionResult, E::Error> { let num_txns = signature_verified_block.len(); let init_timer = VM_INIT_SECONDS.start_timer(); @@ -1288,6 +1290,69 @@ where "Sequential execution must materialize deltas" ); + if resource_group_bcs_fallback { + // Dynamic change set optimizations are enabled, and resource group serialization + // previously failed in bcs serialization for preparing final transaction outputs. + // TODO: remove this fallback when txn errors can be created from block executor. + + let finalize = |group_key| -> BTreeMap<_, _> { + unsync_map + .finalize_group(&group_key) + .map(|(resource_tag, value_with_layout)| { + ( + resource_tag, + value_with_layout + .extract_value_no_layout() + .extract_raw_bytes() + .expect("Deletions should already be applied"), + ) + }) + .collect() + }; + + // The IDs are not exchanged but it doesn't change the types (Bytes) or size. + let serialization_error = output + .group_reads_needing_delayed_field_exchange() + .iter() + .any(|(group_key, _)| { + fail_point!("fail-point-resource-group-serialization", |_| { + true + }); + + let finalized_group = finalize(group_key.clone()); + bcs::to_bytes(&finalized_group).is_err() + }) + || output.resource_group_write_set().into_iter().any( + |(group_key, _, group_ops)| { + fail_point!("fail-point-resource-group-serialization", |_| { + true + }); + + let mut finalized_group = finalize(group_key); + for (value_tag, (group_op, _)) in group_ops { + if group_op.is_deletion() { + finalized_group.remove(&value_tag); + } else { + finalized_group.insert( + value_tag, + group_op + .extract_raw_bytes() + .expect("Not a deletion"), + ); + } + } + bcs::to_bytes(&finalized_group).is_err() + }, + ); + + if serialization_error { + // The corresponding error / alert must already be triggered, the goal in sequential + // fallback is to just skip any transactions that would cause such serialization errors. + ret.push(E::Output::skip_output()); + continue; + } + }; + // Apply the writes. // TODO[agg_v2](fix): return code invariant error if dynamic change set optimizations disabled. Self::apply_output_sequential(&unsync_map, &output)?; @@ -1297,7 +1362,8 @@ where let group_metadata_ops = output.resource_group_metadata_ops(); let mut finalized_groups = Vec::with_capacity(group_metadata_ops.len()); for (group_key, group_metadata_op) in group_metadata_ops.into_iter() { - let finalized_group = unsync_map.finalize_group(&group_key); + let finalized_group: Vec<_> = + unsync_map.finalize_group(&group_key).collect(); if finalized_group.is_empty() != group_metadata_op.is_deletion() { // TODO[agg_v2](fix): code invariant error if dynamic change set optimizations disabled. // TODO[agg_v2](fix): make sure this cannot be triggered by an user transaction @@ -1313,7 +1379,8 @@ where for (group_key, group_metadata_op) in output.group_reads_needing_delayed_field_exchange() { - let finalized_group = unsync_map.finalize_group(&group_key); + let finalized_group: Vec<_> = + unsync_map.finalize_group(&group_key).collect(); if finalized_group.is_empty() != group_metadata_op.is_deletion() { return Err(code_invariant_error(format!( "Group is empty = {} but op is deletion = {} in sequential execution", @@ -1452,12 +1519,21 @@ where executor_arguments, signature_verified_block, base_view, + false, ) }; - // Sequential execution fallback - // Only worth doing if we did parallel before, i.e. if we did a different pass. - if self.config.local.concurrency_level > 1 { + let resource_group_bcs_fallback = matches!( + ret, + Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + ))) + ); + + if self.config.local.concurrency_level > 1 || resource_group_bcs_fallback { + // Sequential execution fallback, only worth doing if we did a different pass before, + // i.e. parallel, or without resource group serialization fallback configured. + if let Err(BlockExecutionError::FallbackToSequential(_)) = &ret { // Any error logs are already written at appropriate levels. debug!("Sequential_fallback occurred"); @@ -1470,6 +1546,8 @@ where executor_arguments, signature_verified_block, base_view, + // Always enable resource group serialization handling in fallback. + true, ); } } diff --git a/aptos-move/block-executor/src/proptest_types/baseline.rs b/aptos-move/block-executor/src/proptest_types/baseline.rs index fe61de4386554..12a10968ec4e3 100644 --- a/aptos-move/block-executor/src/proptest_types/baseline.rs +++ b/aptos-move/block-executor/src/proptest_types/baseline.rs @@ -365,10 +365,7 @@ impl BaselineOutput { results.iter().skip(committed).for_each(|output| { // Ensure the transaction is skipped based on the output. - assert!(output.writes.is_empty()); - assert!(output.deltas.is_empty()); - assert!(output.read_results.is_empty()); - assert_eq!(output.total_gas, 0); + assert!(output.skipped); // Implies that materialize_delta_writes was never called, as should // be for skipped transactions. diff --git a/aptos-move/block-executor/src/proptest_types/tests.rs b/aptos-move/block-executor/src/proptest_types/tests.rs index 7f642919db2aa..45a4e68921d82 100644 --- a/aptos-move/block-executor/src/proptest_types/tests.rs +++ b/aptos-move/block-executor/src/proptest_types/tests.rs @@ -567,7 +567,7 @@ fn non_empty_group( executor_thread_pool.clone(), None, ) - .execute_transactions_sequential((), &transactions, &data_view); + .execute_transactions_sequential((), &transactions, &data_view, false); // TODO: test dynamic disabled as well. BaselineOutput::generate(&transactions, None).assert_output(&output); diff --git a/aptos-move/block-executor/src/proptest_types/types.rs b/aptos-move/block-executor/src/proptest_types/types.rs index a25015af51c31..cf831b54786ab 100644 --- a/aptos-move/block-executor/src/proptest_types/types.rs +++ b/aptos-move/block-executor/src/proptest_types/types.rs @@ -966,6 +966,7 @@ where read_group_sizes, materialized_delta_writes: OnceCell::new(), total_gas: behavior.gas, + skipped: false, }) }, MockTransaction::SkipRest(gas) => { @@ -997,6 +998,7 @@ pub(crate) struct MockOutput { pub(crate) read_group_sizes: Vec<(K, u64)>, pub(crate) materialized_delta_writes: OnceCell>, pub(crate) total_gas: u64, + pub(crate) skipped: bool, } impl TransactionOutput for MockOutput @@ -1100,6 +1102,7 @@ where read_group_sizes: vec![], materialized_delta_writes: OnceCell::new(), total_gas: 0, + skipped: true, } } diff --git a/aptos-move/block-executor/src/unit_tests/mod.rs b/aptos-move/block-executor/src/unit_tests/mod.rs index 92d4c31c60d88..60d1d9c25a8c4 100644 --- a/aptos-move/block-executor/src/unit_tests/mod.rs +++ b/aptos-move/block-executor/src/unit_tests/mod.rs @@ -9,7 +9,7 @@ use crate::{ baseline::BaselineOutput, types::{ DeltaDataView, KeyType, MockEvent, MockIncarnation, MockOutput, MockTask, - MockTransaction, ValueType, + MockTransaction, NonEmptyGroupDataView, ValueType, }, }, scheduler::{ @@ -33,9 +33,127 @@ use claims::assert_matches; use fail::FailScenario; use rand::{prelude::*, random}; use std::{ - cmp::min, collections::BTreeMap, fmt::Debug, hash::Hash, marker::PhantomData, sync::Arc, + cmp::min, + collections::{BTreeMap, HashMap, HashSet}, + fmt::Debug, + hash::Hash, + marker::PhantomData, + sync::Arc, }; +#[test] +fn resource_group_bcs_fallback() { + let no_group_incarnation_1: MockIncarnation, MockEvent> = MockIncarnation::new( + vec![KeyType::(1, false)], + vec![( + KeyType::(2, false), + ValueType::from_value(vec![5], true), + )], + vec![], + vec![], + 10, + ); + let no_group_incarnation_2: MockIncarnation, MockEvent> = MockIncarnation::new( + vec![KeyType::(3, false), KeyType::(4, false)], + vec![( + KeyType::(1, false), + ValueType::from_value(vec![5], true), + )], + vec![], + vec![], + 10, + ); + let t_1 = MockTransaction::from_behavior(no_group_incarnation_1); + let t_3 = MockTransaction::from_behavior(no_group_incarnation_2); + + let mut group_incarnation: MockIncarnation, MockEvent> = + MockIncarnation::new(vec![KeyType::(1, false)], vec![], vec![], vec![], 10); + group_incarnation.group_writes.push(( + KeyType::(100, false), + HashMap::from([(101, ValueType::from_value(vec![5], true))]), + )); + let t_2 = MockTransaction::from_behavior(group_incarnation); + let transactions = Vec::from([t_1, t_2, t_3]); + + let data_view = NonEmptyGroupDataView::> { + group_keys: HashSet::new(), + }; + let executor_thread_pool = Arc::new( + rayon::ThreadPoolBuilder::new() + .num_threads(num_cpus::get()) + .build() + .unwrap(), + ); + let block_executor = BlockExecutor::< + MockTransaction, MockEvent>, + MockTask, MockEvent>, + NonEmptyGroupDataView>, + NoOpTransactionCommitHook, MockEvent>, usize>, + ExecutableTestType, + >::new( + BlockExecutorConfig::new_no_block_limit(num_cpus::get()), + executor_thread_pool, + None, + ); + + // Execute the block normally. + let output = block_executor.execute_transactions_parallel((), &transactions, &data_view); + match output { + Ok(block_output) => { + let txn_outputs = block_output.into_transaction_outputs_forced(); + assert_eq!(txn_outputs.len(), 3); + assert!(!txn_outputs[0].writes.is_empty()); + assert!(!txn_outputs[2].writes.is_empty()); + assert!(!txn_outputs[1].group_writes.is_empty()); + }, + Err(_) => unreachable!("Must succeed: failpoint not yet set up"), + }; + + // Set up and sanity check failpoint. + let scenario = FailScenario::setup(); + assert!(fail::has_failpoints()); + fail::cfg("fail-point-resource-group-serialization", "return()").unwrap(); + assert!(!fail::list().is_empty()); + + let par_output = block_executor.execute_transactions_parallel((), &transactions, &data_view); + assert_matches!( + par_output, + Err(PanicOr::Or( + IntentionalFallbackToSequential::FallbackFromParallel + )) + ); + + let seq_output = + block_executor.execute_transactions_sequential((), &transactions, &data_view, false); + assert_matches!( + seq_output, + Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + ))) + ); + + // Now execute with fallback handling for resource group serialization error: + let fallback_output = + block_executor.execute_transactions_sequential((), &transactions, &data_view, true); + let fallback_output_block = block_executor.execute_block((), &transactions, &data_view); + for output in [fallback_output, fallback_output_block] { + match output { + Ok(block_output) => { + let txn_outputs = block_output.into_transaction_outputs_forced(); + assert_eq!(txn_outputs.len(), 3); + assert!(!txn_outputs[0].writes.is_empty()); + assert!(!txn_outputs[2].writes.is_empty()); + + // But now transaction 1 must be skipped. + assert!(txn_outputs[1].skipped); + }, + Err(_) => unreachable!("Must succeed: fallback"), + }; + } + + scenario.teardown(); +} + #[test] fn block_output_err_precedence() { let incarnation: MockIncarnation, MockEvent> = MockIncarnation::new( @@ -82,7 +200,7 @@ fn block_output_err_precedence() { assert_matches!( output, Err(PanicOr::Or( - IntentionalFallbackToSequential::ResourceGroupSerializationError + IntentionalFallbackToSequential::FallbackFromParallel )) ); scenario.teardown(); diff --git a/aptos-move/mvhashmap/src/unsync_map.rs b/aptos-move/mvhashmap/src/unsync_map.rs index 738de54a17e21..abcb30f094314 100644 --- a/aptos-move/mvhashmap/src/unsync_map.rs +++ b/aptos-move/mvhashmap/src/unsync_map.rs @@ -134,7 +134,7 @@ impl< } /// Contains the latest group ops for the given group key. - pub fn finalize_group(&self, group_key: &K) -> Vec<(T, ValueWithLayout)> { + pub fn finalize_group(&self, group_key: &K) -> impl Iterator)> { self.group_cache .borrow() .get(group_key) @@ -142,7 +142,6 @@ impl< .borrow() .clone() .into_iter() - .collect() } pub fn insert_group_op( @@ -280,7 +279,7 @@ mod test { map: &UnsyncMap>, usize, TestValue, ExecutableTestType, ()>, key: &KeyType>, ) -> HashMap> { - map.finalize_group(key).into_iter().collect() + map.finalize_group(key).collect() } // TODO[agg_v2](test) Add tests with non trivial layout @@ -402,7 +401,7 @@ mod test { let ap = KeyType(b"/foo/b".to_vec()); let map = UnsyncMap::>, usize, TestValue, ExecutableTestType, ()>::new(); - map.finalize_group(&ap); + let _ = map.finalize_group(&ap).collect::>(); } #[test] From 316368601a40ea8320c391269ead9adc55ee0533 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Thu, 8 Feb 2024 16:21:34 -0800 Subject: [PATCH 045/328] [dag] concurrent dag store (#11505) * [dag] implement concurrent dag store * [dag] monitor handler methods --- Cargo.lock | 6 +- consensus/src/dag/adapter.rs | 13 +- consensus/src/dag/bootstrap.rs | 12 +- consensus/src/dag/dag_driver.rs | 46 ++-- consensus/src/dag/dag_fetcher.rs | 19 +- consensus/src/dag/dag_handler.rs | 117 +++++---- consensus/src/dag/dag_state_sync.rs | 21 +- consensus/src/dag/dag_store.rs | 238 ++++++++++++------ consensus/src/dag/health/chain_health.rs | 2 + consensus/src/dag/order_rule.rs | 7 +- consensus/src/dag/rb_handler.rs | 8 +- consensus/src/dag/tests/dag_driver_tests.rs | 7 +- .../src/dag/tests/dag_state_sync_tests.rs | 31 +-- consensus/src/dag/tests/dag_test.rs | 62 +++-- consensus/src/dag/tests/fetcher_test.rs | 9 +- consensus/src/dag/tests/order_rule_tests.rs | 30 ++- consensus/src/dag/tests/rb_handler_tests.rs | 15 +- 17 files changed, 373 insertions(+), 270 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4bd0898ea09cc..f4bff31a1d2ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7478,7 +7478,7 @@ dependencies = [ "fixed-hash 0.8.0", "impl-codec 0.6.0", "impl-rlp", - "scale-info 2.10.0", + "scale-info 1.0.0", "tiny-keccak", ] @@ -7559,7 +7559,7 @@ dependencies = [ "impl-codec 0.6.0", "impl-rlp", "primitive-types 0.12.2", - "scale-info 2.10.0", + "scale-info 1.0.0", "uint", ] @@ -12878,7 +12878,7 @@ dependencies = [ "fixed-hash 0.8.0", "impl-codec 0.6.0", "impl-rlp", - "scale-info 2.10.0", + "scale-info 1.0.0", "uint", ] diff --git a/consensus/src/dag/adapter.rs b/consensus/src/dag/adapter.rs index 3cca20d15e3b6..4ab1056e08330 100644 --- a/consensus/src/dag/adapter.rs +++ b/consensus/src/dag/adapter.rs @@ -1,12 +1,14 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::observability::counters::{NUM_NODES_PER_BLOCK, NUM_ROUNDS_PER_BLOCK}; +use super::{ + dag_store::DagStore, + observability::counters::{NUM_NODES_PER_BLOCK, NUM_ROUNDS_PER_BLOCK}, +}; use crate::{ consensusdb::{CertifiedNodeSchema, ConsensusDB, DagVoteSchema, NodeSchema}, counters::update_counters_for_committed_blocks, dag::{ - dag_store::Dag, storage::{CommitEvent, DAGStorage}, CertifiedNode, Node, NodeId, Vote, }, @@ -89,7 +91,7 @@ pub(crate) fn compute_initial_block_and_ledger_info( pub(super) struct OrderedNotifierAdapter { executor_channel: UnboundedSender, - dag: Arc>, + dag: Arc, parent_block_info: Arc>, epoch_state: Arc, ledger_info_provider: Arc>, @@ -99,7 +101,7 @@ pub(super) struct OrderedNotifierAdapter { impl OrderedNotifierAdapter { pub(super) fn new( executor_channel: UnboundedSender, - dag: Arc>, + dag: Arc, epoch_state: Arc, parent_block_info: BlockInfo, ledger_info_provider: Arc>, @@ -207,8 +209,7 @@ impl OrderedNotifier for OrderedNotifierAdapter { block_created_ts .write() .retain(|&round, _| round > commit_decision.commit_info().round()); - dag.write() - .commit_callback(commit_decision.commit_info().round()); + dag.commit_callback(commit_decision.commit_info().round()); ledger_info_provider .write() .notify_commit_proof(commit_decision); diff --git a/consensus/src/dag/bootstrap.rs b/consensus/src/dag/bootstrap.rs index f1ade85ebe65b..04a01a6cb141b 100644 --- a/consensus/src/dag/bootstrap.rs +++ b/consensus/src/dag/bootstrap.rs @@ -8,7 +8,7 @@ use super::{ dag_handler::NetworkHandler, dag_network::TDAGNetworkSender, dag_state_sync::{DagStateSynchronizer, StateSyncTrigger}, - dag_store::Dag, + dag_store::DagStore, health::{ChainHealthBackoff, HealthBackoff, PipelineLatencyBasedBackpressure, TChainHealth}, order_rule::OrderRule, rb_handler::NodeBroadcastHandler, @@ -60,7 +60,7 @@ use futures_channel::{ mpsc::{UnboundedReceiver, UnboundedSender}, oneshot, }; -use std::{collections::HashMap, fmt, sync::Arc, time::Duration}; +use std::{collections::HashMap, fmt, ops::Deref, sync::Arc, time::Duration}; use tokio::{ runtime::Handle, select, @@ -70,7 +70,7 @@ use tokio_retry::strategy::ExponentialBackoff; #[derive(Clone)] struct BootstrapBaseState { - dag_store: Arc>, + dag_store: Arc, order_rule: OrderRule, ledger_info_provider: Arc, ordered_notifier: Arc, @@ -131,7 +131,7 @@ impl ActiveMode { ) -> Option { info!( LogSchema::new(LogEvent::ActiveMode) - .round(self.base_state.dag_store.read().highest_round()), + .round(self.base_state.dag_store.deref().read().highest_round()), highest_committed_round = self .base_state .ledger_info_provider @@ -500,13 +500,13 @@ impl DagBootstrapper { .saturating_sub(dag_window_size_config), ); - let dag = Arc::new(RwLock::new(Dag::new( + let dag = Arc::new(DagStore::new( self.epoch_state.clone(), self.storage.clone(), self.payload_manager.clone(), initial_round, dag_window_size_config, - ))); + )); let ordered_notifier = Arc::new(OrderedNotifierAdapter::new( self.ordered_nodes_tx.clone(), diff --git a/consensus/src/dag/dag_driver.rs b/consensus/src/dag/dag_driver.rs index 6c9b9141ad6e8..8af13c5bd8c77 100644 --- a/consensus/src/dag/dag_driver.rs +++ b/consensus/src/dag/dag_driver.rs @@ -1,12 +1,11 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::health::HealthBackoff; +use super::{dag_store::DagStore, health::HealthBackoff}; use crate::{ dag::{ adapter::TLedgerInfoProvider, dag_fetcher::TFetchRequester, - dag_store::Dag, errors::DagDriverError, observability::{ counters::{self, NODE_PAYLOAD_SIZE, NUM_TXNS_PER_NODE}, @@ -24,11 +23,10 @@ use crate::{ }, payload_client::PayloadClient, }; -use anyhow::bail; +use anyhow::{bail, ensure}; use aptos_config::config::DagPayloadConfig; use aptos_consensus_types::common::{Author, Payload, PayloadFilter}; use aptos_crypto::hash::CryptoHash; -use aptos_infallible::RwLock; use aptos_logger::{debug, error}; use aptos_reliable_broadcast::ReliableBroadcast; use aptos_time_service::{TimeService, TimeServiceTrait}; @@ -46,7 +44,7 @@ use tokio_retry::strategy::ExponentialBackoff; pub(crate) struct DagDriver { author: Author, epoch_state: Arc, - dag: Arc>, + dag: Arc, payload_client: Arc, reliable_broadcast: Arc>, time_service: TimeService, @@ -67,7 +65,7 @@ impl DagDriver { pub fn new( author: Author, epoch_state: Arc, - dag: Arc>, + dag: Arc, payload_client: Arc, reliable_broadcast: Arc>, time_service: TimeService, @@ -127,23 +125,35 @@ impl DagDriver { async fn add_node(&mut self, node: CertifiedNode) -> anyhow::Result<()> { let (highest_strong_link_round, strong_links) = { - let mut dag_writer = self.dag.write(); + { + let dag_reader = self.dag.read(); - if !dag_writer.all_exists(node.parents_metadata()) { - if let Err(err) = self.fetch_requester.request_for_certified_node(node) { - error!("request to fetch failed: {}", err); + // Ensure the window hasn't moved, so we don't request fetch unnecessarily. + ensure!(node.round() >= dag_reader.lowest_round(), "stale node"); + + if !dag_reader.all_exists(node.parents_metadata()) { + if let Err(err) = self.fetch_requester.request_for_certified_node(node) { + error!("request to fetch failed: {}", err); + } + bail!(DagDriverError::MissingParents); } - bail!(DagDriverError::MissingParents); } - dag_writer.add_node(node)?; + // Note on concurrency: it is possible that a prune operation kicks in here and + // moves the window forward making the `node` stale, but we guarantee that the + // order rule only visits `window` length rounds, so having node around should + // be fine. Any stale node inserted due to this race will be cleaned up with + // the next prune operation. + + self.dag.add_node(node)?; + let dag_reader = self.dag.read(); let highest_strong_links_round = - dag_writer.highest_strong_links_round(&self.epoch_state.verifier); + dag_reader.highest_strong_links_round(&self.epoch_state.verifier); ( highest_strong_links_round, // unwrap is for round 0 - dag_writer + dag_reader .get_strong_links_for_round( highest_strong_links_round, &self.epoch_state.verifier, @@ -320,12 +330,10 @@ impl RpcHandler for DagDriver { debug!(LogSchema::new(LogEvent::ReceiveCertifiedNode) .remote_peer(*certified_node.author()) .round(certified_node.round())); - { - let dag_reader = self.dag.read(); - if dag_reader.exists(certified_node.metadata()) { - return Ok(CertifiedAck::new(epoch)); - } + if self.dag.read().exists(certified_node.metadata()) { + return Ok(CertifiedAck::new(epoch)); } + observe_node(certified_node.timestamp(), NodeStage::CertifiedNodeReceived); NUM_TXNS_PER_NODE.observe(certified_node.payload().len() as f64); NODE_PAYLOAD_SIZE.observe(certified_node.payload().size() as f64); diff --git a/consensus/src/dag/dag_fetcher.rs b/consensus/src/dag/dag_fetcher.rs index 8d6542603ca99..1f61ac5d495c6 100644 --- a/consensus/src/dag/dag_fetcher.rs +++ b/consensus/src/dag/dag_fetcher.rs @@ -1,10 +1,9 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::DAGRpcResult; +use super::{dag_store::DagStore, DAGRpcResult}; use crate::dag::{ dag_network::{RpcResultWithResponder, TDAGNetworkSender}, - dag_store::Dag, errors::FetchRequestHandleError, observability::logging::{LogEvent, LogSchema}, types::{CertifiedNode, FetchResponse, Node, NodeMetadata, RemoteFetchRequest}, @@ -14,7 +13,6 @@ use anyhow::{anyhow, ensure}; use aptos_bitvec::BitVec; use aptos_config::config::DagFetcherConfig; use aptos_consensus_types::common::Author; -use aptos_infallible::RwLock; use aptos_logger::{debug, error, info}; use aptos_time_service::TimeService; use aptos_types::epoch_state::EpochState; @@ -131,7 +129,7 @@ impl LocalFetchRequest { pub struct DagFetcherService { inner: DagFetcher, - dag: Arc>, + dag: Arc, request_rx: Receiver, ordered_authors: Vec, } @@ -140,7 +138,7 @@ impl DagFetcherService { pub fn new( epoch_state: Arc, network: Arc, - dag: Arc>, + dag: Arc, time_service: TimeService, config: DagFetcherConfig, ) -> ( @@ -226,7 +224,7 @@ pub trait TDagFetcher: Send { &self, remote_request: RemoteFetchRequest, responders: Vec, - dag: Arc>, + dag: Arc, ) -> anyhow::Result<()>; } @@ -259,7 +257,7 @@ impl TDagFetcher for DagFetcher { &self, remote_request: RemoteFetchRequest, responders: Vec, - dag: Arc>, + dag: Arc, ) -> anyhow::Result<()> { debug!( LogSchema::new(LogEvent::FetchNodes), @@ -289,9 +287,8 @@ impl TDagFetcher for DagFetcher { let certified_nodes = fetch_response.certified_nodes(); // TODO: support chunk response or fallback to state sync { - let mut dag_writer = dag.write(); for node in certified_nodes.into_iter().rev() { - if let Err(e) = dag_writer.add_node(node) { + if let Err(e) = dag.add_node(node) { error!(error = ?e, "failed to add node"); } } @@ -319,12 +316,12 @@ impl TDagFetcher for DagFetcher { } pub struct FetchRequestHandler { - dag: Arc>, + dag: Arc, author_to_index: HashMap, } impl FetchRequestHandler { - pub fn new(dag: Arc>, epoch_state: Arc) -> Self { + pub fn new(dag: Arc, epoch_state: Arc) -> Self { Self { dag, author_to_index: epoch_state.verifier.address_to_validator_index().clone(), diff --git a/consensus/src/dag/dag_handler.rs b/consensus/src/dag/dag_handler.rs index 8d5a7812cbb06..b366cd2bd0118 100644 --- a/consensus/src/dag/dag_handler.rs +++ b/consensus/src/dag/dag_handler.rs @@ -75,6 +75,7 @@ impl NetworkHandler { move |rpc_request: IncomingDAGRequest| { let epoch_state = epoch_state.clone(); async move { + let epoch = rpc_request.req.epoch; let result = rpc_request .req .try_into() @@ -85,16 +86,15 @@ impl NetworkHandler { )?; Ok(dag_message) }); - (result, rpc_request.sender, rpc_request.responder) + (result, epoch, rpc_request.sender, rpc_request.responder) } }, ); loop { select! { - (msg, author, responder) = verified_msg_stream.select_next_some() => { - debug!("receive verified message"); - match self.process_verified_message(msg, author, responder).await { + (msg, epoch, author, responder) = verified_msg_stream.select_next_some() => { + monitor!("dag_on_verified_msg", match self.process_verified_message(msg, epoch, author, responder).await { Ok(sync_status) => { if matches!(sync_status, SyncOutcome::NeedsSync(_) | SyncOutcome::EpochEnds) { return sync_status; @@ -103,30 +103,32 @@ impl NetworkHandler { Err(e) => { warn!(error = ?e, "error processing rpc"); } - } + }); }, Some(new_round) = self.new_round_event.recv() => { - self.dag_driver.enter_new_round(new_round).await; - self.node_receiver.gc(); + monitor!("dag_on_new_round_event", { + self.dag_driver.enter_new_round(new_round).await; + self.node_receiver.gc(); + }); } Some(res) = self.node_fetch_waiter.next() => { - match res { + monitor!("dag_on_node_fetch", match res { Ok(node) => if let Err(e) = self.node_receiver.process(node).await { warn!(error = ?e, "error processing node fetch notification"); }, Err(e) => { debug!("sender dropped channel: {}", e); }, - }; + }); }, Some(res) = self.certified_node_fetch_waiter.next() => { - match res { + monitor!("dag_on_cert_node_fetch", match res { Ok(certified_node) => if let Err(e) = self.dag_driver.process(certified_node).await { warn!(error = ?e, "error processing certified node fetch notification"); }, Err(e) => { debug!("sender dropped channel: {}", e); }, - }; + }); } } } @@ -135,6 +137,7 @@ impl NetworkHandler { async fn process_verified_message( &mut self, dag_message_result: anyhow::Result, + epoch: u64, author: Author, responder: RpcResponder, ) -> anyhow::Result { @@ -142,63 +145,73 @@ impl NetworkHandler { match dag_message_result { Ok(dag_message) => { debug!( + epoch = epoch, author = author, message = dag_message, - "process verified message" + "Verified DAG message" ); match dag_message { - DAGMessage::NodeMsg(node) => self - .node_receiver - .process(node) - .await - .map(|r| r.into()) - .map_err(|err| { - err.downcast::() - .map_or(DAGError::Unknown, |err| { - DAGError::NodeBroadcastHandleError(err) - }) - }), + DAGMessage::NodeMsg(node) => monitor!( + "dag_on_node_msg", + self.node_receiver + .process(node) + .await + .map(|r| r.into()) + .map_err(|err| { + err.downcast::() + .map_or(DAGError::Unknown, |err| { + DAGError::NodeBroadcastHandleError(err) + }) + }) + ), DAGMessage::CertifiedNodeMsg(certified_node_msg) => { - match self.state_sync_trigger.check(certified_node_msg).await? { - SyncOutcome::Synced(Some(certified_node_msg)) => self - .dag_driver - .process(certified_node_msg.certified_node()) - .await - .map(|r| r.into()) - .map_err(|err| { - err.downcast::() - .map_or(DAGError::Unknown, |err| { - DAGError::DagDriverError(err) - }) - }), - status @ (SyncOutcome::NeedsSync(_) | SyncOutcome::EpochEnds) => { - return Ok(status) - }, - _ => unreachable!(), - } + monitor!("dag_on_cert_node_msg", { + match self.state_sync_trigger.check(certified_node_msg).await? { + SyncOutcome::Synced(Some(certified_node_msg)) => self + .dag_driver + .process(certified_node_msg.certified_node()) + .await + .map(|r| r.into()) + .map_err(|err| { + err.downcast::() + .map_or(DAGError::Unknown, |err| { + DAGError::DagDriverError(err) + }) + }), + status @ (SyncOutcome::NeedsSync(_) + | SyncOutcome::EpochEnds) => return Ok(status), + _ => unreachable!(), + } + }) }, - DAGMessage::FetchRequest(request) => self - .fetch_receiver - .process(request) - .await - .map(|r| r.into()) - .map_err(|err| { - err.downcast::() - .map_or(DAGError::Unknown, DAGError::FetchRequestHandleError) - }), + DAGMessage::FetchRequest(request) => monitor!( + "dag_on_fetch_request", + self.fetch_receiver + .process(request) + .await + .map(|r| r.into()) + .map_err(|err| { + err.downcast::().map_or( + DAGError::Unknown, + DAGError::FetchRequestHandleError, + ) + }) + ), _ => unreachable!("verification must catch this error"), } }, Err(err) => { - error!(error = ?err, "error verifying message"); + error!(error = ?err, "DAG message verification failed"); Err(DAGError::MessageVerificationError) }, } }; debug!( - "responding to process_rpc {:?}", - response.as_ref().map(|r| r.name()) + epoch = epoch, + sender = author, + response = response.as_ref().map(|r| r.name()), + "RPC response" ); let response: DAGRpcResult = response diff --git a/consensus/src/dag/dag_state_sync.rs b/consensus/src/dag/dag_state_sync.rs index ae27a952d9a2b..776cdf830dc14 100644 --- a/consensus/src/dag/dag_state_sync.rs +++ b/consensus/src/dag/dag_state_sync.rs @@ -3,7 +3,7 @@ use super::{ adapter::TLedgerInfoProvider, dag_fetcher::TDagFetcher, - dag_store::Dag, + dag_store::DagStore, storage::DAGStorage, types::{CertifiedNodeMessage, RemoteFetchRequest}, ProofNotifier, @@ -15,7 +15,6 @@ use crate::{ use anyhow::ensure; use aptos_channels::aptos_channel; use aptos_consensus_types::common::{Author, Round}; -use aptos_infallible::RwLock; use aptos_logger::{debug, error}; use aptos_time_service::TimeService; use aptos_types::{ @@ -45,7 +44,7 @@ impl fmt::Display for SyncOutcome { pub(super) struct StateSyncTrigger { epoch_state: Arc, ledger_info_provider: Arc, - dag_store: Arc>, + dag_store: Arc, proof_notifier: Arc, dag_window_size_config: Round, } @@ -54,7 +53,7 @@ impl StateSyncTrigger { pub(super) fn new( epoch_state: Arc, ledger_info_provider: Arc, - dag_store: Arc>, + dag_store: Arc, proof_notifier: Arc, dag_window_size_config: Round, ) -> Self { @@ -186,9 +185,9 @@ impl DagStateSynchronizer { pub(crate) fn build_request( &self, node: &CertifiedNodeMessage, - current_dag_store: Arc>, + current_dag_store: Arc, highest_committed_anchor_round: Round, - ) -> (RemoteFetchRequest, Vec, Arc>) { + ) -> (RemoteFetchRequest, Vec, Arc) { let commit_li = node.ledger_info(); { @@ -212,13 +211,13 @@ impl DagStateSynchronizer { .commit_info() .round() .saturating_sub(self.dag_window_size_config); - let sync_dag_store = Arc::new(RwLock::new(Dag::new_empty( + let sync_dag_store = Arc::new(DagStore::new_empty( self.epoch_state.clone(), self.storage.clone(), self.payload_manager.clone(), start_round, self.dag_window_size_config, - ))); + )); let bitmask = { sync_dag_store.read().bitmask(target_round) }; let request = RemoteFetchRequest::new( self.epoch_state.epoch, @@ -240,9 +239,9 @@ impl DagStateSynchronizer { dag_fetcher: impl TDagFetcher, request: RemoteFetchRequest, responders: Vec, - sync_dag_store: Arc>, + sync_dag_store: Arc, commit_li: LedgerInfoWithSignatures, - ) -> anyhow::Result { + ) -> anyhow::Result { match dag_fetcher .fetch(request, responders, sync_dag_store.clone()) .await @@ -256,7 +255,7 @@ impl DagStateSynchronizer { self.state_computer.sync_to(commit_li).await?; - Ok(Arc::into_inner(sync_dag_store).unwrap().into_inner()) + Ok(Arc::into_inner(sync_dag_store).unwrap()) } } diff --git a/consensus/src/dag/dag_store.rs b/consensus/src/dag/dag_store.rs index 9bd9708367f4c..7c9bf95d713d7 100644 --- a/consensus/src/dag/dag_store.rs +++ b/consensus/src/dag/dag_store.rs @@ -12,10 +12,12 @@ use crate::{ use anyhow::{anyhow, ensure}; use aptos_consensus_types::common::{Author, Round}; use aptos_crypto::HashValue; +use aptos_infallible::RwLock; use aptos_logger::{debug, error, warn}; use aptos_types::{epoch_state::EpochState, validator_verifier::ValidatorVerifier}; use std::{ collections::{BTreeMap, HashMap, HashSet}, + ops::Deref, sync::Arc, }; @@ -37,72 +39,25 @@ impl NodeStatus { *self = NodeStatus::Ordered(self.as_node().clone()); } } -/// Data structure that stores the DAG representation, it maintains round based index. +/// Data structure that stores the in-memory DAG representation, it maintains round based index. #[derive(Clone)] -pub struct Dag { +pub struct InMemDag { nodes_by_round: BTreeMap>>, /// Map between peer id to vector index author_to_index: HashMap, - storage: Arc, - payload_manager: Arc, start_round: Round, epoch_state: Arc, /// The window we maintain between highest committed round and initial round window_size: u64, } -impl Dag { - pub fn new( - epoch_state: Arc, - storage: Arc, - payload_manager: Arc, - start_round: Round, - window_size: u64, - ) -> Self { - let mut all_nodes = storage.get_certified_nodes().unwrap_or_default(); - all_nodes.sort_unstable_by_key(|(_, node)| node.round()); - let mut to_prune = vec![]; - // Reconstruct the continuous dag starting from start_round and gc unrelated nodes - let mut dag = Self::new_empty( - epoch_state, - storage.clone(), - payload_manager, - start_round, - window_size, - ); - for (digest, certified_node) in all_nodes { - // TODO: save the storage call in this case - if let Err(e) = dag.add_node(certified_node) { - debug!("Delete node after bootstrap due to {}", e); - to_prune.push(digest); - } - } - if let Err(e) = storage.delete_certified_nodes(to_prune) { - error!("Error deleting expired nodes: {:?}", e); - } - if dag.is_empty() { - warn!( - "[DAG] Start with empty DAG store at {}, need state sync", - dag.start_round - ); - } - dag - } - - pub fn new_empty( - epoch_state: Arc, - storage: Arc, - payload_manager: Arc, - start_round: Round, - window_size: u64, - ) -> Self { +impl InMemDag { + pub fn new_empty(epoch_state: Arc, start_round: Round, window_size: u64) -> Self { let author_to_index = epoch_state.verifier.address_to_validator_index().clone(); let nodes_by_round = BTreeMap::new(); Self { nodes_by_round, author_to_index, - storage, - payload_manager, start_round, epoch_state, window_size, @@ -110,19 +65,18 @@ impl Dag { } pub(crate) fn lowest_round(&self) -> Round { - *self - .nodes_by_round - .first_key_value() - .map(|(round, _)| round) - .unwrap_or(&self.start_round) + self.start_round } pub fn highest_round(&self) -> Round { + // If stale nodes exist on the BTreeMap, ignore their rounds when calculating + // the highest round. *self .nodes_by_round .last_key_value() .map(|(round, _)| round) .unwrap_or(&self.start_round) + .max(&self.start_round) } /// The highest strong links round is either the highest round or the highest round - 1 @@ -133,14 +87,37 @@ impl Dag { .map_or_else(|| highest_round.saturating_sub(1), |_| highest_round) } - pub fn add_node(&mut self, node: CertifiedNode) -> anyhow::Result<()> { + #[cfg(test)] + pub fn add_node_for_test(&mut self, node: CertifiedNode) -> anyhow::Result<()> { + self.validate_new_node(&node)?; + self.add_validated_node(node) + } + + fn add_validated_node(&mut self, node: CertifiedNode) -> anyhow::Result<()> { + let round = node.round(); + ensure!( + round >= self.lowest_round(), + "dag was pruned. given round: {}, lowest round: {}", + round, + self.lowest_round() + ); + + let node = Arc::new(node); + let round_ref = self + .get_node_ref_mut(node.round(), node.author()) + .expect("must be present"); + ensure!(round_ref.is_none(), "race during insertion"); + *round_ref = Some(NodeStatus::Unordered(node.clone())); + Ok(()) + } + + fn validate_new_node(&mut self, node: &CertifiedNode) -> anyhow::Result<()> { ensure!( node.epoch() == self.epoch_state.epoch, "different epoch {}, current {}", node.epoch(), self.epoch_state.epoch ); - let node = Arc::new(node); let author = node.metadata().author(); let index = *self .author_to_index @@ -169,13 +146,6 @@ impl Dag { .entry(round) .or_insert_with(|| vec![None; self.author_to_index.len()]); ensure!(round_ref[index].is_none(), "duplicate node"); - - // mutate after all checks pass - self.storage.save_certified_node(&node)?; - debug!("Added node {}", node.id()); - round_ref[index] = Some(NodeStatus::Unordered(node.clone())); - self.payload_manager - .prefetch_payload_data(node.payload(), node.metadata().timestamp()); Ok(()) } @@ -211,10 +181,14 @@ impl Dag { round_ref[*index].as_ref() } - pub fn get_node_ref_mut(&mut self, round: Round, author: &Author) -> Option<&mut NodeStatus> { + fn get_node_ref_mut( + &mut self, + round: Round, + author: &Author, + ) -> Option<&mut Option> { let index = self.author_to_index.get(author)?; let round_ref = self.nodes_by_round.get_mut(&round)?; - round_ref[*index].as_mut() + Some(&mut round_ref[*index]) } fn get_round_iter(&self, round: Round) -> Option> { @@ -367,7 +341,7 @@ impl Dag { DagSnapshotBitmask::new(lowest_round, bitmask) } - pub(super) fn prune(&mut self) { + pub(super) fn prune(&mut self) -> BTreeMap>> { let to_keep = self.nodes_by_round.split_off(&self.start_round); let to_prune = std::mem::replace(&mut self.nodes_by_round, to_keep); debug!( @@ -375,22 +349,19 @@ impl Dag { self.start_round, to_prune.first_key_value().map(|v| v.0).unwrap() ); - let digests = to_prune - .iter() - .flat_map(|(_, round_ref)| round_ref.iter().flatten()) - .map(|node_status| *node_status.as_node().metadata().digest()) - .collect(); - if let Err(e) = self.storage.delete_certified_nodes(digests) { - error!("Error deleting expired nodes: {:?}", e); - } + to_prune } - pub fn commit_callback(&mut self, commit_round: Round) { + fn commit_callback( + &mut self, + commit_round: Round, + ) -> Option>>> { let new_start_round = commit_round.saturating_sub(3 * self.window_size); if new_start_round > self.start_round { self.start_round = new_start_round; - self.prune(); + return Some(self.prune()); } + None } pub(super) fn highest_ordered_anchor_round(&self) -> Option { @@ -408,3 +379,114 @@ impl Dag { self.nodes_by_round.is_empty() && self.start_round > 1 } } + +pub struct DagStore { + dag: RwLock, + storage: Arc, + payload_manager: Arc, +} + +impl DagStore { + pub fn new( + epoch_state: Arc, + storage: Arc, + payload_manager: Arc, + start_round: Round, + window_size: u64, + ) -> Self { + let mut all_nodes = storage.get_certified_nodes().unwrap_or_default(); + all_nodes.sort_unstable_by_key(|(_, node)| node.round()); + let mut to_prune = vec![]; + // Reconstruct the continuous dag starting from start_round and gc unrelated nodes + let dag = Self::new_empty( + epoch_state, + storage.clone(), + payload_manager, + start_round, + window_size, + ); + for (digest, certified_node) in all_nodes { + // TODO: save the storage call in this case + if let Err(e) = dag.add_node(certified_node) { + debug!("Delete node after bootstrap due to {}", e); + to_prune.push(digest); + } + } + if let Err(e) = storage.delete_certified_nodes(to_prune) { + error!("Error deleting expired nodes: {:?}", e); + } + if dag.read().is_empty() { + warn!( + "[DAG] Start with empty DAG store at {}, need state sync", + start_round + ); + } + dag + } + + pub fn new_empty( + epoch_state: Arc, + storage: Arc, + payload_manager: Arc, + start_round: Round, + window_size: u64, + ) -> Self { + let dag = InMemDag::new_empty(epoch_state, start_round, window_size); + Self { + dag: RwLock::new(dag), + storage, + payload_manager, + } + } + + pub fn new_for_test( + dag: InMemDag, + storage: Arc, + payload_manager: Arc, + ) -> Self { + Self { + dag: RwLock::new(dag), + storage, + payload_manager, + } + } + + pub fn add_node(&self, node: CertifiedNode) -> anyhow::Result<()> { + self.dag.write().validate_new_node(&node)?; + + // Note on concurrency: it is possible that a prune operation kicks in here and + // moves the window forward making the `node` stale. Any stale node inserted + // due to this race will be cleaned up with the next prune operation. + + // mutate after all checks pass + self.storage.save_certified_node(&node)?; + + debug!("Added node {}", node.id()); + self.payload_manager + .prefetch_payload_data(node.payload(), node.metadata().timestamp()); + + self.dag.write().add_validated_node(node) + } + + pub fn commit_callback(&self, commit_round: Round) { + let to_prune = self.dag.write().commit_callback(commit_round); + if let Some(to_prune) = to_prune { + let digests = to_prune + .iter() + .flat_map(|(_, round_ref)| round_ref.iter().flatten()) + .map(|node_status| *node_status.as_node().metadata().digest()) + .collect(); + if let Err(e) = self.storage.delete_certified_nodes(digests) { + error!("Error deleting expired nodes: {:?}", e); + } + } + } +} + +impl Deref for DagStore { + type Target = RwLock; + + fn deref(&self) -> &Self::Target { + &self.dag + } +} diff --git a/consensus/src/dag/health/chain_health.rs b/consensus/src/dag/health/chain_health.rs index 9206d2ac1f17d..bcbe8a2d88f2f 100644 --- a/consensus/src/dag/health/chain_health.rs +++ b/consensus/src/dag/health/chain_health.rs @@ -68,6 +68,7 @@ impl ChainHealthBackoff { impl TChainHealth for ChainHealthBackoff { fn get_round_backoff(&self, round: Round) -> Option { let chain_health_backoff = self.get_chain_health_backoff(round); + if let Some(value) = chain_health_backoff { CHAIN_HEALTH_BACKOFF_TRIGGERED.observe(1.0); Some(Duration::from_millis(value.backoff_proposal_delay_ms)) @@ -79,6 +80,7 @@ impl TChainHealth for ChainHealthBackoff { fn get_round_payload_limits(&self, round: Round) -> Option<(u64, u64)> { let chain_health_backoff = self.get_chain_health_backoff(round); + chain_health_backoff.map(|value| { ( value.max_sending_block_txns_override, diff --git a/consensus/src/dag/order_rule.rs b/consensus/src/dag/order_rule.rs index bbc899ad2d059..cabafca461153 100644 --- a/consensus/src/dag/order_rule.rs +++ b/consensus/src/dag/order_rule.rs @@ -1,10 +1,11 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 +use super::dag_store::DagStore; use crate::dag::{ adapter::OrderedNotifier, anchor_election::AnchorElection, - dag_store::{Dag, NodeStatus}, + dag_store::NodeStatus, observability::{ logging::{LogEvent, LogSchema}, tracing::{observe_node, NodeStage}, @@ -24,7 +25,7 @@ pub struct OrderRule { epoch_state: Arc, // TODO: try to share order rule, instead of this Arc. lowest_unordered_anchor_round: Arc>, - dag: Arc>, + dag: Arc, anchor_election: Arc, notifier: Arc, dag_window_size_config: Round, @@ -34,7 +35,7 @@ impl OrderRule { pub fn new( epoch_state: Arc, lowest_unordered_anchor_round: Round, - dag: Arc>, + dag: Arc, anchor_election: Arc, notifier: Arc, dag_window_size_config: Round, diff --git a/consensus/src/dag/rb_handler.rs b/consensus/src/dag/rb_handler.rs index df80b810249b5..bb814b6671f49 100644 --- a/consensus/src/dag/rb_handler.rs +++ b/consensus/src/dag/rb_handler.rs @@ -1,12 +1,11 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::health::HealthBackoff; +use super::{dag_store::DagStore, health::HealthBackoff}; use crate::{ dag::{ dag_fetcher::TFetchRequester, dag_network::RpcHandler, - dag_store::Dag, errors::NodeBroadcastHandleError, observability::{ logging::{LogEvent, LogSchema}, @@ -21,7 +20,6 @@ use crate::{ use anyhow::{bail, ensure}; use aptos_config::config::DagPayloadConfig; use aptos_consensus_types::common::{Author, Round}; -use aptos_infallible::RwLock; use aptos_logger::{debug, error}; use aptos_types::{ epoch_state::EpochState, @@ -33,7 +31,7 @@ use async_trait::async_trait; use std::{collections::BTreeMap, mem, sync::Arc}; pub(crate) struct NodeBroadcastHandler { - dag: Arc>, + dag: Arc, votes_by_round_peer: BTreeMap>, signer: Arc, epoch_state: Arc, @@ -47,7 +45,7 @@ pub(crate) struct NodeBroadcastHandler { impl NodeBroadcastHandler { pub fn new( - dag: Arc>, + dag: Arc, signer: Arc, epoch_state: Arc, storage: Arc, diff --git a/consensus/src/dag/tests/dag_driver_tests.rs b/consensus/src/dag/tests/dag_driver_tests.rs index 7be1231c1bc2d..0186b722eb488 100644 --- a/consensus/src/dag/tests/dag_driver_tests.rs +++ b/consensus/src/dag/tests/dag_driver_tests.rs @@ -7,7 +7,7 @@ use crate::{ dag_driver::DagDriver, dag_fetcher::TFetchRequester, dag_network::{RpcWithFallback, TDAGNetworkSender}, - dag_store::Dag, + dag_store::DagStore, errors::DagDriverError, health::{HealthBackoff, NoChainHealth, NoPipelineBackpressure}, order_rule::OrderRule, @@ -25,7 +25,6 @@ use crate::{ use aptos_bounded_executor::BoundedExecutor; use aptos_config::config::DagPayloadConfig; use aptos_consensus_types::common::{Author, Round}; -use aptos_infallible::RwLock; use aptos_reliable_broadcast::{RBNetworkSender, ReliableBroadcast}; use aptos_time_service::TimeService; use aptos_types::{ @@ -122,13 +121,13 @@ fn setup( let mock_ledger_info = LedgerInfo::mock_genesis(None); let mock_ledger_info = generate_ledger_info_with_sig(signers, mock_ledger_info); let storage = Arc::new(MockStorage::new_with_ledger_info(mock_ledger_info.clone())); - let dag = Arc::new(RwLock::new(Dag::new( + let dag = Arc::new(DagStore::new( epoch_state.clone(), storage.clone(), Arc::new(MockPayloadManager {}), 0, TEST_DAG_WINDOW, - ))); + )); let rb = Arc::new(ReliableBroadcast::new( signers.iter().map(|s| s.author()).collect(), diff --git a/consensus/src/dag/tests/dag_state_sync_tests.rs b/consensus/src/dag/tests/dag_state_sync_tests.rs index fbacd6b39eb93..12be85039f724 100644 --- a/consensus/src/dag/tests/dag_state_sync_tests.rs +++ b/consensus/src/dag/tests/dag_state_sync_tests.rs @@ -6,7 +6,7 @@ use crate::{ adapter::OrderedNotifier, dag_fetcher::{FetchRequestHandler, TDagFetcher}, dag_state_sync::DagStateSynchronizer, - dag_store::Dag, + dag_store::DagStore, storage::DAGStorage, tests::{ dag_test::MockStorage, @@ -19,7 +19,6 @@ use crate::{ }; use aptos_consensus_types::common::{Author, Round}; use aptos_crypto::HashValue; -use aptos_infallible::RwLock; use aptos_reliable_broadcast::RBNetworkSender; use aptos_time_service::TimeService; use aptos_types::{ @@ -74,7 +73,7 @@ impl TDAGNetworkSender for MockDAGNetworkSender { } struct MockDagFetcher { - target_dag: Arc>, + target_dag: Arc, epoch_state: Arc, } @@ -84,17 +83,15 @@ impl TDagFetcher for MockDagFetcher { &self, remote_request: RemoteFetchRequest, _responders: Vec, - new_dag: Arc>, + new_dag: Arc, ) -> anyhow::Result<()> { let response = FetchRequestHandler::new(self.target_dag.clone(), self.epoch_state.clone()) .process(remote_request) .await .unwrap(); - let mut new_dag_writer = new_dag.write(); - for node in response.certified_nodes().into_iter().rev() { - new_dag_writer.add_node(node).unwrap() + new_dag.write().add_node_for_test(node).unwrap() } Ok(()) @@ -152,33 +149,31 @@ async fn test_dag_state_sync() { .collect::>(); let nodes = generate_dag_nodes(&virtual_dag, &validators); - let mut fast_dag = Dag::new( + let fast_dag = Arc::new(DagStore::new( epoch_state.clone(), Arc::new(MockStorage::new()), Arc::new(MockPayloadManager {}), 1, 0, - ); + )); for round_nodes in &nodes { for node in round_nodes.iter().flatten() { - fast_dag.add_node(node.clone()).unwrap(); + fast_dag.write().add_node_for_test(node.clone()).unwrap(); } } - let fast_dag = Arc::new(RwLock::new(fast_dag)); - let mut slow_dag = Dag::new( + let slow_dag = Arc::new(DagStore::new( epoch_state.clone(), Arc::new(MockStorage::new()), Arc::new(MockPayloadManager {}), 1, 0, - ); + )); for round_nodes in nodes.iter().take(SLOW_DAG_ROUNDS as usize) { for node in round_nodes.iter().flatten() { - slow_dag.add_node(node.clone()).unwrap(); + slow_dag.write().add_node_for_test(node.clone()).unwrap(); } } - let slow_dag = Arc::new(RwLock::new(slow_dag)); let li_node = nodes[LI_ROUNDS as usize - 1] .first() @@ -229,9 +224,9 @@ async fn test_dag_state_sync() { let new_dag = sync_result.unwrap(); assert_eq!( - new_dag.lowest_round(), + new_dag.read().lowest_round(), (LI_ROUNDS - TEST_DAG_WINDOW) as Round ); - assert_eq!(new_dag.highest_round(), NUM_ROUNDS as Round); - assert_none!(new_dag.highest_ordered_anchor_round(),); + assert_eq!(new_dag.read().highest_round(), NUM_ROUNDS as Round); + assert_none!(new_dag.read().highest_ordered_anchor_round(),); } diff --git a/consensus/src/dag/tests/dag_test.rs b/consensus/src/dag/tests/dag_test.rs index 7eb30e77a77dc..579b3ebdfad03 100644 --- a/consensus/src/dag/tests/dag_test.rs +++ b/consensus/src/dag/tests/dag_test.rs @@ -3,7 +3,7 @@ use super::helpers::MockPayloadManager; use crate::dag::{ - dag_store::Dag, + dag_store::DagStore, storage::{CommitEvent, DAGStorage}, tests::helpers::{new_certified_node, TEST_DAG_WINDOW}, types::{CertifiedNode, DagSnapshotBitmask, Node}, @@ -109,7 +109,12 @@ impl DAGStorage for MockStorage { } } -fn setup() -> (Vec, Arc, Dag, Arc) { +fn setup() -> ( + Vec, + Arc, + DagStore, + Arc, +) { let (signers, validator_verifier) = random_validator_verifier(4, None, false); let epoch_state = Arc::new(EpochState { epoch: 1, @@ -117,7 +122,7 @@ fn setup() -> (Vec, Arc, Dag, Arc) { }); let storage = Arc::new(MockStorage::new()); let payload_manager = Arc::new(MockPayloadManager {}); - let dag = Dag::new( + let dag = DagStore::new( epoch_state.clone(), storage.clone(), payload_manager, @@ -129,80 +134,85 @@ fn setup() -> (Vec, Arc, Dag, Arc) { #[test] fn test_dag_insertion_succeed() { - let (signers, epoch_state, mut dag, _) = setup(); + let (signers, epoch_state, dag, _) = setup(); // Round 1 - nodes 0, 1, 2 links to vec![] for signer in &signers[0..3] { let node = new_certified_node(1, signer.author(), vec![]); - assert!(dag.add_node(node).is_ok()); + assert!(dag.write().add_node_for_test(node).is_ok()); } let parents = dag + .read() .get_strong_links_for_round(1, &epoch_state.verifier) .unwrap(); // Round 2 nodes 0, 1, 2 links to 0, 1, 2 for signer in &signers[0..3] { let node = new_certified_node(2, signer.author(), parents.clone()); - assert!(dag.add_node(node).is_ok()); + assert!(dag.write().add_node_for_test(node).is_ok()); } // Round 3 nodes 1, 2 links to 0, 1, 2 let parents = dag + .read() .get_strong_links_for_round(2, &epoch_state.verifier) .unwrap(); for signer in &signers[1..3] { let node = new_certified_node(3, signer.author(), parents.clone()); - assert!(dag.add_node(node).is_ok()); + assert!(dag.write().add_node_for_test(node).is_ok()); } // not enough strong links assert!(dag + .read() .get_strong_links_for_round(3, &epoch_state.verifier) .is_none()); } #[test] fn test_dag_insertion_failure() { - let (signers, epoch_state, mut dag, _) = setup(); + let (signers, epoch_state, dag, _) = setup(); // Round 1 - nodes 0, 1, 2 links to vec![] for signer in &signers[0..3] { let node = new_certified_node(1, signer.author(), vec![]); - assert!(dag.add_node(node.clone()).is_ok()); + assert!(dag.write().add_node_for_test(node.clone()).is_ok()); // duplicate node - assert!(dag.add_node(node).is_err()); + assert!(dag.write().add_node_for_test(node).is_err()); } let missing_node = new_certified_node(1, signers[3].author(), vec![]); let mut parents = dag + .read() .get_strong_links_for_round(1, &epoch_state.verifier) .unwrap(); parents.push(missing_node.certificate()); let node = new_certified_node(2, signers[0].author(), parents.clone()); // parents not exist - assert!(dag.add_node(node).is_err()); + assert!(dag.write().add_node_for_test(node).is_err()); let node = new_certified_node(3, signers[0].author(), vec![]); // round too high - assert!(dag.add_node(node).is_err()); + assert!(dag.write().add_node_for_test(node).is_err()); let node = new_certified_node(2, signers[0].author(), parents[0..3].to_vec()); - assert!(dag.add_node(node).is_ok()); + assert!(dag.write().add_node_for_test(node).is_ok()); let node = new_certified_node(2, signers[0].author(), vec![]); // equivocation node - assert!(dag.add_node(node).is_err()); + assert!(dag.write().add_node_for_test(node).is_err()); } #[test] fn test_dag_recover_from_storage() { - let (signers, epoch_state, mut dag, storage) = setup(); + let (signers, epoch_state, dag, storage) = setup(); let mut metadatas = vec![]; for round in 1..10 { let parents = dag + .read() .get_strong_links_for_round(round, &epoch_state.verifier) .unwrap_or_default(); for signer in &signers[0..3] { @@ -211,7 +221,7 @@ fn test_dag_recover_from_storage() { assert!(dag.add_node(node).is_ok()); } } - let new_dag = Dag::new( + let new_dag = DagStore::new( epoch_state.clone(), storage.clone(), Arc::new(MockPayloadManager {}), @@ -220,7 +230,7 @@ fn test_dag_recover_from_storage() { ); for metadata in &metadatas { - assert!(new_dag.exists(metadata)); + assert!(new_dag.read().exists(metadata)); } let new_epoch_state = Arc::new(EpochState { @@ -228,7 +238,7 @@ fn test_dag_recover_from_storage() { verifier: epoch_state.verifier.clone(), }); - let _new_epoch_dag = Dag::new( + let _new_epoch_dag = DagStore::new( new_epoch_state, storage.clone(), Arc::new(MockPayloadManager {}), @@ -240,40 +250,42 @@ fn test_dag_recover_from_storage() { #[test] fn test_dag_bitmask() { - let (signers, epoch_state, mut dag, _) = setup(); + let (signers, epoch_state, dag, _) = setup(); assert_eq!( - dag.bitmask(15), + dag.read().bitmask(15), DagSnapshotBitmask::new(1, vec![vec![false; 4]; 15]) ); for round in 1..5 { let parents = dag + .read() .get_strong_links_for_round(round, &epoch_state.verifier) .unwrap_or_default(); for signer in &signers[0..3] { let node = new_certified_node(round, signer.author(), parents.clone()); - assert!(dag.add_node(node).is_ok()); + assert!(dag.write().add_node_for_test(node).is_ok()); } } let mut bitmask = vec![vec![true, true, true, false]; 4]; bitmask.resize(15, vec![false; 4]); - assert_eq!(dag.bitmask(15), DagSnapshotBitmask::new(1, bitmask)); + assert_eq!(dag.read().bitmask(15), DagSnapshotBitmask::new(1, bitmask)); // Populate the fourth author for all rounds for round in 1..5 { let parents = dag + .read() .get_strong_links_for_round(round, &epoch_state.verifier) .unwrap_or_default(); let node = new_certified_node(round, signers[3].author(), parents.clone()); - assert!(dag.add_node(node).is_ok()); + assert!(dag.write().add_node_for_test(node).is_ok()); } assert_eq!( - dag.bitmask(15), + dag.read().bitmask(15), DagSnapshotBitmask::new(5, vec![vec![false; 4]; 11]) ); assert_eq!( - dag.bitmask(6), + dag.read().bitmask(6), DagSnapshotBitmask::new(5, vec![vec![false; 4]; 2]) ); } diff --git a/consensus/src/dag/tests/fetcher_test.rs b/consensus/src/dag/tests/fetcher_test.rs index c5c18941f72a6..5067e7088ed81 100644 --- a/consensus/src/dag/tests/fetcher_test.rs +++ b/consensus/src/dag/tests/fetcher_test.rs @@ -3,12 +3,11 @@ use super::dag_test::MockStorage; use crate::dag::{ dag_fetcher::FetchRequestHandler, - dag_store::Dag, + dag_store::DagStore, tests::helpers::{new_certified_node, MockPayloadManager, TEST_DAG_WINDOW}, types::{DagSnapshotBitmask, FetchResponse, RemoteFetchRequest}, RpcHandler, }; -use aptos_infallible::RwLock; use aptos_types::{epoch_state::EpochState, validator_verifier::random_validator_verifier}; use claims::assert_ok_eq; use std::sync::Arc; @@ -21,13 +20,13 @@ async fn test_dag_fetcher_receiver() { verifier: validator_verifier, }); let storage = Arc::new(MockStorage::new()); - let dag = Arc::new(RwLock::new(Dag::new( + let dag = Arc::new(DagStore::new( epoch_state.clone(), storage, Arc::new(MockPayloadManager {}), 0, TEST_DAG_WINDOW, - ))); + )); let mut fetcher = FetchRequestHandler::new(dag.clone(), epoch_state); @@ -36,7 +35,7 @@ async fn test_dag_fetcher_receiver() { // Round 1 - nodes 0, 1, 2 links to vec![] for signer in &signers[0..3] { let node = new_certified_node(1, signer.author(), vec![]); - assert!(dag.write().add_node(node.clone()).is_ok()); + assert!(dag.add_node(node.clone()).is_ok()); first_round_nodes.push(node); } diff --git a/consensus/src/dag/tests/order_rule_tests.rs b/consensus/src/dag/tests/order_rule_tests.rs index 857ac8fd5fc3f..9c482f484a8ab 100644 --- a/consensus/src/dag/tests/order_rule_tests.rs +++ b/consensus/src/dag/tests/order_rule_tests.rs @@ -4,7 +4,7 @@ use crate::dag::{ adapter::OrderedNotifier, anchor_election::RoundRobinAnchorElection, - dag_store::Dag, + dag_store::{DagStore, InMemDag}, order_rule::OrderRule, tests::{ dag_test::MockStorage, @@ -14,7 +14,7 @@ use crate::dag::{ CertifiedNode, }; use aptos_consensus_types::common::{Author, Round}; -use aptos_infallible::{Mutex, RwLock}; +use aptos_infallible::Mutex; use aptos_types::{epoch_state::EpochState, validator_verifier::random_validator_verifier}; use async_trait::async_trait; use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}; @@ -93,7 +93,7 @@ impl OrderedNotifier for TestNotifier { fn create_order_rule( epoch_state: Arc, - dag: Arc>, + dag: Arc, ) -> (OrderRule, UnboundedReceiver>>) { let anchor_election = Arc::new(RoundRobinAnchorElection::new( epoch_state.verifier.get_ordered_account_addresses(), @@ -134,10 +134,10 @@ proptest! { epoch: 1, verifier: validator_verifier, }); - let mut dag = Dag::new(epoch_state.clone(), Arc::new(MockStorage::new()), Arc::new(MockPayloadManager{}), 0, TEST_DAG_WINDOW); + let mut dag = InMemDag::new_empty(epoch_state.clone(), 0, TEST_DAG_WINDOW); for round_nodes in &nodes { for node in round_nodes.iter().flatten() { - dag.add_node(node.clone()).unwrap(); + dag.add_node_for_test(node.clone()).unwrap(); } } let flatten_nodes: Vec<_> = nodes.into_iter().flatten().flatten().collect(); @@ -145,7 +145,7 @@ proptest! { rayon::scope(|s| { for seq in sequences { s.spawn(|_| { - let dag = Arc::new(RwLock::new(dag.clone())); + let dag = Arc::new(DagStore::new_for_test(dag.clone(),Arc::new(MockStorage::new()), Arc::new(MockPayloadManager {}))); let (mut order_rule, mut receiver) = create_order_rule(epoch_state.clone(), dag); for idx in seq { order_rule.process_new_node(flatten_nodes[idx].metadata()); @@ -159,7 +159,7 @@ proptest! { } }); // order produced by process_all - let dag = Arc::new(RwLock::new(dag.clone())); + let dag = Arc::new(DagStore::new_for_test(dag.clone(),Arc::new(MockStorage::new()), Arc::new(MockPayloadManager {}))); let (mut order_rule, mut receiver) = create_order_rule(epoch_state.clone(), dag); order_rule.process_all(); let mut ordered = vec![]; @@ -221,20 +221,18 @@ fn test_order_rule_basic() { epoch: 1, verifier: validator_verifier, }); - let mut dag = Dag::new( - epoch_state.clone(), - Arc::new(MockStorage::new()), - Arc::new(MockPayloadManager {}), - 0, - TEST_DAG_WINDOW, - ); + let mut dag = InMemDag::new_empty(epoch_state.clone(), 0, TEST_DAG_WINDOW); for round_nodes in &nodes { for node in round_nodes.iter().flatten() { - dag.add_node(node.clone()).unwrap(); + dag.add_node_for_test(node.clone()).unwrap(); } } let display = |node: &NodeMetadata| (node.round(), *author_indexes.get(node.author()).unwrap()); - let dag = Arc::new(RwLock::new(dag.clone())); + let dag = Arc::new(DagStore::new_for_test( + dag.clone(), + Arc::new(MockStorage::new()), + Arc::new(MockPayloadManager {}), + )); let (mut order_rule, mut receiver) = create_order_rule(epoch_state, dag); for node in nodes.iter().flatten().flatten() { order_rule.process_new_node(node.metadata()); diff --git a/consensus/src/dag/tests/rb_handler_tests.rs b/consensus/src/dag/tests/rb_handler_tests.rs index ac510a3fc5685..a9f49270dd35d 100644 --- a/consensus/src/dag/tests/rb_handler_tests.rs +++ b/consensus/src/dag/tests/rb_handler_tests.rs @@ -3,7 +3,7 @@ use crate::dag::{ dag_fetcher::TFetchRequester, - dag_store::Dag, + dag_store::DagStore, errors::NodeBroadcastHandleError, health::{HealthBackoff, NoChainHealth, NoPipelineBackpressure}, rb_handler::NodeBroadcastHandler, @@ -16,7 +16,6 @@ use crate::dag::{ NodeId, RpcHandler, Vote, }; use aptos_config::config::DagPayloadConfig; -use aptos_infallible::RwLock; use aptos_types::{ aggregate_signature::PartialSignatures, epoch_state::EpochState, @@ -50,13 +49,13 @@ async fn test_node_broadcast_receiver_succeed() { // Scenario: Start DAG from beginning let storage = Arc::new(MockStorage::new()); - let dag = Arc::new(RwLock::new(Dag::new( + let dag = Arc::new(DagStore::new( epoch_state.clone(), storage.clone(), Arc::new(MockPayloadManager {}), 0, TEST_DAG_WINDOW, - ))); + )); let health_backoff = HealthBackoff::new( epoch_state.clone(), @@ -109,13 +108,13 @@ async fn test_node_broadcast_receiver_failure() { .iter() .map(|signer| { let storage = Arc::new(MockStorage::new()); - let dag = Arc::new(RwLock::new(Dag::new( + let dag = Arc::new(DagStore::new( epoch_state.clone(), storage.clone(), Arc::new(MockPayloadManager {}), 0, TEST_DAG_WINDOW, - ))); + )); NodeBroadcastHandler::new( dag, @@ -196,13 +195,13 @@ async fn test_node_broadcast_receiver_storage() { }); let storage = Arc::new(MockStorage::new()); - let dag = Arc::new(RwLock::new(Dag::new( + let dag = Arc::new(DagStore::new( epoch_state.clone(), storage.clone(), Arc::new(MockPayloadManager {}), 0, TEST_DAG_WINDOW, - ))); + )); let node = new_node(1, 10, signers[0].author(), vec![]); From b1fad9b5f8261644f83e3269feb3fe597cfb5b1d Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Thu, 8 Feb 2024 18:23:41 -0800 Subject: [PATCH 046/328] [dag] parallel message handler implementation (#11685) * [dag] concurrent network handler * [dag] make RoundState interior mutable * [dag] undo FetchWaiter FusedStream impl --- config/src/config/dag_consensus_config.rs | 2 - consensus/src/dag/bootstrap.rs | 3 +- consensus/src/dag/dag_driver.rs | 51 +++--- consensus/src/dag/dag_fetcher.rs | 2 +- consensus/src/dag/dag_handler.rs | 167 ++++++++++++------ consensus/src/dag/dag_network.rs | 2 +- consensus/src/dag/order_rule.rs | 8 +- consensus/src/dag/rb_handler.rs | 22 ++- consensus/src/dag/round_state.rs | 115 ++++++------ consensus/src/dag/tests/dag_driver_tests.rs | 6 +- consensus/src/dag/tests/fetcher_test.rs | 2 +- consensus/src/dag/tests/integration_tests.rs | 12 +- consensus/src/dag/tests/order_rule_tests.rs | 5 +- consensus/src/dag/tests/rb_handler_tests.rs | 6 +- .../src/test_utils/mock_payload_manager.rs | 2 +- 15 files changed, 249 insertions(+), 156 deletions(-) diff --git a/config/src/config/dag_consensus_config.rs b/config/src/config/dag_consensus_config.rs index 2011f0697ed7b..ce0a3b5818be1 100644 --- a/config/src/config/dag_consensus_config.rs +++ b/config/src/config/dag_consensus_config.rs @@ -122,14 +122,12 @@ impl Default for ReliableBroadcastConfig { #[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] #[serde(default, deny_unknown_fields)] pub struct DagRoundStateConfig { - pub round_event_channel_size: usize, pub adaptive_responsive_minimum_wait_time_ms: u64, } impl Default for DagRoundStateConfig { fn default() -> Self { Self { - round_event_channel_size: 1024, adaptive_responsive_minimum_wait_time_ms: 500, } } diff --git a/consensus/src/dag/bootstrap.rs b/consensus/src/dag/bootstrap.rs index 04a01a6cb141b..53bfaf7bcc137 100644 --- a/consensus/src/dag/bootstrap.rs +++ b/consensus/src/dag/bootstrap.rs @@ -581,8 +581,7 @@ impl DagBootstrapper { self.config.fetcher_config.clone(), ); let fetch_requester = Arc::new(fetch_requester); - let (new_round_tx, new_round_rx) = - tokio::sync::mpsc::channel(round_state_config.round_event_channel_size); + let (new_round_tx, new_round_rx) = tokio::sync::mpsc::unbounded_channel(); let round_state = RoundState::new( new_round_tx.clone(), Box::new(AdaptiveResponsive::new( diff --git a/consensus/src/dag/dag_driver.rs b/consensus/src/dag/dag_driver.rs index 8af13c5bd8c77..ff7487915702f 100644 --- a/consensus/src/dag/dag_driver.rs +++ b/consensus/src/dag/dag_driver.rs @@ -27,6 +27,7 @@ use anyhow::{bail, ensure}; use aptos_config::config::DagPayloadConfig; use aptos_consensus_types::common::{Author, Payload, PayloadFilter}; use aptos_crypto::hash::CryptoHash; +use aptos_infallible::Mutex; use aptos_logger::{debug, error}; use aptos_reliable_broadcast::ReliableBroadcast; use aptos_time_service::{TimeService, TimeServiceTrait}; @@ -48,9 +49,9 @@ pub(crate) struct DagDriver { payload_client: Arc, reliable_broadcast: Arc>, time_service: TimeService, - rb_abort_handle: Option<(AbortHandle, u64)>, + rb_abort_handle: Mutex>, storage: Arc, - order_rule: OrderRule, + order_rule: Mutex, fetch_requester: Arc, ledger_info_provider: Arc, round_state: RoundState, @@ -85,16 +86,16 @@ impl DagDriver { let highest_strong_links_round = dag.read().highest_strong_links_round(&epoch_state.verifier); - let mut driver = Self { + let driver = Self { author, epoch_state, dag, payload_client, reliable_broadcast, time_service, - rb_abort_handle: None, + rb_abort_handle: Mutex::new(None), storage, - order_rule, + order_rule: Mutex::new(order_rule), fetch_requester, ledger_info_provider, round_state, @@ -112,7 +113,10 @@ impl DagDriver { LogSchema::new(LogEvent::NewRound).round(node.round()), "Resume round" ); - driver.round_state.set_current_round(node.round()); + driver + .round_state + .set_current_round(node.round()) + .expect("must succeed"); driver.broadcast_node(node); } else { // kick start a new round @@ -123,7 +127,7 @@ impl DagDriver { driver } - async fn add_node(&mut self, node: CertifiedNode) -> anyhow::Result<()> { + fn add_node(&self, node: CertifiedNode) -> anyhow::Result<()> { let (highest_strong_link_round, strong_links) = { { let dag_reader = self.dag.read(); @@ -165,19 +169,22 @@ impl DagDriver { let minimum_delay = self .health_backoff .backoff_duration(highest_strong_link_round + 1); - self.round_state - .check_for_new_round(highest_strong_link_round, strong_links, minimum_delay) - .await; + self.round_state.check_for_new_round( + highest_strong_link_round, + strong_links, + minimum_delay, + ); Ok(()) } - pub async fn enter_new_round(&mut self, new_round: Round) { - if self.round_state.current_round() >= new_round { + pub async fn enter_new_round(&self, new_round: Round) { + if let Err(e) = self.round_state.set_current_round(new_round) { + debug!(error=?e, "cannot enter round"); return; } debug!(LogSchema::new(LogEvent::NewRound).round(new_round)); - self.round_state.set_current_round(new_round); counters::CURRENT_ROUND.set(new_round as i64); + let strong_links = self .dag .read() @@ -272,7 +279,7 @@ impl DagDriver { self.broadcast_node(new_node); } - fn broadcast_node(&mut self, node: Node) { + fn broadcast_node(&self, node: Node) { let rb = self.reliable_broadcast.clone(); let rb2 = self.reliable_broadcast.clone(); let (abort_handle, abort_registration) = AbortHandle::new_pair(); @@ -305,14 +312,17 @@ impl DagDriver { ); rb2.broadcast(certified_node_msg, cert_ack_set) }); + let author = self.author; let task = async move { - debug!("Start reliable broadcast for round {}", round); + debug!("{} Start reliable broadcast for round {}", author, round); core_task.await; debug!("Finish reliable broadcast for round {}", round); }; tokio::spawn(Abortable::new(task, abort_registration)); - if let Some((prev_handle, prev_round_timestamp)) = - self.rb_abort_handle.replace((abort_handle, timestamp)) + if let Some((prev_handle, prev_round_timestamp)) = self + .rb_abort_handle + .lock() + .replace((abort_handle, timestamp)) { observe_round(prev_round_timestamp, RoundStage::Finished); prev_handle.abort(); @@ -325,7 +335,7 @@ impl RpcHandler for DagDriver { type Request = CertifiedNode; type Response = CertifiedAck; - async fn process(&mut self, certified_node: Self::Request) -> anyhow::Result { + async fn process(&self, certified_node: Self::Request) -> anyhow::Result { let epoch = certified_node.metadata().epoch(); debug!(LogSchema::new(LogEvent::ReceiveCertifiedNode) .remote_peer(*certified_node.author()) @@ -340,8 +350,7 @@ impl RpcHandler for DagDriver { let node_metadata = certified_node.metadata().clone(); self.add_node(certified_node) - .await - .map(|_| self.order_rule.process_new_node(&node_metadata))?; + .map(|_| self.order_rule.lock().process_new_node(&node_metadata))?; Ok(CertifiedAck::new(epoch)) } @@ -349,7 +358,7 @@ impl RpcHandler for DagDriver { impl Drop for DagDriver { fn drop(&mut self) { - if let Some((handle, _)) = &self.rb_abort_handle { + if let Some((handle, _)) = self.rb_abort_handle.lock().as_ref() { handle.abort() } } diff --git a/consensus/src/dag/dag_fetcher.rs b/consensus/src/dag/dag_fetcher.rs index 1f61ac5d495c6..c3b013e894863 100644 --- a/consensus/src/dag/dag_fetcher.rs +++ b/consensus/src/dag/dag_fetcher.rs @@ -334,7 +334,7 @@ impl RpcHandler for FetchRequestHandler { type Request = RemoteFetchRequest; type Response = FetchResponse; - async fn process(&mut self, message: Self::Request) -> anyhow::Result { + async fn process(&self, message: Self::Request) -> anyhow::Result { let dag_reader = self.dag.read(); // `Certified Node`: In the good case, there should exist at least one honest validator that diff --git a/consensus/src/dag/dag_handler.rs b/consensus/src/dag/dag_handler.rs index b366cd2bd0118..681d262406f62 100644 --- a/consensus/src/dag/dag_handler.rs +++ b/consensus/src/dag/dag_handler.rs @@ -22,19 +22,18 @@ use aptos_channels::aptos_channel; use aptos_consensus_types::common::{Author, Round}; use aptos_logger::{debug, error, warn}; use aptos_types::epoch_state::EpochState; -use futures::StreamExt; +use futures::{stream::FuturesUnordered, StreamExt}; use std::sync::Arc; -use tokio::select; +use tokio::{runtime::Handle, select}; pub(crate) struct NetworkHandler { epoch_state: Arc, - node_receiver: NodeBroadcastHandler, - dag_driver: DagDriver, - fetch_receiver: FetchRequestHandler, + node_receiver: Arc, + dag_driver: Arc, node_fetch_waiter: FetchWaiter, certified_node_fetch_waiter: FetchWaiter, - state_sync_trigger: StateSyncTrigger, - new_round_event: tokio::sync::mpsc::Receiver, + new_round_event: tokio::sync::mpsc::UnboundedReceiver, + verified_msg_processor: Arc, } impl NetworkHandler { @@ -46,32 +45,49 @@ impl NetworkHandler { node_fetch_waiter: FetchWaiter, certified_node_fetch_waiter: FetchWaiter, state_sync_trigger: StateSyncTrigger, - new_round_event: tokio::sync::mpsc::Receiver, + new_round_event: tokio::sync::mpsc::UnboundedReceiver, ) -> Self { + let node_receiver = Arc::new(node_receiver); + let dag_driver = Arc::new(dag_driver); Self { - epoch_state, - node_receiver, - dag_driver, - fetch_receiver, + epoch_state: epoch_state.clone(), + node_receiver: node_receiver.clone(), + dag_driver: dag_driver.clone(), node_fetch_waiter, certified_node_fetch_waiter, - state_sync_trigger, new_round_event, + verified_msg_processor: Arc::new(VerifiedMessageProcessor { + node_receiver, + dag_driver, + fetch_receiver, + state_sync_trigger, + epoch_state, + }), } } pub async fn run( - mut self, + self, dag_rpc_rx: &mut aptos_channel::Receiver, executor: BoundedExecutor, _buffer: Vec, ) -> SyncOutcome { // TODO: process buffer - let epoch_state = self.epoch_state.clone(); + let NetworkHandler { + epoch_state, + node_receiver, + dag_driver, + mut node_fetch_waiter, + mut certified_node_fetch_waiter, + mut new_round_event, + verified_msg_processor, + .. + } = self; + // TODO: feed in the executor based on verification Runtime let mut verified_msg_stream = concurrent_map( dag_rpc_rx, - executor, + executor.clone(), move |rpc_request: IncomingDAGRequest| { let epoch_state = epoch_state.clone(); async move { @@ -91,51 +107,98 @@ impl NetworkHandler { }, ); + let dag_driver_clone = dag_driver.clone(); + let node_receiver_clone = node_receiver.clone(); + let handle = tokio::spawn(async move { + while let Some(new_round) = new_round_event.recv().await { + monitor!("dag_on_new_round_event", { + dag_driver_clone.enter_new_round(new_round).await; + node_receiver_clone.gc(); + }); + } + }); + defer!(handle.abort()); + + let mut futures = FuturesUnordered::new(); + // A separate executor to ensure the message verification sender (above) and receiver (below) are + // not blocking each other. + // TODO: make this configurable + let executor = BoundedExecutor::new(8, Handle::current()); loop { select! { - (msg, epoch, author, responder) = verified_msg_stream.select_next_some() => { - monitor!("dag_on_verified_msg", match self.process_verified_message(msg, epoch, author, responder).await { - Ok(sync_status) => { - if matches!(sync_status, SyncOutcome::NeedsSync(_) | SyncOutcome::EpochEnds) { - return sync_status; - } - }, - Err(e) => { - warn!(error = ?e, "error processing rpc"); - } - }); + Some((msg, epoch, author, responder)) = verified_msg_stream.next() => { + let verified_msg_processor = verified_msg_processor.clone(); + let f = executor.spawn(async move { + monitor!("dag_on_verified_msg", { + match verified_msg_processor.process_verified_message(msg, epoch, author, responder).await { + Ok(sync_status) => { + if matches!( + sync_status, + SyncOutcome::NeedsSync(_) | SyncOutcome::EpochEnds + ) { + return Some(sync_status); + } + }, + Err(e) => { + warn!(error = ?e, "error processing rpc"); + }, + }; + None + }) + }).await; + futures.push(f); }, - Some(new_round) = self.new_round_event.recv() => { - monitor!("dag_on_new_round_event", { - self.dag_driver.enter_new_round(new_round).await; - self.node_receiver.gc(); - }); - } - Some(res) = self.node_fetch_waiter.next() => { - monitor!("dag_on_node_fetch", match res { - Ok(node) => if let Err(e) = self.node_receiver.process(node).await { - warn!(error = ?e, "error processing node fetch notification"); - }, - Err(e) => { - debug!("sender dropped channel: {}", e); - }, - }); + Some(status) = futures.next() => { + if let Some(status) = status.expect("future must not panic") { + return status; + } + }, + Some(result) = certified_node_fetch_waiter.next() => { + let dag_driver_clone = dag_driver.clone(); + executor.spawn(async move { + monitor!("dag_on_cert_node_fetch", match result { + Ok(certified_node) => { + if let Err(e) = dag_driver_clone.process(certified_node).await { + warn!(error = ?e, "error processing certified node fetch notification"); + } + }, + Err(e) => { + debug!("sender dropped channel: {}", e); + }, + }); + }).await; + }, + Some(result) = node_fetch_waiter.next() => { + let node_receiver_clone = node_receiver.clone(); + executor.spawn(async move { + monitor!("dag_on_node_fetch", match result { + Ok(node) => { + if let Err(e) = node_receiver_clone.process(node).await { + warn!(error = ?e, "error processing node fetch notification"); + } + }, + Err(e) => { + debug!("sender dropped channel: {}", e); + }, + }); + }).await; }, - Some(res) = self.certified_node_fetch_waiter.next() => { - monitor!("dag_on_cert_node_fetch", match res { - Ok(certified_node) => if let Err(e) = self.dag_driver.process(certified_node).await { - warn!(error = ?e, "error processing certified node fetch notification"); }, - Err(e) => { - debug!("sender dropped channel: {}", e); - }, - }); - } } } } +} + +struct VerifiedMessageProcessor { + node_receiver: Arc, + dag_driver: Arc, + fetch_receiver: FetchRequestHandler, + state_sync_trigger: StateSyncTrigger, + epoch_state: Arc, +} +impl VerifiedMessageProcessor { async fn process_verified_message( - &mut self, + &self, dag_message_result: anyhow::Result, epoch: u64, author: Author, diff --git a/consensus/src/dag/dag_network.rs b/consensus/src/dag/dag_network.rs index 2a635f95ee72a..d3c1ce5d2b11c 100644 --- a/consensus/src/dag/dag_network.rs +++ b/consensus/src/dag/dag_network.rs @@ -22,7 +22,7 @@ pub trait RpcHandler { type Request; type Response; - async fn process(&mut self, message: Self::Request) -> anyhow::Result; + async fn process(&self, message: Self::Request) -> anyhow::Result; } #[async_trait] diff --git a/consensus/src/dag/order_rule.rs b/consensus/src/dag/order_rule.rs index cabafca461153..839e53f2a3d83 100644 --- a/consensus/src/dag/order_rule.rs +++ b/consensus/src/dag/order_rule.rs @@ -81,7 +81,7 @@ impl OrderRule { /// Find if there's anchors that can be ordered start from `start_round` until `round`, /// if so find next one until nothing can be ordered. - fn check_ordering_between(&mut self, mut start_round: Round, round: Round) { + fn check_ordering_between(&self, mut start_round: Round, round: Round) { while start_round <= round { if let Some(direct_anchor) = self.find_first_anchor_with_enough_votes(start_round, round) @@ -149,7 +149,7 @@ impl OrderRule { } /// Finalize the ordering with the given anchor node, update anchor election and construct blocks for execution. - fn finalize_order(&mut self, anchor: Arc) { + fn finalize_order(&self, anchor: Arc) { let lowest_unordered_anchor_round = *self.lowest_unordered_anchor_round.read(); // Check we're in the expected instance @@ -206,7 +206,7 @@ impl OrderRule { id = anchor.id(), lowest_unordered_anchor_round = lowest_unordered_anchor_round, "Reached round {} with {} nodes", - lowest_round_to_reach, + lowest_anchor_round, ordered_nodes.len() ); @@ -216,7 +216,7 @@ impl OrderRule { } /// Check if this node can trigger anchors to be ordered - pub fn process_new_node(&mut self, node_metadata: &NodeMetadata) { + pub fn process_new_node(&self, node_metadata: &NodeMetadata) { let lowest_unordered_anchor_round = *self.lowest_unordered_anchor_round.read(); let round = node_metadata.round(); diff --git a/consensus/src/dag/rb_handler.rs b/consensus/src/dag/rb_handler.rs index bb814b6671f49..d8e8bbabd0385 100644 --- a/consensus/src/dag/rb_handler.rs +++ b/consensus/src/dag/rb_handler.rs @@ -20,6 +20,7 @@ use crate::{ use anyhow::{bail, ensure}; use aptos_config::config::DagPayloadConfig; use aptos_consensus_types::common::{Author, Round}; +use aptos_infallible::Mutex; use aptos_logger::{debug, error}; use aptos_types::{ epoch_state::EpochState, @@ -32,7 +33,7 @@ use std::{collections::BTreeMap, mem, sync::Arc}; pub(crate) struct NodeBroadcastHandler { dag: Arc, - votes_by_round_peer: BTreeMap>, + votes_by_round_peer: Mutex>>, signer: Arc, epoch_state: Arc, storage: Arc, @@ -60,7 +61,7 @@ impl NodeBroadcastHandler { Self { dag, - votes_by_round_peer, + votes_by_round_peer: Mutex::new(votes_by_round_peer), signer, epoch_state, storage, @@ -72,16 +73,18 @@ impl NodeBroadcastHandler { } } - pub fn gc(&mut self) { + pub fn gc(&self) { let lowest_round = self.dag.read().lowest_round(); if let Err(e) = self.gc_before_round(lowest_round) { error!("Error deleting votes: {}", e); } } - pub fn gc_before_round(&mut self, min_round: Round) -> anyhow::Result<()> { - let to_retain = self.votes_by_round_peer.split_off(&min_round); - let to_delete = mem::replace(&mut self.votes_by_round_peer, to_retain); + pub fn gc_before_round(&self, min_round: Round) -> anyhow::Result<()> { + let mut votes_by_round_peer_guard = self.votes_by_round_peer.lock(); + let to_retain = votes_by_round_peer_guard.split_off(&min_round); + let to_delete = mem::replace(&mut *votes_by_round_peer_guard, to_retain); + drop(votes_by_round_peer_guard); let to_delete = to_delete .iter() @@ -190,7 +193,7 @@ impl RpcHandler for NodeBroadcastHandler { type Request = Node; type Response = Vote; - async fn process(&mut self, node: Self::Request) -> anyhow::Result { + async fn process(&self, node: Self::Request) -> anyhow::Result { ensure!( !self.health_backoff.stop_voting(), NodeBroadcastHandleError::VoteRefused @@ -202,8 +205,8 @@ impl RpcHandler for NodeBroadcastHandler { .remote_peer(*node.author()) .round(node.round())); - let votes_by_peer = self - .votes_by_round_peer + let mut votes_by_round_peer_guard = self.votes_by_round_peer.lock(); + let votes_by_peer = votes_by_round_peer_guard .entry(node.metadata().round()) .or_default(); match votes_by_peer.get(node.metadata().author()) { @@ -211,6 +214,7 @@ impl RpcHandler for NodeBroadcastHandler { let signature = node.sign_vote(&self.signer)?; let vote = Vote::new(node.metadata().clone(), signature); + // TODO: make this concurrent self.storage.save_vote(&node.id(), &vote)?; votes_by_peer.insert(*node.author(), vote.clone()); diff --git a/consensus/src/dag/round_state.rs b/consensus/src/dag/round_state.rs index 53c6c7e3ba7b9..77a4afd9ca3e4 100644 --- a/consensus/src/dag/round_state.rs +++ b/consensus/src/dag/round_state.rs @@ -5,99 +5,106 @@ use crate::dag::{ observability::tracing::{observe_round, RoundStage}, types::NodeCertificate, }; +use anyhow::ensure; use aptos_consensus_types::common::Round; -use aptos_infallible::duration_since_epoch; +use aptos_infallible::{duration_since_epoch, Mutex}; use aptos_types::epoch_state::EpochState; -use async_trait::async_trait; use std::{cmp::Ordering, sync::Arc, time::Duration}; use tokio::task::JoinHandle; pub struct RoundState { - current_round: Round, - event_sender: tokio::sync::mpsc::Sender, + current_round: Mutex, + event_sender: tokio::sync::mpsc::UnboundedSender, responsive_check: Box, } impl RoundState { pub fn new( - event_sender: tokio::sync::mpsc::Sender, + event_sender: tokio::sync::mpsc::UnboundedSender, responsive_check: Box, ) -> Self { Self { - current_round: 0, + current_round: Mutex::new(0), event_sender, responsive_check, } } - pub async fn check_for_new_round( - &mut self, + pub fn check_for_new_round( + &self, highest_strong_links_round: Round, strong_links: Vec, minimum_delay: Duration, ) { - match self.current_round.cmp(&highest_strong_links_round) { + let current_round = *self.current_round.lock(); + match current_round.cmp(&highest_strong_links_round) { // we're behind, move forward immediately Ordering::Less => { // the receiver can be dropped if we move to a new epoch - let _ = self.event_sender.send(highest_strong_links_round + 1).await; - }, - Ordering::Equal => { - self.responsive_check - .check_for_new_round(highest_strong_links_round, strong_links, minimum_delay) - .await + let _ = self.event_sender.send(highest_strong_links_round + 1); }, + Ordering::Equal => self.responsive_check.check_for_new_round( + highest_strong_links_round, + strong_links, + minimum_delay, + ), Ordering::Greater => (), } } pub fn current_round(&self) -> Round { - self.current_round + *self.current_round.lock() } - pub fn set_current_round(&mut self, new_round: Round) { - self.current_round = new_round; + pub fn set_current_round(&self, new_round: Round) -> anyhow::Result<()> { + let mut current_round = self.current_round.lock(); + ensure!( + *current_round < new_round, + "current round {} is newer than new round {}", + current_round, + new_round + ); + *current_round = new_round; self.responsive_check.reset(); + Ok(()) } } /// Interface to decide if we should move forward to a new round -#[async_trait] -pub trait ResponsiveCheck: Send { - async fn check_for_new_round( - &mut self, +pub trait ResponsiveCheck: Send + Sync { + fn check_for_new_round( + &self, highest_strong_links_round: Round, strong_links: Vec, health_backoff_delay: Duration, ); - fn reset(&mut self); + fn reset(&self); } /// Move as fast as 2f+1 pub struct OptimisticResponsive { - event_sender: tokio::sync::mpsc::Sender, + event_sender: tokio::sync::mpsc::UnboundedSender, } impl OptimisticResponsive { - pub fn new(event_sender: tokio::sync::mpsc::Sender) -> Self { + pub fn new(event_sender: tokio::sync::mpsc::UnboundedSender) -> Self { Self { event_sender } } } -#[async_trait] impl ResponsiveCheck for OptimisticResponsive { - async fn check_for_new_round( - &mut self, + fn check_for_new_round( + &self, highest_strong_links_round: Round, _strong_links: Vec, _health_backoff_delay: Duration, ) { let new_round = highest_strong_links_round + 1; - let _ = self.event_sender.send(new_round).await; + let _ = self.event_sender.send(new_round); } - fn reset(&mut self) {} + fn reset(&self) {} } enum State { @@ -106,48 +113,54 @@ enum State { Sent, } +struct AdaptiveResponsiveInner { + start_time: Duration, + state: State, +} + /// More sophisticated strategy to move round forward given 2f+1 strong links /// Delay if backpressure is triggered. /// Move as soon as 3f+1 is ready. (TODO: make it configurable) /// Move if minimal wait time is reached. pub struct AdaptiveResponsive { + inner: Mutex, epoch_state: Arc, - start_time: Duration, minimal_wait_time: Duration, - event_sender: tokio::sync::mpsc::Sender, - state: State, + event_sender: tokio::sync::mpsc::UnboundedSender, } impl AdaptiveResponsive { pub fn new( - event_sender: tokio::sync::mpsc::Sender, + event_sender: tokio::sync::mpsc::UnboundedSender, epoch_state: Arc, minimal_wait_time: Duration, ) -> Self { Self { + inner: Mutex::new(AdaptiveResponsiveInner { + start_time: duration_since_epoch(), + state: State::Initial, + }), epoch_state, - start_time: duration_since_epoch(), minimal_wait_time, event_sender, - state: State::Initial, } } } -#[async_trait] impl ResponsiveCheck for AdaptiveResponsive { - async fn check_for_new_round( - &mut self, + fn check_for_new_round( + &self, highest_strong_links_round: Round, strong_links: Vec, health_backoff_delay: Duration, ) { - if matches!(self.state, State::Sent) { + let mut inner = self.inner.lock(); + if matches!(inner.state, State::Sent) { return; } let new_round = highest_strong_links_round + 1; observe_round( - self.start_time.as_micros() as u64, + inner.start_time.as_micros() as u64, RoundStage::StrongLinkReceived, ); let voting_power = self @@ -163,28 +176,30 @@ impl ResponsiveCheck for AdaptiveResponsive { }; // voting power == 3f+1 and pass wait time if health backoff - let duration_since_start = duration_since_epoch().saturating_sub(self.start_time); + let duration_since_start = duration_since_epoch().saturating_sub(inner.start_time); if voting_power == self.epoch_state.verifier.total_voting_power() && (duration_since_start >= wait_time || !is_health_backoff) { - let _ = self.event_sender.send(new_round).await; - if let State::Scheduled(handle) = std::mem::replace(&mut self.state, State::Sent) { + let _ = self.event_sender.send(new_round); + if let State::Scheduled(handle) = std::mem::replace(&mut inner.state, State::Sent) { handle.abort(); } - } else if matches!(self.state, State::Initial) { + } else if matches!(inner.state, State::Initial) { // wait until minimal time reaches before sending let sender = self.event_sender.clone(); let wait_time = wait_time.saturating_sub(duration_since_start); let handle = tokio::spawn(async move { tokio::time::sleep(wait_time).await; - let _ = sender.send(new_round).await; + let _ = sender.send(new_round); }); - self.state = State::Scheduled(handle); + inner.state = State::Scheduled(handle); } } - fn reset(&mut self) { - self.start_time = duration_since_epoch(); - self.state = State::Initial; + fn reset(&self) { + let mut inner = self.inner.lock(); + + inner.start_time = duration_since_epoch(); + inner.state = State::Initial; } } diff --git a/consensus/src/dag/tests/dag_driver_tests.rs b/consensus/src/dag/tests/dag_driver_tests.rs index 0186b722eb488..abc412070be6e 100644 --- a/consensus/src/dag/tests/dag_driver_tests.rs +++ b/consensus/src/dag/tests/dag_driver_tests.rs @@ -155,7 +155,7 @@ fn setup( let ledger_info_provider = Arc::new(MockLedgerInfoProvider { latest_ledger_info: mock_ledger_info, }); - let (round_tx, _round_rx) = tokio::sync::mpsc::channel(10); + let (round_tx, _round_rx) = tokio::sync::mpsc::unbounded_channel(); let round_state = RoundState::new( round_tx.clone(), Box::new(OptimisticResponsive::new(round_tx)), @@ -190,7 +190,7 @@ async fn test_certified_node_handler() { let network_sender = Arc::new(MockNetworkSender { _drop_notifier: None, }); - let mut driver = setup(&signers, validator_verifier, network_sender); + let driver = setup(&signers, validator_verifier, network_sender); let first_round_node = new_certified_node(1, signers[0].author(), vec![]); // expect an ack for a valid message @@ -215,7 +215,7 @@ async fn test_dag_driver_drop() { let network_sender = Arc::new(MockNetworkSender { _drop_notifier: Some(tx), }); - let mut driver = setup(&signers, validator_verifier, network_sender); + let driver = setup(&signers, validator_verifier, network_sender); driver.enter_new_round(1).await; diff --git a/consensus/src/dag/tests/fetcher_test.rs b/consensus/src/dag/tests/fetcher_test.rs index 5067e7088ed81..9941ed04b103f 100644 --- a/consensus/src/dag/tests/fetcher_test.rs +++ b/consensus/src/dag/tests/fetcher_test.rs @@ -28,7 +28,7 @@ async fn test_dag_fetcher_receiver() { TEST_DAG_WINDOW, )); - let mut fetcher = FetchRequestHandler::new(dag.clone(), epoch_state); + let fetcher = FetchRequestHandler::new(dag.clone(), epoch_state); let mut first_round_nodes = vec![]; diff --git a/consensus/src/dag/tests/integration_tests.rs b/consensus/src/dag/tests/integration_tests.rs index 725300073db70..5a70ca26bb5ee 100644 --- a/consensus/src/dag/tests/integration_tests.rs +++ b/consensus/src/dag/tests/integration_tests.rs @@ -214,10 +214,10 @@ async fn test_dag_e2e() { let mut playground = NetworkPlayground::new(runtime.handle().clone()); let (signers, validators) = random_validator_verifier(num_nodes, None, false); let (nodes, mut ordered_node_receivers) = bootstrap_nodes(&mut playground, signers, validators); - for node in nodes { - runtime.spawn(node.start()); - } - + let tasks: Vec<_> = nodes + .into_iter() + .map(|node| runtime.spawn(node.start())) + .collect(); runtime.spawn(playground.start()); for _ in 1..10 { @@ -233,5 +233,9 @@ async fn test_dag_e2e() { assert_eq!(a, first); } } + for task in tasks { + task.abort(); + let _ = task.await; + } runtime.shutdown_background(); } diff --git a/consensus/src/dag/tests/order_rule_tests.rs b/consensus/src/dag/tests/order_rule_tests.rs index 9c482f484a8ab..fdbb2429aa7d2 100644 --- a/consensus/src/dag/tests/order_rule_tests.rs +++ b/consensus/src/dag/tests/order_rule_tests.rs @@ -146,7 +146,7 @@ proptest! { for seq in sequences { s.spawn(|_| { let dag = Arc::new(DagStore::new_for_test(dag.clone(),Arc::new(MockStorage::new()), Arc::new(MockPayloadManager {}))); - let (mut order_rule, mut receiver) = create_order_rule(epoch_state.clone(), dag); + let (order_rule, mut receiver) = create_order_rule(epoch_state.clone(), dag); for idx in seq { order_rule.process_new_node(flatten_nodes[idx].metadata()); } @@ -233,7 +233,8 @@ fn test_order_rule_basic() { Arc::new(MockStorage::new()), Arc::new(MockPayloadManager {}), )); - let (mut order_rule, mut receiver) = create_order_rule(epoch_state, dag); + let (order_rule, mut receiver): (OrderRule, UnboundedReceiver>>) = + create_order_rule(epoch_state, dag); for node in nodes.iter().flatten().flatten() { order_rule.process_new_node(node.metadata()); } diff --git a/consensus/src/dag/tests/rb_handler_tests.rs b/consensus/src/dag/tests/rb_handler_tests.rs index a9f49270dd35d..11938cd7fd19d 100644 --- a/consensus/src/dag/tests/rb_handler_tests.rs +++ b/consensus/src/dag/tests/rb_handler_tests.rs @@ -68,7 +68,7 @@ async fn test_node_broadcast_receiver_succeed() { assert_ne!(wellformed_node.digest(), equivocating_node.digest()); - let mut rb_receiver = NodeBroadcastHandler::new( + let rb_receiver = NodeBroadcastHandler::new( dag, signers[3].clone(), epoch_state.clone(), @@ -205,7 +205,7 @@ async fn test_node_broadcast_receiver_storage() { let node = new_node(1, 10, signers[0].author(), vec![]); - let mut rb_receiver = NodeBroadcastHandler::new( + let rb_receiver = NodeBroadcastHandler::new( dag.clone(), signers[3].clone(), epoch_state.clone(), @@ -227,7 +227,7 @@ async fn test_node_broadcast_receiver_storage() { sig )],); - let mut rb_receiver = NodeBroadcastHandler::new( + let rb_receiver = NodeBroadcastHandler::new( dag, signers[3].clone(), epoch_state.clone(), diff --git a/consensus/src/test_utils/mock_payload_manager.rs b/consensus/src/test_utils/mock_payload_manager.rs index 581f114d12520..29de64a5bf351 100644 --- a/consensus/src/test_utils/mock_payload_manager.rs +++ b/consensus/src/test_utils/mock_payload_manager.rs @@ -68,7 +68,7 @@ impl PayloadClient for MockPayloadManager { ) -> Result<(Vec, Payload), QuorumStoreError> { // generate 1k txn is too slow with coverage instrumentation Ok(( - vec![ValidatorTransaction::dummy(vec![0xFF; 1024])], + vec![ValidatorTransaction::dummy(vec![0xFF; 1])], random_payload(10), )) } From c81eab9951b60a58da7cfeec3551f71bc8b94058 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Thu, 8 Feb 2024 20:07:50 -0800 Subject: [PATCH 047/328] [dag] support parallel rb voting (#11743) * [dag] support parallel rb voting --- consensus/src/dag/rb_handler.rs | 56 ++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/consensus/src/dag/rb_handler.rs b/consensus/src/dag/rb_handler.rs index d8e8bbabd0385..2d3f307030d24 100644 --- a/consensus/src/dag/rb_handler.rs +++ b/consensus/src/dag/rb_handler.rs @@ -29,11 +29,16 @@ use aptos_types::{ validator_txn::ValidatorTransaction, }; use async_trait::async_trait; +use claims::assert_some; +use dashmap::DashSet; use std::{collections::BTreeMap, mem, sync::Arc}; pub(crate) struct NodeBroadcastHandler { dag: Arc, + /// Note: The mutex around BTreeMap is to work around Rust Sync semantics. + /// Fine grained concurrency is implemented by the DashSet below. votes_by_round_peer: Mutex>>, + votes_fine_grained_lock: DashSet<(Round, Author)>, signer: Arc, epoch_state: Arc, storage: Arc, @@ -62,6 +67,7 @@ impl NodeBroadcastHandler { Self { dag, votes_by_round_peer: Mutex::new(votes_by_round_peer), + votes_fine_grained_lock: DashSet::with_capacity(epoch_state.verifier.len() * 10), signer, epoch_state, storage, @@ -199,31 +205,43 @@ impl RpcHandler for NodeBroadcastHandler { NodeBroadcastHandleError::VoteRefused ); + let key = (node.round(), *node.author()); + ensure!( + self.votes_fine_grained_lock.insert(key), + "concurrent insertion" + ); + defer!({ + assert_some!(self.votes_fine_grained_lock.remove(&key)); + }); + let node = self.validate(node)?; observe_node(node.timestamp(), NodeStage::NodeReceived); debug!(LogSchema::new(LogEvent::ReceiveNode) .remote_peer(*node.author()) .round(node.round())); - let mut votes_by_round_peer_guard = self.votes_by_round_peer.lock(); - let votes_by_peer = votes_by_round_peer_guard - .entry(node.metadata().round()) - .or_default(); - match votes_by_peer.get(node.metadata().author()) { - None => { - let signature = node.sign_vote(&self.signer)?; - let vote = Vote::new(node.metadata().clone(), signature); - - // TODO: make this concurrent - self.storage.save_vote(&node.id(), &vote)?; - votes_by_peer.insert(*node.author(), vote.clone()); - - debug!(LogSchema::new(LogEvent::Vote) - .remote_peer(*node.author()) - .round(node.round())); - Ok(vote) - }, - Some(ack) => Ok(ack.clone()), + if let Some(ack) = self + .votes_by_round_peer + .lock() + .entry(node.round()) + .or_default() + .get(node.author()) + { + return Ok(ack.clone()); } + + let signature = node.sign_vote(&self.signer)?; + let vote = Vote::new(node.metadata().clone(), signature); + self.storage.save_vote(&node.id(), &vote)?; + self.votes_by_round_peer + .lock() + .get_mut(&node.round()) + .expect("must exist") + .insert(*node.author(), vote.clone()); + + debug!(LogSchema::new(LogEvent::Vote) + .remote_peer(*node.author()) + .round(node.round())); + Ok(vote) } } From e1732715857ba152e81496f93957b66477b5fbb5 Mon Sep 17 00:00:00 2001 From: Alin Tomescu Date: Thu, 8 Feb 2024 22:02:44 -0800 Subject: [PATCH 048/328] Properly handle `exp_horizon` + zkid.move VK & Configuration initialization in Rust (#11966) --- aptos-move/aptos-vm/src/zkid_validation.rs | 71 ++++--- .../framework/aptos-framework/doc/genesis.md | 2 - .../framework/aptos-framework/doc/zkid.md | 175 +++++++----------- .../aptos-framework/sources/genesis.move | 2 - .../aptos-framework/sources/zkid.move | 77 +++----- aptos-move/vm-genesis/src/lib.rs | 31 ++++ .../generate-format/tests/staged/api.yaml | 1 + .../generate-format/tests/staged/aptos.yaml | 1 + .../tests/staged/consensus.yaml | 1 + testsuite/smoke-test/src/zkid.rs | 35 +++- types/src/bn254_circom.rs | 35 +++- types/src/jwks/mod.rs | 6 +- types/src/move_utils/as_move_value.rs | 12 ++ types/src/on_chain_config/mod.rs | 1 + types/src/transaction/authenticator.rs | 4 +- types/src/zkid.rs | 42 ++++- 16 files changed, 281 insertions(+), 215 deletions(-) diff --git a/aptos-move/aptos-vm/src/zkid_validation.rs b/aptos-move/aptos-vm/src/zkid_validation.rs index d449f7ebe0c29..b483eb84c83e1 100644 --- a/aptos-move/aptos-vm/src/zkid_validation.rs +++ b/aptos-move/aptos-vm/src/zkid_validation.rs @@ -16,14 +16,40 @@ use aptos_types::{ }; use move_binary_format::errors::Location; use move_core_types::{language_storage::CORE_CODE_ADDRESS, move_resource::MoveStructType}; +use serde::Deserialize; macro_rules! value_deserialization_error { - ($message:expr) => { + ($message:expr) => {{ VMStatus::error( StatusCode::VALUE_DESERIALIZATION_ERROR, Some($message.to_owned()), ) - }; + }}; +} + +fn get_resource_on_chain Deserialize<'a>>( + resolver: &impl AptosMoveResolver, +) -> anyhow::Result { + let bytes = resolver + .get_resource(&CORE_CODE_ADDRESS, &T::struct_tag()) + .map_err(|e| e.finish(Location::Undefined).into_vm_status())? + .ok_or_else(|| { + value_deserialization_error!(format!( + "get_resource failed on {}::{}::{}", + CORE_CODE_ADDRESS.to_hex_literal(), + T::struct_tag().module, + T::struct_tag().name + )) + })?; + let obj = bcs::from_bytes::(&bytes).map_err(|_| { + value_deserialization_error!(format!( + "could not deserialize {}::{}::{}", + CORE_CODE_ADDRESS.to_hex_literal(), + T::struct_tag().module, + T::struct_tag().name + )) + })?; + Ok(obj) } fn get_current_time_onchain( @@ -35,37 +61,20 @@ fn get_current_time_onchain( } fn get_jwks_onchain(resolver: &impl AptosMoveResolver) -> anyhow::Result { - let bytes = resolver - .get_resource(&CORE_CODE_ADDRESS, &PatchedJWKs::struct_tag()) - .map_err(|e| e.finish(Location::Undefined).into_vm_status())? - .ok_or_else(|| value_deserialization_error!("get_resource failed on PatchedJWKs"))?; - let jwks = bcs::from_bytes::(&bytes) - .map_err(|_| value_deserialization_error!("could not deserialize PatchedJWKs"))?; - Ok(jwks) + PatchedJWKs::fetch_config(resolver) + .ok_or_else(|| value_deserialization_error!("could not deserialize PatchedJWKs")) } fn get_groth16_vk_onchain( resolver: &impl AptosMoveResolver, ) -> anyhow::Result { - let bytes = resolver - .get_resource(&CORE_CODE_ADDRESS, &Groth16VerificationKey::struct_tag()) - .map_err(|e| e.finish(Location::Undefined).into_vm_status())? - .ok_or_else(|| value_deserialization_error!("get_resource failed on Groth16 VK"))?; - let vk = bcs::from_bytes::(&bytes) - .map_err(|_| value_deserialization_error!("could not deserialize Groth16 VK"))?; - Ok(vk) + get_resource_on_chain::(resolver) } fn get_configs_onchain( resolver: &impl AptosMoveResolver, ) -> anyhow::Result { - let bytes = resolver - .get_resource(&CORE_CODE_ADDRESS, &Configuration::struct_tag()) - .map_err(|e| e.finish(Location::Undefined).into_vm_status())? - .ok_or_else(|| value_deserialization_error!("get_resource failed on zkID configuration"))?; - let configs = bcs::from_bytes::(&bytes) - .map_err(|_| value_deserialization_error!("could not deserialize zkID configuration"))?; - Ok(configs) + get_resource_on_chain::(resolver) } fn get_jwk_for_zkid_authenticator( @@ -132,6 +141,10 @@ pub fn validate_zkid_authenticators( match &zkid_sig.sig { ZkpOrOpenIdSig::Groth16Zkp(proof) => match jwk { JWK::RSA(rsa_jwk) => { + if proof.exp_horizon_secs > config.max_exp_horizon_secs { + return Err(invalid_signature!("The expiration horizon is too long")); + } + // If an `aud` override was set for account recovery purposes, check that it is // in the allow-list on-chain. if proof.override_aud_val.is_some() { @@ -150,10 +163,14 @@ pub fn validate_zkid_authenticators( })?; } - let public_inputs_hash = - get_public_inputs_hash(zkid_sig, zkid_pub_key, &rsa_jwk, config).map_err( - |_| invalid_signature!("Could not compute public inputs hash"), - )?; + let public_inputs_hash = get_public_inputs_hash( + zkid_sig, + zkid_pub_key, + &rsa_jwk, + proof.exp_horizon_secs, + config, + ) + .map_err(|_| invalid_signature!("Could not compute public inputs hash"))?; proof .verify_proof(public_inputs_hash, pvk) .map_err(|_| invalid_signature!("Proof verification failed"))?; diff --git a/aptos-move/framework/aptos-framework/doc/genesis.md b/aptos-move/framework/aptos-framework/doc/genesis.md index 8683381ac43b1..fcc8afa9f61b1 100644 --- a/aptos-move/framework/aptos-framework/doc/genesis.md +++ b/aptos-move/framework/aptos-framework/doc/genesis.md @@ -63,7 +63,6 @@ use 0x1::vector; use 0x1::version; use 0x1::vesting; -use 0x1::zkid;
@@ -367,7 +366,6 @@ Genesis step 1: Initialize aptos framework account and core modules on chain. state_storage::initialize(&aptos_framework_account); timestamp::set_time_has_started(&aptos_framework_account); jwks::initialize(&aptos_framework_account); - zkid::initialize(&aptos_framework_account, zkid::devnet_groth16_vk(), zkid::default_devnet_configuration()); }
diff --git a/aptos-move/framework/aptos-framework/doc/zkid.md b/aptos-move/framework/aptos-framework/doc/zkid.md index ddbff02c95c41..3ebc307caac96 100644 --- a/aptos-move/framework/aptos-framework/doc/zkid.md +++ b/aptos-move/framework/aptos-framework/doc/zkid.md @@ -9,14 +9,13 @@ - [Resource `Groth16VerificationKey`](#0x1_zkid_Groth16VerificationKey) - [Resource `Configuration`](#0x1_zkid_Configuration) - [Constants](#@Constants_0) -- [Function `initialize`](#0x1_zkid_initialize) - [Function `new_groth16_verification_key`](#0x1_zkid_new_groth16_verification_key) - [Function `new_configuration`](#0x1_zkid_new_configuration) -- [Function `devnet_groth16_vk`](#0x1_zkid_devnet_groth16_vk) -- [Function `default_devnet_configuration`](#0x1_zkid_default_devnet_configuration) - [Function `update_groth16_verification_key`](#0x1_zkid_update_groth16_verification_key) - [Function `update_configuration`](#0x1_zkid_update_configuration) - [Function `update_training_wheels`](#0x1_zkid_update_training_wheels) +- [Function `remove_all_override_auds`](#0x1_zkid_remove_all_override_auds) +- [Function `add_override_aud`](#0x1_zkid_add_override_aud)
use 0x1::option;
@@ -203,33 +202,6 @@ The training wheels PK needs to be 32 bytes long.
 
 
 
-
-
-## Function `initialize`
-
-
-
-
public(friend) fun initialize(fx: &signer, vk: zkid::Groth16VerificationKey, constants: zkid::Configuration)
-
- - - -
-Implementation - - -
public(friend) fun initialize(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) {
-    system_addresses::assert_aptos_framework(fx);
-
-    move_to(fx, vk);
-    move_to(fx, constants);
-}
-
- - - -
- ## Function `new_groth16_verification_key` @@ -245,7 +217,12 @@ The training wheels PK needs to be 32 bytes long. Implementation -
public fun new_groth16_verification_key(alpha_g1: vector<u8>, beta_g2: vector<u8>, gamma_g2: vector<u8>, delta_g2: vector<u8>, gamma_abc_g1: vector<vector<u8>>): Groth16VerificationKey {
+
public fun new_groth16_verification_key(alpha_g1: vector<u8>,
+                                        beta_g2: vector<u8>,
+                                        gamma_g2: vector<u8>,
+                                        delta_g2: vector<u8>,
+                                        gamma_abc_g1: vector<vector<u8>>
+): Groth16VerificationKey {
     Groth16VerificationKey {
         alpha_g1,
         beta_g2,
@@ -302,77 +279,6 @@ The training wheels PK needs to be 32 bytes long.
 
 
 
-
-
-
-
-## Function `devnet_groth16_vk`
-
-Returns the Groth16 VK for our devnet deployment.
-
-
-
public fun devnet_groth16_vk(): zkid::Groth16VerificationKey
-
- - - -
-Implementation - - -
public fun devnet_groth16_vk(): Groth16VerificationKey {
-    Groth16VerificationKey {
-        alpha_g1: x"6d1c152d2705e35fe7a07a66eb8a10a7f42f1e38c412fbbc3ac7f9affc25dc24",
-        beta_g2: x"e20a834c55ae6e2fcbd66636e09322727f317aff8957dd342afa11f936ef7c02cfdc8c9862849a0442bcaa4e03f45343e8bf261ef4ab58cead2efc17100a3b16",
-        gamma_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19",
-        delta_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19",
-        gamma_abc_g1: vector[
-            x"9aae6580d6040e77969d70e748e861664228e3567e77aa99822f8a4a19c29101",
-            x"e38ad8b845e3ef599232b43af2a64a73ada04d5f0e73f1848e6631e17a247415",
-        ],
-    }
-}
-
- - - -
- - - -## Function `default_devnet_configuration` - -Returns the configuration for our devnet deployment. - - -
public fun default_devnet_configuration(): zkid::Configuration
-
- - - -
-Implementation - - -
public fun default_devnet_configuration(): Configuration {
-    // TODO(zkid): Put reasonable defaults & circuit-specific constants here.
-    Configuration {
-        override_aud_vals: vector[],
-        max_zkid_signatures_per_txn: 3,
-        max_exp_horizon_secs: 100_255_944, // ~1160 days
-        training_wheels_pubkey: option::some(x"aa"),
-        // The commitment is using the Poseidon-BN254 hash function, hence the 254-bit (32 byte) size.
-        nonce_commitment_num_bytes: 32,
-        max_commited_epk_bytes: 3 * 31,
-        max_iss_field_bytes: 126,
-        max_extra_field_bytes:  350,
-        max_jwt_header_b64_bytes: 300,
-    }
-}
-
- - -
@@ -381,7 +287,7 @@ Returns the configuration for our devnet deployment. -
public fun update_groth16_verification_key(fx: &signer, alpha_g1: vector<u8>, beta_g2: vector<u8>, gamma_g2: vector<u8>, delta_g2: vector<u8>, gamma_abc_g1: vector<vector<u8>>)
+
public fun update_groth16_verification_key(fx: &signer, vk: zkid::Groth16VerificationKey)
 
@@ -390,13 +296,7 @@ Returns the configuration for our devnet deployment. Implementation -
public fun update_groth16_verification_key(fx: &signer,
-                                           alpha_g1: vector<u8>,
-                                           beta_g2: vector<u8>,
-                                           gamma_g2: vector<u8>,
-                                           delta_g2: vector<u8>,
-                                           gamma_abc_g1: vector<vector<u8>>,
-) acquires Groth16VerificationKey {
+
public fun update_groth16_verification_key(fx: &signer, vk: Groth16VerificationKey) acquires Groth16VerificationKey {
     system_addresses::assert_aptos_framework(fx);
 
     if (exists<Groth16VerificationKey>(signer::address_of(fx))) {
@@ -409,7 +309,6 @@ Returns the configuration for our devnet deployment.
         } = move_from<Groth16VerificationKey>(signer::address_of(fx));
     };
 
-    let vk = new_groth16_verification_key(alpha_g1, beta_g2, gamma_g2, delta_g2, gamma_abc_g1);
     move_to(fx, vk);
 }
 
@@ -486,6 +385,60 @@ Returns the configuration for our devnet deployment. + + + + +## Function `remove_all_override_auds` + + + +
public fun remove_all_override_auds(fx: &signer)
+
+ + + +
+Implementation + + +
public fun remove_all_override_auds(fx: &signer) acquires Configuration {
+    system_addresses::assert_aptos_framework(fx);
+
+    let config = borrow_global_mut<Configuration>(signer::address_of(fx));
+    config.override_aud_vals = vector[];
+}
+
+ + + +
+ + + +## Function `add_override_aud` + + + +
public fun add_override_aud(fx: &signer, aud: string::String)
+
+ + + +
+Implementation + + +
public fun add_override_aud(fx: &signer, aud: String) acquires Configuration {
+    system_addresses::assert_aptos_framework(fx);
+
+    let config = borrow_global_mut<Configuration>(signer::address_of(fx));
+    vector::push_back(&mut config.override_aud_vals, aud);
+}
+
+ + +
diff --git a/aptos-move/framework/aptos-framework/sources/genesis.move b/aptos-move/framework/aptos-framework/sources/genesis.move index 682f568ed2c62..4a01ea1532eb6 100644 --- a/aptos-move/framework/aptos-framework/sources/genesis.move +++ b/aptos-move/framework/aptos-framework/sources/genesis.move @@ -29,7 +29,6 @@ module aptos_framework::genesis { use aptos_framework::transaction_validation; use aptos_framework::version; use aptos_framework::vesting; - use aptos_framework::zkid; const EDUPLICATE_ACCOUNT: u64 = 1; const EACCOUNT_DOES_NOT_EXIST: u64 = 2; @@ -133,7 +132,6 @@ module aptos_framework::genesis { state_storage::initialize(&aptos_framework_account); timestamp::set_time_has_started(&aptos_framework_account); jwks::initialize(&aptos_framework_account); - zkid::initialize(&aptos_framework_account, zkid::devnet_groth16_vk(), zkid::default_devnet_configuration()); } /// Genesis step 2: Initialize Aptos coin. diff --git a/aptos-move/framework/aptos-framework/sources/zkid.move b/aptos-move/framework/aptos-framework/sources/zkid.move index 97b7b9d32f240..169ccde3a5158 100644 --- a/aptos-move/framework/aptos-framework/sources/zkid.move +++ b/aptos-move/framework/aptos-framework/sources/zkid.move @@ -53,22 +53,20 @@ module aptos_framework::zkid { max_jwt_header_b64_bytes: u32, } - // genesis.move needs to initialize the devnet VK - friend aptos_framework::genesis; - - public(friend) fun initialize(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) { + #[test_only] + public fun initialize_for_test(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) { system_addresses::assert_aptos_framework(fx); move_to(fx, vk); move_to(fx, constants); } - #[test_only] - public fun initialize_for_test(fx: &signer, vk: Groth16VerificationKey, constants: Configuration) { - initialize(fx, vk, constants) - } - - public fun new_groth16_verification_key(alpha_g1: vector, beta_g2: vector, gamma_g2: vector, delta_g2: vector, gamma_abc_g1: vector>): Groth16VerificationKey { + public fun new_groth16_verification_key(alpha_g1: vector, + beta_g2: vector, + gamma_g2: vector, + delta_g2: vector, + gamma_abc_g1: vector> + ): Groth16VerificationKey { Groth16VerificationKey { alpha_g1, beta_g2, @@ -102,46 +100,9 @@ module aptos_framework::zkid { } } - /// Returns the Groth16 VK for our devnet deployment. - public fun devnet_groth16_vk(): Groth16VerificationKey { - Groth16VerificationKey { - alpha_g1: x"6d1c152d2705e35fe7a07a66eb8a10a7f42f1e38c412fbbc3ac7f9affc25dc24", - beta_g2: x"e20a834c55ae6e2fcbd66636e09322727f317aff8957dd342afa11f936ef7c02cfdc8c9862849a0442bcaa4e03f45343e8bf261ef4ab58cead2efc17100a3b16", - gamma_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19", - delta_g2: x"edf692d95cbdde46ddda5ef7d422436779445c5e66006a42761e1f12efde0018c212f3aeb785e49712e7a9353349aaf1255dfb31b7bf60723a480d9293938e19", - gamma_abc_g1: vector[ - x"9aae6580d6040e77969d70e748e861664228e3567e77aa99822f8a4a19c29101", - x"e38ad8b845e3ef599232b43af2a64a73ada04d5f0e73f1848e6631e17a247415", - ], - } - } - - /// Returns the configuration for our devnet deployment. - public fun default_devnet_configuration(): Configuration { - // TODO(zkid): Put reasonable defaults & circuit-specific constants here. - Configuration { - override_aud_vals: vector[], - max_zkid_signatures_per_txn: 3, - max_exp_horizon_secs: 100_255_944, // ~1160 days - training_wheels_pubkey: option::some(x"aa"), - // The commitment is using the Poseidon-BN254 hash function, hence the 254-bit (32 byte) size. - nonce_commitment_num_bytes: 32, - max_commited_epk_bytes: 3 * 31, - max_iss_field_bytes: 126, - max_extra_field_bytes: 350, - max_jwt_header_b64_bytes: 300, - } - } - // Sets the zkID Groth16 verification key, only callable via governance proposal. // WARNING: If a malicious key is set, this would lead to stolen funds. - public fun update_groth16_verification_key(fx: &signer, - alpha_g1: vector, - beta_g2: vector, - gamma_g2: vector, - delta_g2: vector, - gamma_abc_g1: vector>, - ) acquires Groth16VerificationKey { + public fun update_groth16_verification_key(fx: &signer, vk: Groth16VerificationKey) acquires Groth16VerificationKey { system_addresses::assert_aptos_framework(fx); if (exists(signer::address_of(fx))) { @@ -154,7 +115,6 @@ module aptos_framework::zkid { } = move_from(signer::address_of(fx)); }; - let vk = new_groth16_verification_key(alpha_g1, beta_g2, gamma_g2, delta_g2, gamma_abc_g1); move_to(fx, vk); } @@ -191,4 +151,23 @@ module aptos_framework::zkid { let config = borrow_global_mut(signer::address_of(fx)); config.training_wheels_pubkey = pk; } + + // Convenience method to append to clear the set of zkID override `aud`'s, only callable via governance proposal. + // WARNING: When no override `aud` is set, recovery of zkID accounts associated with applications that disappeared + // is no longer possible. + public fun remove_all_override_auds(fx: &signer) acquires Configuration { + system_addresses::assert_aptos_framework(fx); + + let config = borrow_global_mut(signer::address_of(fx)); + config.override_aud_vals = vector[]; + } + + // Convenience method to append to the set of zkID override `aud`'s, only callable via governance proposal. + // WARNING: If a malicious override `aud` is set, this would lead to stolen funds. + public fun add_override_aud(fx: &signer, aud: String) acquires Configuration { + system_addresses::assert_aptos_framework(fx); + + let config = borrow_global_mut(signer::address_of(fx)); + vector::push_back(&mut config.override_aud_vals, aud); + } } diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 382807e67aaa5..c68ada1f48899 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -19,14 +19,18 @@ use aptos_gas_schedule::{ }; use aptos_types::{ account_config::{self, aptos_test_root_address, events::NewEpochEvent, CORE_CODE_ADDRESS}, + bn254_circom, + bn254_circom::Groth16VerificationKey, chain_id::ChainId, contract_event::{ContractEvent, ContractEventV1}, + move_utils::as_move_value::AsMoveValue, on_chain_config::{ FeatureFlag, Features, GasScheduleV2, OnChainConsensusConfig, OnChainExecutionConfig, TimedFeaturesBuilder, APTOS_MAX_KNOWN_VERSION, }, transaction::{authenticator::AuthenticationKey, ChangeSet, Transaction, WriteSetPayload}, write_set::TransactionWrite, + zkid, }; use aptos_vm::{ data_cache::AsMoveResolver, @@ -51,6 +55,7 @@ const GENESIS_MODULE_NAME: &str = "genesis"; const GOVERNANCE_MODULE_NAME: &str = "aptos_governance"; const CODE_MODULE_NAME: &str = "code"; const VERSION_MODULE_NAME: &str = "version"; +const ZKID_MODULE_NAME: &str = "zkid"; const NUM_SECONDS_PER_YEAR: u64 = 365 * 24 * 60 * 60; const MICRO_SECONDS_PER_SECOND: u64 = 1_000_000; @@ -249,6 +254,7 @@ pub fn encode_genesis_change_set( if genesis_config.is_test { allow_core_resources_to_set_version(&mut session); } + initialize_zkid(&mut session); set_genesis_end(&mut session); // Reconfiguration should happen after all on-chain invocations. @@ -525,6 +531,31 @@ fn initialize_on_chain_governance(session: &mut SessionExt, genesis_config: &Gen ); } +fn initialize_zkid(session: &mut SessionExt) { + let config = zkid::Configuration::new_for_devnet_and_testing(); + exec_function( + session, + ZKID_MODULE_NAME, + "update_configuration", + vec![], + serialize_values(&vec![ + MoveValue::Signer(CORE_CODE_ADDRESS), + config.as_move_value(), + ]), + ); + let vk = Groth16VerificationKey::from(bn254_circom::DEVNET_VERIFYING_KEY.clone()); + exec_function( + session, + ZKID_MODULE_NAME, + "update_groth16_verification_key", + vec![], + serialize_values(&vec![ + MoveValue::Signer(CORE_CODE_ADDRESS), + vk.as_move_value(), + ]), + ); +} + fn create_accounts(session: &mut SessionExt, accounts: &[AccountBalance]) { let accounts_bytes = bcs::to_bytes(accounts).expect("AccountMaps can be serialized"); let mut serialized_values = serialize_values(&vec![MoveValue::Signer(CORE_CODE_ADDRESS)]); diff --git a/testsuite/generate-format/tests/staged/api.yaml b/testsuite/generate-format/tests/staged/api.yaml index 782ded3e31a22..f5bad867e9119 100644 --- a/testsuite/generate-format/tests/staged/api.yaml +++ b/testsuite/generate-format/tests/staged/api.yaml @@ -459,6 +459,7 @@ SignedGroth16Zkp: - extra_field: STR - override_aud_val: OPTION: STR + - exp_horizon_secs: U64 SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/generate-format/tests/staged/aptos.yaml b/testsuite/generate-format/tests/staged/aptos.yaml index a9b1a2432a886..0cadcf1f1be95 100644 --- a/testsuite/generate-format/tests/staged/aptos.yaml +++ b/testsuite/generate-format/tests/staged/aptos.yaml @@ -391,6 +391,7 @@ SignedGroth16Zkp: - extra_field: STR - override_aud_val: OPTION: STR + - exp_horizon_secs: U64 SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/generate-format/tests/staged/consensus.yaml b/testsuite/generate-format/tests/staged/consensus.yaml index c33b28ac42223..1093b74174061 100644 --- a/testsuite/generate-format/tests/staged/consensus.yaml +++ b/testsuite/generate-format/tests/staged/consensus.yaml @@ -750,6 +750,7 @@ SignedGroth16Zkp: - extra_field: STR - override_aud_val: OPTION: STR + - exp_horizon_secs: U64 SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/smoke-test/src/zkid.rs b/testsuite/smoke-test/src/zkid.rs index bb2bc12e236ed..fd06332451309 100644 --- a/testsuite/smoke-test/src/zkid.rs +++ b/testsuite/smoke-test/src/zkid.rs @@ -13,7 +13,7 @@ use aptos_logger::{debug, info}; use aptos_rest_client::Client; use aptos_sdk::types::{AccountKey, LocalAccount}; use aptos_types::{ - bn254_circom::{G1Bytes, G2Bytes}, + bn254_circom::{G1Bytes, G2Bytes, Groth16VerificationKey}, jwks::{ jwk::{JWKMoveStruct, JWK}, rsa::RSA_JWK, @@ -24,8 +24,8 @@ use aptos_types::{ SignedTransaction, }, zkid::{ - Groth16Zkp, IdCommitment, OpenIdSig, Pepper, SignedGroth16Zkp, ZkIdPublicKey, - ZkIdSignature, ZkpOrOpenIdSig, + Configuration, Groth16Zkp, IdCommitment, OpenIdSig, Pepper, SignedGroth16Zkp, + ZkIdPublicKey, ZkIdSignature, ZkpOrOpenIdSig, }, }; use move_core_types::account_address::AccountAddress; @@ -378,6 +378,7 @@ async fn test_zkid_groth16_verifies() { // TODO(zkid): Refactor tests to be modular and add test for bad training wheels signature (commented out below). //let bad_sk = Ed25519PrivateKey::generate(&mut thread_rng()); + let config = Configuration::new_for_devnet_and_testing(); let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), @@ -386,6 +387,7 @@ async fn test_zkid_groth16_verifies() { //training_wheels_signature: EphemeralSignature::ed25519(bad_sk.sign(&proof).unwrap()), extra_field: "\"family_name\":\"Straka\",".to_string(), override_aud_val: None, + exp_horizon_secs: config.max_exp_horizon_secs, }), jwt_header, exp_timestamp_secs: 1900255944, @@ -396,10 +398,14 @@ async fn test_zkid_groth16_verifies() { let signed_txn = SignedTransaction::new_zkid(raw_txn, sender_zkid_public_key, zk_sig); info!("Submit zero knowledge transaction"); - info.client() + let result = info + .client() .submit_without_serializing_response(&signed_txn) - .await - .unwrap(); + .await; + + if let Err(e) = result { + panic!("Error with Groth16 TXN verification: {:?}", e) + } } #[tokio::test] @@ -485,6 +491,7 @@ async fn test_zkid_groth16_signature_transaction_submission_proof_signature_chec let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); + let config = Configuration::new_for_devnet_and_testing(); let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), @@ -492,6 +499,7 @@ async fn test_zkid_groth16_signature_transaction_submission_proof_signature_chec training_wheels_signature: EphemeralSignature::ed25519(tw_sk.sign(&proof).unwrap()), extra_field: "\"family_name\":\"Straka\",".to_string(), override_aud_val: None, + exp_horizon_secs: config.max_exp_horizon_secs, }), jwt_header, exp_timestamp_secs: 1900255944, @@ -519,6 +527,21 @@ async fn test_setup(swarm: &mut LocalSwarm, cli: &mut CliTestFramework) -> Ed255 .await .expect("Epoch 2 taking too long to come!"); + let maybe_response = client + .get_account_resource_bcs::( + AccountAddress::ONE, + "0x1::zkid::Groth16VerificationKey", + ) + .await; + let vk = maybe_response.unwrap().into_inner(); + println!("Groth16 VK: {:?}", vk); + + let maybe_response = client + .get_account_resource_bcs::(AccountAddress::ONE, "0x1::zkid::Configuration") + .await; + let config = maybe_response.unwrap().into_inner(); + println!("zkID configuration: {:?}", config); + let iss = "https://accounts.google.com"; let jwk = RSA_JWK { kid:"test_jwk".to_owned(), diff --git a/types/src/bn254_circom.rs b/types/src/bn254_circom.rs index 34d98c404c0b3..3e6098ba3d468 100644 --- a/types/src/bn254_circom.rs +++ b/types/src/bn254_circom.rs @@ -2,6 +2,7 @@ use crate::{ jwks::rsa::RSA_JWK, + move_utils::as_move_value::AsMoveValue, zkid::{Configuration, IdCommitment, ZkIdPublicKey, ZkIdSignature, ZkpOrOpenIdSig}, }; use anyhow::bail; @@ -10,7 +11,12 @@ use ark_bn254::{Bn254, Fq, Fq2, Fr, G1Affine, G1Projective, G2Affine, G2Projecti use ark_ff::PrimeField; use ark_groth16::{PreparedVerifyingKey, VerifyingKey}; use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -use move_core_types::{ident_str, identifier::IdentStr, move_resource::MoveStructType}; +use move_core_types::{ + ident_str, + identifier::IdentStr, + move_resource::MoveStructType, + value::{MoveStruct, MoveValue}, +}; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; use serde_big_array::BigArray; @@ -33,13 +39,27 @@ macro_rules! serialize { /// Reflection of aptos_framework::zkid::Groth16PreparedVerificationKey #[derive(Serialize, Deserialize, Debug)] pub struct Groth16VerificationKey { - alpha_g1: Vec, - beta_g2: Vec, - gamma_g2: Vec, - delta_g2: Vec, - gamma_abc_g1: Vec>, + pub alpha_g1: Vec, + pub beta_g2: Vec, + pub gamma_g2: Vec, + pub delta_g2: Vec, + pub gamma_abc_g1: Vec>, +} + +impl AsMoveValue for Groth16VerificationKey { + fn as_move_value(&self) -> MoveValue { + MoveValue::Struct(MoveStruct::Runtime(vec![ + self.alpha_g1.as_move_value(), + self.beta_g2.as_move_value(), + self.gamma_g2.as_move_value(), + self.delta_g2.as_move_value(), + self.gamma_abc_g1.as_move_value(), + ])) + } } +/// WARNING: This struct uses resource groups on the Move side. Do NOT implement OnChainConfig +/// for it, since `OnChainConfig::fetch_config` does not work with resource groups (yet). impl MoveStructType for Groth16VerificationKey { const MODULE_NAME: &'static IdentStr = ident_str!("zkid"); const STRUCT_NAME: &'static IdentStr = ident_str!("Groth16VerificationKey"); @@ -322,6 +342,7 @@ pub fn get_public_inputs_hash( sig: &ZkIdSignature, pk: &ZkIdPublicKey, jwk: &RSA_JWK, + exp_horizon_secs: u64, config: &Configuration, ) -> anyhow::Result { let extra_field_hashed; @@ -360,7 +381,7 @@ pub fn get_public_inputs_hash( frs.push(Fr::from(sig.exp_timestamp_secs)); // Add the epk lifespan as a scalar - frs.push(Fr::from(config.max_exp_horizon_secs)); + frs.push(Fr::from(exp_horizon_secs)); // Add the hash of the iss (formatted key-value pair string). let formatted_iss = format!("\"iss\":\"{}\",", pk.iss); diff --git a/types/src/jwks/mod.rs b/types/src/jwks/mod.rs index bae7c46633964..0bd884eb5a524 100644 --- a/types/src/jwks/mod.rs +++ b/types/src/jwks/mod.rs @@ -184,9 +184,9 @@ impl PatchedJWKs { } } -impl MoveStructType for PatchedJWKs { - const MODULE_NAME: &'static IdentStr = ident_str!("jwks"); - const STRUCT_NAME: &'static IdentStr = ident_str!("PatchedJWKs"); +impl OnChainConfig for PatchedJWKs { + const MODULE_IDENTIFIER: &'static str = "jwks"; + const TYPE_IDENTIFIER: &'static str = "PatchedJWKs"; } /// A JWK update in format of `ProviderJWKs` and a multi-signature of it as a quorum certificate. diff --git a/types/src/move_utils/as_move_value.rs b/types/src/move_utils/as_move_value.rs index 6e3634107cf18..6e99c6e89ec06 100644 --- a/types/src/move_utils/as_move_value.rs +++ b/types/src/move_utils/as_move_value.rs @@ -39,6 +39,18 @@ impl AsMoveValue for u8 { } } +impl AsMoveValue for u16 { + fn as_move_value(&self) -> MoveValue { + MoveValue::U16(*self) + } +} + +impl AsMoveValue for u32 { + fn as_move_value(&self) -> MoveValue { + MoveValue::U32(*self) + } +} + impl AsMoveValue for u64 { fn as_move_value(&self) -> MoveValue { MoveValue::U64(*self) diff --git a/types/src/on_chain_config/mod.rs b/types/src/on_chain_config/mod.rs index fee2010623a21..960945cbc5185 100644 --- a/types/src/on_chain_config/mod.rs +++ b/types/src/on_chain_config/mod.rs @@ -161,6 +161,7 @@ pub trait OnChainConfig: Send + Sync + DeserializeOwned { Self::deserialize_default_impl(bytes) } + /// TODO: This does not work if `T`'s reflection on the Move side is using resource groups. fn fetch_config(storage: &T) -> Option where T: ConfigStorage + ?Sized, diff --git a/types/src/transaction/authenticator.rs b/types/src/transaction/authenticator.rs index cb354f032a08d..05483e7c0c10f 100644 --- a/types/src/transaction/authenticator.rs +++ b/types/src/transaction/authenticator.rs @@ -1126,7 +1126,7 @@ mod tests { use crate::{ bn254_circom::{G1Bytes, G2Bytes}, transaction::{webauthn::AssertionSignature, SignedTransaction}, - zkid::{Groth16Zkp, IdCommitment, OpenIdSig, Pepper, SignedGroth16Zkp}, + zkid::{Configuration, Groth16Zkp, IdCommitment, OpenIdSig, Pepper, SignedGroth16Zkp}, }; use aptos_crypto::{ ed25519::Ed25519PrivateKey, @@ -1797,6 +1797,7 @@ mod tests { let proof_sig = sender.sign(&proof).unwrap(); let ephem_proof_sig = EphemeralSignature::ed25519(proof_sig); ephem_proof_sig.verify(&proof, &epk).unwrap(); + let config = Configuration::new_for_devnet_and_testing(); let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), @@ -1806,6 +1807,7 @@ mod tests { ), extra_field: "\"family_name\":\"Straka\",".to_string(), override_aud_val: None, + exp_horizon_secs: config.max_exp_horizon_secs, }), jwt_header: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_owned(), exp_timestamp_secs: 1900255944, diff --git a/types/src/zkid.rs b/types/src/zkid.rs index 03ade9234cc0b..4a6e5e6906fca 100644 --- a/types/src/zkid.rs +++ b/types/src/zkid.rs @@ -3,6 +3,7 @@ use crate::{ bn254_circom::{G1Bytes, G2Bytes}, jwks::rsa::RSA_JWK, + move_utils::as_move_value::AsMoveValue, on_chain_config::CurrentTimeMicroseconds, transaction::{ authenticator::{ @@ -22,6 +23,7 @@ use move_core_types::{ ident_str, identifier::IdentStr, move_resource::MoveStructType, + value::{MoveStruct, MoveValue}, vm_status::{StatusCode, VMStatus}, }; use serde::{Deserialize, Serialize}; @@ -59,17 +61,34 @@ pub struct Configuration { pub max_jwt_header_b64_bytes: u32, } +impl AsMoveValue for Configuration { + fn as_move_value(&self) -> MoveValue { + MoveValue::Struct(MoveStruct::Runtime(vec![ + self.override_aud_vals.as_move_value(), + self.max_zkid_signatures_per_txn.as_move_value(), + self.max_exp_horizon_secs.as_move_value(), + self.training_wheels_pubkey.as_move_value(), + self.nonce_commitment_num_bytes.as_move_value(), + self.max_commited_epk_bytes.as_move_value(), + self.max_iss_field_bytes.as_move_value(), + self.max_extra_field_bytes.as_move_value(), + self.max_jwt_header_b64_bytes.as_move_value(), + ])) + } +} + +/// WARNING: This struct uses resource groups on the Move side. Do NOT implement OnChainConfig +/// for it, since `OnChainConfig::fetch_config` does not work with resource groups (yet). impl MoveStructType for Configuration { const MODULE_NAME: &'static IdentStr = ident_str!("zkid"); const STRUCT_NAME: &'static IdentStr = ident_str!("Configuration"); } impl Configuration { - #[cfg(test)] - const OVERRIDE_AUD_FOR_TESTING: &'static str = "some_override_aud"; + /// Should only be used for testing. + pub const OVERRIDE_AUD_FOR_TESTING: &'static str = "some_override_aud"; - #[cfg(test)] - pub fn new_for_testing() -> Configuration { + pub fn new_for_devnet_and_testing() -> Configuration { const POSEIDON_BYTES_PACKED_PER_SCALAR: u16 = 31; Configuration { @@ -292,11 +311,18 @@ pub struct Groth16Zkp { #[derive(Clone, Debug, Deserialize, PartialEq, Eq, Hash, Serialize)] pub struct SignedGroth16Zkp { pub proof: Groth16Zkp, - /// The signature of the proof signed by the private key of the `ephemeral_pubkey`. + /// A signature on the proof (via the ephemeral SK) to prevent malleability attacks. pub non_malleability_signature: EphemeralSignature, + /// A signature on the proof (via the training wheels SK) to mitigate against flaws in our circuit pub training_wheels_signature: EphemeralSignature, + /// An extra field (e.g., `"":"") that will be matched publicly in the JWT pub extra_field: String, + /// Will be set to the override `aud` value that the circuit should match, instead of the `aud` in the IDC. + /// This will allow users to recover their zkID accounts derived by an application that is no longer online. pub override_aud_val: Option, + /// The expiration horizon that the circuit should enforce on the expiration date committed in the nonce. + /// This must be <= `Configuration::max_expiration_horizon_secs`. + pub exp_horizon_secs: u64, } impl SignedGroth16Zkp { @@ -664,6 +690,7 @@ mod test { let proof_sig = sender.sign(&proof).unwrap(); let ephem_proof_sig = EphemeralSignature::ed25519(proof_sig); + let config = Configuration::new_for_devnet_and_testing(); let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), @@ -673,6 +700,7 @@ mod test { ), extra_field: "\"family_name\":\"Straka\",".to_string(), override_aud_val: None, + exp_horizon_secs: config.max_exp_horizon_secs, }), jwt_header: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_owned(), exp_timestamp_secs: 1900255944, @@ -702,7 +730,7 @@ mod test { }; let public_inputs_hash = - get_public_inputs_hash(&zk_sig, &zk_pk, &jwk, &Configuration::new_for_testing()) + get_public_inputs_hash(&zk_sig, &zk_pk, &jwk, config.max_exp_horizon_secs, &config) .unwrap(); proof @@ -759,7 +787,7 @@ mod test { let uid_key = "sub"; let uid_val = "248289761001"; let exp_timestamp_secs = 1311281970; - let config = Configuration::new_for_testing(); + let config = Configuration::new_for_devnet_and_testing(); let pepper = 76; let zkid_pk = ZkIdPublicKey { From 2b3cce44b3e54cb30a74d86d077ce372d793610f Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Thu, 8 Feb 2024 22:41:34 -0800 Subject: [PATCH 049/328] [dag] broadcast nodes within window till all validators ack (#11751) * [dag] broadcast nodes within window till all validators ack * [dag] use DropGuard to drop handles * move BoundedVecDeque to aptos-collections * use BoundedVecDeque in MetadataAdapter --- Cargo.lock | 5 + Cargo.toml | 20 +++- consensus/Cargo.toml | 10 +- .../leader_reputation_adapter.rs | 16 +-- consensus/src/dag/dag_driver.rs | 23 ++-- crates/aptos-collections/Cargo.toml | 15 +++ .../src/bounded_vec_deque.rs | 100 ++++++++++++++++++ crates/aptos-collections/src/lib.rs | 5 + 8 files changed, 163 insertions(+), 31 deletions(-) create mode 100644 crates/aptos-collections/Cargo.toml create mode 100644 crates/aptos-collections/src/bounded_vec_deque.rs create mode 100644 crates/aptos-collections/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f4bff31a1d2ea..77d96186f631b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -762,6 +762,10 @@ dependencies = [ "clap_complete", ] +[[package]] +name = "aptos-collections" +version = "0.1.0" + [[package]] name = "aptos-comparison-testing" version = "0.1.0" @@ -867,6 +871,7 @@ dependencies = [ "aptos-bounded-executor", "aptos-cached-packages", "aptos-channels", + "aptos-collections", "aptos-config", "aptos-consensus-notifications", "aptos-consensus-types", diff --git a/Cargo.toml b/Cargo.toml index a38f2f4190375..b7d1760740736 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ members = [ "crates/aptos-bcs-utils", "crates/aptos-bitvec", "crates/aptos-build-info", + "crates/aptos-collections", "crates/aptos-compression", "crates/aptos-crypto", "crates/aptos-crypto-derive", @@ -291,6 +292,7 @@ aptos-build-info = { path = "crates/aptos-build-info" } aptos-cached-packages = { path = "aptos-move/framework/cached-packages" } aptos-channels = { path = "crates/channel" } aptos-cli-common = { path = "crates/aptos-cli-common" } +aptos-collections = { path = "crates/aptos-collections" } aptos-compression = { path = "crates/aptos-compression" } aptos-consensus = { path = "consensus" } aptos-consensus-notifications = { path = "state-sync/inter-component/consensus-notifications" } @@ -486,7 +488,10 @@ claims = "0.7" clap = { version = "4.3.9", features = ["derive", "unstable-styles"] } clap-verbosity-flag = "2.1.1" clap_complete = "4.4.1" -cloud-storage = { version = "0.11.1", features = ["global-client", "rustls-tls"], default-features = false } +cloud-storage = { version = "0.11.1", features = [ + "global-client", + "rustls-tls", +], default-features = false } codespan-reporting = "0.11.1" concurrent-queue = "2.2.0" console-subscriber = "0.1.8" @@ -618,7 +623,11 @@ rand = "0.7.3" rand_core = "0.5.1" random_word = "0.3.0" rayon = "1.5.2" -redis = { version = "0.22.3", features = ["tokio-comp", "script", "connection-manager"] } +redis = { version = "0.22.3", features = [ + "tokio-comp", + "script", + "connection-manager", +] } redis-test = { version = "0.1.1", features = ["aio"] } regex = "1.9.3" reqwest = { version = "0.11.11", features = [ @@ -632,7 +641,7 @@ reqwest-retry = "0.2.1" ring = { version = "0.16.20", features = ["std"] } ripemd = "0.1.1" rocksdb = { version = "0.21.0", features = ["lz4"] } -rstack-self = { version = "0.3.0", features = ["dw"], default_features = false } +rstack-self = { version = "0.3.0", features = ["dw"], default_features = false } rstest = "0.15.0" rusty-fork = "0.3.0" rustversion = "1.0.14" @@ -646,7 +655,10 @@ siphasher = "0.3.10" serde = { version = "1.0.193", features = ["derive", "rc"] } serde-big-array = "0.5.1" serde_bytes = "0.11.6" -serde_json = { version = "1.0.81", features = ["preserve_order", "arbitrary_precision"] } # Note: arbitrary_precision is required to parse u256 in JSON +serde_json = { version = "1.0.81", features = [ + "preserve_order", + "arbitrary_precision", +] } # Note: arbitrary_precision is required to parse u256 in JSON serde_repr = "0.1" serde_merge = "0.1.3" serde-name = "0.1.1" diff --git a/consensus/Cargo.toml b/consensus/Cargo.toml index ed3bbfee77989..275ebe0ba527f 100644 --- a/consensus/Cargo.toml +++ b/consensus/Cargo.toml @@ -17,6 +17,7 @@ anyhow = { workspace = true } aptos-bitvec = { workspace = true } aptos-bounded-executor = { workspace = true } aptos-channels = { workspace = true } +aptos-collections = { workspace = true } aptos-config = { workspace = true } aptos-consensus-notifications = { workspace = true } aptos-consensus-types = { workspace = true } @@ -97,5 +98,12 @@ tempfile = { workspace = true } [features] default = [] -fuzzing = ["aptos-consensus-types/fuzzing", "aptos-config/fuzzing", "aptos-crypto/fuzzing", "aptos-mempool/fuzzing", "aptos-types/fuzzing", "aptos-safety-rules/testing"] +fuzzing = [ + "aptos-consensus-types/fuzzing", + "aptos-config/fuzzing", + "aptos-crypto/fuzzing", + "aptos-mempool/fuzzing", + "aptos-types/fuzzing", + "aptos-safety-rules/testing", +] failpoints = ["fail/failpoints"] diff --git a/consensus/src/dag/anchor_election/leader_reputation_adapter.rs b/consensus/src/dag/anchor_election/leader_reputation_adapter.rs index ea34d450eb937..3d58d5cd31b47 100644 --- a/consensus/src/dag/anchor_election/leader_reputation_adapter.rs +++ b/consensus/src/dag/anchor_election/leader_reputation_adapter.rs @@ -14,20 +14,18 @@ use crate::{ }, }; use aptos_bitvec::BitVec; +use aptos_collections::BoundedVecDeque; use aptos_consensus_types::common::{Author, Round}; use aptos_crypto::HashValue; use aptos_infallible::Mutex; use aptos_types::account_config::NewBlockEvent; use move_core_types::account_address::AccountAddress; -use std::{ - collections::{HashMap, VecDeque}, - sync::Arc, -}; +use std::{collections::HashMap, sync::Arc}; pub struct MetadataBackendAdapter { epoch_to_validators: HashMap>, window_size: usize, - sliding_window: Mutex>, + sliding_window: Mutex>, } impl MetadataBackendAdapter { @@ -38,7 +36,7 @@ impl MetadataBackendAdapter { Self { epoch_to_validators, window_size, - sliding_window: Mutex::new(VecDeque::new()), + sliding_window: Mutex::new(BoundedVecDeque::new(window_size)), } } @@ -46,11 +44,7 @@ impl MetadataBackendAdapter { if !self.epoch_to_validators.contains_key(&event.epoch()) { return; } - let mut lock = self.sliding_window.lock(); - if lock.len() == self.window_size { - lock.pop_back(); - } - lock.push_front(event); + self.sliding_window.lock().push_front(event); } // TODO: we should change NewBlockEvent on LeaderReputation to take a trait diff --git a/consensus/src/dag/dag_driver.rs b/consensus/src/dag/dag_driver.rs index ff7487915702f..682602be07f5c 100644 --- a/consensus/src/dag/dag_driver.rs +++ b/consensus/src/dag/dag_driver.rs @@ -24,12 +24,13 @@ use crate::{ payload_client::PayloadClient, }; use anyhow::{bail, ensure}; +use aptos_collections::BoundedVecDeque; use aptos_config::config::DagPayloadConfig; use aptos_consensus_types::common::{Author, Payload, PayloadFilter}; use aptos_crypto::hash::CryptoHash; use aptos_infallible::Mutex; use aptos_logger::{debug, error}; -use aptos_reliable_broadcast::ReliableBroadcast; +use aptos_reliable_broadcast::{DropGuard, ReliableBroadcast}; use aptos_time_service::{TimeService, TimeServiceTrait}; use aptos_types::{block_info::Round, epoch_state::EpochState}; use aptos_validator_transaction_pool as vtxn_pool; @@ -49,7 +50,7 @@ pub(crate) struct DagDriver { payload_client: Arc, reliable_broadcast: Arc>, time_service: TimeService, - rb_abort_handle: Mutex>, + rb_handles: Mutex>, storage: Arc, order_rule: Mutex, fetch_requester: Arc, @@ -93,7 +94,7 @@ impl DagDriver { payload_client, reliable_broadcast, time_service, - rb_abort_handle: Mutex::new(None), + rb_handles: Mutex::new(BoundedVecDeque::new(window_size_config as usize)), storage, order_rule: Mutex::new(order_rule), fetch_requester, @@ -319,13 +320,13 @@ impl DagDriver { debug!("Finish reliable broadcast for round {}", round); }; tokio::spawn(Abortable::new(task, abort_registration)); - if let Some((prev_handle, prev_round_timestamp)) = self - .rb_abort_handle + if let Some((_handle, prev_round_timestamp)) = self + .rb_handles .lock() - .replace((abort_handle, timestamp)) + .push_back((DropGuard::new(abort_handle), timestamp)) { + // TODO: this observation is inaccurate. observe_round(prev_round_timestamp, RoundStage::Finished); - prev_handle.abort(); } } } @@ -355,11 +356,3 @@ impl RpcHandler for DagDriver { Ok(CertifiedAck::new(epoch)) } } - -impl Drop for DagDriver { - fn drop(&mut self) { - if let Some((handle, _)) = self.rb_abort_handle.lock().as_ref() { - handle.abort() - } - } -} diff --git a/crates/aptos-collections/Cargo.toml b/crates/aptos-collections/Cargo.toml new file mode 100644 index 0000000000000..69c953a35c639 --- /dev/null +++ b/crates/aptos-collections/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "aptos-collections" +description = "Aptos Collections Library" +version = "0.1.0" + +# Workspace inherited keys +authors = { workspace = true } +edition = { workspace = true } +homepage = { workspace = true } +license = { workspace = true } +publish = { workspace = true } +repository = { workspace = true } +rust-version = { workspace = true } + +[dependencies] diff --git a/crates/aptos-collections/src/bounded_vec_deque.rs b/crates/aptos-collections/src/bounded_vec_deque.rs new file mode 100644 index 0000000000000..f21b7a409074e --- /dev/null +++ b/crates/aptos-collections/src/bounded_vec_deque.rs @@ -0,0 +1,100 @@ +// Copyright © Aptos Foundation + +use std::collections::{ + vec_deque::{IntoIter, Iter}, + VecDeque, +}; + +#[derive(Clone)] +pub struct BoundedVecDeque { + inner: VecDeque, + capacity: usize, +} + +impl BoundedVecDeque { + pub fn new(capacity: usize) -> Self { + assert!(capacity > 0); + Self { + inner: VecDeque::with_capacity(capacity), + capacity, + } + } + + pub fn is_full(&self) -> bool { + self.inner.len() == self.capacity + } + + pub fn push_back(&mut self, item: T) -> Option { + let oldest = if self.is_full() { + self.inner.pop_front() + } else { + None + }; + + self.inner.push_back(item); + assert!(self.inner.len() <= self.capacity); + oldest + } + + pub fn push_front(&mut self, item: T) -> Option { + let oldest = if self.is_full() { + self.inner.pop_back() + } else { + None + }; + + self.inner.push_front(item); + assert!(self.inner.len() <= self.capacity); + oldest + } + + pub fn iter(&self) -> Iter<'_, T> { + self.inner.iter() + } +} + +impl IntoIterator for BoundedVecDeque { + type IntoIter = IntoIter; + type Item = T; + + fn into_iter(self) -> Self::IntoIter { + self.inner.into_iter() + } +} + +#[cfg(test)] +mod tests { + use super::BoundedVecDeque; + + #[test] + fn test_bounded_vec_deque_capacity() { + let capacity = 10; + let mut queue = BoundedVecDeque::new(capacity); + for i in 0..capacity { + queue.push_back(i); + } + + assert!(queue.is_full()); + + assert_eq!(queue.push_back(capacity), Some(0)); + + assert_eq!(queue.push_front(0), Some(capacity)); + } + + #[test] + fn test_bounded_vec_deque_iter() { + let capacity = 10; + let mut queue = BoundedVecDeque::new(capacity); + for i in 0..capacity { + queue.push_back(i); + } + + for (i, item) in queue.iter().enumerate() { + assert_eq!(i, *item); + } + + for (i, item) in queue.into_iter().enumerate() { + assert_eq!(i, item); + } + } +} diff --git a/crates/aptos-collections/src/lib.rs b/crates/aptos-collections/src/lib.rs new file mode 100644 index 0000000000000..231323078d2bf --- /dev/null +++ b/crates/aptos-collections/src/lib.rs @@ -0,0 +1,5 @@ +// Copyright © Aptos Foundation + +mod bounded_vec_deque; + +pub use bounded_vec_deque::BoundedVecDeque; From c6f0b03e05d9113099c0bd510c35bd90712dad2c Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Fri, 9 Feb 2024 12:49:18 +0100 Subject: [PATCH 050/328] [trivial] Remove aptos-fuzzer (#11967) --- Cargo.lock | 65 ---- Cargo.toml | 3 - testsuite/aptos-fuzzer/Cargo.toml | 55 ---- testsuite/aptos-fuzzer/README.md | 156 --------- .../CompiledModuleTarget/crash-5d65cfbc | Bin 8353 -> 0 bytes .../CompiledModuleTarget/oom-54725f11 | Bin 3481 -> 0 bytes ...h-34c5631cb9944549796a14547cef7223a6ab78d6 | Bin 947 -> 0 bytes ...h-7619620b59914850df844994de43e3d10684f2b6 | Bin 23 -> 0 bytes ...m-9761fc3aeea49b5f4420ff159ca3f8a6fb0502d0 | Bin 29 -> 0 bytes .../artifacts/ValueTarget/oom-ce8ba3d1 | Bin 51 -> 0 bytes .../insufficient_key_len_slicing_error | Bin 20 -> 0 bytes testsuite/aptos-fuzzer/fuzz/.gitignore | 4 - testsuite/aptos-fuzzer/fuzz/Cargo.toml | 32 -- testsuite/aptos-fuzzer/fuzz/build.rs | 30 -- .../fuzz/fuzz_targets/fuzz_runner.rs | 28 -- .../fuzz/google-oss-fuzz/build.sh | 33 -- .../fuzz/google-oss-fuzz/build_corpus.sh | 14 - .../fuzz/google-oss-fuzz/build_fuzzer.sh | 47 --- .../fuzz/google-oss-fuzz/fuzzer_builder.rs | 16 - testsuite/aptos-fuzzer/lsan_suppressions.txt | 3 - testsuite/aptos-fuzzer/src/bin/flamegraph.rs | 39 --- testsuite/aptos-fuzzer/src/bin/investigate.rs | 55 ---- testsuite/aptos-fuzzer/src/commands.rs | 122 ------- testsuite/aptos-fuzzer/src/coverage.rs | 56 ---- testsuite/aptos-fuzzer/src/fuzz_targets.rs | 117 ------- .../src/fuzz_targets/consensus.rs | 24 -- .../aptos-fuzzer/src/fuzz_targets/executor.rs | 40 --- .../aptos-fuzzer/src/fuzz_targets/mempool.rs | 30 -- .../aptos-fuzzer/src/fuzz_targets/move_vm.rs | 90 ------ .../aptos-fuzzer/src/fuzz_targets/network.rs | 125 -------- .../aptos-fuzzer/src/fuzz_targets/proof.rs | 170 ---------- .../src/fuzz_targets/safety_rules.rs | 110 ------- .../src/fuzz_targets/secure_storage_vault.rs | 299 ------------------ .../aptos-fuzzer/src/fuzz_targets/storage.rs | 279 ---------------- .../src/fuzz_targets/transaction.rs | 146 --------- testsuite/aptos-fuzzer/src/fuzz_targets/vm.rs | 32 -- testsuite/aptos-fuzzer/src/lib.rs | 105 ------ testsuite/aptos-fuzzer/src/main.rs | 152 --------- testsuite/aptos-fuzzer/tests/artifacts.rs | 83 ----- 39 files changed, 2560 deletions(-) delete mode 100644 testsuite/aptos-fuzzer/Cargo.toml delete mode 100644 testsuite/aptos-fuzzer/README.md delete mode 100644 testsuite/aptos-fuzzer/artifacts/CompiledModuleTarget/crash-5d65cfbc delete mode 100644 testsuite/aptos-fuzzer/artifacts/CompiledModuleTarget/oom-54725f11 delete mode 100644 testsuite/aptos-fuzzer/artifacts/ConsensusProposal/crash-34c5631cb9944549796a14547cef7223a6ab78d6 delete mode 100644 testsuite/aptos-fuzzer/artifacts/ValueTarget/crash-7619620b59914850df844994de43e3d10684f2b6 delete mode 100644 testsuite/aptos-fuzzer/artifacts/ValueTarget/oom-9761fc3aeea49b5f4420ff159ca3f8a6fb0502d0 delete mode 100644 testsuite/aptos-fuzzer/artifacts/ValueTarget/oom-ce8ba3d1 delete mode 100644 testsuite/aptos-fuzzer/artifacts/VaultTransitExportResponse/insufficient_key_len_slicing_error delete mode 100644 testsuite/aptos-fuzzer/fuzz/.gitignore delete mode 100644 testsuite/aptos-fuzzer/fuzz/Cargo.toml delete mode 100644 testsuite/aptos-fuzzer/fuzz/build.rs delete mode 100644 testsuite/aptos-fuzzer/fuzz/fuzz_targets/fuzz_runner.rs delete mode 100755 testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build.sh delete mode 100755 testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_corpus.sh delete mode 100755 testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_fuzzer.sh delete mode 100755 testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/fuzzer_builder.rs delete mode 100644 testsuite/aptos-fuzzer/lsan_suppressions.txt delete mode 100644 testsuite/aptos-fuzzer/src/bin/flamegraph.rs delete mode 100644 testsuite/aptos-fuzzer/src/bin/investigate.rs delete mode 100644 testsuite/aptos-fuzzer/src/commands.rs delete mode 100644 testsuite/aptos-fuzzer/src/coverage.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/consensus.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/executor.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/mempool.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/move_vm.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/network.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/proof.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/safety_rules.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/secure_storage_vault.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/storage.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/transaction.rs delete mode 100644 testsuite/aptos-fuzzer/src/fuzz_targets/vm.rs delete mode 100644 testsuite/aptos-fuzzer/src/lib.rs delete mode 100644 testsuite/aptos-fuzzer/src/main.rs delete mode 100644 testsuite/aptos-fuzzer/tests/artifacts.rs diff --git a/Cargo.lock b/Cargo.lock index 77d96186f631b..0c814dcbfa08b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1855,54 +1855,6 @@ dependencies = [ "tiny-keccak", ] -[[package]] -name = "aptos-fuzz" -version = "0.1.0" -dependencies = [ - "aptos-fuzzer", - "libfuzzer-sys", - "once_cell", -] - -[[package]] -name = "aptos-fuzzer" -version = "0.1.0" -dependencies = [ - "anyhow", - "aptos-accumulator", - "aptos-consensus", - "aptos-consensus-types", - "aptos-crypto", - "aptos-db", - "aptos-executor", - "aptos-executor-types", - "aptos-jellyfish-merkle", - "aptos-language-e2e-tests", - "aptos-mempool", - "aptos-network", - "aptos-proptest-helpers", - "aptos-safety-rules", - "aptos-scratchpad", - "aptos-storage-interface", - "aptos-types", - "aptos-vault-client", - "bcs 0.1.4", - "byteorder", - "clap 4.4.14", - "datatest-stable", - "hex", - "move-binary-format", - "move-core-types", - "move-vm-types", - "once_cell", - "proptest", - "proptest-derive 0.4.0", - "rand 0.7.3", - "rusty-fork", - "sha-1", - "stats_alloc", -] - [[package]] name = "aptos-gas-algebra" version = "0.0.1" @@ -14565,17 +14517,6 @@ dependencies = [ "warp", ] -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - [[package]] name = "sha1" version = "0.10.6" @@ -15057,12 +14998,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "stats_alloc" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c0e04424e733e69714ca1bbb9204c1a57f09f5493439520f9f68c132ad25eec" - [[package]] name = "status-line" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index b7d1760740736..464e6f6e906f4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,8 +168,6 @@ members = [ "storage/schemadb", "storage/scratchpad", "storage/storage-interface", - "testsuite/aptos-fuzzer", - "testsuite/aptos-fuzzer/fuzz", "testsuite/dos/http_test", "testsuite/dos/listener", "testsuite/dos/sender", @@ -327,7 +325,6 @@ aptos-faucet-metrics-server = { path = "crates/aptos-faucet/metrics-server" } aptos-fallible = { path = "crates/fallible" } aptos-forge = { path = "testsuite/forge" } aptos-framework = { path = "aptos-move/framework" } -aptos-fuzzer = { path = "testsuite/aptos-fuzzer" } fuzzer = { path = "testsuite/fuzzer" } aptos-abstract-gas-usage = { path = "aptos-move/aptos-abstract-gas-usage" } aptos-gas-meter = { path = "aptos-move/aptos-gas-meter" } diff --git a/testsuite/aptos-fuzzer/Cargo.toml b/testsuite/aptos-fuzzer/Cargo.toml deleted file mode 100644 index c4d560e81c6ff..0000000000000 --- a/testsuite/aptos-fuzzer/Cargo.toml +++ /dev/null @@ -1,55 +0,0 @@ -[package] -name = "aptos-fuzzer" -description = "Aptos fuzzer" -version = "0.1.0" - -# Workspace inherited keys -authors = { workspace = true } -edition = { workspace = true } -homepage = { workspace = true } -license = { workspace = true } -publish = { workspace = true } -repository = { workspace = true } -rust-version = { workspace = true } - -[dependencies] -anyhow = { workspace = true } -aptos-accumulator = { workspace = true, features = ["fuzzing"] } -aptos-consensus = { workspace = true, features = ["fuzzing"] } -aptos-consensus-types = { workspace = true, features = ["fuzzing"] } -aptos-crypto = { workspace = true, features = ["fuzzing"] } -aptos-db = { workspace = true, features = ["fuzzing"] } -aptos-executor = { workspace = true, features = ["fuzzing"] } -aptos-executor-types = { workspace = true, features = ["fuzzing"] } -aptos-jellyfish-merkle = { workspace = true, features = ["fuzzing"] } -aptos-language-e2e-tests = { workspace = true } -aptos-mempool = { workspace = true } -aptos-network = { workspace = true, features = ["fuzzing"] } -aptos-proptest-helpers = { workspace = true } -aptos-safety-rules = { workspace = true, features = ["fuzzing", "testing"] } -aptos-scratchpad = { workspace = true, features = ["fuzzing"] } -aptos-storage-interface = { workspace = true } -aptos-types = { workspace = true, features = ["fuzzing"] } -aptos-vault-client = { workspace = true, features = ["fuzzing"] } -bcs = { workspace = true } -byteorder = { workspace = true } -clap = { workspace = true } -hex = { workspace = true } -move-binary-format = { workspace = true, features = ["fuzzing"] } -move-core-types = { workspace = true, features = ["fuzzing"] } -move-vm-types = { workspace = true, features = ["fuzzing"] } -once_cell = { workspace = true } -proptest = { workspace = true } -proptest-derive = { workspace = true } -rand = { workspace = true } -rusty-fork = { workspace = true } -sha-1 = { workspace = true } - -[dev-dependencies] -datatest-stable = { workspace = true } -rusty-fork = { workspace = true } -stats_alloc = { workspace = true } - -[[test]] -harness = false -name = "artifacts" diff --git a/testsuite/aptos-fuzzer/README.md b/testsuite/aptos-fuzzer/README.md deleted file mode 100644 index aee26b2ad8f61..0000000000000 --- a/testsuite/aptos-fuzzer/README.md +++ /dev/null @@ -1,156 +0,0 @@ -## Fuzzing support for Aptos - -This crate contains support for fuzzing Aptos targets. This support sincludes: - -* corpus generation with `proptest` -* automatically running failing examples with `cargo test` - -### Prerequisites - -Install [`cargo-fuzz`](https://rust-fuzz.github.io/book/cargo-fuzz.html) if not already available: `cargo install cargo-fuzz`. - -### Fuzzing a target - -First, switch to the directory this README is in: `cd testsuite/aptos-fuzzer`. - -To list out known fuzz targets, run `cargo run --bin aptos-fuzzer list`. - -To be effective, fuzzing requires a corpus of existing inputs. This -crate contains support for generating corpuses with `proptest`. Generate -a corpus with `cargo run --bin aptos-fuzzer generate `. - -Once a corpus has been generated, the fuzzer is ready to use, simply run: - -``` -RUSTC_BOOTSTRAP=1 cargo run --bin aptos-fuzzer --release fuzz -``` - -For more options, run `cargo run --bin aptos-fuzzer -- --help`. Note that `RUSTC_BOOTSTRAP=1` is -required as `cargo fuzz` uses unstable compiler flags. - -### Adding a new target - -Fuzz targets go in `src/fuzz_targets/`. Adding a new target involves -creating a new type and implementing `FuzzTargetImpl` for it. - -For examples, see the existing implementations in `src/fuzz_targets/`. - -Remember to add your target to `ALL_TARGETS` in `src/fuzz_targets.rs`. -Once that has been done, `cargo run --bin aptos-fuzzer list` should list your new target. - -### Debugging and testing artifacts - -If the fuzzer finds a failing artifact, it will save the artifact to a -file inside the `fuzz` directory and print its path. To add this -artifact to the test suite, copy it to a file inside -`artifacts//`. - -`cargo test` will now test the deserializer against the new artifact. -The test will likely fail at first use. - -Note that `cargo test` runs each test in a separate process by default -to isolate failures and memory usage; if you're attaching a debugger and -are running a single test, set `NO_FORK=1` to disable forking. - -Once the deserializer has been fixed, check the artifact into the -`artifacts//` directory. The artifact will then act as a -regression test in `cargo test` runs. - -There are two ways to reproduce an issue to investigate a finding: - -1. run the harness test (the code the fuzzer runs) directly -2. run the fuzzer code - -The following command (with your own artifact contained in a similar path) -will run the harness test with your input: - -``` -cargo run --bin investigate -- -i artifacts/compiled_module/crash-5d7f403f -``` - -The following command will run libfuzzer on the relevant target with your input: - -``` -# build single fuzzer for target using instruction in the 'google oss-fuzz integration' section -./fuzzer input -``` - -Note that this should work out of the box for crashes, -but timeouts might need a `-timeout 25` argument to libfuzzer, -and out of memory might need a `-rss_limit_mb=2560` argumnent to libfuzzer. - -See [Google OSS-Fuzz's documentation on reproducing bugs](https://google.github.io/oss-fuzz/advanced-topics/reproducing/) as well. - -### Flamegraph - -To obtain a flamegraph of a harness test, run the following command: - -```sh -FUZZ_TARGET=compiled_module cargo flamegraph -p aptos-fuzzer --bin flamegraph -``` - -It is good to first generate some corpus and run the fuzzer over it for a bit (to find new corpus). The larger corpus, the better flamegraph you will obtain. - -### Fuzzing Coverage - -To test coverage of our fuzzers you can run the following command with [grcov](https://github.com/mozilla/grcov): - -```sh -RUSTFLAGS='--cfg feature="fuzzing"' CORPUS_PATH=fuzz/corpus cargo xtest --html-cov-dir -p aptos-fuzzer -- --test-threads 1 --ignored coverage -``` - -### Building a single fuzzer - -To integrate our fuzzers with [Google OSS-Fuzz](https://github.com/google/oss-fuzz) project, -we need to have one binary per fuzzer. -This can also be handy when you want to analyze a fuzzer with tools like Instruments. -For this, build.rs can create a fuzzer binary based on an environement variable. -Use it as such: - -```sh -cd aptos-core/testsuite/aptos-fuzzer -fuzz/google-oss-fuzz/build_fuzzer.sh ConsensusProposal . -./ConsensusProposal -``` - -### Troubleshooting - -#### My backtrace does not contain file names and line numbers - -You need to use `llvm-symbolizer`, see https://github.com/rust-fuzz/cargo-fuzz/issues/160 - -#### macOS: Linking with `cc` failed - -Make sure Xcode is updated to the latest version. Remeber to actually -`xcode-select` the new app folder and `cargo clean` before rebuilding again. - -```sh -sudo xcode-select -s /Applications/Xcode_X.Y.Z.app -``` - -If you get a linker error like - -```sh -$ RUSTC_BOOTSTRAP=1 cargo run --bin aptos-fuzzer --release fuzz -# ... -error: linking with `cc` failed: exit code: 1 - | - = note: "cc" "-m64" "-L" "/Users/philiphayes/.rustup/toolchains/nightly-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" # ... - = note: Undefined symbols for architecture x86_64: - "_CFMutableAttributedStringGetTypeID", referenced from: - _$LT$core_foundation..attributed_string..CFMutableAttributedString$u20$as$u20$core_foundation..base..TCFType$GT$::type_id::h9f6f71bdd347aca0 # ... - ld: symbol(s) not found for architecture x86_64 - clang: error: linker command failed with exit code 1 (use -v to see invocation) - -error: aborting due to previous error -``` - -This is probably due to an issue in core-foundation-rs (https://github.com/servo/core-foundation-rs/pull/357) -that was fixed in the latest version, but one of our transitive dependencies -`native-tls` only has the update in its `master` branch. To fix this problem, add -the following to the end of `aptos-core/Cargo.toml`: - -```toml -[patch.crates-io] -native-tls = { git = "https://github.com/sfackler/rust-native-tls" } -``` diff --git a/testsuite/aptos-fuzzer/artifacts/CompiledModuleTarget/crash-5d65cfbc b/testsuite/aptos-fuzzer/artifacts/CompiledModuleTarget/crash-5d65cfbc deleted file mode 100644 index 9002dd73e99777a9978bf09df0b2969caf8cc72f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8353 zcmeHLYm-!067MS8OlE2xOi#}<-P1jcyatBAK*D3x5E4m(1|?C9Ml={l zg(@ft1k1ul3>FC@z6hg{NU8#*#F!GQEWTM-ez!CqtTG?M%*5}meL5+B0V%cm_MCgq z-DjV**Is+y?&+T1ym98?nUq1s%mOHJ*fTu+gToy$z+R5@KP~VtS~7oiz;=#oEdqo~ z!9)yP;gY<~31|)9ZUruJp5^dI@>m|I(>Zmr4fqr7HIqYRJ6yX>Y{j;?KC=u(>m)W4 z7?uiBrr$ba7&Q{)3{nnRYhr6!jA^kZ5tCRG7&v-318bCv_+Yf~mK14uZ?!RJe8ZO- z)!!S9-%EtXgsa@ha|4Y=x+%Wje{?K~Q2>g>a*#RDo9 zV#()hIgf591?yIbS#Hcgf|8SR){dp6H)o=Z%cYP>xv`Y2%9vc@O2%}gQBR|ou@hG6 ziA!5o6BB0L>QGWvmc~}H(jAzwL~3x|v}7=nHV&?@MFcLgrp=kvt#-V{tV*Fu0wT3E zaw&@d-2ql4^s*AVRT(j{y9+E4CLwEpwU8;uI^bTI^>7>DrXd@FO)&St-4C-F*aEi| zZW}NI`(fZCFdqdTfY}cBAg}}WA()3D9|Lv*kH9<%c?@nB%*TOGz&#G^hW#Ymr+_`M zPry70^J&=6!0mY>A!ghOq5r&0cMwcgM1tk}_g zez^g~+s!8G_3noDhD!rTOtg)&2CGJNbqEz${kVR=Uk|N`oC(O74;pV=?4n3Q0tYeeeE5WyK!`#M z4KeSzGg|3GL`g`1&=M|)`Jj@4b7`x;u=8&|KhDq7Mb6Mko`KIz^?r(MnRI ziiDxB(lk8taipgWtcK-g8~V_6)45?Jt5BiW!CS~IHstQ2WlrcGdRL!cAkjvW6eg}^ zP@R)^vQd%#N{re#Wl|)Dmxv9*+fX;M z9W^s0t8Ei1ah8GF1uhPF#UJ=ITW6v}surmWH)r@%gq8N}$YrWrVC%T=T3+nAo13mO#04BbhlHO>&J?xLt+w@boow*0+7wm`hYU>e2*^RzMxe z*9cYN7P8b@Q%bNUm^tOLA$^rv==i3pFM9K_;HtK+y0|b}9%yA^&b0wqvgPzq`s|3T zV)D>l4=GQ;{rU#YauQcpv>RC%CCD2Mt#QaHh>DCv*Jzs9Hrk*lJ|=6##ue>eBNRxx zO;unFy3_2d7j=5JzA0$YblDnFRcADkOv6t@`lOgETR@F28tvS3{nY;14YQT0Tjx%_ zw(#3y-N{_~G49e+eRwumJo%$5!wV;lygvWj z@$;3+-w(fXb8g}EPrlQiVDW{Yo$mSZ-nZ60SeSXT^XN>^<>$BlVf4@6JYHWs8}E}$ zr+KK;b#=MnF6`_^&~1nN>_iE}{bqf?nJk;3AyXQ1@h}F5`H5|B^7ICW`!+woU*#k{ z#pnNzoMZz2|1d{u_98#xkI@p;1E9=h*~$Nn*3lZCPVsE zs7Y01qGDPqW~A!u7*>wCwRPEE$LhK)AD3<8u4CNnTqd_JUc6Agadidds_q&XrU=#K zK>xzePyCu$KOGNWKeaIT{M^FaneShx2=mXKJF#o&tqYgt%Gfgh!`Ch*?JDu3YYytA zysX++e&oQrC%=2{Adg{n{>#L2&OLG0S zL{b>#qftWS3i%e~x6~8qLNpY$q>)D4(mI`n>q8ZBQi)tUYJ(Z%M=GsBhTksYC2iaC zTe8TYZEGPe*h*KuRIgR7b%5~(*g(ZcqAV7srX$DbPlU%B>EGo55SEbgKH+S+`jp~t4-w5DB0i``sTt?LSb^LBL&R-Le(E;iHes6z{4Xo; EZ+1QKJpcdz diff --git a/testsuite/aptos-fuzzer/artifacts/CompiledModuleTarget/oom-54725f11 b/testsuite/aptos-fuzzer/artifacts/CompiledModuleTarget/oom-54725f11 deleted file mode 100644 index 652cad16c27fd1c093cff9cc569d91f22dcb0e33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3481 zcmYjS30PIt7Cw9Ld(L4Nr$h}E1g?TyMDjfzLRMyjNm^*Vijt>hH0Y;1H4}ReE(!>U z_lBazEb}1AtO%DxpJ0N9p{A7H3ywH&!Xd=ex7I$qzIXNPvxl|*^{;=eeR%oxxxw!Q z+YrHyd?^UR^YG9b7`)(NW*COUWBVHncKAGoVYNmO>{p6{@R$gK_?avSu2c{-N!D-% z6Di475XQpXDjy~;FtI)cleb}F;{+gj@Y*;2@db9_NA~NA{$^&bV%6i0-C{e#ODov1 zkmj*z*GbM5Qv2!UVwN$@?2wy5c86A*NJ;~3%4Tf_a{Dknd7O}2&!pN4)lMy!87cYV z(in30TbgA>&bH86Jrxog$<`Dq#1ydX^Q`JNDQRO}jV$L~B8s9U5+aEbqf~;0Bw4`% zMtdAZ*|e47TO?oyM)1guT5h3{L|lsKte%LH72-*_gFYJcfrThhiZ<|{!UBx&nBgc% z40d5Qw33G6;HEkS0B#{NiW|5M0}llFJOJNCD~V7$q=Hkq zD0m~3C~s*;;-ESV@{tE94)EnJYW;ZGd33BiXoMPaZyo`r^7*SgxX4xH5@6XxNyEe8 z891u?sMJ+h2==2~-Kr+cHO8shU5wfT7hXvKl}|Pz zajfW{V&hs=i;mRtF&Z=+n03Z7txmE%_c5Kswt$-gbb5ZILni$&nAf*AuP z=7@g0fat(GP?8J!IXI`PULq_h*sC#AO(awk8i>b%Q>YB04+VjM3|m-~qaNa=!m9Se(_IZ?4F;XXa`n{t`UiyJ={$=mZKMAu=5oDa zD5?($Fqg;a7MZIPTk91=L5{g9b4qibl35=G5y9Hu^Tj|V^I(G|p}|$>Wv)+%1g{h& zW5=N>t@W1lEtb?`x7qF;MPYBPvLw{J@}9P@snJ}xOUbM(Tcc#;S1E?_;vh>&RA_Ti zUs>Kp*S@A?05%jxYa`93GK`Ux5Y$^@S}?V*>|l6r?l(&!13tjOJ#jVWn!;rsL0-!4 zlmgd)bt~V{DMn+aVyuZ(va+-1`9!SacAIy2oA)JpZZeleFPa{r4V&K+SNp!3B`+@! zs8}+Rm8|%^mW&j0MXVdpj+))GIS~$YFD+4w6@@eUni|YSdL=8y==ODMz4wunQ2*xr za2{qpw4*uS!(wO*GM7~8!gc3zdy98kV&Wplg((@|)x8=VXn#0_ULzPP>gYVdy99uDuzToq@Q_k zyQQ$k6Eo>3`g(oy-X4A0$FFwPKW$p!?{&zjP?s7XJ21-g{v7c;>&uJ%ANk**sXE_G z{oIYq%del#4E_9jcKG=36~P;3>9@bOXT+)A{`aVez)ocw^|YkY%Cec9m`W=LEWKT4FuzXG^uOc@Fy=(rJhXoKq=xx}ebXDPkne*eefO&>HnI(JPq zgu0a#zwz}8btiX!ve$CwxA0}pC(X?Es$FfE7`*@E8S8Bw<~KAAZvDz_-t??b|G6-I z%(T~@g!|-tdt-U!%M-G@7p@JTv$m$LC3ba0*}WBK2K*vsE#B#C<5TNAI?wLirLjM> zEDn9=g|OxrXP;RS^p!<^xxK-)ndf$`aqH=y;_`IC-G-63qI0I&nfi?$t5Pm*o^ZhQ z?i#Q8U-?;&3%}p39k!@GV$G)ce_xw@;&NuhYTvCT$2y*LhwOWG-M%-^CinS&p_^Iv zk^am0OCMidBP+icG? zu3ew-;9PtEegAgvjPd>X+dtbdYr)d|k6sVDvGT0(`0bIJ>0>q>XkYKWrF}|aYSBe` zeFgg}GVWRFryHcRW=U_P+uGSHH=Y)kTs%!C_bvGH)7?i;j9R2vKN4&fI)oT=Mo1?f zc~Aap6Im%1&5J1*Ro>3Fogf!$Ny{(nQU;CbWWo<|MZIm`=0&N!q$ob#W{{iHL&M*_~)= zAG9APVqG!KA7sM>>QF33bvlnssAi*Fr#v&+X0)s~lhN8oNzC@wr%zcm872%byH4z1 zci23}#&zWWg$`A6tim+Q{YOtLZ70M3&{Lbqr_Qj!!f3iBKqE|?G0E=y_gCpTQ!<4= zhE~FJlYMe8B>2ivCgS3F>K@g0w$Y~#lgRlkj0$c(U1s`ABBP0BmSiLjg7ftFU1YS2 zZjvT_h2~D_Bv;3WKQgD0WeW9(>7q;Py(?}~Yr$)*y9b%+z28|ATRPSJ3muF%lAi-) z!FS}r&urv|vt&e58nrV`AN-Z%b}|REF6A+`7kr&;k2s#ZLv6>;@SHft@wn?K7nhtK c;?pwr+90zQCVP6=51alV!g<8i&BR^zUuXuQqyPW_ diff --git a/testsuite/aptos-fuzzer/artifacts/ConsensusProposal/crash-34c5631cb9944549796a14547cef7223a6ab78d6 b/testsuite/aptos-fuzzer/artifacts/ConsensusProposal/crash-34c5631cb9944549796a14547cef7223a6ab78d6 deleted file mode 100644 index 34a9c55934e2c47b04ac005551015f42e4826724..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 947 zcmZSlj|vo2j^BRKabr^4^8ed^uPf*8XMg~OXMY2{GOp^_^IviJx=!@cOik9`DC!g( zot;B{Lwy`W{Da~H3>=+ZJ^X!KT!Z309D_YTW+XriLXeCICYS}c;tKy)2f|kPU|PYz zppIrHPCJP6239-JtWfALs_AWf=PVd@R6i(L$t#|R$IWPYXnn~wo2?)jdRm?S8)fd7>2EwxpGb+VD4-lbpsxDMD%mMzud$mg;>h*O{rkH4=@1KaumTc6h>&rBCs@3R384WJf8dM+%@b&H3=G&4 R(}|jePGZuAX5hrc000K6EXe=> diff --git a/testsuite/aptos-fuzzer/artifacts/ValueTarget/crash-7619620b59914850df844994de43e3d10684f2b6 b/testsuite/aptos-fuzzer/artifacts/ValueTarget/crash-7619620b59914850df844994de43e3d10684f2b6 deleted file mode 100644 index 7072b2272a90beae6e6b23cf24f7a9f0bdc91239..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 23 WcmZQz00VYbRyIaP2%F(QqZR-JrU66% diff --git a/testsuite/aptos-fuzzer/artifacts/ValueTarget/oom-9761fc3aeea49b5f4420ff159ca3f8a6fb0502d0 b/testsuite/aptos-fuzzer/artifacts/ValueTarget/oom-9761fc3aeea49b5f4420ff159ca3f8a6fb0502d0 deleted file mode 100644 index f8fa7d09851bd44b2281198ee1de0629417675b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29 XcmZQz00RLwAjJ-0gGmjxZww3o1~dUe diff --git a/testsuite/aptos-fuzzer/artifacts/ValueTarget/oom-ce8ba3d1 b/testsuite/aptos-fuzzer/artifacts/ValueTarget/oom-ce8ba3d1 deleted file mode 100644 index 9f6fb4f2c89881ed6ccbd86c949087f299c64194..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 51 ecmZQz00R|92+hC-rC}5ckii7wtXsDZ$OHfp`~o}x diff --git a/testsuite/aptos-fuzzer/artifacts/VaultTransitExportResponse/insufficient_key_len_slicing_error b/testsuite/aptos-fuzzer/artifacts/VaultTransitExportResponse/insufficient_key_len_slicing_error deleted file mode 100644 index ac53d840460219b31261b3f7d7c095a3cf856129..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20 Wcmd;Jyu`@B;PGF8!2?8tkOu%J=mS*% diff --git a/testsuite/aptos-fuzzer/fuzz/.gitignore b/testsuite/aptos-fuzzer/fuzz/.gitignore deleted file mode 100644 index 572e03bdf321b..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ - -target -corpus -artifacts diff --git a/testsuite/aptos-fuzzer/fuzz/Cargo.toml b/testsuite/aptos-fuzzer/fuzz/Cargo.toml deleted file mode 100644 index fb5c52cdbd088..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/Cargo.toml +++ /dev/null @@ -1,32 +0,0 @@ -[package] -name = "aptos-fuzz" -description = "Aptos fuzzer fuzz" -version = "0.1.0" - -# Workspace inherited keys -authors = { workspace = true } -edition = { workspace = true } -homepage = { workspace = true } -license = { workspace = true } -publish = { workspace = true } -repository = { workspace = true } -rust-version = { workspace = true } - -[package.metadata] -cargo-fuzz = true - -[dependencies] -aptos-fuzzer = { workspace = true } -libfuzzer-sys = { workspace = true } -once_cell = { workspace = true } - -[[bin]] -name = "fuzz_runner" -path = "fuzz_targets/fuzz_runner.rs" -test = false - -# used for integration with Google OSS-Fuzz (see README) -[[bin]] -name = "fuzzer_builder" -path = "google-oss-fuzz/fuzzer_builder.rs" -test = false diff --git a/testsuite/aptos-fuzzer/fuzz/build.rs b/testsuite/aptos-fuzzer/fuzz/build.rs deleted file mode 100644 index 62a04b6add9dc..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/build.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use std::{env, fs::File, io::prelude::*, path::PathBuf}; - -fn main() { - // needed to build different binaries based on env var - println!("cargo:rerun-if-env-changed=SINGLE_FUZZ_TARGET"); - println!("cargo:rerun-if-env-changed=RUSTFLAGS"); - let fuzz_target = match env::var("SINGLE_FUZZ_TARGET") { - Ok(x) => x, - // default value for build to work - Err(_) => "vm_value".to_string(), - }; - - // fuzzer file to write - let fuzzer_content = format!( - "const FUZZ_TARGET: &str = \"{fuzz_target}\";", - fuzz_target = fuzz_target, - ); - - // path of file to create (OUT_DIR/fuzzer.rs) - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - let out_path = out_path.join("fuzzer.rs"); - - // write to file - let mut file = File::create(out_path).unwrap(); - file.write_all(fuzzer_content.as_bytes()).unwrap(); -} diff --git a/testsuite/aptos-fuzzer/fuzz/fuzz_targets/fuzz_runner.rs b/testsuite/aptos-fuzzer/fuzz/fuzz_targets/fuzz_runner.rs deleted file mode 100644 index 0123582cd278a..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/fuzz_targets/fuzz_runner.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -#![no_main] - -use aptos_fuzzer::FuzzTarget; -use libfuzzer_sys::fuzz_target; -use once_cell::sync::Lazy; -use std::process; - -static FUZZ_TARGET: Lazy = Lazy::new(|| { - match FuzzTarget::from_env() { - Ok(target) => target, - Err(err) => { - // Lazy behaves poorly with panics, so abort here. - eprintln!( - "*** [fuzz_runner] Error while determining fuzz target: {}", - err - ); - process::abort(); - }, - } -}); - -fuzz_target!(|data: &[u8]| { - FUZZ_TARGET.fuzz(data); -}); diff --git a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build.sh b/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build.sh deleted file mode 100755 index f980c87e82c28..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/bash -eux -# Copyright © Aptos Foundation -# Parts of the project are originally copyright © Meta Platforms, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# This build script is used with Google OSS-Fuzz to build fuzzer with their docker container. -# It must be called from aptos-core/testsuite/aptos-fuzzer -# usage: OUT=out_dir ./build.sh - -# recipe: -# ------- -# 1. we list all the fuzzers and save to a file fuzzer_list -# 2. we build the corpus for each fuzzer -# 3. we build all the fuzzers - -# fetch all dependencies (needed for patching rocksdb) -cargo fetch - -# 1. list fuzzers -cargo run --bin aptos-fuzzer list --no-desc > fuzzer_list - -# 2. build corpus and move to $OUT -cat fuzzer_list | while read -r line -do - fuzz/google-oss-fuzz/build_corpus.sh $line $OUT -done - -# 3. build all the fuzzers! -cat fuzzer_list | while read -r line -do - # build & move fuzzer to $OUT - fuzz/google-oss-fuzz/build_fuzzer.sh $line $OUT -done diff --git a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_corpus.sh b/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_corpus.sh deleted file mode 100755 index 1557d8fa03923..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_corpus.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -eux -# Copyright © Aptos Foundation -# Parts of the project are originally copyright © Meta Platforms, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# this file generates 128 corpus files for a target, zips it all, and move zipfile to an outdir -# usage: ./build_corpus.sh ConsensusProposal outdir - -export SINGLE_FUZZ_TARGET="$1" -export OUT_DIR="$2" - -cargo run --bin aptos-fuzzer generate -n 128 $SINGLE_FUZZ_TARGET -zip -r $OUT_DIR/"$SINGLE_FUZZ_TARGET"_seed_corpus.zip fuzz/corpus/$SINGLE_FUZZ_TARGET -rm -r fuzz/corpus/$SINGLE_FUZZ_TARGET diff --git a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_fuzzer.sh b/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_fuzzer.sh deleted file mode 100755 index 47217380aa16d..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/build_fuzzer.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash -eux -# Copyright © Aptos Foundation -# Parts of the project are originally copyright © Meta Platforms, Inc. -# SPDX-License-Identifier: Apache-2.0 - -# this file builds a single fuzzer target -# usage: ./build_fuzzer.sh ConsensusProposal outdir - -export SINGLE_FUZZ_TARGET="$1" -export OUT_DIR="$2" - -# RUSTC_BOOTSTRAP: to get some nightly features like ASAN -export RUSTC_BOOTSTRAP=1 - -# for rocksdb we need to link libc++ at the end -if [ "$(uname)" == "Darwin" ]; then - export RUSTFLAGS="" - export TARGET="x86_64-apple-darwin" -else - export RUSTFLAGS="-C link-arg=-L/usr/local/lib -C link-arg=-lc++" - export TARGET="x86_64-unknown-linux-gnu" -fi - -# export fuzzing flags -RUSTFLAGS="$RUSTFLAGS --cfg fuzzing" # used to change code logic -RUSTFLAGS="$RUSTFLAGS -Zsanitizer=address" # address sanitizer (ASAN) - -# export SanitizerCoverage options (used by libfuzzer) -RUSTFLAGS="$RUSTFLAGS -Cpasses=sancov" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-level=4" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-trace-compares" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-inline-8bit-counters" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-trace-geps" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-prune-blocks=0" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-pc-table" -RUSTFLAGS="$RUSTFLAGS -Cllvm-args=-sanitizer-coverage-stack-depth" - -# export codegen flags (https://doc.rust-lang.org/rustc/codegen-options/index.html) -RUSTFLAGS="$RUSTFLAGS -Ccodegen-units=1" -RUSTFLAGS="$RUSTFLAGS -Cdebug-assertions" # to get debug_assert in rust - -export RUSTFLAGS - -# build -cargo build --manifest-path fuzz/Cargo.toml --bin fuzzer_builder --target $TARGET -# move fuzzer to $OUT -mv $SRC/aptos-core/target/$TARGET/debug/fuzzer_builder $OUT_DIR/$SINGLE_FUZZ_TARGET diff --git a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/fuzzer_builder.rs b/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/fuzzer_builder.rs deleted file mode 100755 index 6f1de2fdebb75..0000000000000 --- a/testsuite/aptos-fuzzer/fuzz/google-oss-fuzz/fuzzer_builder.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -#![no_main] - -use aptos_fuzzer::FuzzTarget; -use libfuzzer_sys::fuzz_target; - -// contains FUZZ_TARGET -include!(concat!(env!("OUT_DIR"), "/fuzzer.rs")); - -fuzz_target!(|data: &[u8]| { - let fuzzer = FuzzTarget::by_name(FUZZ_TARGET).unwrap(); - fuzzer.fuzz(data); -}); diff --git a/testsuite/aptos-fuzzer/lsan_suppressions.txt b/testsuite/aptos-fuzzer/lsan_suppressions.txt deleted file mode 100644 index db7b498f77c68..0000000000000 --- a/testsuite/aptos-fuzzer/lsan_suppressions.txt +++ /dev/null @@ -1,3 +0,0 @@ -leak:lazy_static -leak:backtrace -leak:aptos_mempool::tests::mocks::MockSharedMempool diff --git a/testsuite/aptos-fuzzer/src/bin/flamegraph.rs b/testsuite/aptos-fuzzer/src/bin/flamegraph.rs deleted file mode 100644 index 14c95493ca0e9..0000000000000 --- a/testsuite/aptos-fuzzer/src/bin/flamegraph.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use aptos_fuzzer::FuzzTarget; -use std::{env, fs, path::PathBuf}; - -// -// Flamegraph -// ================ -// -// See README for more information - -fn main() { - // get target - let fuzz_target = env::var("FUZZ_TARGET").expect("pass fuzz target as FUZZ_TARGET env var"); - let fuzz_target = FuzzTarget::by_name(&fuzz_target) - .expect("valid target passed as FUZZ_TARGET environment variable"); - - // get path to corpus/ folder - let mut corpus_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap()); - corpus_dir.push("fuzz"); - corpus_dir.push("corpus"); - corpus_dir.push(fuzz_target.name()); - - // check if it exists - assert!( - corpus_dir.exists(), - "path to fuzzing corpus does not exist: {:?}", - corpus_dir, - ); - - // run every corpus files for this target - for corpus_file in corpus_dir.read_dir().unwrap() { - let corpus_file = corpus_file.unwrap().path(); - let data = fs::read(corpus_file).expect("failed to read artifact"); - fuzz_target.fuzz(&data); - } -} diff --git a/testsuite/aptos-fuzzer/src/bin/investigate.rs b/testsuite/aptos-fuzzer/src/bin/investigate.rs deleted file mode 100644 index 92fa368ec2ca8..0000000000000 --- a/testsuite/aptos-fuzzer/src/bin/investigate.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use aptos_fuzzer::FuzzTarget; -use clap::Parser; -use std::{fs, path::PathBuf}; - -#[derive(Debug, Parser)] -#[clap( - name = "Aptos-Fuzzer Investigator", - author = "Aptos", - about = "Utility tool to investigate fuzzing artifacts" -)] -struct Args { - /// Admission Control port to connect to. - #[clap(short = 'i', long)] - pub input_file: Option, -} - -fn main() { - // args - let args = Args::parse(); - - // check if it exists - let input_file = PathBuf::from(args.input_file.expect("input file must be set via -i")); - if !input_file.exists() { - println!("usage: cargo run investigate -i "); - return; - } - - // get target from path (input_file = ...//) - let mut ancestors = input_file.ancestors(); - ancestors.next(); // skip full path - let target_name = ancestors - .next() - .expect("input file should be inside target directory") - .iter() - .last() - .unwrap() - .to_str() - .unwrap(); - let target = FuzzTarget::by_name(target_name) - .unwrap_or_else(|| panic!("unknown fuzz target: {}", target_name)); - - // run the target fuzzer on the file - let data = fs::read(input_file).expect("failed to read artifact"); - target.fuzz(&data); -} - -#[test] -fn verify_tool() { - use clap::CommandFactory; - Args::command().debug_assert() -} diff --git a/testsuite/aptos-fuzzer/src/commands.rs b/testsuite/aptos-fuzzer/src/commands.rs deleted file mode 100644 index e90b32b1ef4a9..0000000000000 --- a/testsuite/aptos-fuzzer/src/commands.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::FuzzTarget; -use anyhow::{bail, format_err, Context, Result}; -use aptos_proptest_helpers::ValueGenerator; -use sha1::{Digest, Sha1}; -use std::{ - env, - ffi::OsString, - fs, - io::Write, - path::{Path, PathBuf}, - process::Command, -}; - -/// Generates data for this fuzz target into the output directory. Returns the number of items -/// generated. -/// -/// The corpus directory should be present at the time this method is called. -pub fn make_corpus( - target: FuzzTarget, - num_items: usize, - corpus_dir: &Path, - debug: bool, -) -> Result { - // TODO: Allow custom proptest configs? - let mut gen = ValueGenerator::new(); - - let mut sha1 = Sha1::new(); - - let mut idx = 0; - while idx < num_items { - let result = match target.generate(idx, &mut gen) { - Some(bytes) => bytes, - None => { - // No value could be generated. Assume that corpus generation has been exhausted. - break; - }, - }; - // Use the SHA-1 of the result as the file name. - sha1.update(&result); - - let hash = sha1.finalize_reset(); - let name = hex::encode(hash.as_slice()); - let path = corpus_dir.join(name); - let mut f = fs::File::create(&path) - .with_context(|| format!("Failed to create file: {:?}", path))?; - if debug { - println!("Writing {} bytes to file: {:?}", result.len(), path); - } - - f.write_all(&result) - .with_context(|| format!("Failed to write to file: {:?}", path))?; - idx += 1; - } - Ok(idx) -} - -/// Fuzz a target by running `cargo fuzz run`. -pub fn fuzz_target( - target: FuzzTarget, - corpus_dir: PathBuf, - artifact_dir: PathBuf, - mut args: Vec, -) -> Result<()> { - static FUZZ_RUNNER: &str = "fuzz_runner"; - - // Do a bit of arg parsing -- look for a "--" and insert the target and corpus directory - // before that. - let dash_dash_pos = args.iter().position(|x| x == "--"); - let splice_pos = dash_dash_pos.unwrap_or(args.len()); - args.splice(splice_pos..splice_pos, vec![ - FUZZ_RUNNER.into(), - corpus_dir.into(), - ]); - - // The artifact dir goes at the end. - if dash_dash_pos.is_none() { - args.push("--".into()); - } - let mut artifact_arg: OsString = "-artifact_prefix=".into(); - artifact_arg.push(&artifact_dir); - // Add a trailing slash as required by libfuzzer to put the artifact in a directory. - artifact_arg.push("/"); - args.push(artifact_arg); - - // Pass the target name in as an environment variable. - // Use the manifest directory as the current one. - let manifest_dir = env::var_os("CARGO_MANIFEST_DIR").ok_or_else(|| { - format_err!("Fuzzing requires CARGO_MANIFEST_DIR to be set (are you using `cargo run`?)") - })?; - - let status = Command::new("cargo") - .arg("fuzz") - .arg("run") - .args(args) - .current_dir(manifest_dir) - .env(FuzzTarget::ENV_VAR, target.name()) - // We want to fuzz with the same version of the compiler as production, but cargo-fuzz only - // runs on nightly. This is a test-only environment so this use of RUSTC_BOOTSTRAP seems - // appropriate. - .env("RUSTC_BOOTSTRAP", "1") - .status() - .context("cargo fuzz run errored")?; - if !status.success() { - bail!("cargo fuzz run failed with status {}", status); - } - Ok(()) -} - -/// List all known fuzz targets. -pub fn list_targets(no_desc: bool) { - for target in FuzzTarget::all_targets() { - if no_desc { - println!("{}", target.name()) - } else { - println!(" * {0: <24} {1}", target.name(), target.description()) - } - } -} diff --git a/testsuite/aptos-fuzzer/src/coverage.rs b/testsuite/aptos-fuzzer/src/coverage.rs deleted file mode 100644 index eefc8151068f4..0000000000000 --- a/testsuite/aptos-fuzzer/src/coverage.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::FuzzTarget; -use std::{env, fs, path::PathBuf}; - -// -// Fuzzing Coverage -// ================ -// -// This test is here to test coverage of our fuzzers. -// The current tool we use (tarpaulin) only works on test, -// hence, we need this to be a test. -// - -#[test] -#[ignore] -fn coverage() { - // get path to corpus/ folder from env var CORPUS_PATH. - let corpus_path = match env::var_os("CORPUS_PATH") { - Some(corpus_path) => PathBuf::from(&corpus_path), - None => { - let crate_dir = env!("CARGO_MANIFEST_DIR"); - PathBuf::from(&crate_dir).join("fuzz/corpus") - }, - }; - - // check if it exists - assert!( - corpus_path.exists(), - "path to fuzzing corpus must exists or be provided" - ); - - // iterate over each target (corpus//...) - for filepath in corpus_path - .read_dir() - .expect("CORPUS_PATH should be a readable directory") - { - // get target - let filepath = filepath.unwrap().path(); - let target_name = filepath.file_name().unwrap().to_str().unwrap(); - let target = FuzzTarget::by_name(target_name) - .unwrap_or_else(|| panic!("unknown fuzz target: {}", target_name)); - - // run every corpus files for this target - for corpus_file in filepath - .read_dir() - .expect("every corpus/ should be a readable directory") - { - let corpus_file = corpus_file.unwrap().path(); - let data = fs::read(corpus_file).expect("failed to read artifact"); - target.fuzz(&data); - } - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets.rs b/testsuite/aptos-fuzzer/src/fuzz_targets.rs deleted file mode 100644 index 61d6d4334e1ed..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets.rs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{FuzzTarget, FuzzTargetImpl}; -use anyhow::{format_err, Result}; -use once_cell::sync::Lazy; -use std::{collections::BTreeMap, env}; - -// List fuzz target modules here. -mod consensus; -mod executor; -mod mempool; -mod move_vm; -mod network; -mod proof; -mod safety_rules; -mod secure_storage_vault; -mod storage; -mod transaction; -mod vm; - -// TODO(joshlind): add a fuzzer for state sync v2! - -static ALL_TARGETS: Lazy>> = Lazy::new(|| { - // List fuzz targets here in this format: - let targets: Vec> = vec![ - // Consensus - Box::::default(), - // Executor - Box::::default(), - // Mempool - Box::::default(), - // Move VM - Box::::default(), - // Proof - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - // Network - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - // Safety Rules Server (LSR) - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - // Secure Storage Vault - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - // Storage - // Box::new(storage::StorageSaveBlocks::default()), - Box::::default(), - //Box::new(storage::JellyfishGetWithProof::default()), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - // Transaction - Box::::default(), - Box::::default(), - Box::::default(), - Box::::default(), - // VM - Box::::default(), - ]; - targets - .into_iter() - .map(|target| (target.name(), target)) - .collect() -}); - -impl FuzzTarget { - /// The environment variable used for passing fuzz targets to child processes. - pub(crate) const ENV_VAR: &'static str = "FUZZ_TARGET"; - - /// Get the current fuzz target from the environment. - pub fn from_env() -> Result { - let name = env::var(Self::ENV_VAR)?; - Self::by_name(&name).ok_or_else(|| format_err!("Unknown fuzz target '{}'", name)) - } - - /// Get a fuzz target by name. - pub fn by_name(name: &str) -> Option { - ALL_TARGETS.get(name).map(|target| FuzzTarget(&**target)) - } - - /// A list of all fuzz targets. - pub fn all_targets() -> impl Iterator { - ALL_TARGETS.values().map(|target| FuzzTarget(&**target)) - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/consensus.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/consensus.rs deleted file mode 100644 index b5ef4a95711f4..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/consensus.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::FuzzTargetImpl; -use aptos_consensus::round_manager_fuzzing::{fuzz_proposal, generate_corpus_proposal}; -use aptos_proptest_helpers::ValueGenerator; - -#[derive(Clone, Debug, Default)] -pub struct ConsensusProposal; - -impl FuzzTargetImpl for ConsensusProposal { - fn description(&self) -> &'static str { - "Consensus proposal messages" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(generate_corpus_proposal()) - } - - fn fuzz(&self, data: &[u8]) { - fuzz_proposal(data); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/executor.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/executor.rs deleted file mode 100644 index 473872ece91a9..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/executor.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_crypto::HashValue; -use aptos_executor::fuzzing::fuzz_execute_and_commit_blocks; -use aptos_proptest_helpers::ValueGenerator; -use aptos_types::{ledger_info::LedgerInfoWithSignatures, transaction::Transaction}; -use proptest::{collection::vec, prelude::*}; - -#[derive(Clone, Debug, Default)] -pub struct ExecuteAndCommitChunk; - -#[derive(Clone, Debug, Default)] -pub struct ExecuteAndCommitBlocks; - -impl FuzzTargetImpl for ExecuteAndCommitBlocks { - fn description(&self) -> &'static str { - "LEC > executor::execute_block & executor::commit_blocks" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(execute_and_commit_blocks_input())) - } - - fn fuzz(&self, data: &[u8]) { - let (blocks, li_with_sigs) = fuzz_data_to_value(data, execute_and_commit_blocks_input()); - fuzz_execute_and_commit_blocks(blocks, li_with_sigs); - } -} - -prop_compose! { - fn execute_and_commit_blocks_input()( - blocks in vec((any::(), vec(any::(), 0..10)), 0..10), - li_with_sigs in any::() - ) -> (Vec<(HashValue, Vec)>, LedgerInfoWithSignatures) { - (blocks, li_with_sigs) - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/mempool.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/mempool.rs deleted file mode 100644 index df2419766fbd0..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/mempool.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_mempool::fuzzing::{ - mempool_incoming_transactions_strategy, test_mempool_process_incoming_transactions_impl, -}; -use aptos_proptest_helpers::ValueGenerator; - -#[derive(Debug, Default)] -pub struct MempoolIncomingTransactions; - -impl FuzzTargetImpl for MempoolIncomingTransactions { - fn description(&self) -> &'static str { - "Transactions submitted to mempool" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy( - mempool_incoming_transactions_strategy(), - )) - } - - fn fuzz(&self, data: &[u8]) { - let (txns, timeline_state) = - fuzz_data_to_value(data, mempool_incoming_transactions_strategy()); - test_mempool_process_incoming_transactions_impl(txns, timeline_state); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/move_vm.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/move_vm.rs deleted file mode 100644 index b67d366ba28ce..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/move_vm.rs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::FuzzTargetImpl; -use anyhow::{bail, Result}; -use aptos_proptest_helpers::ValueGenerator; -use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt}; -use move_core_types::value::{LayoutTag, MoveStructLayout, MoveTypeLayout}; -use move_vm_types::values::{prop::layout_and_value_strategy, Value}; -use std::io::Cursor; - -#[derive(Clone, Debug, Default)] -pub struct ValueTarget; - -impl FuzzTargetImpl for ValueTarget { - fn description(&self) -> &'static str { - "VM values + types (custom deserializer)" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - let (layout, value) = gen.generate(layout_and_value_strategy()); - - // Values as currently serialized are not self-describing, so store a serialized form of the - // layout + kind info along with the value as well. - let layout_blob = bcs::to_bytes(&layout).unwrap(); - let value_blob = value.simple_serialize(&layout).expect("must serialize"); - - let mut blob = vec![]; - // Prefix the layout blob with its length. - blob.write_u64::(layout_blob.len() as u64) - .expect("writing should work"); - blob.extend_from_slice(&layout_blob); - blob.extend_from_slice(&value_blob); - Some(blob) - } - - fn fuzz(&self, data: &[u8]) { - let _ = deserialize(data); - } -} - -fn is_valid_layout(layout: &MoveTypeLayout) -> bool { - use MoveTypeLayout as L; - - match layout { - L::Bool | L::U8 | L::U16 | L::U32 | L::U64 | L::U128 | L::U256 | L::Address | L::Signer => { - true - }, - - L::Vector(layout) | L::Tagged(LayoutTag::IdentifierMapping(_), layout) => { - is_valid_layout(layout) - }, - - L::Struct(struct_layout) => { - if !matches!(struct_layout, MoveStructLayout::Runtime(_)) - || struct_layout.fields().is_empty() - { - return false; - } - struct_layout.fields().iter().all(is_valid_layout) - }, - } -} - -fn deserialize(data: &[u8]) -> Result<()> { - let mut data = Cursor::new(data); - // Read the length of the layout blob. - let layout_len = data.read_u64::()? as usize; - let position = data.position() as usize; - let data = &data.into_inner()[position..]; - - if data.len() < layout_len { - bail!("too little data"); - } - let layout_data = &data[..layout_len]; - let value_data = &data[layout_len..]; - - let layout: MoveTypeLayout = bcs::from_bytes(layout_data)?; - - // The fuzzer may alter the raw bytes, resulting in invalid layouts that will not - // pass the bytecode verifier. We need to filter these out as they can show up as - // false positives. - if !is_valid_layout(&layout) { - bail!("bad layout") - } - - let _ = Value::simple_deserialize(value_data, &layout); - Ok(()) -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/network.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/network.rs deleted file mode 100644 index d50dea8d70b41..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/network.rs +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -// -// Noise wrapper -// -use aptos_network::noise::fuzzing::{ - fuzz_initiator, fuzz_post_handshake, fuzz_responder, generate_corpus, -}; -use aptos_proptest_helpers::ValueGenerator; - -#[derive(Clone, Debug, Default)] -pub struct NetworkNoiseInitiator; -impl FuzzTargetImpl for NetworkNoiseInitiator { - fn description(&self) -> &'static str { - "Network Noise crate initiator side" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - Some(generate_corpus(gen)) - } - - fn fuzz(&self, data: &[u8]) { - fuzz_initiator(data); - } -} - -#[derive(Clone, Debug, Default)] -pub struct NetworkNoiseResponder; -impl FuzzTargetImpl for NetworkNoiseResponder { - fn description(&self) -> &'static str { - "Network Noise crate responder side" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - Some(generate_corpus(gen)) - } - - fn fuzz(&self, data: &[u8]) { - fuzz_responder(data); - } -} - -#[derive(Clone, Debug, Default)] -pub struct NetworkNoiseStream; -impl FuzzTargetImpl for NetworkNoiseStream { - fn description(&self) -> &'static str { - "Network Noise crate stream" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - Some(generate_corpus(gen)) - } - - fn fuzz(&self, data: &[u8]) { - fuzz_post_handshake(data); - } -} - -// -// Handshake protocol -// - -use aptos_network::fuzzing::{ - exchange_handshake_input, fuzz_network_handshake_protocol_exchange, - fuzz_network_handshake_protocol_negotiation, perform_handshake_input, -}; - -#[derive(Clone, Debug, Default)] -pub struct NetworkHandshakeExchange; -impl FuzzTargetImpl for NetworkHandshakeExchange { - fn description(&self) -> &'static str { - "network handshake protocol starting with the exchange of HandshakeMsg" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(exchange_handshake_input())) - } - - fn fuzz(&self, data: &[u8]) { - let (own_handshake, their_handshake) = fuzz_data_to_value(data, exchange_handshake_input()); - fuzz_network_handshake_protocol_exchange(&own_handshake, their_handshake); - } -} - -#[derive(Clone, Debug, Default)] -pub struct NetworkHandshakeNegotiation; -impl FuzzTargetImpl for NetworkHandshakeNegotiation { - fn description(&self) -> &'static str { - "network handshake protocol skipping the exchange straight to the negotiation" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(perform_handshake_input())) - } - - fn fuzz(&self, data: &[u8]) { - let (own_handshake, their_handshake) = fuzz_data_to_value(data, perform_handshake_input()); - fuzz_network_handshake_protocol_negotiation(&own_handshake, &their_handshake); - } -} - -// -// Peer NetworkMessages Receive -// - -use aptos_network::peer; - -#[derive(Clone, Debug, Default)] -pub struct PeerNetworkMessagesReceive; -impl FuzzTargetImpl for PeerNetworkMessagesReceive { - fn description(&self) -> &'static str { - "network peer actor reading and deserializing multiple inbound NetworkMessages" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - Some(peer::fuzzing::generate_corpus(gen)) - } - - fn fuzz(&self, data: &[u8]) { - peer::fuzzing::fuzz(data); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/proof.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/proof.rs deleted file mode 100644 index ed2596f38c793..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/proof.rs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_crypto::HashValue; -use aptos_proptest_helpers::ValueGenerator; -use aptos_types::{ - ledger_info::LedgerInfo, - proof::{ - SparseMerkleProof, TestAccumulatorProof, TestAccumulatorRangeProof, - TransactionInfoListWithProof, TransactionInfoWithProof, - }, - state_store::state_value::StateValue, - transaction::Version, -}; -use proptest::prelude::*; -use proptest_derive::Arbitrary; - -#[derive(Clone, Debug, Default)] -pub struct TestAccumulatorProofFuzzer; - -#[derive(Debug, Arbitrary)] -struct TestAccumulatorProofFuzzerInput { - proof: TestAccumulatorProof, - expected_root_hash: HashValue, - element_hash: HashValue, - element_index: u64, -} - -impl FuzzTargetImpl for TestAccumulatorProofFuzzer { - fn description(&self) -> &'static str { - "Proof: TestAccumulatorProof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy( - any::(), - )) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, any::()); - let _res = input.proof.verify( - input.expected_root_hash, - input.element_hash, - input.element_index, - ); - } -} - -#[derive(Clone, Debug, Default)] -pub struct SparseMerkleProofFuzzer; - -#[derive(Debug, Arbitrary)] -struct SparseMerkleProofFuzzerInput { - proof: SparseMerkleProof, - expected_root_hash: HashValue, - element_key: HashValue, - element_blob: Option, -} - -impl FuzzTargetImpl for SparseMerkleProofFuzzer { - fn description(&self) -> &'static str { - "Proof: SparseMerkleProof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(any::())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, any::()); - let _res = input.proof.verify( - input.expected_root_hash, - input.element_key, - input.element_blob.as_ref(), - ); - } -} - -#[derive(Clone, Debug, Default)] -pub struct TestAccumulatorRangeProofFuzzer; - -#[derive(Debug, Arbitrary)] -struct TestAccumulatorRangeProofFuzzerInput { - proof: TestAccumulatorRangeProof, - expected_root_hash: HashValue, - first_leaf_index: Option, - leaf_hashes: Vec, -} - -impl FuzzTargetImpl for TestAccumulatorRangeProofFuzzer { - fn description(&self) -> &'static str { - "Proof: TestAccumulatorRangeProof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(any::< - TestAccumulatorRangeProofFuzzerInput, - >())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, any::()); - let _res = input.proof.verify( - input.expected_root_hash, - input.first_leaf_index, - &input.leaf_hashes[..], - ); - } -} - -#[derive(Clone, Debug, Default)] -pub struct TransactionInfoWithProofFuzzer; - -#[derive(Debug, Arbitrary)] -struct TransactionInfoWithProofFuzzerInput { - proof: TransactionInfoWithProof, - ledger_info: LedgerInfo, - transaction_version: Version, -} - -impl FuzzTargetImpl for TransactionInfoWithProofFuzzer { - fn description(&self) -> &'static str { - "Proof: TransactionInfoWithProof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(any::< - TransactionInfoWithProofFuzzerInput, - >())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, any::()); - let _res = input - .proof - .verify(&input.ledger_info, input.transaction_version); - } -} - -#[derive(Clone, Debug, Default)] -pub struct TransactionInfoListWithProofFuzzer; - -#[derive(Debug, Arbitrary)] -struct TransactionInfoListWithProofFuzzerInput { - proof: TransactionInfoListWithProof, - ledger_info: LedgerInfo, - first_transaction_version: Option, -} - -impl FuzzTargetImpl for TransactionInfoListWithProofFuzzer { - fn description(&self) -> &'static str { - "Proof: TransactionInfoListWithProof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(any::< - TransactionInfoListWithProofFuzzerInput, - >())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, any::()); - let _res = input - .proof - .verify(&input.ledger_info, input.first_transaction_version); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/safety_rules.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/safety_rules.rs deleted file mode 100644 index d38285cb02c0f..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/safety_rules.rs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_proptest_helpers::ValueGenerator; -use aptos_safety_rules::{ - fuzzing::{fuzz_construct_and_sign_vote_two_chain, fuzz_sign_timeout_with_qc}, - fuzzing_utils::{ - arb_block_data, arb_epoch_change_proof, arb_safety_rules_input, arb_timeout, - arb_vote_proposal, - fuzzing::{fuzz_handle_message, fuzz_initialize, fuzz_sign_proposal}, - }, -}; - -#[derive(Clone, Debug, Default)] -pub struct SafetyRulesHandleMessage; - -/// This implementation will fuzz the handle_message() method of the safety rules serializer -/// service. -impl FuzzTargetImpl for SafetyRulesHandleMessage { - fn description(&self) -> &'static str { - "Safety rules: handle_message()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_safety_rules_input())) - } - - fn fuzz(&self, data: &[u8]) { - let safety_rules_input = fuzz_data_to_value(data, arb_safety_rules_input()); - let _ = fuzz_handle_message(safety_rules_input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct SafetyRulesInitialize; - -/// This implementation will fuzz the initialize() method of safety rules. -impl FuzzTargetImpl for SafetyRulesInitialize { - fn description(&self) -> &'static str { - "Safety rules: initialize()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_epoch_change_proof())) - } - - fn fuzz(&self, data: &[u8]) { - let epoch_change_proof = fuzz_data_to_value(data, arb_epoch_change_proof()); - let _ = fuzz_initialize(epoch_change_proof); - } -} - -#[derive(Clone, Debug, Default)] -pub struct SafetyRulesConstructAndSignVote; - -/// This implementation will fuzz the construct_and_sign_vote() method of safety rules. -impl FuzzTargetImpl for SafetyRulesConstructAndSignVote { - fn description(&self) -> &'static str { - "Safety rules: construct_and_sign_vote()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_vote_proposal())) - } - - fn fuzz(&self, data: &[u8]) { - let vote_proposal = fuzz_data_to_value(data, arb_vote_proposal()); - let _ = fuzz_construct_and_sign_vote_two_chain(vote_proposal); - } -} - -#[derive(Clone, Debug, Default)] -pub struct SafetyRulesSignProposal; - -/// This implementation will fuzz the sign_proposal() method of safety rules. -impl FuzzTargetImpl for SafetyRulesSignProposal { - fn description(&self) -> &'static str { - "Safety rules: sign_proposal()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_block_data())) - } - - fn fuzz(&self, data: &[u8]) { - let block_data = fuzz_data_to_value(data, arb_block_data()); - let _ = fuzz_sign_proposal(&block_data); - } -} - -#[derive(Clone, Debug, Default)] -pub struct SafetyRulesSignTimeout; - -/// This implementation will fuzz the sign_timeout() method of safety rules. -impl FuzzTargetImpl for SafetyRulesSignTimeout { - fn description(&self) -> &'static str { - "Safety rules: sign_timeout()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_timeout())) - } - - fn fuzz(&self, data: &[u8]) { - let timeout = fuzz_data_to_value(data, arb_timeout()); - let _ = fuzz_sign_timeout_with_qc(timeout); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/secure_storage_vault.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/secure_storage_vault.rs deleted file mode 100644 index 6465651d3ee6c..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/secure_storage_vault.rs +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_proptest_helpers::ValueGenerator; -use aptos_vault_client::{ - fuzzing::{ - arb_generic_response, arb_policy_list_response, arb_secret_list_response, - arb_secret_read_response, arb_token_create_response, arb_token_renew_response, - arb_transit_create_response, arb_transit_export_response, arb_transit_list_response, - arb_transit_read_response, arb_transit_sign_response, arb_unsealed_response, - }, - process_generic_response, process_policy_list_response, process_policy_read_response, - process_secret_list_response, process_secret_read_response, process_token_create_response, - process_token_renew_response, process_transit_create_response, process_transit_export_response, - process_transit_list_response, process_transit_read_response, process_transit_restore_response, - process_transit_sign_response, process_unsealed_response, -}; - -#[derive(Clone, Debug, Default)] -pub struct VaultGenericResponse; - -/// This implementation will fuzz process_generic_response(): the method used by the vault -/// client to process generic responses from the vault backend. -impl FuzzTargetImpl for VaultGenericResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_generic_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_generic_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_generic_response()); - let _ = process_generic_response(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultPolicyReadResponse; - -/// This implementation will fuzz process_policy_read_response(): the method used by the vault -/// client to process policies read from the vault backend. -impl FuzzTargetImpl for VaultPolicyReadResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_policy_read_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_generic_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_generic_response()); - let _ = process_policy_read_response(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultPolicyListResponse; - -/// This implementation will fuzz process_policy_list_response(): the method used by the vault -/// client to process policy lists from the vault backend. -impl FuzzTargetImpl for VaultPolicyListResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_policy_list_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_policy_list_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_policy_list_response()); - let _ = process_policy_list_response(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultSecretListResponse; - -/// This implementation will fuzz process_secret_list_response(): the method used by the vault -/// client to process secrets listed from the vault backend. -impl FuzzTargetImpl for VaultSecretListResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_secret_list_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_secret_list_response())) - } - - fn fuzz(&self, data: &[u8]) { - let response = fuzz_data_to_value(data, arb_secret_list_response()); - let _ = process_secret_list_response(response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultSecretReadResponse; - -/// This implementation will fuzz process_secret_read_response(): the method used by the vault -/// client to process secrets read from the vault backend. -impl FuzzTargetImpl for VaultSecretReadResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_secret_read_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_secret_read_response())) - } - - fn fuzz(&self, data: &[u8]) { - let (response, key, secret) = fuzz_data_to_value(data, arb_secret_read_response()); - let _ = process_secret_read_response(&secret, &key, response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTokenCreateResponse; - -/// This implementation will fuzz process_token_create_response(): the method used by the vault -/// client to process a token create request from the vault backend. -impl FuzzTargetImpl for VaultTokenCreateResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_token_create_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_token_create_response())) - } - - fn fuzz(&self, data: &[u8]) { - let response = fuzz_data_to_value(data, arb_token_create_response()); - let _ = process_token_create_response(response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTokenRenewResponse; - -/// This implementation will fuzz process_token_renew_response(): the method used by the vault -/// client to process a token renew request from the vault backend. -impl FuzzTargetImpl for VaultTokenRenewResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_token_renew_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_token_renew_response())) - } - - fn fuzz(&self, data: &[u8]) { - let response = fuzz_data_to_value(data, arb_token_renew_response()); - let _ = process_token_renew_response(response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTransitCreateResponse; - -/// This implementation will fuzz process_transit_create_response(): the method used by the vault -/// client to process a key create request from the vault backend. -impl FuzzTargetImpl for VaultTransitCreateResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_transit_create_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_transit_create_response())) - } - - fn fuzz(&self, data: &[u8]) { - let (response, name) = fuzz_data_to_value(data, arb_transit_create_response()); - let _ = process_transit_create_response(&name, response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTransitExportResponse; - -/// This implementation will fuzz process_transit_export_response(): the method used by the vault -/// client to process a key export request from the vault backend. -impl FuzzTargetImpl for VaultTransitExportResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_transit_export_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_transit_export_response())) - } - - fn fuzz(&self, data: &[u8]) { - let (response, name, version) = fuzz_data_to_value(data, arb_transit_export_response()); - let _ = process_transit_export_response(&name, version, response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTransitListResponse; - -/// This implementation will fuzz process_transit_list_response(): the method used by the vault -/// client to process a key list request from the vault backend. -impl FuzzTargetImpl for VaultTransitListResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_transit_list_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_transit_list_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_transit_list_response()); - let _ = process_transit_list_response(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTransitReadResponse; - -/// This implementation will fuzz process_transit_read_response(): the method used by the vault -/// client to process a key read request from the vault backend. -impl FuzzTargetImpl for VaultTransitReadResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_transit_read_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_transit_read_response())) - } - - fn fuzz(&self, data: &[u8]) { - let (response, name) = fuzz_data_to_value(data, arb_transit_read_response()); - let _ = process_transit_read_response(&name, response); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTransitRestoreResponse; - -/// This implementation will fuzz process_transit_restore_response(): the method used by the vault -/// client to process a key restore request from the vault backend. -impl FuzzTargetImpl for VaultTransitRestoreResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_transit_restore_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_generic_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_generic_response()); - let _ = process_transit_restore_response(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultTransitSignResponse; - -/// This implementation will fuzz process_transit_sign_response(): the method used by the vault -/// client to process a signature request from the vault backend. -impl FuzzTargetImpl for VaultTransitSignResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_transit_sign_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_transit_sign_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_transit_sign_response()); - let _ = process_transit_sign_response(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct VaultUnsealedResponse; - -/// This implementation will fuzz process_unsealed_response(): the method used by the vault -/// client to process an unsealed request from the vault backend. -impl FuzzTargetImpl for VaultUnsealedResponse { - fn description(&self) -> &'static str { - "Secure storage vault: process_unsealed_response()" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_unsealed_response())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_unsealed_response()); - let _ = process_unsealed_response(input); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/storage.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/storage.rs deleted file mode 100644 index af6b023118306..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/storage.rs +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_accumulator::test_helpers::{ - arb_hash_batch, arb_list_of_hash_batches, arb_three_hash_batches, arb_two_hash_batches, - test_append_empty_impl, test_append_many_impl, test_consistency_proof_impl, - test_get_frozen_subtree_hashes_impl, test_proof_impl, test_range_proof_impl, -}; -use aptos_crypto::HashValue; -use aptos_db::{ - db::test_helper::{arb_blocks_to_commit, test_save_blocks_impl}, - schema::fuzzing::fuzz_decode, -}; -use aptos_jellyfish_merkle::test_helper::{ - arb_existent_kvs_and_nonexistent_keys, arb_kv_pair_with_distinct_last_nibble, - arb_tree_with_index, test_get_leaf_count, test_get_range_proof, test_get_with_proof, - test_get_with_proof_with_distinct_last_nibble, -}; -use aptos_proptest_helpers::ValueGenerator; -use aptos_scratchpad::test_utils::proptest_helpers::{ - arb_smt_correctness_case, test_smt_correctness_impl, -}; -use aptos_types::state_store::state_key::StateKey; -use proptest::{ - collection::{hash_set, vec}, - prelude::*, -}; - -#[derive(Clone, Debug, Default)] -pub struct StorageSaveBlocks; - -impl FuzzTargetImpl for StorageSaveBlocks { - fn description(&self) -> &'static str { - "Storage save blocks" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_blocks_to_commit())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_blocks_to_commit()); - let threshold = fuzz_data_to_value(data, 10..20usize); - test_save_blocks_impl(input, threshold); - } -} - -#[derive(Clone, Debug, Default)] -pub struct StorageSchemaDecode; - -impl FuzzTargetImpl for StorageSchemaDecode { - fn description(&self) -> &'static str { - "Storage schemas do not panic on corrupted bytes." - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - Some(gen.generate(prop_oneof![ - 100 => vec(any::(), 0..1024), - 1 => vec(any::(), 1024..1024 * 10), - ])) - } - - fn fuzz(&self, data: &[u8]) { - fuzz_decode(data) - } -} - -//============== JellyfishMerkleTree ============= - -#[derive(Clone, Debug, Default)] -pub struct JellyfishGetWithProof; - -impl FuzzTargetImpl for JellyfishGetWithProof { - fn description(&self) -> &'static str { - "JellyfishMerkleTree get with proof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy( - arb_existent_kvs_and_nonexistent_keys::(1000, 100), - )) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value( - data, - arb_existent_kvs_and_nonexistent_keys::(1000, 100), - ); - test_get_with_proof(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct JellyfishGetWithProofWithDistinctLastNibble; - -impl FuzzTargetImpl for JellyfishGetWithProofWithDistinctLastNibble { - fn description(&self) -> &'static str { - "JellyfishMerkleTree get with proof with distinct last nibble" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy( - arb_kv_pair_with_distinct_last_nibble::(), - )) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_kv_pair_with_distinct_last_nibble::()); - test_get_with_proof_with_distinct_last_nibble(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct JellyfishGetRangeProof; - -impl FuzzTargetImpl for JellyfishGetRangeProof { - fn description(&self) -> &'static str { - "JellyfishMerkleTree get range proof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_tree_with_index::(100))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_tree_with_index::(100)); - test_get_range_proof(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct JellyfishGetLeafCount; - -impl FuzzTargetImpl for JellyfishGetLeafCount { - fn description(&self) -> &'static str { - "JellyfishMerkleTree get leaf count" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(hash_set(any::(), 1..1000))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, hash_set(any::(), 1..1000)); - test_get_leaf_count(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct AccumulatorFrozenSubtreeHashes; - -impl FuzzTargetImpl for AccumulatorFrozenSubtreeHashes { - fn description(&self) -> &'static str { - "Accumulator frozen subtree hashes" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_hash_batch(1000))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_hash_batch(1000)); - test_get_frozen_subtree_hashes_impl(input); - } -} - -//============== Scratchpad ============= - -#[derive(Clone, Debug, Default)] -pub struct SparseMerkleCorrectness; - -impl FuzzTargetImpl for SparseMerkleCorrectness { - fn description(&self) -> &'static str { - "Scratchpad SMT correctness." - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_smt_correctness_case())) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_smt_correctness_case()); - test_smt_correctness_impl(input) - } -} - -//============== Accumulator ============= - -#[derive(Clone, Debug, Default)] -pub struct AccumulatorProof; - -impl FuzzTargetImpl for AccumulatorProof { - fn description(&self) -> &'static str { - "Accumulator proof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_two_hash_batches(100))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_two_hash_batches(100)); - test_proof_impl(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct AccumulatorConsistencyProof; - -impl FuzzTargetImpl for AccumulatorConsistencyProof { - fn description(&self) -> &'static str { - "Accumulator consistency proof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_two_hash_batches(100))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_two_hash_batches(100)); - test_consistency_proof_impl(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct AccumulatorRangeProof; - -impl FuzzTargetImpl for AccumulatorRangeProof { - fn description(&self) -> &'static str { - "Accumulator range proof" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_three_hash_batches(100))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_three_hash_batches(100)); - test_range_proof_impl(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct AccumulatorAppendMany; - -impl FuzzTargetImpl for AccumulatorAppendMany { - fn description(&self) -> &'static str { - "Accumulator amend many leaves" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_list_of_hash_batches(10, 10))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_list_of_hash_batches(10, 10)); - test_append_many_impl(input); - } -} - -#[derive(Clone, Debug, Default)] -pub struct AccumulatorAppendEmpty; - -impl FuzzTargetImpl for AccumulatorAppendEmpty { - fn description(&self) -> &'static str { - "Accumulator amend empty leave" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(arb_hash_batch(100))) - } - - fn fuzz(&self, data: &[u8]) { - let input = fuzz_data_to_value(data, arb_hash_batch(100)); - test_append_empty_impl(input); - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/transaction.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/transaction.rs deleted file mode 100644 index eebd4661935c4..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/transaction.rs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::{corpus_from_strategy, fuzz_data_to_value, FuzzTargetImpl}; -use aptos_language_e2e_tests::account_universe::{ - all_transactions_strategy, log_balance_strategy, run_and_assert_universe, AUTransactionGen, - AccountPickStyle, AccountUniverseGen, -}; -use aptos_proptest_helpers::ValueGenerator; -use aptos_types::transaction::SignedTransaction; -use once_cell::sync::Lazy; -use proptest::{ - collection::vec, - prelude::*, - strategy::{Strategy, ValueTree}, - test_runner::{self, RngAlgorithm, TestRunner}, -}; - -#[derive(Clone, Debug, Default)] -pub struct LanguageTransactionExecution; - -impl FuzzTargetImpl for LanguageTransactionExecution { - fn description(&self) -> &'static str { - "Language execute randomly generated transactions" - } - - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(corpus_from_strategy(run_and_assert_universe_input())) - } - - fn fuzz(&self, data: &[u8]) { - let (universe, txns) = fuzz_data_to_value(data, run_and_assert_universe_input()); - run_and_assert_universe(universe, txns).unwrap(); - } -} - -prop_compose! { - fn run_and_assert_universe_input()( - universe in AccountUniverseGen::strategy(2..20, log_balance_strategy(10_000_000), AccountPickStyle::Unlimited), - txns in vec(all_transactions_strategy(1, 1_000_000), 1..40) - ) -> (AccountUniverseGen, Vec) { - (universe, txns) - } -} - -#[derive(Clone, Debug, Default)] -pub struct SignedTransactionTarget; - -impl FuzzTargetImpl for SignedTransactionTarget { - fn description(&self) -> &'static str { - "SignedTransaction (BCS deserializer)" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - let value = gen.generate(any_with::(())); - Some(bcs::to_bytes(&value).expect("serialization should work")) - } - - fn fuzz(&self, data: &[u8]) { - let _: Result = bcs::from_bytes(data); - } -} - -/// This fuzzer ensures that we cannot mutate the serialization of a test transaction/ -/// To do this, it generates a single transaction via a seeded proptest and serializes it, -/// The fuzzer then mutates this serialized transaction in hope of deserializing it to the same transaction. -#[derive(Clone, Debug, Default)] -pub struct MutatedSignedTransaction; - -static SIGNED_TXN: Lazy = Lazy::new(|| { - let seed = [0u8; 32]; - let recorder_rng = test_runner::TestRng::from_seed(RngAlgorithm::ChaCha, &seed); - let mut runner = TestRunner::new_with_rng(test_runner::Config::default(), recorder_rng); - SignedTransaction::arbitrary() - .new_tree(&mut runner) - .expect("creating a new value should succeed") - .current() -}); - -static SERIALIZED_SIGNED_TXN: Lazy> = - Lazy::new(|| bcs::to_bytes(&SIGNED_TXN.clone()).expect("serialization should work")); - -impl FuzzTargetImpl for MutatedSignedTransaction { - fn description(&self) -> &'static str { - "SignedTransaction (BCS serialized -> mutation -> deserializer)" - } - - /// We always return the same serialized signed transaction for corpus generation, - /// as we only fuzz the serialization of a unique transaction. - /// This is quite a limited fuzzer, refer to TwoSignedTransactions for a different approach. - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option> { - Some(SERIALIZED_SIGNED_TXN.clone()) - } - - fn fuzz(&self, data: &[u8]) { - // it is possible that the fuzzer sends the same serialization, - // which is not useful as we know that it'll lead to the same signed transaction - if data == SERIALIZED_SIGNED_TXN.as_slice() { - return; - } - - if let Ok(signed_txn) = bcs::from_bytes::(data) { - assert_ne!(*SIGNED_TXN, signed_txn); - } - } -} - -#[derive(Clone, Debug, Default)] -pub struct TwoSignedTransactions; - -impl FuzzTargetImpl for TwoSignedTransactions { - fn description(&self) -> &'static str { - "Two different SignedTransactions serialization -> different SignedTransactions" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - let txn = gen.generate(any_with::(())); - let mut serialized_txn = bcs::to_bytes(&txn).expect("serialization should work"); - // return [serialized_txn | serialized_txn] - serialized_txn.extend_from_slice(&serialized_txn.clone()); - Some(serialized_txn) - } - - fn fuzz(&self, data: &[u8]) { - if data.is_empty() || data.len() % 2 != 0 { - // can't cut data in two equal parts - return; - } - - // data is two similar serialized transactions [txn1 | txn2] - let (txn1, txn2) = data.split_at(data.len() / 2); - - // ensure the parts are different - if txn1 == txn2 { - return; - } - - // ensure the deserialization is different - if let Ok(txn1) = bcs::from_bytes::(txn1) { - if let Ok(txn2) = bcs::from_bytes::(txn2) { - assert_ne!(txn1, txn2); - } - } - } -} diff --git a/testsuite/aptos-fuzzer/src/fuzz_targets/vm.rs b/testsuite/aptos-fuzzer/src/fuzz_targets/vm.rs deleted file mode 100644 index 641206d363832..0000000000000 --- a/testsuite/aptos-fuzzer/src/fuzz_targets/vm.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use crate::FuzzTargetImpl; -use aptos_proptest_helpers::ValueGenerator; -use move_binary_format::file_format::CompiledModule; -use proptest::prelude::*; - -#[derive(Clone, Debug, Default)] -pub struct CompiledModuleTarget; - -impl FuzzTargetImpl for CompiledModuleTarget { - fn description(&self) -> &'static str { - "VM CompiledModule (custom deserializer)" - } - - fn generate(&self, _idx: usize, gen: &mut ValueGenerator) -> Option> { - let value = gen.generate(any_with::(16)); - let mut out = vec![]; - value - .serialize(&mut out) - .expect("serialization should work"); - Some(out) - } - - fn fuzz(&self, data: &[u8]) { - // Errors are OK -- the fuzzer cares about panics and OOMs. Note that - // `CompiledModule::deserialize` also runs the bounds checker, which is desirable here. - let _ = CompiledModule::deserialize(data); - } -} diff --git a/testsuite/aptos-fuzzer/src/lib.rs b/testsuite/aptos-fuzzer/src/lib.rs deleted file mode 100644 index 0bd53959a78b5..0000000000000 --- a/testsuite/aptos-fuzzer/src/lib.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use aptos_proptest_helpers::ValueGenerator; -use proptest::{ - strategy::{Strategy, ValueTree}, - test_runner::{self, RngAlgorithm, TestRunner}, -}; -use rand::RngCore; -use std::{ffi::CString, fmt, ops::Deref, os::raw::c_char, str::FromStr}; - -pub mod commands; -#[cfg(test)] -mod coverage; -pub mod fuzz_targets; - -/// Implementation for a particular target of a fuzz operation. -pub trait FuzzTargetImpl: Sync + Send + fmt::Debug { - /// The name of the fuzz target. - /// By default, we use the struct name, however, implementations may prefer to override this. - fn name(&self) -> &'static str { - std::any::type_name::() - .rsplit("::") - .next() - .expect("Implementation struct name must have at least one component") - } - - /// A description for this target. - fn description(&self) -> &'static str; - - /// Generates a new example for this target to store in the corpus. `idx` is the current index - /// of the item being generated, starting from 0. - /// - /// Returns `Some(bytes)` if a value was generated, or `None` if no value can be generated. - fn generate(&self, _idx: usize, _gen: &mut ValueGenerator) -> Option>; - - /// Fuzz the target with this data. The fuzzer tests for panics or OOMs with this method. - fn fuzz(&self, data: &[u8]); -} - -/// A fuzz target. -#[derive(Copy, Clone, Debug)] -pub struct FuzzTarget(&'static (dyn FuzzTargetImpl + 'static)); - -impl Deref for FuzzTarget { - type Target = dyn FuzzTargetImpl + 'static; - - fn deref(&self) -> &Self::Target { - self.0 - } -} - -impl FromStr for FuzzTarget { - type Err = String; - - fn from_str(s: &str) -> Result { - FuzzTarget::by_name(s).ok_or_else(|| format!("Fuzz target '{}' not found (run `list`)", s)) - } -} - -/// Helper to generate random bytes that can be used with proptest -/// to generate a value following the passed strategy. -fn corpus_from_strategy(strategy: impl Strategy) -> Vec { - // randomly-seeded recording RNG - let mut seed = [0u8; 32]; - let mut rng = rand::thread_rng(); - rng.fill_bytes(&mut seed); - let recorder_rng = test_runner::TestRng::from_seed(RngAlgorithm::Recorder, &seed); - let mut runner = TestRunner::new_with_rng(test_runner::Config::default(), recorder_rng); - - // generate the value - strategy - .new_tree(&mut runner) - .expect("creating a new value should succeed") - .current(); - - // dump the bytes - runner.bytes_used() -} - -/// Helper to convert a bytearray to a value implementing the Arbitrary trait. -pub fn fuzz_data_to_value( - data: &[u8], - strategy: impl Strategy, -) -> T { - // setup proptest with passthrough RNG - let passthrough_rng = - test_runner::TestRng::from_seed(test_runner::RngAlgorithm::PassThrough, data); - let config = test_runner::Config::default(); - let mut runner = TestRunner::new_with_rng(config, passthrough_rng); - - // create a value based on the arbitrary implementation of T - let strategy_tree = strategy.new_tree(&mut runner).expect("should not happen"); - strategy_tree.current() -} - -/// Bake lsan suppressions into the binary -#[no_mangle] -pub extern "C" fn __lsan_default_suppressions() -> *const c_char { - let s = CString::new(include_str!("../lsan_suppressions.txt")).unwrap(); - let p = s.as_ptr(); - std::mem::forget(s); - p -} diff --git a/testsuite/aptos-fuzzer/src/main.rs b/testsuite/aptos-fuzzer/src/main.rs deleted file mode 100644 index fd7fac114bc20..0000000000000 --- a/testsuite/aptos-fuzzer/src/main.rs +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 -//! Helpers for fuzz testing. - -use aptos_fuzzer::{commands, FuzzTarget}; -use clap::Parser; -use std::{env, ffi::OsString, fs, path::PathBuf}; - -#[derive(Debug, Parser)] -#[clap(name = "fuzzer", about = "Aptos fuzzer")] -struct Opt { - /// Print extended debug output - #[clap(long = "debug")] - debug: bool, - #[clap(subcommand)] - cmd: Command, -} - -/// The default number of items to generate in a corpus. -const GENERATE_DEFAULT_ITEMS: usize = 128; - -#[derive(Debug, Parser)] -enum Command { - /// Generate corpus for a particular fuzz target - #[clap(name = "generate")] - Generate { - /// Number of items to generate in the corpus - #[clap( - short = 'n', - long = "num-items", - default_value_t = GENERATE_DEFAULT_ITEMS - )] - num_items: usize, - /// Custom directory for corpus output to be stored in (required if not running under - /// `cargo run`) - #[clap(long = "corpus-dir", value_parser)] - corpus_dir: Option, - #[clap(name = "TARGET")] - /// Name of target to generate (use `list` to list) - target: FuzzTarget, - }, - /// Run fuzzer on specified target (must be run under `cargo run`) - #[clap(name = "fuzz")] - Fuzz { - /// Target to fuzz (use `list` to list targets) - #[clap(name = "TARGET", required = true)] - target: FuzzTarget, - /// Custom directory for corpus - #[clap(long = "corpus-dir", value_parser)] - corpus_dir: Option, - /// Custom directory for artifacts - #[clap(long = "artifact-dir", value_parser)] - artifact_dir: Option, - /// Arguments for `cargo fuzz run` - #[clap(name = "ARGS", value_parser, allow_hyphen_values = true)] - args: Vec, - }, - /// List fuzz targets - #[clap(name = "list")] - List { - /// Only print out names, no descriptions. - #[clap(long = "no-desc", short = 'n')] - no_desc: bool, - }, -} - -/// The default directory for corpuses. Also return whether the directory was freshly created. -fn default_corpus_dir(target: FuzzTarget) -> (PathBuf, bool) { - default_dir(target, "corpus") -} - -/// The default directory for artifacts. -fn default_artifact_dir(target: FuzzTarget) -> PathBuf { - default_dir(target, "artifacts").0 -} - -fn default_dir(target: FuzzTarget, intermediate_dir: &str) -> (PathBuf, bool) { - let mut dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").expect( - "--corpus-dir not set and this binary is not running under cargo run. \ - Either use cargo run or pass in the --corpus-dir flag.", - )); - // If a "fuzz" subdirectory doesn't exist, the user might be doing it wrong. - dir.push("fuzz"); - if !dir.is_dir() { - panic!( - "Subdirectory {:?} of cargo manifest directory does not exist \ - (did you run `cargo fuzz init`?)", - dir - ); - } - - // The name of the corpus is derived from the name of the target. - dir.push(intermediate_dir); - dir.push(target.name()); - - println!("Using default {} directory: {:?}", intermediate_dir, dir); - let created = !dir.exists(); - fs::create_dir_all(&dir).expect("Failed to create directory"); - (dir, created) -} - -fn main() { - let opt: Opt = Opt::parse(); - - match opt.cmd { - Command::Generate { - num_items, - corpus_dir, - target, - } => { - let corpus_dir = corpus_dir.unwrap_or_else(|| default_corpus_dir(target).0); - let item_count = commands::make_corpus(target, num_items, &corpus_dir, opt.debug) - .expect("Failed to create corpus"); - println!("Wrote {} items to corpus", item_count); - }, - Command::Fuzz { - corpus_dir, - artifact_dir, - target, - args, - } => { - let corpus_dir = match corpus_dir { - Some(dir) => { - // Don't generate the corpus here -- custom directory means the user knows - // what they're doing. - dir - }, - None => { - let (dir, created) = default_corpus_dir(target); - if created { - println!("New corpus, generating..."); - commands::make_corpus(target, GENERATE_DEFAULT_ITEMS, &dir, opt.debug) - .expect("Failed to create corpus"); - } - dir - }, - }; - let artifact_dir = artifact_dir.unwrap_or_else(|| default_artifact_dir(target)); - commands::fuzz_target(target, corpus_dir, artifact_dir, args).unwrap(); - }, - Command::List { no_desc } => { - commands::list_targets(no_desc); - }, - } -} - -#[test] -fn verify_tool() { - use clap::CommandFactory; - Opt::command().debug_assert() -} diff --git a/testsuite/aptos-fuzzer/tests/artifacts.rs b/testsuite/aptos-fuzzer/tests/artifacts.rs deleted file mode 100644 index 2b491446bb6f9..0000000000000 --- a/testsuite/aptos-fuzzer/tests/artifacts.rs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -//! Test artifacts: examples known to have crashed in the past. - -use aptos_fuzzer::FuzzTarget; -use rusty_fork::{fork, rusty_fork_id}; -use stats_alloc::{Region, StatsAlloc, INSTRUMENTED_SYSTEM}; -use std::{alloc::System, env, fs, path::Path}; - -#[global_allocator] -static GLOBAL: &StatsAlloc = &INSTRUMENTED_SYSTEM; - -/// The memory limit for each deserializer, in bytes. -const MEMORY_LIMIT: usize = 256 * 1024 * 1024; - -datatest_stable::harness!(test_artifact, "artifacts", r"^.*/.*"); - -fn test_artifact(artifact_path: &Path) -> datatest_stable::Result<()> { - let test_name = test_name(artifact_path); - - if no_fork() { - test_artifact_impl(artifact_path); - } else { - fork( - &test_name, - rusty_fork_id!(), - |_| {}, - |child, _file| { - let status = child.wait().expect("failed to wait for child"); - assert!( - status.success(), - "child exited unsuccessfully with {}", - status - ); - }, - || test_artifact_impl(artifact_path), - )?; - } - - Ok(()) -} - -fn no_fork() -> bool { - env::var_os("NO_FORK").map_or(false, |x| x == "1") -} - -fn test_artifact_impl(artifact_path: &Path) { - // Extract the target from the path -- it's the second component after "artifacts/". - let target_name = artifact_path - .iter() - .nth(1) - .expect("artifact path must be in format 'artifacts//'"); - let target_name = target_name.to_str().expect("target must be valid Unicode"); - let target = FuzzTarget::by_name(target_name) - .unwrap_or_else(|| panic!("unknown fuzz target: {}", target_name)); - let data = fs::read(artifact_path).expect("failed to read artifact"); - - let reg = Region::new(GLOBAL); - target.fuzz(&data); - let stats = reg.change(); - - eprintln!("stats: {:?}", stats); - assert!( - stats.bytes_allocated <= MEMORY_LIMIT, - "Deserializer used too much memory: allocated {} bytes (max {} bytes)", - stats.bytes_allocated, - MEMORY_LIMIT - ); -} - -fn test_name(artifact_path: &Path) -> String { - // This matches the test name generated by datatest. - let mut test_name = "test_artifact::".to_string(); - - let path = artifact_path - .strip_prefix("artifacts/") - .expect("artifact path doesn't begin with artifacts/"); - let subname = path.to_str().expect("name must be valid unicode"); - test_name.push_str(subname); - test_name -} From a83b5f709b19b5f3706c10faf821203b06b51fb1 Mon Sep 17 00:00:00 2001 From: Balaji Arun Date: Fri, 9 Feb 2024 08:17:35 -0800 Subject: [PATCH 051/328] [dag] cache votes without re-counting (#11808) * [dag] cache votes without re-counting * [dag] keep broadcasting node until all ack --- consensus/src/dag/dag_driver.rs | 19 +++-- consensus/src/dag/dag_store.rs | 88 ++++++++++++++++----- consensus/src/dag/order_rule.rs | 2 +- consensus/src/dag/rb_handler.rs | 9 +++ consensus/src/dag/tests/helpers.rs | 2 +- consensus/src/dag/tests/rb_handler_tests.rs | 2 +- consensus/src/dag/types.rs | 63 +++++++++------ types/src/validator_verifier.rs | 7 ++ 8 files changed, 142 insertions(+), 50 deletions(-) diff --git a/consensus/src/dag/dag_driver.rs b/consensus/src/dag/dag_driver.rs index 682602be07f5c..01b33dedb5a17 100644 --- a/consensus/src/dag/dag_driver.rs +++ b/consensus/src/dag/dag_driver.rs @@ -37,9 +37,9 @@ use aptos_validator_transaction_pool as vtxn_pool; use async_trait::async_trait; use futures::{ executor::block_on, - future::{AbortHandle, Abortable}, - FutureExt, + future::{join, AbortHandle, Abortable}, }; +use futures_channel::oneshot; use std::{collections::HashSet, sync::Arc, time::Duration}; use tokio_retry::strategy::ExponentialBackoff; @@ -284,8 +284,9 @@ impl DagDriver { let rb = self.reliable_broadcast.clone(); let rb2 = self.reliable_broadcast.clone(); let (abort_handle, abort_registration) = AbortHandle::new_pair(); + let (tx, rx) = oneshot::channel(); let signature_builder = - SignatureBuilder::new(node.metadata().clone(), self.epoch_state.clone()); + SignatureBuilder::new(node.metadata().clone(), self.epoch_state.clone(), tx); let cert_ack_set = CertificateAckState::new(self.epoch_state.verifier.len()); let latest_ledger_info = self.ledger_info_provider.clone(); @@ -298,7 +299,12 @@ impl DagDriver { defer!( observe_round(timestamp, RoundStage::NodeBroadcasted); ); rb.broadcast(node, signature_builder).await }; - let core_task = node_broadcast.then(move |certificate| { + let certified_broadcast = async move { + let Ok(certificate) = rx.await else { + error!("channel closed before receiving ceritifcate"); + return; + }; + debug!( LogSchema::new(LogEvent::BroadcastCertifiedNode), id = node_clone.id() @@ -311,8 +317,9 @@ impl DagDriver { certified_node, latest_ledger_info.get_latest_ledger_info(), ); - rb2.broadcast(certified_node_msg, cert_ack_set) - }); + rb2.broadcast(certified_node_msg, cert_ack_set).await + }; + let core_task = join(node_broadcast, certified_broadcast); let author = self.author; let task = async move { debug!("{} Start reliable broadcast for round {}", author, round); diff --git a/consensus/src/dag/dag_store.rs b/consensus/src/dag/dag_store.rs index 7c9bf95d713d7..4023830412b92 100644 --- a/consensus/src/dag/dag_store.rs +++ b/consensus/src/dag/dag_store.rs @@ -1,7 +1,10 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use super::types::{DagSnapshotBitmask, NodeMetadata}; +use super::{ + types::{DagSnapshotBitmask, NodeMetadata}, + Node, +}; use crate::{ dag::{ storage::DAGStorage, @@ -23,19 +26,23 @@ use std::{ #[derive(Clone)] pub enum NodeStatus { - Unordered(Arc), + Unordered { + node: Arc, + aggregated_weak_voting_power: u128, + aggregated_strong_voting_power: u128, + }, Ordered(Arc), } impl NodeStatus { pub fn as_node(&self) -> &Arc { match self { - NodeStatus::Unordered(node) | NodeStatus::Ordered(node) => node, + NodeStatus::Unordered { node, .. } | NodeStatus::Ordered(node) => node, } } pub fn mark_as_ordered(&mut self) { - assert!(matches!(self, NodeStatus::Unordered(_))); + assert!(matches!(self, NodeStatus::Unordered { .. })); *self = NodeStatus::Ordered(self.as_node().clone()); } } @@ -107,7 +114,12 @@ impl InMemDag { .get_node_ref_mut(node.round(), node.author()) .expect("must be present"); ensure!(round_ref.is_none(), "race during insertion"); - *round_ref = Some(NodeStatus::Unordered(node.clone())); + *round_ref = Some(NodeStatus::Unordered { + node: node.clone(), + aggregated_weak_voting_power: 0, + aggregated_strong_voting_power: 0, + }); + self.update_votes(&node, true); Ok(()) } @@ -149,6 +161,39 @@ impl InMemDag { Ok(()) } + pub fn update_votes(&mut self, node: &Node, update_link_power: bool) { + if node.round() <= self.lowest_round() { + return; + } + + let voting_power = self + .epoch_state + .verifier + .get_voting_power(node.author()) + .expect("must exist"); + + for parent in node.parents_metadata() { + let node_status = self + .get_node_ref_mut(parent.round(), parent.author()) + .expect("must exist"); + match node_status { + Some(NodeStatus::Unordered { + aggregated_weak_voting_power, + aggregated_strong_voting_power, + .. + }) => { + if update_link_power { + *aggregated_strong_voting_power += voting_power as u128; + } else { + *aggregated_weak_voting_power += voting_power as u128; + } + }, + Some(NodeStatus::Ordered(_)) => {}, + None => unreachable!("parents must exist before voting for a node"), + } + } + } + pub fn exists(&self, metadata: &NodeMetadata) -> bool { self.get_node_ref_by_metadata(metadata).is_some() } @@ -211,24 +256,29 @@ impl InMemDag { .map(|node_status| node_status.as_node()) } - // TODO: I think we can cache votes in the NodeStatus::Unordered pub fn check_votes_for_node( &self, metadata: &NodeMetadata, validator_verifier: &ValidatorVerifier, ) -> bool { - self.get_round_iter(metadata.round() + 1) - .map(|next_round_iter| { - let votes = next_round_iter - .filter(|node_status| { - node_status - .as_node() - .parents() - .iter() - .any(|cert| cert.metadata() == metadata) - }) - .map(|node_status| node_status.as_node().author()); - validator_verifier.check_voting_power(votes, false).is_ok() + self.get_node_ref_by_metadata(metadata) + .map(|node_status| match node_status { + NodeStatus::Unordered { + aggregated_weak_voting_power, + aggregated_strong_voting_power, + .. + } => { + validator_verifier + .check_aggregated_voting_power(*aggregated_weak_voting_power, true) + .is_ok() + || validator_verifier + .check_aggregated_voting_power(*aggregated_strong_voting_power, false) + .is_ok() + }, + NodeStatus::Ordered(_) => { + error!("checking voting power for Ordered node"); + true + }, }) .unwrap_or(false) } @@ -260,7 +310,7 @@ impl InMemDag { .flat_map(|(_, round_ref)| round_ref.iter_mut()) .flatten() .filter(move |node_status| { - matches!(node_status, NodeStatus::Unordered(_)) + matches!(node_status, NodeStatus::Unordered { .. }) && reachable_filter(node_status.as_node()) }) } diff --git a/consensus/src/dag/order_rule.rs b/consensus/src/dag/order_rule.rs index 839e53f2a3d83..3f3a7aea00f66 100644 --- a/consensus/src/dag/order_rule.rs +++ b/consensus/src/dag/order_rule.rs @@ -136,7 +136,7 @@ impl OrderRule { .reachable( Some(current_anchor.metadata().clone()).iter(), Some(*self.lowest_unordered_anchor_round.read()), - |node_status| matches!(node_status, NodeStatus::Unordered(_)), + |node_status| matches!(node_status, NodeStatus::Unordered { .. }), ) // skip the current anchor itself .skip(1) diff --git a/consensus/src/dag/rb_handler.rs b/consensus/src/dag/rb_handler.rs index 2d3f307030d24..a484b75d6c0b9 100644 --- a/consensus/src/dag/rb_handler.rs +++ b/consensus/src/dag/rb_handler.rs @@ -104,6 +104,13 @@ impl NodeBroadcastHandler { } fn validate(&self, node: Node) -> anyhow::Result { + ensure!( + node.epoch() == self.epoch_state.epoch, + "different epoch {}, current {}", + node.epoch(), + self.epoch_state.epoch + ); + let num_vtxns = node.validator_txns().len() as u64; ensure!(num_vtxns <= self.vtxn_config.per_block_limit_txn_count()); for vtxn in node.validator_txns() { @@ -239,6 +246,8 @@ impl RpcHandler for NodeBroadcastHandler { .expect("must exist") .insert(*node.author(), vote.clone()); + self.dag.write().update_votes(&node, false); + debug!(LogSchema::new(LogEvent::Vote) .remote_peer(*node.author()) .round(node.round())); diff --git a/consensus/src/dag/tests/helpers.rs b/consensus/src/dag/tests/helpers.rs index d401968ff2664..7b651ac2d2bb0 100644 --- a/consensus/src/dag/tests/helpers.rs +++ b/consensus/src/dag/tests/helpers.rs @@ -40,7 +40,7 @@ pub(crate) fn new_node( parents: Vec, ) -> Node { Node::new( - 0, + 1, round, author, timestamp, diff --git a/consensus/src/dag/tests/rb_handler_tests.rs b/consensus/src/dag/tests/rb_handler_tests.rs index 11938cd7fd19d..9713f7e31f073 100644 --- a/consensus/src/dag/tests/rb_handler_tests.rs +++ b/consensus/src/dag/tests/rb_handler_tests.rs @@ -223,7 +223,7 @@ async fn test_node_broadcast_receiver_storage() { let sig = rb_receiver.process(node).await.expect("must succeed"); assert_ok_eq!(storage.get_votes(), vec![( - NodeId::new(0, 1, signers[0].author()), + NodeId::new(1, 1, signers[0].author()), sig )],); diff --git a/consensus/src/dag/types.rs b/consensus/src/dag/types.rs index a25248aecff41..4f677bf193961 100644 --- a/consensus/src/dag/types.rs +++ b/consensus/src/dag/types.rs @@ -30,12 +30,13 @@ use aptos_types::{ validator_txn::ValidatorTransaction, validator_verifier::ValidatorVerifier, }; +use futures_channel::oneshot; use serde::{Deserialize, Serialize}; use std::{ cmp::min, collections::HashSet, fmt::{Display, Formatter}, - ops::Deref, + ops::{Deref, DerefMut}, sync::Arc, }; @@ -343,7 +344,7 @@ impl Node { } } -#[derive(Serialize, Deserialize, PartialEq, Debug, Eq, Hash, Clone)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Eq, Hash, Clone, PartialOrd, Ord)] pub struct NodeId { epoch: u64, round: Round, @@ -534,47 +535,65 @@ impl TryFrom for Vote { pub struct SignatureBuilder { metadata: NodeMetadata, - partial_signatures: Mutex, + inner: Mutex<(PartialSignatures, Option>)>, epoch_state: Arc, } impl SignatureBuilder { - pub fn new(metadata: NodeMetadata, epoch_state: Arc) -> Arc { + pub fn new( + metadata: NodeMetadata, + epoch_state: Arc, + tx: oneshot::Sender, + ) -> Arc { Arc::new(Self { metadata, - partial_signatures: Mutex::new(PartialSignatures::empty()), + inner: Mutex::new((PartialSignatures::empty(), Some(tx))), epoch_state, }) } } impl BroadcastStatus for Arc { - type Aggregated = NodeCertificate; + type Aggregated = (); type Message = Node; type Response = Vote; + /// Processes the [Vote]s received for a given [Node]. Once a supermajority voting power + /// is reached, this method sends [NodeCertificate] into a channel. It will only return + /// successfully when [Vote]s are received from all the peers. fn add(&self, peer: Author, ack: Self::Response) -> anyhow::Result> { ensure!(self.metadata == ack.metadata, "Digest mismatch"); ack.verify(peer, &self.epoch_state.verifier)?; debug!(LogSchema::new(LogEvent::ReceiveVote) .remote_peer(peer) .round(self.metadata.round())); - let mut signatures_lock = self.partial_signatures.lock(); - signatures_lock.add_signature(peer, ack.signature); - Ok(self - .epoch_state - .verifier - .check_voting_power(signatures_lock.signatures().keys(), true) - .ok() - .map(|_| { - let aggregated_signature = self - .epoch_state - .verifier - .aggregate_signatures(&signatures_lock) - .expect("Signature aggregation should succeed"); - observe_node(self.metadata.timestamp(), NodeStage::CertAggregated); - NodeCertificate::new(self.metadata.clone(), aggregated_signature) - })) + let mut guard = self.inner.lock(); + let (partial_signatures, tx) = guard.deref_mut(); + partial_signatures.add_signature(peer, ack.signature); + + if tx.is_some() + && self + .epoch_state + .verifier + .check_voting_power(partial_signatures.signatures().keys(), true) + .is_ok() + { + let aggregated_signature = self + .epoch_state + .verifier + .aggregate_signatures(partial_signatures) + .expect("Signature aggregation should succeed"); + observe_node(self.metadata.timestamp(), NodeStage::CertAggregated); + let certificate = NodeCertificate::new(self.metadata.clone(), aggregated_signature); + + _ = tx.take().expect("must exist").send(certificate); + } + + if partial_signatures.signatures().len() == self.epoch_state.verifier.len() { + Ok(Some(())) + } else { + Ok(None) + } } } diff --git a/types/src/validator_verifier.rs b/types/src/validator_verifier.rs index 5e48ea057a4a7..f035e3bb0bf02 100644 --- a/types/src/validator_verifier.rs +++ b/types/src/validator_verifier.rs @@ -381,7 +381,14 @@ impl ValidatorVerifier { check_super_majority: bool, ) -> std::result::Result { let aggregated_voting_power = self.sum_voting_power(authors)?; + self.check_aggregated_voting_power(aggregated_voting_power, check_super_majority) + } + pub fn check_aggregated_voting_power( + &self, + aggregated_voting_power: u128, + check_super_majority: bool, + ) -> std::result::Result { let target = if check_super_majority { self.quorum_voting_power } else { From 9076381c47ed0181654f85d459e2a77c20f44276 Mon Sep 17 00:00:00 2001 From: Justin Chang <37165464+just-in-chang@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:55:10 -0800 Subject: [PATCH 052/328] [NFT Metadata Crawler] SHA256 file names + last_transaction_version migration (#11953) * sha cdn uri + txn version migration * lint --- Cargo.lock | 1 + ecosystem/nft-metadata-crawler-parser/Cargo.toml | 1 + .../down.sql | 1 + .../up.sql | 1 + .../src/models/nft_metadata_crawler_uris.rs | 11 +++++++++++ .../models/nft_metadata_crawler_uris_query.rs | 2 ++ .../nft-metadata-crawler-parser/src/schema.rs | 1 + .../src/utils/database.rs | 1 + .../nft-metadata-crawler-parser/src/utils/gcs.rs | 10 ++++++---- .../nft-metadata-crawler-parser/src/worker.rs | 16 ++++++++++------ 10 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/down.sql create mode 100644 ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/up.sql diff --git a/Cargo.lock b/Cargo.lock index 0c814dcbfa08b..c2b5c7dfe70ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3001,6 +3001,7 @@ dependencies = [ "reqwest", "serde", "serde_json", + "sha256", "tokio", "tracing", "url", diff --git a/ecosystem/nft-metadata-crawler-parser/Cargo.toml b/ecosystem/nft-metadata-crawler-parser/Cargo.toml index fdfc355bd4ec0..d29dab05676db 100644 --- a/ecosystem/nft-metadata-crawler-parser/Cargo.toml +++ b/ecosystem/nft-metadata-crawler-parser/Cargo.toml @@ -41,6 +41,7 @@ regex = { workspace = true } reqwest = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } +sha256 = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } url = { workspace = true } diff --git a/ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/down.sql b/ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/down.sql new file mode 100644 index 0000000000000..1ae21664754e2 --- /dev/null +++ b/ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/down.sql @@ -0,0 +1 @@ +ALTER TABLE IF EXISTS nft_metadata_crawler.parsed_asset_uris DROP COLUMN last_transaction_version; diff --git a/ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/up.sql b/ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/up.sql new file mode 100644 index 0000000000000..10f990fcfe14d --- /dev/null +++ b/ecosystem/nft-metadata-crawler-parser/migrations/2024-02-08-013147_add_last_transaction_version/up.sql @@ -0,0 +1 @@ +ALTER TABLE IF EXISTS nft_metadata_crawler.parsed_asset_uris ADD COLUMN last_transaction_version BIGINT NOT NULL DEFAULT 0; diff --git a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs index a630b53d150ec..cca0ca62b16ec 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris.rs @@ -23,6 +23,7 @@ pub struct NFTMetadataCrawlerURIs { image_optimizer_retry_count: i32, animation_optimizer_retry_count: i32, do_not_parse: bool, + last_transaction_version: i64, } impl NFTMetadataCrawlerURIs { @@ -38,6 +39,7 @@ impl NFTMetadataCrawlerURIs { image_optimizer_retry_count: 0, animation_optimizer_retry_count: 0, do_not_parse: false, + last_transaction_version: 0, } } @@ -155,6 +157,14 @@ impl NFTMetadataCrawlerURIs { pub fn set_do_not_parse(&mut self, do_not_parse: bool) { self.do_not_parse = do_not_parse; } + + pub fn get_last_transaction_version(&self) -> i64 { + self.last_transaction_version + } + + pub fn set_last_transaction_version(&mut self, last_transaction_version: i64) { + self.last_transaction_version = last_transaction_version; + } } impl From for NFTMetadataCrawlerURIs { @@ -170,6 +180,7 @@ impl From for NFTMetadataCrawlerURIs { image_optimizer_retry_count: query.image_optimizer_retry_count, animation_optimizer_retry_count: query.animation_optimizer_retry_count, do_not_parse: query.do_not_parse, + last_transaction_version: query.last_transaction_version, } } } diff --git a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs index 0ea8a1a250b9a..963065659448c 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/models/nft_metadata_crawler_uris_query.rs @@ -27,6 +27,7 @@ pub struct NFTMetadataCrawlerURIsQuery { pub animation_optimizer_retry_count: i32, pub inserted_at: chrono::NaiveDateTime, pub do_not_parse: bool, + pub last_transaction_version: i64, } impl NFTMetadataCrawlerURIsQuery { @@ -120,6 +121,7 @@ impl Default for NFTMetadataCrawlerURIsQuery { animation_optimizer_retry_count: 0, inserted_at: chrono::NaiveDateTime::default(), do_not_parse: false, + last_transaction_version: 0, } } } diff --git a/ecosystem/nft-metadata-crawler-parser/src/schema.rs b/ecosystem/nft-metadata-crawler-parser/src/schema.rs index 8c1de4b3e2471..f18c47ac3a4ec 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/schema.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/schema.rs @@ -22,6 +22,7 @@ pub mod nft_metadata_crawler { animation_optimizer_retry_count -> Int4, inserted_at -> Timestamp, do_not_parse -> Bool, + last_transaction_version -> Int8, } } diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs index 84214131f6c11..063876db2f925 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/database.rs @@ -52,6 +52,7 @@ pub fn upsert_uris( json_parser_retry_count.eq(excluded(json_parser_retry_count)), animation_optimizer_retry_count.eq(excluded(animation_optimizer_retry_count)), do_not_parse.eq(excluded(do_not_parse)), + last_transaction_version.eq(excluded(last_transaction_version)), )); let debug_query = diesel::debug_query::(&query).to_string(); diff --git a/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs b/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs index e69b40beb0633..b615aeb96fd31 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/utils/gcs.rs @@ -21,12 +21,13 @@ use std::time::Duration; /// Writes JSON Value to GCS pub async fn write_json_to_gcs( bucket: &str, - id: &str, + uri: &str, json: &Value, client: &Client, ) -> anyhow::Result { GCS_UPLOAD_INVOCATION_COUNT.inc(); - let filename = format!("cdn/{}.json", id); + let hashed_uri = sha256::digest(uri); + let filename = format!("cdn/{}.json", hashed_uri); let json_string = json.to_string(); let json_bytes = json_string.into_bytes(); @@ -74,11 +75,12 @@ pub async fn write_json_to_gcs( pub async fn write_image_to_gcs( img_format: ImageFormat, bucket: &str, - id: &str, + uri: &str, buffer: Vec, client: &Client, ) -> anyhow::Result { GCS_UPLOAD_INVOCATION_COUNT.inc(); + let hashed_uri = sha256::digest(uri); let extension = match img_format { ImageFormat::Gif | ImageFormat::Avif | ImageFormat::Png => img_format .extensions_str() @@ -88,7 +90,7 @@ pub async fn write_image_to_gcs( _ => "jpeg".to_string(), }; - let filename = format!("cdn/{}.{}", id, extension); + let filename = format!("cdn/{}.{}", hashed_uri, extension); let upload_type = UploadType::Simple(Media { name: filename.clone().into(), content_type: format!("image/{}", extension).into(), diff --git a/ecosystem/nft-metadata-crawler-parser/src/worker.rs b/ecosystem/nft-metadata-crawler-parser/src/worker.rs index 3899f55de62a4..613ce19e8c9a5 100644 --- a/ecosystem/nft-metadata-crawler-parser/src/worker.rs +++ b/ecosystem/nft-metadata-crawler-parser/src/worker.rs @@ -60,12 +60,14 @@ impl Worker { last_transaction_timestamp: chrono::NaiveDateTime, force: bool, ) -> Self { + let mut model = NFTMetadataCrawlerURIs::new(asset_uri); + model.set_last_transaction_version(last_transaction_version as i64); let worker = Self { config, conn, gcs_client, pubsub_message: pubsub_message.to_string(), - model: NFTMetadataCrawlerURIs::new(asset_uri), + model, asset_data_id: asset_data_id.to_string(), asset_uri: asset_uri.to_string(), last_transaction_version, @@ -150,7 +152,7 @@ impl Worker { self.log_info("Writing JSON to GCS"); let cdn_json_uri_result = write_json_to_gcs( &self.config.bucket, - &self.asset_data_id, + &self.asset_uri, &json, &self.gcs_client, ) @@ -211,7 +213,7 @@ impl Worker { .unwrap_or_else(|_| { self.log_warn("Failed to parse raw_image_uri", None); PARSE_URI_TYPE_COUNT.with_label_values(&["other"]).inc(); - raw_image_uri + raw_image_uri.clone() }); // Resize and optimize image @@ -243,7 +245,7 @@ impl Worker { let cdn_image_uri_result = write_image_to_gcs( format, &self.config.bucket, - &self.asset_data_id, + &raw_image_uri, image, &self.gcs_client, ) @@ -304,7 +306,7 @@ impl Worker { .unwrap_or_else(|_| { self.log_warn("Failed to parse raw_animation_uri", None); PARSE_URI_TYPE_COUNT.with_label_values(&["other"]).inc(); - raw_animation_uri + raw_animation_uri.clone() }); // Resize and optimize animation @@ -336,7 +338,7 @@ impl Worker { let cdn_animation_uri_result = write_image_to_gcs( format, &self.config.bucket, - &self.asset_data_id, + &raw_animation_uri, animation, &self.gcs_client, ) @@ -359,6 +361,8 @@ impl Worker { } } + self.model + .set_last_transaction_version(self.last_transaction_version as i64); if self.model.get_json_parser_retry_count() > MAX_NUM_PARSE_RETRIES || self.model.get_image_optimizer_retry_count() > MAX_NUM_PARSE_RETRIES || self.model.get_animation_optimizer_retry_count() > MAX_NUM_PARSE_RETRIES From fdc041f37e4cb17d2c7f4bb2e0ad784a3f007614 Mon Sep 17 00:00:00 2001 From: David Wolinsky Date: Sat, 10 Feb 2024 06:42:26 +0800 Subject: [PATCH 053/328] [framework] introduce private entry function for auth key rotation (#11969) This makes it explicit that were rotating an authentication key and eliminates the need for generating the complex proof the existing rotation method requires. This is viable because this is a private entry function that only a transaction can call into that is no scripts or other functions can call into. --- .../framework/aptos-framework/doc/account.md | 70 +++++++++++++++++++ .../aptos-framework/sources/account.move | 34 +++++++++ .../aptos-framework/sources/account.spec.move | 31 ++++++++ .../src/aptos_framework_sdk_builder.rs | 40 +++++++++++ 4 files changed, 175 insertions(+) diff --git a/aptos-move/framework/aptos-framework/doc/account.md b/aptos-move/framework/aptos-framework/doc/account.md index 2c9c1e59af575..9565d16e617ad 100644 --- a/aptos-move/framework/aptos-framework/doc/account.md +++ b/aptos-move/framework/aptos-framework/doc/account.md @@ -29,6 +29,7 @@ - [Function `increment_sequence_number`](#0x1_account_increment_sequence_number) - [Function `get_authentication_key`](#0x1_account_get_authentication_key) - [Function `rotate_authentication_key_internal`](#0x1_account_rotate_authentication_key_internal) +- [Function `rotate_authentication_key_call`](#0x1_account_rotate_authentication_key_call) - [Function `rotate_authentication_key`](#0x1_account_rotate_authentication_key) - [Function `rotate_authentication_key_with_rotation_capability`](#0x1_account_rotate_authentication_key_with_rotation_capability) - [Function `offer_rotation_capability`](#0x1_account_offer_rotation_capability) @@ -66,6 +67,7 @@ - [Function `increment_sequence_number`](#@Specification_1_increment_sequence_number) - [Function `get_authentication_key`](#@Specification_1_get_authentication_key) - [Function `rotate_authentication_key_internal`](#@Specification_1_rotate_authentication_key_internal) + - [Function `rotate_authentication_key_call`](#@Specification_1_rotate_authentication_key_call) - [Function `rotate_authentication_key`](#@Specification_1_rotate_authentication_key) - [Function `rotate_authentication_key_with_rotation_capability`](#@Specification_1_rotate_authentication_key_with_rotation_capability) - [Function `offer_rotation_capability`](#@Specification_1_offer_rotation_capability) @@ -1168,6 +1170,38 @@ the resource account. + + + + +## Function `rotate_authentication_key_call` + +Entry function-only rotation key function that allows the signer update their authentication_key. + + +
entry fun rotate_authentication_key_call(account: &signer, new_auth_key: vector<u8>)
+
+ + + +
+Implementation + + +
entry fun rotate_authentication_key_call(account: &signer, new_auth_key: vector<u8>) acquires Account, OriginatingAddress {
+    let addr = signer::address_of(account);
+    assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST));
+    assert!(
+        vector::length(&new_auth_key) == 32,
+        error::invalid_argument(EMALFORMED_AUTHENTICATION_KEY)
+    );
+    let account_resource = borrow_global_mut<Account>(addr);
+    update_auth_key_and_originating_address_table(addr, account_resource, new_auth_key);
+}
+
+ + +
@@ -2483,6 +2517,42 @@ The length of new_auth_key is 32. + + +### Function `rotate_authentication_key_call` + + +
entry fun rotate_authentication_key_call(account: &signer, new_auth_key: vector<u8>)
+
+ + +The Account existed under the signer before the call. +The length of new_auth_key is 32. + + +
let addr = signer::address_of(account);
+aborts_if !exists<Account>(addr);
+aborts_if vector::length(new_auth_key) != 32;
+let account_resource = global<Account>(addr);
+let curr_auth_key = from_bcs::deserialize<address>(account_resource.authentication_key);
+let originating_addr = addr;
+let address_map = global<OriginatingAddress>(@aptos_framework).address_map;
+let new_auth_key_addr = from_bcs::deserialize<address>(new_auth_key);
+aborts_if !exists<OriginatingAddress>(@aptos_framework);
+aborts_if !from_bcs::deserializable<address>(account_resource.authentication_key);
+aborts_if table::spec_contains(address_map, curr_auth_key) &&
+    table::spec_get(address_map, curr_auth_key) != originating_addr;
+aborts_if curr_auth_key != new_auth_key_addr && table::spec_contains(address_map, new_auth_key_addr);
+include UpdateAuthKeyAndOriginatingAddressTableAbortsIf {
+    originating_addr: addr,
+    new_auth_key_vector: new_auth_key,
+};
+let post auth_key = global<Account>(addr).authentication_key;
+ensures auth_key == new_auth_key;
+
+ + + diff --git a/aptos-move/framework/aptos-framework/sources/account.move b/aptos-move/framework/aptos-framework/sources/account.move index b91da76192d95..76bea0e3132c5 100644 --- a/aptos-move/framework/aptos-framework/sources/account.move +++ b/aptos-move/framework/aptos-framework/sources/account.move @@ -278,6 +278,18 @@ module aptos_framework::account { account_resource.authentication_key = new_auth_key; } + /// Entry function-only rotation key function that allows the signer update their authentication_key. + entry fun rotate_authentication_key_call(account: &signer, new_auth_key: vector) acquires Account, OriginatingAddress { + let addr = signer::address_of(account); + assert!(exists_at(addr), error::not_found(EACCOUNT_DOES_NOT_EXIST)); + assert!( + vector::length(&new_auth_key) == 32, + error::invalid_argument(EMALFORMED_AUTHENTICATION_KEY) + ); + let account_resource = borrow_global_mut(addr); + update_auth_key_and_originating_address_table(addr, account_resource, new_auth_key); + } + /// Generic authentication key rotation function that allows the user to rotate their authentication key from any scheme to any scheme. /// To authorize the rotation, we need two signatures: /// - the first signature `cap_rotate_key` refers to the signature by the account owner's current key on a valid `RotationProofChallenge`, @@ -1323,6 +1335,28 @@ module aptos_framework::account { assert!(borrow_global(alice_addr).authentication_key == new_auth_key, 0); } + + #[test(account = @aptos_framework)] + public entry fun test_simple_rotation(account: &signer) acquires Account, OriginatingAddress { + initialize(account); + + let alice_addr = @0x1234; + let alice = create_account_unchecked(alice_addr); + + let (_new_sk, new_pk) = ed25519::generate_keys(); + let new_pk_unvalidated = ed25519::public_key_to_unvalidated(&new_pk); + let new_auth_key = ed25519::unvalidated_public_key_to_authentication_key(&new_pk_unvalidated); + let new_addr = from_bcs::to_address(new_auth_key); + + rotate_authentication_key_call(&alice, new_auth_key); + + let address_map = &mut borrow_global_mut(@aptos_framework).address_map; + let expected_originating_address = table::borrow(address_map, new_addr); + assert!(*expected_originating_address == alice_addr, 0); + assert!(borrow_global(alice_addr).authentication_key == new_auth_key, 0); + } + + #[test(account = @aptos_framework)] #[expected_failure(abort_code = 0x20014, location = Self)] public entry fun test_max_guid(account: &signer) acquires Account { diff --git a/aptos-move/framework/aptos-framework/sources/account.spec.move b/aptos-move/framework/aptos-framework/sources/account.spec.move index 7a5371cd8ee6c..91e1aca7751ce 100644 --- a/aptos-move/framework/aptos-framework/sources/account.spec.move +++ b/aptos-move/framework/aptos-framework/sources/account.spec.move @@ -203,6 +203,37 @@ spec aptos_framework::account { ensures account_resource.authentication_key == new_auth_key; } + /// The Account existed under the signer before the call. + /// The length of new_auth_key is 32. + spec rotate_authentication_key_call(account: &signer, new_auth_key: vector) { + let addr = signer::address_of(account); + aborts_if !exists(addr); + aborts_if vector::length(new_auth_key) != 32; + let account_resource = global(addr); + let curr_auth_key = from_bcs::deserialize
(account_resource.authentication_key); + + // Verify all properties in update_auth_key_and_originating_address_table + let originating_addr = addr; + + let address_map = global(@aptos_framework).address_map; + let new_auth_key_addr = from_bcs::deserialize
(new_auth_key); + + aborts_if !exists(@aptos_framework); + aborts_if !from_bcs::deserializable
(account_resource.authentication_key); + aborts_if table::spec_contains(address_map, curr_auth_key) && + table::spec_get(address_map, curr_auth_key) != originating_addr; + + aborts_if curr_auth_key != new_auth_key_addr && table::spec_contains(address_map, new_auth_key_addr); + + include UpdateAuthKeyAndOriginatingAddressTableAbortsIf { + originating_addr: addr, + new_auth_key_vector: new_auth_key, + }; + + let post auth_key = global(addr).authentication_key; + ensures auth_key == new_auth_key; + } + spec fun spec_assert_valid_rotation_proof_signature_and_get_auth_key(scheme: u8, public_key_bytes: vector, signature: vector, challenge: RotationProofChallenge): vector; spec assert_valid_rotation_proof_signature_and_get_auth_key(scheme: u8, public_key_bytes: vector, signature: vector, challenge: &RotationProofChallenge): vector { diff --git a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs index c54667d9a8b64..6ccbc6e86afdb 100644 --- a/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs +++ b/aptos-move/framework/cached-packages/src/aptos_framework_sdk_builder.rs @@ -131,6 +131,11 @@ pub enum EntryFunctionCall { cap_update_table: Vec, }, + /// Entry function-only rotation key function that allows the signer update their authentication_key. + AccountRotateAuthenticationKeyCall { + new_auth_key: Vec, + }, + AccountRotateAuthenticationKeyWithRotationCapability { rotation_cap_offerer_address: AccountAddress, new_scheme: u8, @@ -948,6 +953,9 @@ impl EntryFunctionCall { cap_rotate_key, cap_update_table, ), + AccountRotateAuthenticationKeyCall { new_auth_key } => { + account_rotate_authentication_key_call(new_auth_key) + }, AccountRotateAuthenticationKeyWithRotationCapability { rotation_cap_offerer_address, new_scheme, @@ -1655,6 +1663,22 @@ pub fn account_rotate_authentication_key( )) } +/// Entry function-only rotation key function that allows the signer update their authentication_key. +pub fn account_rotate_authentication_key_call(new_auth_key: Vec) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 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, + ]), + ident_str!("account").to_owned(), + ), + ident_str!("rotate_authentication_key_call").to_owned(), + vec![], + vec![bcs::to_bytes(&new_auth_key).unwrap()], + )) +} + pub fn account_rotate_authentication_key_with_rotation_capability( rotation_cap_offerer_address: AccountAddress, new_scheme: u8, @@ -4123,6 +4147,18 @@ mod decoder { } } + pub fn account_rotate_authentication_key_call( + payload: &TransactionPayload, + ) -> Option { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::AccountRotateAuthenticationKeyCall { + new_auth_key: bcs::from_bytes(script.args().get(0)?).ok()?, + }) + } else { + None + } + } + pub fn account_rotate_authentication_key_with_rotation_capability( payload: &TransactionPayload, ) -> Option { @@ -5564,6 +5600,10 @@ static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy Date: Fri, 9 Feb 2024 19:35:44 -0500 Subject: [PATCH 054/328] fix value extraction, dont fallback unconditionally (#11972) --- aptos-move/block-executor/src/executor.rs | 33 ++++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index 047b22dc6b4ed..20dbdade90590 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -1299,10 +1299,13 @@ where unsync_map .finalize_group(&group_key) .map(|(resource_tag, value_with_layout)| { + let value = match value_with_layout { + ValueWithLayout::RawFromStorage(value) + | ValueWithLayout::Exchanged(value, _) => value, + }; ( resource_tag, - value_with_layout - .extract_value_no_layout() + value .extract_raw_bytes() .expect("Deletions should already be applied"), ) @@ -1523,16 +1526,16 @@ where ) }; - let resource_group_bcs_fallback = matches!( + let mut resource_group_bcs_fallback = matches!( ret, Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( IntentionalFallbackToSequential::ResourceGroupSerializationError ))) ); - if self.config.local.concurrency_level > 1 || resource_group_bcs_fallback { + if self.config.local.concurrency_level > 1 && !resource_group_bcs_fallback { // Sequential execution fallback, only worth doing if we did a different pass before, - // i.e. parallel, or without resource group serialization fallback configured. + // i.e. parallel. This fallback does not handle resource group serialization issues. if let Err(BlockExecutionError::FallbackToSequential(_)) = &ret { // Any error logs are already written at appropriate levels. @@ -1546,12 +1549,28 @@ where executor_arguments, signature_verified_block, base_view, - // Always enable resource group serialization handling in fallback. - true, + false, + ); + resource_group_bcs_fallback = matches!( + ret, + Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + ))) ); } } + if resource_group_bcs_fallback { + alert!("Resource group serialization fallback"); + init_speculative_logs(signature_verified_block.len()); + ret = self.execute_transactions_sequential( + executor_arguments, + signature_verified_block, + base_view, + true, + ); + } + // If after trying available fallbacks, we still are askign to do a fallback, // something unrecoverable went wrong. if let Err(BlockExecutionError::FallbackToSequential(e)) = &ret { From f2f02ecca9cbbd7eb0837dc6a74658f94b17e9c9 Mon Sep 17 00:00:00 2001 From: "Brian (Sunghoon) Cho" Date: Mon, 12 Feb 2024 11:20:10 -0800 Subject: [PATCH 055/328] [txn emitter] one liner to fix create-accounts command (#11957) ### Description Create accounts doesn't take a separate init_max_gas_per_txn, so assign it to max_gas_per_txn. ### Test Plan Run command locally. In future, we need an integration test that keeps this from breaking. --- crates/transaction-emitter-lib/src/wrappers.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/transaction-emitter-lib/src/wrappers.rs b/crates/transaction-emitter-lib/src/wrappers.rs index 1947d83c15fc3..72f8097bf50e2 100644 --- a/crates/transaction-emitter-lib/src/wrappers.rs +++ b/crates/transaction-emitter-lib/src/wrappers.rs @@ -176,6 +176,7 @@ pub async fn create_accounts_command( .init_gas_price_multiplier(1) .expected_gas_per_txn(create_accounts_args.max_gas_per_txn) .max_gas_per_txn(create_accounts_args.max_gas_per_txn) + .init_max_gas_per_txn(create_accounts_args.max_gas_per_txn) .coins_per_account_override(0) .expected_max_txns(0) .prompt_before_spending(); From 9e27701c5e80c9a363c73cde59f7030024be30d1 Mon Sep 17 00:00:00 2001 From: Junkil Park Date: Mon, 12 Feb 2024 11:37:36 -0800 Subject: [PATCH 056/328] [Prover] Added the Prover test for the Diem Framework package (#11875) * moved `move/documentation/examples` to `move/move-examples`. * Adjusted the dependency path * Added the Prover test for the Diem Framework package --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + third_party/move/move-examples/Cargo.toml | 15 +++++++++++++++ .../diem-framework/build_all.sh | 0 .../diem-framework/crates/cli/Cargo.toml | 0 .../diem-framework/crates/cli/src/main.rs | 0 .../crates/crypto-derive/Cargo.toml | 0 .../crates/crypto-derive/src/hasher.rs | 0 .../crates/crypto-derive/src/lib.rs | 0 .../crates/crypto-derive/src/unions.rs | 0 .../diem-framework/crates/crypto/Cargo.toml | 0 .../diem-framework/crates/crypto/README.md | 0 .../crates/crypto/benches/ed25519.rs | 0 .../diem-framework/crates/crypto/benches/noise.rs | 0 .../diem-framework/crates/crypto/src/compat.rs | 0 .../diem-framework/crates/crypto/src/ed25519.rs | 0 .../diem-framework/crates/crypto/src/error.rs | 0 .../diem-framework/crates/crypto/src/hash.rs | 0 .../diem-framework/crates/crypto/src/hkdf.rs | 0 .../diem-framework/crates/crypto/src/lib.rs | 0 .../crates/crypto/src/multi_ed25519.rs | 0 .../diem-framework/crates/crypto/src/noise.rs | 0 .../diem-framework/crates/crypto/src/tags.rs | 0 .../crates/crypto/src/test_utils.rs | 0 .../diem-framework/crates/crypto/src/traits.rs | 0 .../crates/crypto/src/unit_tests/bcs_test.rs | 0 .../crates/crypto/src/unit_tests/compat_test.rs | 0 .../src/unit_tests/compilation/cross_test.rs | 0 .../compilation/cross_test_trait_obj.rs | 0 .../compilation/cross_test_trait_obj_pub.rs | 0 .../compilation/cross_test_trait_obj_sig.rs | 0 .../src/unit_tests/compilation/small_kdf.rs | 0 .../crates/crypto/src/unit_tests/cross_test.rs | 0 .../crates/crypto/src/unit_tests/cryptohasher.rs | 0 .../crates/crypto/src/unit_tests/ed25519_test.rs | 0 .../crates/crypto/src/unit_tests/hash_test.rs | 0 .../crates/crypto/src/unit_tests/hkdf_test.rs | 0 .../crates/crypto/src/unit_tests/mod.rs | 0 .../crypto/src/unit_tests/multi_ed25519_test.rs | 0 .../crates/crypto/src/unit_tests/noise_test.rs | 0 .../crates/crypto/src/validatable.rs | 0 .../diem-framework/crates/crypto/src/x25519.rs | 0 .../crypto/test_vectors/noise_cacophony.txt | 0 .../diem-framework/crates/natives/Cargo.toml | 0 .../diem-framework/crates/natives/src/account.rs | 0 .../diem-framework/crates/natives/src/lib.rs | 0 .../crates/natives/src/signature.rs | 0 .../diem-framework/move-packages/DPN/Move.toml | 4 ++-- .../DPN/sources/AccountAdministrationScripts.move | 0 .../DPN/sources/AccountCreationScripts.move | 0 .../DPN/sources/AccountFreezing.move | 0 .../move-packages/DPN/sources/AccountLimits.move | 0 .../move-packages/DPN/sources/Authenticator.move | 0 .../move-packages/DPN/sources/CRSN.move | 0 .../move-packages/DPN/sources/ChainId.move | 0 .../move-packages/DPN/sources/CoreAddresses.move | 0 .../DPN/sources/DesignatedDealer.move | 0 .../move-packages/DPN/sources/Diem.move | 0 .../move-packages/DPN/sources/DiemAccount.move | 0 .../move-packages/DPN/sources/DiemBlock.move | 0 .../move-packages/DPN/sources/DiemConfig.move | 0 .../DPN/sources/DiemConsensusConfig.move | 0 .../move-packages/DPN/sources/DiemId.move | 0 .../move-packages/DPN/sources/DiemSystem.move | 0 .../move-packages/DPN/sources/DiemTimestamp.move | 0 .../sources/DiemTransactionPublishingOption.move | 0 .../move-packages/DPN/sources/DiemVMConfig.move | 0 .../move-packages/DPN/sources/DiemVersion.move | 0 .../DPN/sources/DualAttestation.move | 0 .../move-packages/DPN/sources/Genesis.move | 0 .../DPN/sources/NetworkIdentity.move | 0 .../DPN/sources/ParallelExecutionConfig.move | 0 .../move-packages/DPN/sources/PaymentScripts.move | 0 .../move-packages/DPN/sources/README | 0 .../DPN/sources/RecoveryAddress.move | 0 .../DPN/sources/RegisteredCurrencies.move | 0 .../move-packages/DPN/sources/Roles.move | 0 .../DPN/sources/SharedEd25519PublicKey.move | 0 .../move-packages/DPN/sources/Signature.move | 0 .../move-packages/DPN/sources/SlidingNonce.move | 0 .../DPN/sources/SystemAdministrationScripts.move | 0 .../move-packages/DPN/sources/TransactionFee.move | 0 .../DPN/sources/TreasuryComplianceScripts.move | 0 .../move-packages/DPN/sources/VASP.move | 0 .../move-packages/DPN/sources/VASPDomain.move | 0 .../sources/ValidatorAdministrationScripts.move | 0 .../DPN/sources/ValidatorConfig.move | 0 .../DPN/sources/ValidatorOperatorConfig.move | 0 .../move-packages/DPN/sources/XDX.move | 0 .../move-packages/DPN/sources/XUS.move | 0 .../DPN/tests/AccountFreezingTests.move | 0 .../move-packages/DPN/tests/AccountLimits.move | 0 .../DPN/tests/AuthenticatorTests.move | 0 .../move-packages/DPN/tests/CRSNTests.move | 0 .../DPN/tests/CoreAddressesTests.move | 0 .../move-packages/DPN/tests/CurrenciesTests.move | 0 .../move-packages/DPN/tests/DiemBlockTests.move | 0 .../move-packages/DPN/tests/DiemConfigTests.move | 0 .../move-packages/DPN/tests/DiemTests.move | 0 .../DPN/tests/DiemTimestampTests.move | 0 .../move-packages/DPN/tests/DiemVersionTests.move | 0 .../DPN/tests/RegisteredCurrencyTests.move | 0 .../move-packages/DPN/tests/RolesTests.move | 0 .../DPN/tests/SharedEd25519PublicKeyTests.move | 0 .../move-packages/DPN/tests/SignatureTests.move | 0 .../DPN/tests/TransactionFeeTests.move | 0 .../DPN/tests/ValidatorConfigTests.move | 0 .../DPN/tests/ValidatorOperatorConfigTests.move | 0 .../DPN/tests/WalletModuleTests.move | 0 .../move-packages/DPN/tests/XUSTests.move | 0 .../diem-framework/move-packages/core/Move.toml | 0 .../diem-framework/move-packages/core/README.md | 0 .../move-packages/core/sources/Account.move | 0 .../move-packages/core/sources/ChainId.move | 0 .../move-packages/core/sources/CoreGenesis.move | 0 .../move-packages/core/sources/DiemBlock.move | 0 .../move-packages/core/sources/DiemConfig.move | 0 .../move-packages/core/sources/DiemTimestamp.move | 0 .../move-packages/core/sources/Signature.move | 0 .../core/sources/SystemAddresses.move | 0 .../core/sources/configs/DiemConsensusConfig.move | 0 .../core/sources/configs/DiemSystem.move | 0 .../core/sources/configs/DiemVMConfig.move | 0 .../core/sources/configs/DiemVersion.move | 0 .../sources/configs/ParallelExecutionConfig.move | 0 .../core/sources/configs/ValidatorConfig.move | 0 .../sources/configs/ValidatorOperatorConfig.move | 0 .../move-packages/experimental/Move.toml | 0 .../sources/AccountCreationScripts.move | 0 .../move-packages/experimental/sources/BARS.move | 0 .../experimental/sources/ExperimentalAccount.move | 0 .../experimental/sources/Genesis.move | 0 .../experimental/sources/MultiToken.move | 0 .../experimental/sources/MultiTokenBalance.move | 0 .../move-packages/experimental/sources/NFT.move | 0 .../experimental/sources/NFTGallery.move | 0 .../sources/SystemAdministrationScripts.move | 0 .../move-packages/experimental/sources/Vote.move | 0 .../configs/ExperimentalConsensusConfig.move | 0 .../ExperimentalParallelExecutionConfig.move | 0 .../sources/configs/ExperimentalVMConfig.move | 0 .../configs/ExperimentalValidatorConfig.move | 0 .../ExperimentalValidatorOperatorConfig.move | 0 .../sources/configs/ExperimentalValidatorSet.move | 0 .../sources/configs/ExperimentalVersion.move | 0 .../experimental/sources/configs/README.md | 0 .../experimental/tests/MultiTokenTests.move | 0 .../experimental/tests/NFTTests.move | 0 .../experimental/tests/VoteTests.move | 0 .../diem-framework/prove_all.sh | 0 .../diem-framework/test_all.sh | 0 .../experimental/basic-coin/Move.toml | 2 +- .../basic-coin/sources/BasicCoin.move | 0 .../experimental/coin-swap/Move.toml | 4 ++-- .../experimental/coin-swap/sources/CoinSwap.move | 0 .../experimental/coin-swap/sources/GoldCoin.move | 0 .../experimental/coin-swap/sources/PoolToken.move | 0 .../coin-swap/sources/SilverCoin.move | 0 .../experimental/math-puzzle/Move.toml | 0 .../experimental/math-puzzle/README.md | 0 .../experimental/math-puzzle/sources/puzzle.move | 0 .../experimental/rounding-error/Move.toml | 2 +- .../rounding-error/sources/Reserve.move | 0 .../rounding-error/sources/Uniswap.move | 0 .../experimental/verify-sort/Move.toml | 2 +- .../experimental/verify-sort/sources/loop.move | 0 third_party/move/move-examples/src/lib.rs | 3 +++ .../move/move-examples/tests/move_prover_tests.rs | 10 ++++++++++ 168 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 third_party/move/move-examples/Cargo.toml rename third_party/move/{documentation/examples => move-examples}/diem-framework/build_all.sh (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/cli/Cargo.toml (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/cli/src/main.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto-derive/Cargo.toml (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto-derive/src/hasher.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto-derive/src/lib.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto-derive/src/unions.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/Cargo.toml (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/README.md (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/benches/ed25519.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/benches/noise.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/compat.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/ed25519.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/error.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/hash.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/hkdf.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/lib.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/multi_ed25519.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/noise.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/tags.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/test_utils.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/traits.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/bcs_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/compat_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_pub.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_sig.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/compilation/small_kdf.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/cross_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/cryptohasher.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/hash_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/mod.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/multi_ed25519_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/unit_tests/noise_test.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/validatable.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/src/x25519.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/crypto/test_vectors/noise_cacophony.txt (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/natives/Cargo.toml (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/natives/src/account.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/natives/src/lib.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/crates/natives/src/signature.rs (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/Move.toml (64%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/AccountAdministrationScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/AccountCreationScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/AccountFreezing.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/AccountLimits.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/Authenticator.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/CRSN.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/ChainId.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/CoreAddresses.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DesignatedDealer.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/Diem.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemAccount.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemBlock.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemConsensusConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemId.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemSystem.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemTimestamp.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemTransactionPublishingOption.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemVMConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DiemVersion.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/DualAttestation.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/Genesis.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/NetworkIdentity.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/ParallelExecutionConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/PaymentScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/README (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/RecoveryAddress.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/RegisteredCurrencies.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/Roles.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/SharedEd25519PublicKey.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/Signature.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/SlidingNonce.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/SystemAdministrationScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/TransactionFee.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/TreasuryComplianceScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/VASP.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/VASPDomain.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/ValidatorAdministrationScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/ValidatorConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/ValidatorOperatorConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/XDX.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/sources/XUS.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/AccountLimits.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/CRSNTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/CoreAddressesTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/CurrenciesTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/DiemBlockTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/DiemConfigTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/DiemTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/DiemVersionTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/RolesTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/SignatureTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/WalletModuleTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/DPN/tests/XUSTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/Move.toml (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/README.md (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/Account.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/ChainId.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/CoreGenesis.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/DiemBlock.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/DiemConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/DiemTimestamp.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/Signature.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/SystemAddresses.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/DiemConsensusConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/DiemSystem.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/DiemVMConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/DiemVersion.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/ParallelExecutionConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/ValidatorConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/core/sources/configs/ValidatorOperatorConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/Move.toml (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/AccountCreationScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/BARS.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/ExperimentalAccount.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/Genesis.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/MultiToken.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/NFT.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/NFTGallery.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/SystemAdministrationScripts.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/Vote.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalConsensusConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalParallelExecutionConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalVMConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorOperatorConfig.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorSet.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/ExperimentalVersion.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/sources/configs/README.md (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/tests/MultiTokenTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/tests/NFTTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/move-packages/experimental/tests/VoteTests.move (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/prove_all.sh (100%) rename third_party/move/{documentation/examples => move-examples}/diem-framework/test_all.sh (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/basic-coin/Move.toml (53%) rename third_party/move/{documentation/examples => move-examples}/experimental/basic-coin/sources/BasicCoin.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/coin-swap/Move.toml (64%) rename third_party/move/{documentation/examples => move-examples}/experimental/coin-swap/sources/CoinSwap.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/coin-swap/sources/GoldCoin.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/coin-swap/sources/PoolToken.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/coin-swap/sources/SilverCoin.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/math-puzzle/Move.toml (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/math-puzzle/README.md (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/math-puzzle/sources/puzzle.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/rounding-error/Move.toml (68%) rename third_party/move/{documentation/examples => move-examples}/experimental/rounding-error/sources/Reserve.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/rounding-error/sources/Uniswap.move (100%) rename third_party/move/{documentation/examples => move-examples}/experimental/verify-sort/Move.toml (50%) rename third_party/move/{documentation/examples => move-examples}/experimental/verify-sort/sources/loop.move (100%) create mode 100644 third_party/move/move-examples/src/lib.rs create mode 100644 third_party/move/move-examples/tests/move_prover_tests.rs diff --git a/Cargo.lock b/Cargo.lock index c2b5c7dfe70ed..a793e23e9e595 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10768,6 +10768,13 @@ dependencies = [ "serde_json", ] +[[package]] +name = "move-examples" +version = "0.1.1" +dependencies = [ + "move-cli", +] + [[package]] name = "move-explain" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 464e6f6e906f4..f35509da6c97f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -199,6 +199,7 @@ members = [ "third_party/move/move-compiler-v2/transactional-tests", "third_party/move/move-compiler/transactional-tests", "third_party/move/move-core/types", + "third_party/move/move-examples", "third_party/move/move-ir-compiler", "third_party/move/move-ir-compiler/move-bytecode-source-map", "third_party/move/move-ir-compiler/move-ir-to-bytecode", diff --git a/third_party/move/move-examples/Cargo.toml b/third_party/move/move-examples/Cargo.toml new file mode 100644 index 0000000000000..a6c8cae8de76e --- /dev/null +++ b/third_party/move/move-examples/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "move-examples" +version = "0.1.1" +edition = "2021" +authors = ["Diem Association "] +description = "Move examples" +license = "Apache-2.0" +publish = false + +[dependencies] + +[dev-dependencies] +move-cli = { path = "../tools/move-cli" } + +[features] diff --git a/third_party/move/documentation/examples/diem-framework/build_all.sh b/third_party/move/move-examples/diem-framework/build_all.sh similarity index 100% rename from third_party/move/documentation/examples/diem-framework/build_all.sh rename to third_party/move/move-examples/diem-framework/build_all.sh diff --git a/third_party/move/documentation/examples/diem-framework/crates/cli/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/cli/Cargo.toml similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/cli/Cargo.toml rename to third_party/move/move-examples/diem-framework/crates/cli/Cargo.toml diff --git a/third_party/move/documentation/examples/diem-framework/crates/cli/src/main.rs b/third_party/move/move-examples/diem-framework/crates/cli/src/main.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/cli/src/main.rs rename to third_party/move/move-examples/diem-framework/crates/cli/src/main.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto-derive/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/crypto-derive/Cargo.toml similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto-derive/Cargo.toml rename to third_party/move/move-examples/diem-framework/crates/crypto-derive/Cargo.toml diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto-derive/src/hasher.rs b/third_party/move/move-examples/diem-framework/crates/crypto-derive/src/hasher.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto-derive/src/hasher.rs rename to third_party/move/move-examples/diem-framework/crates/crypto-derive/src/hasher.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto-derive/src/lib.rs b/third_party/move/move-examples/diem-framework/crates/crypto-derive/src/lib.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto-derive/src/lib.rs rename to third_party/move/move-examples/diem-framework/crates/crypto-derive/src/lib.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto-derive/src/unions.rs b/third_party/move/move-examples/diem-framework/crates/crypto-derive/src/unions.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto-derive/src/unions.rs rename to third_party/move/move-examples/diem-framework/crates/crypto-derive/src/unions.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/crypto/Cargo.toml similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/Cargo.toml rename to third_party/move/move-examples/diem-framework/crates/crypto/Cargo.toml diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/README.md b/third_party/move/move-examples/diem-framework/crates/crypto/README.md similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/README.md rename to third_party/move/move-examples/diem-framework/crates/crypto/README.md diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/benches/ed25519.rs b/third_party/move/move-examples/diem-framework/crates/crypto/benches/ed25519.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/benches/ed25519.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/benches/ed25519.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/benches/noise.rs b/third_party/move/move-examples/diem-framework/crates/crypto/benches/noise.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/benches/noise.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/benches/noise.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/compat.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/compat.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/compat.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/compat.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/ed25519.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/ed25519.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/ed25519.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/ed25519.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/error.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/error.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/error.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/error.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/hash.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/hash.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/hash.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/hash.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/hkdf.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/hkdf.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/hkdf.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/hkdf.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/lib.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/lib.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/lib.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/lib.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/multi_ed25519.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/multi_ed25519.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/multi_ed25519.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/multi_ed25519.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/noise.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/noise.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/noise.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/noise.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/tags.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/tags.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/tags.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/tags.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/test_utils.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/test_utils.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/test_utils.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/test_utils.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/traits.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/traits.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/traits.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/traits.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/bcs_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/bcs_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/bcs_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/bcs_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compat_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compat_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compat_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compat_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_pub.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_pub.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_pub.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_pub.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_sig.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_sig.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_sig.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/cross_test_trait_obj_sig.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/small_kdf.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/small_kdf.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/compilation/small_kdf.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/compilation/small_kdf.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/cross_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/cross_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/cross_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/cross_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/cryptohasher.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/cryptohasher.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/cryptohasher.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/cryptohasher.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/ed25519_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hash_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/hash_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hash_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/hash_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/hkdf_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/mod.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/mod.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/mod.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/mod.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/multi_ed25519_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/multi_ed25519_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/multi_ed25519_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/multi_ed25519_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/noise_test.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/noise_test.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/unit_tests/noise_test.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/unit_tests/noise_test.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/validatable.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/validatable.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/validatable.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/validatable.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/src/x25519.rs b/third_party/move/move-examples/diem-framework/crates/crypto/src/x25519.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/src/x25519.rs rename to third_party/move/move-examples/diem-framework/crates/crypto/src/x25519.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/crypto/test_vectors/noise_cacophony.txt b/third_party/move/move-examples/diem-framework/crates/crypto/test_vectors/noise_cacophony.txt similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/crypto/test_vectors/noise_cacophony.txt rename to third_party/move/move-examples/diem-framework/crates/crypto/test_vectors/noise_cacophony.txt diff --git a/third_party/move/documentation/examples/diem-framework/crates/natives/Cargo.toml b/third_party/move/move-examples/diem-framework/crates/natives/Cargo.toml similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/natives/Cargo.toml rename to third_party/move/move-examples/diem-framework/crates/natives/Cargo.toml diff --git a/third_party/move/documentation/examples/diem-framework/crates/natives/src/account.rs b/third_party/move/move-examples/diem-framework/crates/natives/src/account.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/natives/src/account.rs rename to third_party/move/move-examples/diem-framework/crates/natives/src/account.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/natives/src/lib.rs b/third_party/move/move-examples/diem-framework/crates/natives/src/lib.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/natives/src/lib.rs rename to third_party/move/move-examples/diem-framework/crates/natives/src/lib.rs diff --git a/third_party/move/documentation/examples/diem-framework/crates/natives/src/signature.rs b/third_party/move/move-examples/diem-framework/crates/natives/src/signature.rs similarity index 100% rename from third_party/move/documentation/examples/diem-framework/crates/natives/src/signature.rs rename to third_party/move/move-examples/diem-framework/crates/natives/src/signature.rs diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/Move.toml b/third_party/move/move-examples/diem-framework/move-packages/DPN/Move.toml similarity index 64% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/Move.toml rename to third_party/move/move-examples/diem-framework/move-packages/DPN/Move.toml index 4063140804ac2..a807a251eaaac 100644 --- a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/Move.toml +++ b/third_party/move/move-examples/diem-framework/move-packages/DPN/Move.toml @@ -11,5 +11,5 @@ CurrencyInfo = "0xA550C18" VMReserved = "0x0" [dependencies] -MoveStdlib = { local = "../../../../../move-stdlib" } -MoveNursery = { local = "../../../../../move-stdlib/nursery" } +MoveStdlib = { local = "../../../../move-stdlib" } +MoveNursery = { local = "../../../../move-stdlib/nursery" } diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountAdministrationScripts.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountAdministrationScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountAdministrationScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountAdministrationScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountCreationScripts.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountCreationScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountCreationScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountCreationScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountFreezing.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountFreezing.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountFreezing.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountFreezing.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountLimits.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountLimits.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/AccountLimits.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/AccountLimits.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Authenticator.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Authenticator.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Authenticator.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Authenticator.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/CRSN.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/CRSN.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/CRSN.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/CRSN.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ChainId.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ChainId.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ChainId.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ChainId.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/CoreAddresses.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/CoreAddresses.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/CoreAddresses.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/CoreAddresses.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DesignatedDealer.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DesignatedDealer.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DesignatedDealer.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DesignatedDealer.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Diem.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Diem.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Diem.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Diem.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemAccount.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemAccount.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemAccount.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemAccount.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemBlock.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemBlock.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemBlock.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemBlock.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemConfig.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemConsensusConfig.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemConsensusConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemConsensusConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemConsensusConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemId.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemId.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemId.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemId.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemSystem.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemSystem.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemSystem.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemSystem.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemTimestamp.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemTimestamp.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemTimestamp.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemTimestamp.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemTransactionPublishingOption.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemTransactionPublishingOption.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemTransactionPublishingOption.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemTransactionPublishingOption.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemVMConfig.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemVMConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemVMConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemVMConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemVersion.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemVersion.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DiemVersion.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DiemVersion.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DualAttestation.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DualAttestation.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/DualAttestation.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/DualAttestation.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Genesis.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Genesis.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Genesis.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Genesis.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/NetworkIdentity.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/NetworkIdentity.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/NetworkIdentity.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/NetworkIdentity.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ParallelExecutionConfig.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ParallelExecutionConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ParallelExecutionConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ParallelExecutionConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/PaymentScripts.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/PaymentScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/PaymentScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/PaymentScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/README b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/README similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/README rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/README diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/RecoveryAddress.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/RecoveryAddress.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/RecoveryAddress.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/RecoveryAddress.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/RegisteredCurrencies.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/RegisteredCurrencies.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/RegisteredCurrencies.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/RegisteredCurrencies.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Roles.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Roles.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Roles.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Roles.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/SharedEd25519PublicKey.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/SharedEd25519PublicKey.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/SharedEd25519PublicKey.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/SharedEd25519PublicKey.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Signature.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Signature.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/Signature.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/Signature.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/SlidingNonce.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/SlidingNonce.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/SlidingNonce.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/SlidingNonce.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/SystemAdministrationScripts.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/SystemAdministrationScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/SystemAdministrationScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/SystemAdministrationScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/TransactionFee.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/TransactionFee.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/TransactionFee.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/TransactionFee.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/TreasuryComplianceScripts.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/TreasuryComplianceScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/TreasuryComplianceScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/TreasuryComplianceScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/VASP.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/VASP.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/VASP.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/VASP.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/VASPDomain.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/VASPDomain.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/VASPDomain.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/VASPDomain.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ValidatorAdministrationScripts.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ValidatorAdministrationScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ValidatorAdministrationScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ValidatorAdministrationScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ValidatorConfig.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ValidatorConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ValidatorConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ValidatorConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ValidatorOperatorConfig.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ValidatorOperatorConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/ValidatorOperatorConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/ValidatorOperatorConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/XDX.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/XDX.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/XDX.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/XDX.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/XUS.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/sources/XUS.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/sources/XUS.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/sources/XUS.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/AccountFreezingTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/AccountLimits.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/AccountLimits.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/AccountLimits.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/AccountLimits.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/AuthenticatorTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/CRSNTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/CRSNTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/CRSNTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/CRSNTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/CoreAddressesTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/CoreAddressesTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/CoreAddressesTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/CoreAddressesTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/CurrenciesTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/CurrenciesTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/CurrenciesTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/CurrenciesTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemBlockTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemConfigTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemTimestampTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/DiemVersionTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/RegisteredCurrencyTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/RolesTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/RolesTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/RolesTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/RolesTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/SharedEd25519PublicKeyTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/SignatureTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/SignatureTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/SignatureTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/SignatureTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/TransactionFeeTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/ValidatorConfigTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/ValidatorOperatorConfigTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/WalletModuleTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/WalletModuleTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/WalletModuleTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/WalletModuleTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/XUSTests.move b/third_party/move/move-examples/diem-framework/move-packages/DPN/tests/XUSTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/DPN/tests/XUSTests.move rename to third_party/move/move-examples/diem-framework/move-packages/DPN/tests/XUSTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/Move.toml b/third_party/move/move-examples/diem-framework/move-packages/core/Move.toml similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/Move.toml rename to third_party/move/move-examples/diem-framework/move-packages/core/Move.toml diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/README.md b/third_party/move/move-examples/diem-framework/move-packages/core/README.md similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/README.md rename to third_party/move/move-examples/diem-framework/move-packages/core/README.md diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/Account.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/Account.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/Account.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/Account.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/ChainId.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/ChainId.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/ChainId.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/ChainId.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/CoreGenesis.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/CoreGenesis.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/CoreGenesis.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/CoreGenesis.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/DiemBlock.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/DiemBlock.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/DiemBlock.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/DiemBlock.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/DiemConfig.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/DiemConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/DiemConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/DiemConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/DiemTimestamp.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/DiemTimestamp.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/DiemTimestamp.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/DiemTimestamp.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/Signature.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/Signature.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/Signature.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/Signature.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/SystemAddresses.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/SystemAddresses.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/SystemAddresses.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/SystemAddresses.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemConsensusConfig.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemConsensusConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemConsensusConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemConsensusConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemSystem.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemSystem.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemSystem.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemSystem.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemVMConfig.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemVMConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemVMConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemVMConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemVersion.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemVersion.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/DiemVersion.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/DiemVersion.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/ParallelExecutionConfig.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/ParallelExecutionConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/ParallelExecutionConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/ParallelExecutionConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/ValidatorConfig.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/ValidatorConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/ValidatorConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/ValidatorConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/ValidatorOperatorConfig.move b/third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/ValidatorOperatorConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/core/sources/configs/ValidatorOperatorConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/core/sources/configs/ValidatorOperatorConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/Move.toml b/third_party/move/move-examples/diem-framework/move-packages/experimental/Move.toml similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/Move.toml rename to third_party/move/move-examples/diem-framework/move-packages/experimental/Move.toml diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/AccountCreationScripts.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/AccountCreationScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/AccountCreationScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/AccountCreationScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/BARS.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/BARS.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/BARS.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/BARS.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/ExperimentalAccount.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/ExperimentalAccount.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/ExperimentalAccount.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/ExperimentalAccount.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/Genesis.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/Genesis.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/Genesis.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/Genesis.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/MultiToken.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiToken.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/MultiToken.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiToken.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/MultiTokenBalance.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/NFT.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/NFT.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/NFT.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/NFT.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/NFTGallery.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/NFTGallery.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/NFTGallery.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/NFTGallery.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/SystemAdministrationScripts.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/SystemAdministrationScripts.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/SystemAdministrationScripts.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/SystemAdministrationScripts.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/Vote.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/Vote.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/Vote.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/Vote.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalConsensusConfig.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalConsensusConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalConsensusConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalConsensusConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalParallelExecutionConfig.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalParallelExecutionConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalParallelExecutionConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalParallelExecutionConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVMConfig.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVMConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVMConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVMConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorConfig.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorOperatorConfig.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorOperatorConfig.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorOperatorConfig.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorOperatorConfig.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorSet.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorSet.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorSet.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalValidatorSet.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVersion.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVersion.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVersion.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/ExperimentalVersion.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/README.md b/third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/README.md similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/sources/configs/README.md rename to third_party/move/move-examples/diem-framework/move-packages/experimental/sources/configs/README.md diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/tests/MultiTokenTests.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/tests/MultiTokenTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/tests/MultiTokenTests.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/tests/MultiTokenTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/tests/NFTTests.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/tests/NFTTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/tests/NFTTests.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/tests/NFTTests.move diff --git a/third_party/move/documentation/examples/diem-framework/move-packages/experimental/tests/VoteTests.move b/third_party/move/move-examples/diem-framework/move-packages/experimental/tests/VoteTests.move similarity index 100% rename from third_party/move/documentation/examples/diem-framework/move-packages/experimental/tests/VoteTests.move rename to third_party/move/move-examples/diem-framework/move-packages/experimental/tests/VoteTests.move diff --git a/third_party/move/documentation/examples/diem-framework/prove_all.sh b/third_party/move/move-examples/diem-framework/prove_all.sh similarity index 100% rename from third_party/move/documentation/examples/diem-framework/prove_all.sh rename to third_party/move/move-examples/diem-framework/prove_all.sh diff --git a/third_party/move/documentation/examples/diem-framework/test_all.sh b/third_party/move/move-examples/diem-framework/test_all.sh similarity index 100% rename from third_party/move/documentation/examples/diem-framework/test_all.sh rename to third_party/move/move-examples/diem-framework/test_all.sh diff --git a/third_party/move/documentation/examples/experimental/basic-coin/Move.toml b/third_party/move/move-examples/experimental/basic-coin/Move.toml similarity index 53% rename from third_party/move/documentation/examples/experimental/basic-coin/Move.toml rename to third_party/move/move-examples/experimental/basic-coin/Move.toml index 48547e2dccb2b..be370f43ad6e6 100644 --- a/third_party/move/documentation/examples/experimental/basic-coin/Move.toml +++ b/third_party/move/move-examples/experimental/basic-coin/Move.toml @@ -6,4 +6,4 @@ version = "0.0.0" BasicCoin = "0xBC" [dependencies] -MoveStdlib = { local = "../../../../move-stdlib/", addr_subst = { "std" = "0x1" } } +MoveStdlib = { local = "../../../move-stdlib/", addr_subst = { "std" = "0x1" } } diff --git a/third_party/move/documentation/examples/experimental/basic-coin/sources/BasicCoin.move b/third_party/move/move-examples/experimental/basic-coin/sources/BasicCoin.move similarity index 100% rename from third_party/move/documentation/examples/experimental/basic-coin/sources/BasicCoin.move rename to third_party/move/move-examples/experimental/basic-coin/sources/BasicCoin.move diff --git a/third_party/move/documentation/examples/experimental/coin-swap/Move.toml b/third_party/move/move-examples/experimental/coin-swap/Move.toml similarity index 64% rename from third_party/move/documentation/examples/experimental/coin-swap/Move.toml rename to third_party/move/move-examples/experimental/coin-swap/Move.toml index fc9dbf64bd43f..73bdfffb8fcd5 100644 --- a/third_party/move/documentation/examples/experimental/coin-swap/Move.toml +++ b/third_party/move/move-examples/experimental/coin-swap/Move.toml @@ -10,5 +10,5 @@ GoldCoin = "0x9C" SilverCoin = "0x5C" [dependencies] -MoveStdlib = { local = "../../../../move-stdlib" } -BasicCoin = { local = "../basic-coin"} +MoveStdlib = { local = "../../../move-stdlib" } +BasicCoin = { local = "../basic-coin" } diff --git a/third_party/move/documentation/examples/experimental/coin-swap/sources/CoinSwap.move b/third_party/move/move-examples/experimental/coin-swap/sources/CoinSwap.move similarity index 100% rename from third_party/move/documentation/examples/experimental/coin-swap/sources/CoinSwap.move rename to third_party/move/move-examples/experimental/coin-swap/sources/CoinSwap.move diff --git a/third_party/move/documentation/examples/experimental/coin-swap/sources/GoldCoin.move b/third_party/move/move-examples/experimental/coin-swap/sources/GoldCoin.move similarity index 100% rename from third_party/move/documentation/examples/experimental/coin-swap/sources/GoldCoin.move rename to third_party/move/move-examples/experimental/coin-swap/sources/GoldCoin.move diff --git a/third_party/move/documentation/examples/experimental/coin-swap/sources/PoolToken.move b/third_party/move/move-examples/experimental/coin-swap/sources/PoolToken.move similarity index 100% rename from third_party/move/documentation/examples/experimental/coin-swap/sources/PoolToken.move rename to third_party/move/move-examples/experimental/coin-swap/sources/PoolToken.move diff --git a/third_party/move/documentation/examples/experimental/coin-swap/sources/SilverCoin.move b/third_party/move/move-examples/experimental/coin-swap/sources/SilverCoin.move similarity index 100% rename from third_party/move/documentation/examples/experimental/coin-swap/sources/SilverCoin.move rename to third_party/move/move-examples/experimental/coin-swap/sources/SilverCoin.move diff --git a/third_party/move/documentation/examples/experimental/math-puzzle/Move.toml b/third_party/move/move-examples/experimental/math-puzzle/Move.toml similarity index 100% rename from third_party/move/documentation/examples/experimental/math-puzzle/Move.toml rename to third_party/move/move-examples/experimental/math-puzzle/Move.toml diff --git a/third_party/move/documentation/examples/experimental/math-puzzle/README.md b/third_party/move/move-examples/experimental/math-puzzle/README.md similarity index 100% rename from third_party/move/documentation/examples/experimental/math-puzzle/README.md rename to third_party/move/move-examples/experimental/math-puzzle/README.md diff --git a/third_party/move/documentation/examples/experimental/math-puzzle/sources/puzzle.move b/third_party/move/move-examples/experimental/math-puzzle/sources/puzzle.move similarity index 100% rename from third_party/move/documentation/examples/experimental/math-puzzle/sources/puzzle.move rename to third_party/move/move-examples/experimental/math-puzzle/sources/puzzle.move diff --git a/third_party/move/documentation/examples/experimental/rounding-error/Move.toml b/third_party/move/move-examples/experimental/rounding-error/Move.toml similarity index 68% rename from third_party/move/documentation/examples/experimental/rounding-error/Move.toml rename to third_party/move/move-examples/experimental/rounding-error/Move.toml index 1cb26f0476e75..53bfc31191c1a 100644 --- a/third_party/move/documentation/examples/experimental/rounding-error/Move.toml +++ b/third_party/move/move-examples/experimental/rounding-error/Move.toml @@ -7,4 +7,4 @@ std = "0x1" NamedAddr = "0xCAFE" [dependencies] -MoveStdlib = { local = "../../../../move-stdlib" } +MoveStdlib = { local = "../../../move-stdlib" } diff --git a/third_party/move/documentation/examples/experimental/rounding-error/sources/Reserve.move b/third_party/move/move-examples/experimental/rounding-error/sources/Reserve.move similarity index 100% rename from third_party/move/documentation/examples/experimental/rounding-error/sources/Reserve.move rename to third_party/move/move-examples/experimental/rounding-error/sources/Reserve.move diff --git a/third_party/move/documentation/examples/experimental/rounding-error/sources/Uniswap.move b/third_party/move/move-examples/experimental/rounding-error/sources/Uniswap.move similarity index 100% rename from third_party/move/documentation/examples/experimental/rounding-error/sources/Uniswap.move rename to third_party/move/move-examples/experimental/rounding-error/sources/Uniswap.move diff --git a/third_party/move/documentation/examples/experimental/verify-sort/Move.toml b/third_party/move/move-examples/experimental/verify-sort/Move.toml similarity index 50% rename from third_party/move/documentation/examples/experimental/verify-sort/Move.toml rename to third_party/move/move-examples/experimental/verify-sort/Move.toml index 1c74136db320c..7fbe6141a4c23 100644 --- a/third_party/move/documentation/examples/experimental/verify-sort/Move.toml +++ b/third_party/move/move-examples/experimental/verify-sort/Move.toml @@ -6,4 +6,4 @@ version = "0.0.0" Loop = "0x42" [dependencies] -MoveStdlib = { local = "../../../../move-stdlib/", addr_subst = { "std" = "0x1" } } +MoveStdlib = { local = "../../../move-stdlib/", addr_subst = { "std" = "0x1" } } diff --git a/third_party/move/documentation/examples/experimental/verify-sort/sources/loop.move b/third_party/move/move-examples/experimental/verify-sort/sources/loop.move similarity index 100% rename from third_party/move/documentation/examples/experimental/verify-sort/sources/loop.move rename to third_party/move/move-examples/experimental/verify-sort/sources/loop.move diff --git a/third_party/move/move-examples/src/lib.rs b/third_party/move/move-examples/src/lib.rs new file mode 100644 index 0000000000000..cd40352f11e98 --- /dev/null +++ b/third_party/move/move-examples/src/lib.rs @@ -0,0 +1,3 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 diff --git a/third_party/move/move-examples/tests/move_prover_tests.rs b/third_party/move/move-examples/tests/move_prover_tests.rs new file mode 100644 index 0000000000000..433f0b4048e44 --- /dev/null +++ b/third_party/move/move-examples/tests/move_prover_tests.rs @@ -0,0 +1,10 @@ +// Copyright (c) The Diem Core Contributors +// Copyright (c) The Move Contributors +// SPDX-License-Identifier: Apache-2.0 + +use move_cli::base::prove::ProverTest; + +#[test] +fn test_diem_framework() { + ProverTest::create("diem-framework/move-packages/DPN").run() +} From c1cd68c9df8ceedddaa4a76011785e720a21f3d0 Mon Sep 17 00:00:00 2001 From: Perry Randall Date: Mon, 12 Feb 2024 10:11:45 -0800 Subject: [PATCH 057/328] [gha] Remove confusing workflow We do not use this workflow for releasing Test Plan: PR checks pass --- .github/workflows/build-node-binaries.yaml | 46 ---------------------- 1 file changed, 46 deletions(-) delete mode 100644 .github/workflows/build-node-binaries.yaml diff --git a/.github/workflows/build-node-binaries.yaml b/.github/workflows/build-node-binaries.yaml deleted file mode 100644 index 43f580f17d5ae..0000000000000 --- a/.github/workflows/build-node-binaries.yaml +++ /dev/null @@ -1,46 +0,0 @@ -# This defines a workflow to make a release build of the aptos node. -# In order to trigger it go to the Actions Tab of the Repo, click "Build Aptos Node Binaries" and then "Run Workflow". - -name: "Build Aptos Node Binaries" - -on: - pull_request: - paths: - - ".github/workflows/build-node-binaries.yaml" - workflow_dispatch: - inputs: - git_ref: - type: string - required: true - description: "The ref to build from i.e. aptos-node-vX.X.X" - -jobs: - build-node-binary: - strategy: - matrix: - os: [ubuntu-20.04, ubuntu-22.04] - name: "Build Aptos Node Binary on ${{ matrix.os }}" - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.inputs.git_ref }} - - uses: aptos-labs/aptos-core/.github/actions/rust-setup@main - - name: Build Aptos Node Binary ${{ matrix.os }} - run: | - set -eux - - OS="${{ matrix.os }}" - SANITIZED_OS="${OS//./-}" - TARNAME="aptos-node-$SANITIZED_OS.tgz" - - cargo build -p aptos-node --release - cd target/release - tar czvf "$TARNAME" aptos-node - mv "$TARNAME" ../../ - - - name: Upload Binary - uses: actions/upload-artifact@v3 - with: - name: aptos-node-${{ matrix.os }} - path: aptos-node-*.tgz From 625118a03f8f49e36c97ed709080a7ddccbe7484 Mon Sep 17 00:00:00 2001 From: jill <121921928+jillxuu@users.noreply.github.com> Date: Mon, 12 Feb 2024 12:07:13 -0800 Subject: [PATCH 058/328] [table info][1/4] separate indexer async v2 db from aptosdb (#11799) * separate indexer async v2 db from aptosdb * address comments * remove unrelated changes --- Cargo.lock | 27 ++------- api/Cargo.toml | 1 + .../src/fake_context.rs | 1 + api/src/accounts.rs | 10 +++- api/src/context.rs | 8 ++- api/src/events.rs | 5 +- api/src/runtime.rs | 5 +- api/src/state.rs | 10 +++- api/src/tests/converter_test.rs | 2 +- api/src/transactions.rs | 24 ++++++-- api/src/view_function.rs | 6 +- api/test-context/src/test_context.rs | 2 +- api/types/Cargo.toml | 2 + api/types/src/convert.rs | 57 +++++++++++++------ .../src/aptos_test_harness.rs | 2 +- .../src/storage_interface.rs | 1 - aptos-node/Cargo.toml | 1 + aptos-node/src/services.rs | 16 +++++- crates/aptos-genesis/src/lib.rs | 1 - crates/aptos-genesis/src/mainnet.rs | 1 - crates/indexer/src/indexer/fetcher.rs | 2 +- crates/indexer/src/runtime.rs | 8 ++- .../indexer-grpc-fullnode/Cargo.toml | 1 + .../indexer-grpc-fullnode/src/runtime.rs | 10 +++- .../src/stream_coordinator.rs | 3 +- .../indexer-grpc-table-info/Cargo.toml | 31 +--------- .../indexer-grpc-table-info/src/runtime.rs | 45 ++++++++++----- .../src/table_info_service.rs | 42 ++++++-------- .../executor-benchmark/src/db_generator.rs | 1 - execution/executor-benchmark/src/lib.rs | 1 - .../src/tests/driver_factory.rs | 1 - storage/aptosdb/src/db/aptosdb_test.rs | 1 - .../src/db/include/aptosdb_internal.rs | 21 ------- .../aptosdb/src/db/include/aptosdb_reader.rs | 47 +-------------- .../src/db/include/aptosdb_testonly.rs | 7 +-- .../aptosdb/src/db/include/aptosdb_writer.rs | 41 ------------- storage/aptosdb/src/db/mod.rs | 8 +-- .../aptosdb/src/fast_sync_storage_wrapper.rs | 2 - storage/backup/backup-cli/src/utils/mod.rs | 1 - storage/db-tool/src/bootstrap.rs | 1 - storage/db-tool/src/replay_verify.rs | 1 - storage/indexer/src/db_ops.rs | 22 +++++++ storage/indexer/src/db_v2.rs | 43 ++++++-------- storage/indexer/src/lib.rs | 2 + storage/indexer/src/table_info_reader.rs | 19 +++++++ storage/storage-interface/src/lib.rs | 32 ----------- 46 files changed, 251 insertions(+), 324 deletions(-) create mode 100644 storage/indexer/src/db_ops.rs create mode 100644 storage/indexer/src/table_info_reader.rs diff --git a/Cargo.lock b/Cargo.lock index a793e23e9e595..2be34d423d123 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,6 +399,7 @@ dependencies = [ "aptos-cached-packages", "aptos-config", "aptos-crypto", + "aptos-db-indexer", "aptos-framework", "aptos-gas-meter", "aptos-gas-schedule", @@ -517,6 +518,7 @@ dependencies = [ "anyhow", "aptos-config", "aptos-crypto", + "aptos-db-indexer", "aptos-framework", "aptos-logger", "aptos-openapi", @@ -2183,6 +2185,7 @@ dependencies = [ "aptos-config", "aptos-crypto", "aptos-db", + "aptos-db-indexer", "aptos-executor", "aptos-executor-types", "aptos-framework", @@ -2299,50 +2302,31 @@ version = "1.0.0" dependencies = [ "anyhow", "aptos-api", - "aptos-api-test-context", "aptos-api-types", "aptos-bitvec", "aptos-config", - "aptos-crypto", "aptos-db", - "aptos-executor", - "aptos-executor-types", - "aptos-framework", - "aptos-genesis", - "aptos-global-constants", + "aptos-db-indexer", "aptos-indexer-grpc-fullnode", "aptos-indexer-grpc-utils", "aptos-logger", "aptos-mempool", - "aptos-mempool-notifications", "aptos-metrics-core", - "aptos-moving-average 0.1.0 (git+https://github.com/aptos-labs/aptos-indexer-processors.git?rev=4801acae7aea30d7e96bbfbe5ec5b04056dfa4cf)", - "aptos-proptest-helpers", "aptos-protos 1.1.2", "aptos-rocksdb-options", "aptos-runtimes", - "aptos-sdk", - "aptos-secure-storage", + "aptos-schemadb", "aptos-storage-interface", - "aptos-temppath", "aptos-types", - "aptos-vm", - "aptos-vm-validator", "base64 0.13.1", "bytes", "chrono", "fail 0.5.1", "futures", - "goldenfile", "hex", "hyper", - "move-binary-format", - "move-core-types", - "move-package", "move-resource-viewer", "once_cell", - "rand 0.7.3", - "regex", "serde", "serde_json", "tokio", @@ -3027,6 +3011,7 @@ dependencies = [ "aptos-data-client", "aptos-data-streaming-service", "aptos-db", + "aptos-db-indexer", "aptos-dkg-runtime", "aptos-event-notifications", "aptos-executor", diff --git a/api/Cargo.toml b/api/Cargo.toml index 7a0aa061fa505..04cd8ec534cc6 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -19,6 +19,7 @@ aptos-bcs-utils = { workspace = true } aptos-build-info = { workspace = true } aptos-config = { workspace = true } aptos-crypto = { workspace = true } +aptos-db-indexer = { workspace = true } aptos-framework = { workspace = true } aptos-gas-schedule = { workspace = true } aptos-global-constants = { workspace = true } diff --git a/api/openapi-spec-generator/src/fake_context.rs b/api/openapi-spec-generator/src/fake_context.rs index 5a87200f855ac..98dee1782b641 100644 --- a/api/openapi-spec-generator/src/fake_context.rs +++ b/api/openapi-spec-generator/src/fake_context.rs @@ -16,5 +16,6 @@ pub fn get_fake_context() -> Context { Arc::new(MockDbReaderWriter), mempool.ac_client, NodeConfig::default(), + None, /* table info reader */ ) } diff --git a/api/src/accounts.rs b/api/src/accounts.rs index 0ae87d4f634b9..4cfa4bc398de8 100644 --- a/api/src/accounts.rs +++ b/api/src/accounts.rs @@ -351,7 +351,10 @@ impl Account { .latest_state_view_poem(&self.latest_ledger_info)?; let converted_resources = state_view .as_move_resolver() - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_resources(resources.iter().map(|(k, v)| (k.clone(), v.as_slice()))) .context("Failed to build move resource response from data in DB") .map_err(|err| { @@ -545,7 +548,10 @@ impl Account { })?; resolver - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .move_struct_fields(resource_type, &bytes) .context("Failed to convert move structs from storage") .map_err(|err| { diff --git a/api/src/context.rs b/api/src/context.rs index cf30dd40b3972..b8a84503ffe18 100644 --- a/api/src/context.rs +++ b/api/src/context.rs @@ -18,6 +18,7 @@ use aptos_api_types::{ }; use aptos_config::config::{NodeConfig, RoleType}; use aptos_crypto::HashValue; +use aptos_db_indexer::table_info_reader::TableInfoReader; use aptos_gas_schedule::{AptosGasParameters, FromOnChainGasSchedule}; use aptos_logger::{error, info, warn, Schema}; use aptos_mempool::{MempoolClientRequest, MempoolClientSender, SubmissionStatus}; @@ -76,6 +77,7 @@ pub struct Context { gas_limit_cache: Arc>, view_function_stats: Arc, simulate_txn_stats: Arc, + pub table_info_reader: Option>, } impl std::fmt::Debug for Context { @@ -90,6 +92,7 @@ impl Context { db: Arc, mp_sender: MempoolClientSender, node_config: NodeConfig, + table_info_reader: Option>, ) -> Self { let (view_function_stats, simulate_txn_stats) = { let log_per_call_stats = node_config.api.periodic_function_stats_sec.is_some(); @@ -126,6 +129,7 @@ impl Context { })), view_function_stats, simulate_txn_stats, + table_info_reader, } } @@ -661,7 +665,7 @@ impl Context { let state_view = self.latest_state_view_poem(ledger_info)?; let resolver = state_view.as_move_resolver(); - let converter = resolver.as_converter(self.db.clone()); + let converter = resolver.as_converter(self.db.clone(), self.table_info_reader.clone()); let txns: Vec = data .into_iter() .map(|t| { @@ -692,7 +696,7 @@ impl Context { let state_view = self.latest_state_view_poem(ledger_info)?; let resolver = state_view.as_move_resolver(); - let converter = resolver.as_converter(self.db.clone()); + let converter = resolver.as_converter(self.db.clone(), self.table_info_reader.clone()); let txns: Vec = data .into_iter() .map(|t| { diff --git a/api/src/events.rs b/api/src/events.rs index f5232bbca725c..53a2f32db04ae 100644 --- a/api/src/events.rs +++ b/api/src/events.rs @@ -186,7 +186,10 @@ impl EventsApi { .context .latest_state_view_poem(&latest_ledger_info)? .as_move_resolver() - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_versioned_events(&events) .context("Failed to convert events from storage into response") .map_err(|err| { diff --git a/api/src/runtime.rs b/api/src/runtime.rs index 0fc82a98614fe..aacab86b4024b 100644 --- a/api/src/runtime.rs +++ b/api/src/runtime.rs @@ -10,6 +10,7 @@ use crate::{ }; use anyhow::Context as AnyhowContext; use aptos_config::config::{ApiConfig, NodeConfig}; +use aptos_db_indexer::table_info_reader::TableInfoReader; use aptos_logger::info; use aptos_mempool::MempoolClientSender; use aptos_storage_interface::DbReader; @@ -34,11 +35,12 @@ pub fn bootstrap( chain_id: ChainId, db: Arc, mp_sender: MempoolClientSender, + table_info_reader: Option>, ) -> anyhow::Result { let max_runtime_workers = get_max_runtime_workers(&config.api); let runtime = aptos_runtimes::spawn_named_runtime("api".into(), Some(max_runtime_workers)); - let context = Context::new(chain_id, db, mp_sender, config.clone()); + let context = Context::new(chain_id, db, mp_sender, config.clone(), table_info_reader); attach_poem_to_runtime(runtime.handle(), context.clone(), config, false) .context("Failed to attach poem to runtime")?; @@ -339,6 +341,7 @@ mod tests { ChainId::test(), context.db.clone(), context.mempool.ac_client.clone(), + None, ); assert!(ret.is_ok()); diff --git a/api/src/state.rs b/api/src/state.rs index 75621f679baa0..34c74b44d4a58 100644 --- a/api/src/state.rs +++ b/api/src/state.rs @@ -315,7 +315,10 @@ impl StateApi { AcceptType::Json => { let resource = state_view .as_move_resolver() - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_resource(&resource_type, &bytes) .context("Failed to deserialize resource data retrieved from DB") .map_err(|err| { @@ -421,7 +424,10 @@ impl StateApi { .state_view(ledger_version.map(|inner| inner.0))?; let resolver = state_view.as_move_resolver(); - let converter = resolver.as_converter(self.context.db.clone()); + let converter = resolver.as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ); // Convert key to lookup version for DB let vm_key = converter diff --git a/api/src/tests/converter_test.rs b/api/src/tests/converter_test.rs index b72703ca21f2f..05be4aafbb11e 100644 --- a/api/src/tests/converter_test.rs +++ b/api/src/tests/converter_test.rs @@ -21,7 +21,7 @@ async fn test_value_conversion() { let state_view = context.latest_state_view(); let resolver = state_view.as_move_resolver(); - let converter = resolver.as_converter(context.db); + let converter = resolver.as_converter(context.db, None); assert_value_conversion(&converter, "u8", 1i32, VmMoveValue::U8(1)); assert_value_conversion(&converter, "u64", "1", VmMoveValue::U64(1)); diff --git a/api/src/transactions.rs b/api/src/transactions.rs index 2b095dd7016bc..5726064112feb 100644 --- a/api/src/transactions.rs +++ b/api/src/transactions.rs @@ -762,7 +762,10 @@ impl TransactionsApi { let timestamp = self.context.get_block_timestamp(ledger_info, txn.version)?; resolver - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_onchain_transaction(timestamp, txn) .context("Failed to convert on chain transaction to Transaction") .map_err(|err| { @@ -774,7 +777,10 @@ impl TransactionsApi { })? }, TransactionData::Pending(txn) => resolver - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_pending_transaction(*txn) .context("Failed to convert on pending transaction to Transaction") .map_err(|err| { @@ -946,7 +952,10 @@ impl TransactionsApi { .context .latest_state_view_poem(ledger_info)? .as_move_resolver() - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_signed_transaction_poem(data.0, self.context.chain_id()) .context("Failed to create SignedTransaction from SubmitTransactionRequest") .map_err(|err| { @@ -1025,7 +1034,7 @@ impl TransactionsApi { .map(|(index, txn)| { self.context .latest_state_view_poem(ledger_info)?.as_move_resolver() - .as_converter(self.context.db.clone()) + .as_converter(self.context.db.clone(), self.context.table_info_reader.clone()) .try_into_signed_transaction_poem(txn, self.context.chain_id()) .context(format!("Failed to create SignedTransaction from SubmitTransactionRequest at position {}", index)) .map_err(|err| { @@ -1117,7 +1126,7 @@ impl TransactionsApi { // We provide the pending transaction so that users have the hash associated let pending_txn = resolver - .as_converter(self.context.db.clone()) + .as_converter(self.context.db.clone(), self.context.table_info_reader.clone()) .try_into_pending_transaction_poem(txn) .context("Failed to build PendingTransaction from mempool response, even though it said the request was accepted") .map_err(|err| SubmitTransactionError::internal_with_code( @@ -1350,7 +1359,10 @@ impl TransactionsApi { let state_view = self.context.latest_state_view_poem(&ledger_info)?; let resolver = state_view.as_move_resolver(); let raw_txn: RawTransaction = resolver - .as_converter(self.context.db.clone()) + .as_converter( + self.context.db.clone(), + self.context.table_info_reader.clone(), + ) .try_into_raw_transaction_poem(request.transaction, self.context.chain_id()) .context("The given transaction is invalid") .map_err(|err| { diff --git a/api/src/view_function.rs b/api/src/view_function.rs index 26767cb5ab286..f87503d40eaf8 100644 --- a/api/src/view_function.rs +++ b/api/src/view_function.rs @@ -97,7 +97,7 @@ fn view_request( ViewFunctionRequest::Json(data) => { let resolver = state_view.as_move_resolver(); resolver - .as_converter(context.db.clone()) + .as_converter(context.db.clone(), context.table_info_reader.clone()) .convert_view_function(data.0) .map_err(|err| { BasicErrorWith404::bad_request_with_code( @@ -171,7 +171,7 @@ fn view_request( AcceptType::Json => { let resolver = state_view.as_move_resolver(); let return_types = resolver - .as_converter(context.db.clone()) + .as_converter(context.db.clone(), context.table_info_reader.clone()) .function_return_types(&view_function) .and_then(|tys| { tys.into_iter() @@ -191,7 +191,7 @@ fn view_request( .zip(return_types.into_iter()) .map(|(v, ty)| { resolver - .as_converter(context.db.clone()) + .as_converter(context.db.clone(), context.table_info_reader.clone()) .try_into_move_value(&ty, &v) }) .collect::>>() diff --git a/api/test-context/src/test_context.rs b/api/test-context/src/test_context.rs index f93400202f75b..800d8bacee042 100644 --- a/api/test-context/src/test_context.rs +++ b/api/test-context/src/test_context.rs @@ -130,7 +130,6 @@ pub fn new_test_context( false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ ) .unwrap(), ) @@ -146,6 +145,7 @@ pub fn new_test_context( db.clone(), mempool.ac_client.clone(), node_config.clone(), + None, /* table info reader */ ); // Configure the testing depending on which API version we're testing. diff --git a/api/types/Cargo.toml b/api/types/Cargo.toml index 7154f0cee7f58..b36f5698cda21 100644 --- a/api/types/Cargo.toml +++ b/api/types/Cargo.toml @@ -16,6 +16,7 @@ rust-version = { workspace = true } anyhow = { workspace = true } aptos-config = { workspace = true } aptos-crypto = { workspace = true } +aptos-db-indexer = { workspace = true } aptos-framework = { workspace = true } aptos-logger = { workspace = true } aptos-openapi = { workspace = true } @@ -35,3 +36,4 @@ poem-openapi = { workspace = true } poem-openapi-derive = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } + diff --git a/api/types/src/convert.rs b/api/types/src/convert.rs index d69c5f7a869de..b9f3a45f78712 100644 --- a/api/types/src/convert.rs +++ b/api/types/src/convert.rs @@ -18,6 +18,7 @@ use crate::{ }; use anyhow::{bail, ensure, format_err, Context as AnyhowContext, Result}; use aptos_crypto::{hash::CryptoHash, HashValue}; +use aptos_db_indexer::table_info_reader::TableInfoReader; use aptos_storage_interface::DbReader; use aptos_types::{ access_path::{AccessPath, Path}, @@ -25,7 +26,7 @@ use aptos_types::{ contract_event::{ContractEvent, EventWithVersion}, state_store::{ state_key::{StateKey, StateKeyInner}, - table::TableHandle, + table::{TableHandle, TableInfo}, }, transaction::{ EntryFunction, ExecutionStatus, ModuleBundle, Multisig, RawTransaction, Script, @@ -62,13 +63,19 @@ const OBJECT_STRUCT: &IdentStr = ident_str!("Object"); pub struct MoveConverter<'a, R: ?Sized> { inner: MoveValueAnnotator<'a, R>, db: Arc, + table_info_reader: Option>, } impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { - pub fn new(inner: &'a R, db: Arc) -> Self { + pub fn new( + inner: &'a R, + db: Arc, + table_info_reader: Option>, + ) -> Self { Self { inner: MoveValueAnnotator::new(inner), db, + table_info_reader, } } @@ -422,12 +429,9 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { key: &[u8], value: &[u8], ) -> Result> { - if !self.db.indexer_enabled() && !self.db.indexer_async_v2_enabled() { - return Ok(None); - } - let table_info = match self.db.get_table_info(handle) { - Ok(ti) => ti, - Err(_) => { + let table_info = match self.get_table_info(handle)? { + Some(ti) => ti, + None => { aptos_logger::warn!( "Table info not found for handle {:?}, can't decode table item. OK for simulation", handle @@ -435,6 +439,7 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { return Ok(None); // if table item not found return None anyway to avoid crash }, }; + let key = self.try_into_move_value(&table_info.key_type, key)?; let value = self.try_into_move_value(&table_info.value_type, value)?; @@ -451,12 +456,9 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { handle: TableHandle, key: &[u8], ) -> Result> { - if !self.db.indexer_enabled() && !self.db.indexer_async_v2_enabled() { - return Ok(None); - } - let table_info = match self.db.get_table_info(handle) { - Ok(ti) => ti, - Err(_) => { + let table_info = match self.get_table_info(handle)? { + Some(ti) => ti, + None => { aptos_logger::warn!( "Table info not found for handle {:?}, can't decode table item. OK for simulation", handle @@ -464,6 +466,7 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { return Ok(None); // if table item not found return None anyway to avoid crash }, }; + let key = self.try_into_move_value(&table_info.key_type, key)?; Ok(Some(DeletedTableData { @@ -924,6 +927,18 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { args, }) } + + fn get_table_info(&self, handle: TableHandle) -> Result> { + if let Some(table_info_reader) = self.table_info_reader.as_ref() { + // Attempt to get table_info from the table_info_reader if it exists + Ok(table_info_reader.get_table_info(handle)?) + } else if self.db.indexer_enabled() { + // Attempt to get table_info from the db if indexer is enabled + Ok(Some(self.db.get_table_info(handle)?)) + } else { + Ok(None) + } + } } impl<'a, R: ModuleResolver + ?Sized> ExplainVMStatus for MoveConverter<'a, R> { @@ -934,12 +949,20 @@ impl<'a, R: ModuleResolver + ?Sized> ExplainVMStatus for MoveConverter<'a, R> { } } pub trait AsConverter { - fn as_converter(&self, db: Arc) -> MoveConverter; + fn as_converter( + &self, + db: Arc, + table_info_reader: Option>, + ) -> MoveConverter; } impl AsConverter for R { - fn as_converter(&self, db: Arc) -> MoveConverter { - MoveConverter::new(self, db) + fn as_converter( + &self, + db: Arc, + table_info_reader: Option>, + ) -> MoveConverter { + MoveConverter::new(self, db, table_info_reader) } } diff --git a/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs b/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs index effee015f0f4e..9a25a4cabf246 100644 --- a/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs +++ b/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs @@ -919,7 +919,7 @@ impl<'a> MoveTestAdapter<'a> for AptosTestAdapter<'a> { }, AptosSubCommand::ViewTableCommand(view_table_cmd) => { let resolver = self.storage.as_move_resolver(); - let converter = resolver.as_converter(Arc::new(FakeDbReader {})); + let converter = resolver.as_converter(Arc::new(FakeDbReader {}), None); let vm_key = converter .try_into_vm_value(&view_table_cmd.key_type, view_table_cmd.key_value) diff --git a/aptos-move/aptos-validator-interface/src/storage_interface.rs b/aptos-move/aptos-validator-interface/src/storage_interface.rs index ca914522f8328..f9ed2da2a90a4 100644 --- a/aptos-move/aptos-validator-interface/src/storage_interface.rs +++ b/aptos-move/aptos-validator-interface/src/storage_interface.rs @@ -32,7 +32,6 @@ impl DBDebuggerInterface { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ ) .map_err(anyhow::Error::from)?, ))) diff --git a/aptos-node/Cargo.toml b/aptos-node/Cargo.toml index 9e87b7bc9cb7d..fa55dbeb1ff31 100644 --- a/aptos-node/Cargo.toml +++ b/aptos-node/Cargo.toml @@ -28,6 +28,7 @@ aptos-crypto = { workspace = true } aptos-data-client = { workspace = true } aptos-data-streaming-service = { workspace = true } aptos-db = { workspace = true } +aptos-db-indexer = { workspace = true } aptos-dkg-runtime = { workspace = true } aptos-event-notifications = { workspace = true } aptos-executor = { workspace = true } diff --git a/aptos-node/src/services.rs b/aptos-node/src/services.rs index 2562a6d848086..ad2c37a914c0f 100644 --- a/aptos-node/src/services.rs +++ b/aptos-node/src/services.rs @@ -11,6 +11,7 @@ use aptos_consensus::{ }; use aptos_consensus_notifications::ConsensusNotifier; use aptos_data_client::client::AptosDataClient; +use aptos_db_indexer::table_info_reader::TableInfoReader; use aptos_event_notifications::{DbBackedOnChainConfig, ReconfigNotificationListener}; use aptos_indexer_grpc_fullnode::runtime::bootstrap as bootstrap_indexer_grpc; use aptos_indexer_grpc_table_info::runtime::bootstrap as bootstrap_indexer_table_info; @@ -52,20 +53,28 @@ pub fn bootstrap_api_and_indexer( let (mempool_client_sender, mempool_client_receiver) = mpsc::channel(AC_SMP_CHANNEL_BUFFER_SIZE); - let indexer_table_info = bootstrap_indexer_table_info( + let (indexer_table_info_runtime, indexer_async_v2) = match bootstrap_indexer_table_info( node_config, chain_id, db_rw.clone(), mempool_client_sender.clone(), - ); + ) { + Some((runtime, indexer_v2)) => (Some(runtime), Some(indexer_v2)), + None => (None, None), + }; // Create the API runtime + let table_info_reader: Option> = indexer_async_v2.map(|arc| { + let trait_object: Arc = arc; + trait_object + }); let api_runtime = if node_config.api.enabled { Some(bootstrap_api( node_config, chain_id, db_rw.reader.clone(), mempool_client_sender.clone(), + table_info_reader.clone(), )?) } else { None @@ -77,6 +86,7 @@ pub fn bootstrap_api_and_indexer( chain_id, db_rw.reader.clone(), mempool_client_sender.clone(), + table_info_reader, ); // Create the indexer runtime @@ -90,7 +100,7 @@ pub fn bootstrap_api_and_indexer( Ok(( mempool_client_receiver, api_runtime, - indexer_table_info, + indexer_table_info_runtime, indexer_runtime, indexer_grpc, )) diff --git a/crates/aptos-genesis/src/lib.rs b/crates/aptos-genesis/src/lib.rs index 1eeeea0f8e178..73633e2d2c73c 100644 --- a/crates/aptos-genesis/src/lib.rs +++ b/crates/aptos-genesis/src/lib.rs @@ -156,7 +156,6 @@ impl GenesisInfo { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ )?; let db_rw = DbReaderWriter::new(aptosdb); aptos_executor::db_bootstrapper::generate_waypoint::(&db_rw, genesis) diff --git a/crates/aptos-genesis/src/mainnet.rs b/crates/aptos-genesis/src/mainnet.rs index d3cbb9c15cce7..7e1aa674dd72d 100644 --- a/crates/aptos-genesis/src/mainnet.rs +++ b/crates/aptos-genesis/src/mainnet.rs @@ -141,7 +141,6 @@ impl MainnetGenesisInfo { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ )?; let db_rw = DbReaderWriter::new(aptosdb); aptos_executor::db_bootstrapper::generate_waypoint::(&db_rw, genesis) diff --git a/crates/indexer/src/indexer/fetcher.rs b/crates/indexer/src/indexer/fetcher.rs index 42f775256b236..c565ddf516eab 100644 --- a/crates/indexer/src/indexer/fetcher.rs +++ b/crates/indexer/src/indexer/fetcher.rs @@ -244,7 +244,7 @@ async fn fetch_nexts( let state_view = context.latest_state_view().unwrap(); let resolver = state_view.as_move_resolver(); - let converter = resolver.as_converter(context.db.clone()); + let converter = resolver.as_converter(context.db.clone(), context.table_info_reader.clone()); let mut transactions = vec![]; for (ind, raw_txn) in raw_txns.into_iter().enumerate() { diff --git a/crates/indexer/src/runtime.rs b/crates/indexer/src/runtime.rs index 14067021107f7..c3bf5a0516c0d 100644 --- a/crates/indexer/src/runtime.rs +++ b/crates/indexer/src/runtime.rs @@ -90,7 +90,13 @@ pub fn bootstrap( let node_config = config.clone(); runtime.spawn(async move { - let context = Arc::new(Context::new(chain_id, db, mp_sender, node_config)); + let context = Arc::new(Context::new( + chain_id, + db, + mp_sender, + node_config, + None, /* table info reader */ + )); run_forever(indexer_config, context).await; }); diff --git a/ecosystem/indexer-grpc/indexer-grpc-fullnode/Cargo.toml b/ecosystem/indexer-grpc/indexer-grpc-fullnode/Cargo.toml index e687cf779d6c1..03a78588be33e 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-fullnode/Cargo.toml +++ b/ecosystem/indexer-grpc/indexer-grpc-fullnode/Cargo.toml @@ -35,6 +35,7 @@ aptos-api = { workspace = true } aptos-api-types = { workspace = true } aptos-bitvec = { workspace = true } aptos-config = { workspace = true } +aptos-db-indexer = { workspace = true } aptos-indexer-grpc-utils = { workspace = true } aptos-logger = { workspace = true } aptos-mempool = { workspace = true } diff --git a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/runtime.rs b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/runtime.rs index 79a92569572cb..3b687b5c8ed2b 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/runtime.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/runtime.rs @@ -7,6 +7,7 @@ use crate::{ }; use aptos_api::context::Context; use aptos_config::config::NodeConfig; +use aptos_db_indexer::table_info_reader::TableInfoReader; use aptos_logger::info; use aptos_mempool::MempoolClientSender; use aptos_protos::{ @@ -34,6 +35,7 @@ pub fn bootstrap( chain_id: ChainId, db: Arc, mp_sender: MempoolClientSender, + table_info_reader: Option>, ) -> Option { if !config.indexer_grpc.enabled { return None; @@ -50,7 +52,13 @@ pub fn bootstrap( let output_batch_size = node_config.indexer_grpc.output_batch_size; runtime.spawn(async move { - let context = Arc::new(Context::new(chain_id, db, mp_sender, node_config)); + let context = Arc::new(Context::new( + chain_id, + db, + mp_sender, + node_config, + table_info_reader, + )); let service_context = ServiceContext { context: context.clone(), processor_task_count, diff --git a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/stream_coordinator.rs b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/stream_coordinator.rs index bc8f68da5119c..dc710b437b232 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/stream_coordinator.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/stream_coordinator.rs @@ -338,7 +338,8 @@ impl IndexerStreamCoordinator { let first_version = raw_txns.first().map(|txn| txn.version).unwrap(); let state_view = context.latest_state_view().unwrap(); let resolver = state_view.as_move_resolver(); - let converter = resolver.as_converter(context.db.clone()); + let converter = + resolver.as_converter(context.db.clone(), context.table_info_reader.clone()); // Enrich data with block metadata let (_, _, block_event) = context diff --git a/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml b/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml index b7f4496ec9f64..d739b3b042c48 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml +++ b/ecosystem/indexer-grpc/indexer-grpc-table-info/Cargo.toml @@ -34,43 +34,18 @@ aptos-api = { workspace = true } aptos-api-types = { workspace = true } aptos-bitvec = { workspace = true } aptos-config = { workspace = true } +aptos-db = { workspace = true } +aptos-db-indexer = { workspace = true } aptos-indexer-grpc-fullnode = { workspace = true } aptos-indexer-grpc-utils = { workspace = true } aptos-logger = { workspace = true } aptos-mempool = { workspace = true } aptos-metrics-core = { workspace = true } -aptos-moving-average = { workspace = true } aptos-protos = { workspace = true } aptos-runtimes = { workspace = true } -aptos-sdk = { workspace = true } +aptos-schemadb = { workspace = true } aptos-storage-interface = { workspace = true } aptos-types = { workspace = true } -aptos-vm = { workspace = true } - -move-binary-format = { workspace = true } -move-core-types = { workspace = true } -move-package = { workspace = true } - -[dev-dependencies] -goldenfile = { workspace = true } -rand = { workspace = true } -regex = { workspace = true } - -aptos-api-test-context = { workspace = true } -aptos-crypto = { workspace = true } -aptos-db = { workspace = true } -aptos-executor = { workspace = true } -aptos-executor-types = { workspace = true } -aptos-framework = { workspace = true } -aptos-genesis = { workspace = true } -aptos-global-constants = { workspace = true } -aptos-mempool = { workspace = true } -aptos-mempool-notifications = { workspace = true } -aptos-proptest-helpers = { workspace = true } -aptos-secure-storage = { workspace = true } -aptos-temppath = { workspace = true } -aptos-vm = { workspace = true } -aptos-vm-validator = { workspace = true } [features] failpoints = ["fail/failpoints"] diff --git a/ecosystem/indexer-grpc/indexer-grpc-table-info/src/runtime.rs b/ecosystem/indexer-grpc/indexer-grpc-table-info/src/runtime.rs index 969f9757f563d..cb5aa9531e880 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-table-info/src/runtime.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-table-info/src/runtime.rs @@ -4,48 +4,65 @@ use crate::table_info_service::TableInfoService; use aptos_api::context::Context; use aptos_config::config::NodeConfig; +use aptos_db_indexer::{db_ops::open_db, db_v2::IndexerAsyncV2}; use aptos_mempool::MempoolClientSender; use aptos_storage_interface::DbReaderWriter; use aptos_types::chain_id::ChainId; use std::sync::Arc; use tokio::runtime::Runtime; +const INDEX_ASYNC_V2_DB_NAME: &str = "index_indexer_async_v2_db"; + /// Creates a runtime which creates a thread pool which sets up fullnode indexer table info service /// Returns corresponding Tokio runtime pub fn bootstrap( config: &NodeConfig, chain_id: ChainId, - db: DbReaderWriter, + db_rw: DbReaderWriter, mp_sender: MempoolClientSender, -) -> Option { +) -> Option<(Runtime, Arc)> { if !config.indexer_table_info.enabled { return None; } let runtime = aptos_runtimes::spawn_named_runtime("table-info".to_string(), None); + // Set up db config and open up the db initially to read metadata let node_config = config.clone(); - let parser_task_count = node_config.indexer_table_info.parser_task_count; - let parser_batch_size = node_config.indexer_table_info.parser_batch_size; - let enable_expensive_logging = node_config.indexer_table_info.enable_expensive_logging; - let next_version = db.reader.get_indexer_async_v2_next_version().unwrap(); + let db_path = node_config + .storage + .get_dir_paths() + .default_root_path() + .join(INDEX_ASYNC_V2_DB_NAME); + let rocksdb_config = node_config.storage.rocksdb_configs.index_db_config; + let db = + open_db(db_path, &rocksdb_config).expect("Failed to open up indexer async v2 db initially"); + + let indexer_async_v2 = + Arc::new(IndexerAsyncV2::new(db).expect("Failed to initialize indexer async v2")); + let indexer_async_v2_clone = Arc::clone(&indexer_async_v2); // Spawn the runtime for table info parsing runtime.spawn(async move { let context = Arc::new(Context::new( chain_id, - db.reader.clone(), + db_rw.reader.clone(), mp_sender, - node_config, + node_config.clone(), + None, )); + let mut parser = TableInfoService::new( context, - next_version, - parser_task_count, - parser_batch_size, - enable_expensive_logging, + indexer_async_v2_clone.next_version(), + node_config.indexer_table_info.parser_task_count, + node_config.indexer_table_info.parser_batch_size, + node_config.indexer_table_info.enable_expensive_logging, + indexer_async_v2_clone, ); - parser.run(db.clone()).await + + parser.run().await; }); - Some(runtime) + + Some((runtime, indexer_async_v2)) } diff --git a/ecosystem/indexer-grpc/indexer-grpc-table-info/src/table_info_service.rs b/ecosystem/indexer-grpc/indexer-grpc-table-info/src/table_info_service.rs index 4d68ba98a9342..af965fac7b993 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-table-info/src/table_info_service.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-table-info/src/table_info_service.rs @@ -4,12 +4,12 @@ use anyhow::Error; use aptos_api::context::Context; use aptos_api_types::TransactionOnChainData; +use aptos_db_indexer::db_v2::IndexerAsyncV2; use aptos_indexer_grpc_fullnode::stream_coordinator::{ IndexerStreamCoordinator, TransactionBatchInfo, }; use aptos_indexer_grpc_utils::counters::{log_grpc_step, IndexerGrpcStep}; use aptos_logger::{debug, error, info, sample, sample::SampleRate}; -use aptos_storage_interface::{DbReaderWriter, DbWriter}; use aptos_types::write_set::WriteSet; use std::{sync::Arc, time::Duration}; use tonic::Status; @@ -24,6 +24,7 @@ pub struct TableInfoService { pub parser_batch_size: u16, pub context: Arc, pub enable_expensive_logging: bool, + pub indexer_async_v2: Arc, } impl TableInfoService { @@ -33,6 +34,7 @@ impl TableInfoService { parser_task_count: u16, parser_batch_size: u16, enable_expensive_logging: bool, + indexer_async_v2: Arc, ) -> Self { Self { current_version: request_start_version, @@ -40,6 +42,7 @@ impl TableInfoService { parser_batch_size, context, enable_expensive_logging, + indexer_async_v2, } } @@ -49,13 +52,13 @@ impl TableInfoService { /// 4. write parsed table info to rocksdb /// 5. after all batches from the loop complete, if pending on items not empty, move on to 6, otherwise, start from 1 again /// 6. retry all the txns in the loop sequentially to clean up the pending on items - pub async fn run(&mut self, db: DbReaderWriter) { + pub async fn run(&mut self) { loop { let start_time = std::time::Instant::now(); let ledger_version = self.get_highest_known_version().await.unwrap_or_default(); let batches = self.get_batches(ledger_version).await; let results = self - .process_multiple_batches(db.clone(), batches, ledger_version) + .process_multiple_batches(self.indexer_async_v2.clone(), batches, ledger_version) .await; let max_version = self.get_max_batch_version(results).unwrap_or_default(); let versions_processed = max_version - self.current_version + 1; @@ -85,18 +88,17 @@ impl TableInfoService { /// 2. Get write sets from transactions and parse write sets to get handle -> key,value type mapping, write the mapping to the rocksdb async fn process_multiple_batches( &self, - db: DbReaderWriter, + indexer_async_v2: Arc, batches: Vec, ledger_version: u64, ) -> Vec> { let mut tasks = vec![]; - let db_writer = db.writer.clone(); let context = self.context.clone(); for batch in batches.iter().cloned() { let task = tokio::spawn(Self::process_single_batch( context.clone(), - db_writer.clone(), + indexer_async_v2.clone(), ledger_version, batch, false, /* end_early_if_pending_on_empty */ @@ -115,8 +117,7 @@ impl TableInfoService { last_batch.start_version + last_batch.num_transactions_to_fetch as u64; // Clean up pending on items across threads - db.writer - .clone() + self.indexer_async_v2 .cleanup_pending_on_items() .expect("[Table Info] Failed to clean up the pending on items"); @@ -126,12 +127,7 @@ impl TableInfoService { // // Risk of this sequential approach is that it could be slow when the txns to process contain extremely // nested table items, but the risk is bounded by the the configuration of the number of txns to process and number of threads - if !db - .reader - .clone() - .is_indexer_async_v2_pending_on_empty() - .unwrap_or(false) - { + if !self.indexer_async_v2.is_indexer_async_v2_pending_on_empty() { let retry_batch = TransactionBatchInfo { start_version: self.current_version, num_transactions_to_fetch: total_txns_to_process as u16, @@ -140,7 +136,7 @@ impl TableInfoService { Self::process_single_batch( context.clone(), - db_writer, + indexer_async_v2.clone(), ledger_version, retry_batch, true, /* end_early_if_pending_on_empty */ @@ -151,16 +147,12 @@ impl TableInfoService { } assert!( - db.reader - .clone() - .is_indexer_async_v2_pending_on_empty() - .unwrap_or(false), + self.indexer_async_v2.is_indexer_async_v2_pending_on_empty(), "Missing data in table info parsing after sequential retry" ); // Update rocksdb's to be processed next version after verifying all txns are successfully parsed - db.writer - .clone() + self.indexer_async_v2 .update_next_version(end_version + 1) .unwrap(); @@ -179,7 +171,7 @@ impl TableInfoService { /// if pending on items are not empty async fn process_single_batch( context: Arc, - db_writer: Arc, + indexer_async_v2: Arc, ledger_version: u64, batch: TransactionBatchInfo, end_early_if_pending_on_empty: bool, @@ -197,7 +189,7 @@ impl TableInfoService { Self::parse_table_info( context.clone(), raw_txns.clone(), - db_writer.clone(), + indexer_async_v2, end_early_if_pending_on_empty, ) .expect("[Table Info] Failed to parse table info"); @@ -270,7 +262,7 @@ impl TableInfoService { fn parse_table_info( context: Arc, raw_txns: Vec, - db_writer: Arc, + indexer_async_v2: Arc, end_early_if_pending_on_empty: bool, ) -> Result<(), Error> { if raw_txns.is_empty() { @@ -281,7 +273,7 @@ impl TableInfoService { let first_version = raw_txns.first().map(|txn| txn.version).unwrap(); let write_sets: Vec = raw_txns.iter().map(|txn| txn.changes.clone()).collect(); let write_sets_slice: Vec<&WriteSet> = write_sets.iter().collect(); - db_writer + indexer_async_v2 .index_table_info( context.db.clone(), first_version, diff --git a/execution/executor-benchmark/src/db_generator.rs b/execution/executor-benchmark/src/db_generator.rs index 2930e0fe875d9..a9fe87b29fae8 100644 --- a/execution/executor-benchmark/src/db_generator.rs +++ b/execution/executor-benchmark/src/db_generator.rs @@ -74,7 +74,6 @@ fn bootstrap_with_genesis(db_dir: impl AsRef, enable_storage_sharding: boo false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ ) .expect("DB should open."), ); diff --git a/execution/executor-benchmark/src/lib.rs b/execution/executor-benchmark/src/lib.rs index b237ff23e0583..faeefcb241561 100644 --- a/execution/executor-benchmark/src/lib.rs +++ b/execution/executor-benchmark/src/lib.rs @@ -66,7 +66,6 @@ where false, config.storage.buffered_state_target_items, config.storage.max_num_nodes_per_lru_cache_shard, - false, ) .expect("DB should open."), ); diff --git a/state-sync/state-sync-driver/src/tests/driver_factory.rs b/state-sync/state-sync-driver/src/tests/driver_factory.rs index 7a7df57591ce6..13d88dd66ba9c 100644 --- a/state-sync/state-sync-driver/src/tests/driver_factory.rs +++ b/state-sync/state-sync-driver/src/tests/driver_factory.rs @@ -40,7 +40,6 @@ fn test_new_initialized_configs() { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ ) .unwrap(); let (_, db_rw) = DbReaderWriter::wrap(db); diff --git a/storage/aptosdb/src/db/aptosdb_test.rs b/storage/aptosdb/src/db/aptosdb_test.rs index 0ad8e5b52b95b..f57be62579a64 100644 --- a/storage/aptosdb/src/db/aptosdb_test.rs +++ b/storage/aptosdb/src/db/aptosdb_test.rs @@ -205,7 +205,6 @@ pub fn test_state_merkle_pruning_impl( false, /* enable_indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* enable_indexer_async_v2 */ ) .unwrap(); diff --git a/storage/aptosdb/src/db/include/aptosdb_internal.rs b/storage/aptosdb/src/db/include/aptosdb_internal.rs index b44cb4a6c7de2..5337cdf99223c 100644 --- a/storage/aptosdb/src/db/include/aptosdb_internal.rs +++ b/storage/aptosdb/src/db/include/aptosdb_internal.rs @@ -56,7 +56,6 @@ impl AptosDB { ledger_commit_lock: std::sync::Mutex::new(()), indexer: None, skip_index_and_usage, - indexer_async_v2: None, } } @@ -69,7 +68,6 @@ impl AptosDB { buffered_state_target_items: usize, max_num_nodes_per_lru_cache_shard: usize, empty_buffered_state_for_restore: bool, - enable_indexer_async_v2: bool, ) -> Result { ensure!( pruner_config.eq(&NO_OP_STORAGE_PRUNER_CONFIG) || !readonly, @@ -101,13 +99,6 @@ impl AptosDB { )?; } - if enable_indexer_async_v2 { - myself.open_indexer_async_v2( - db_paths.default_root_path(), - rocksdb_configs.index_db_config, - )?; - } - Ok(myself) } @@ -153,16 +144,6 @@ impl AptosDB { Ok(()) } - fn open_indexer_async_v2( - &mut self, - db_root_path: impl AsRef, - rocksdb_config: RocksdbConfig, - ) -> Result<()> { - let indexer_async_v2 = IndexerAsyncV2::open(db_root_path, rocksdb_config, DashMap::new())?; - self.indexer_async_v2 = Some(indexer_async_v2); - Ok(()) - } - #[cfg(any(test, feature = "fuzzing"))] fn new_without_pruner + Clone>( db_root_path: P, @@ -170,7 +151,6 @@ impl AptosDB { buffered_state_target_items: usize, max_num_nodes_per_lru_cache_shard: usize, enable_indexer: bool, - enable_indexer_async_v2: bool, ) -> Self { Self::open( StorageDirPaths::from_path(db_root_path), @@ -180,7 +160,6 @@ impl AptosDB { enable_indexer, buffered_state_target_items, max_num_nodes_per_lru_cache_shard, - enable_indexer_async_v2, ) .expect("Unable to open AptosDB") } diff --git a/storage/aptosdb/src/db/include/aptosdb_reader.rs b/storage/aptosdb/src/db/include/aptosdb_reader.rs index 78b4174604f08..95ce8b0a4f113 100644 --- a/storage/aptosdb/src/db/include/aptosdb_reader.rs +++ b/storage/aptosdb/src/db/include/aptosdb_reader.rs @@ -817,11 +817,6 @@ impl DbReader for AptosDB { self.indexer.is_some() } - /// Returns whether the indexer async v2 DB has been enabled or not - fn indexer_async_v2_enabled(&self) -> bool { - self.indexer_async_v2.is_some() - } - fn get_state_storage_usage(&self, version: Option) -> Result { gauged_api("get_state_storage_usage", || { if let Some(v) = version { @@ -830,28 +825,6 @@ impl DbReader for AptosDB { self.state_store.get_usage(version) }) } - - /// Returns the next version for indexer async v2 to be processed - /// It is mainly used by table info service to decide the start version - fn get_indexer_async_v2_next_version(&self) -> Result { - gauged_api("get_indexer_async_v2_next_version", || { - Ok(self - .indexer_async_v2 - .as_ref() - .map(|indexer| indexer.next_version()) - .unwrap_or(0)) - }) - } - - fn is_indexer_async_v2_pending_on_empty(&self) -> Result { - gauged_api("is_indexer_async_v2_pending_on_empty", || { - Ok(self - .indexer_async_v2 - .as_ref() - .map(|indexer| indexer.is_indexer_async_v2_pending_on_empty()) - .unwrap_or(false)) - }) - } } impl AptosDB { @@ -1026,26 +999,8 @@ impl AptosDB { Ok(events_with_version) } - fn get_table_info_option(&self, handle: TableHandle) -> Result> { - if self.indexer_async_v2_enabled() { - return self.get_table_info_from_indexer_async_v2(handle); - } - - self.get_table_info_from_indexer(handle) - } - - fn get_table_info_from_indexer_async_v2( - &self, - handle: TableHandle, - ) -> Result> { - match &self.indexer_async_v2 { - Some(indexer_async_v2) => indexer_async_v2.get_table_info_with_retry(handle), - None => bail!("Indexer Async V2 not enabled."), - } - } - /// TODO(jill): deprecate Indexer once Indexer Async V2 is ready - fn get_table_info_from_indexer(&self, handle: TableHandle) -> Result> { + fn get_table_info_option(&self, handle: TableHandle) -> Result> { match &self.indexer { Some(indexer) => indexer.get_table_info(handle), None => bail!("Indexer not enabled."), diff --git a/storage/aptosdb/src/db/include/aptosdb_testonly.rs b/storage/aptosdb/src/db/include/aptosdb_testonly.rs index 4d0c402132b03..3dea085136ca7 100644 --- a/storage/aptosdb/src/db/include/aptosdb_testonly.rs +++ b/storage/aptosdb/src/db/include/aptosdb_testonly.rs @@ -17,7 +17,6 @@ impl AptosDB { BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, false, /* indexer */ - false, /* indexer async v2 */ ) } @@ -38,14 +37,13 @@ impl AptosDB { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, max_node_cache, - false, /* indexer async v2 */ ) .expect("Unable to open AptosDB") } /// This opens db in non-readonly mode, without the pruner and cache. pub fn new_for_test_no_cache + Clone>(db_root_path: P) -> Self { - Self::new_without_pruner(db_root_path, false, BUFFERED_STATE_TARGET_ITEMS, 0, false, false) + Self::new_without_pruner(db_root_path, false, BUFFERED_STATE_TARGET_ITEMS, 0, false) } /// This opens db in non-readonly mode, without the pruner, and with the indexer @@ -56,7 +54,6 @@ impl AptosDB { BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, true, /* indexer */ - true, /* indexer async v2 */ ) } @@ -71,7 +68,6 @@ impl AptosDB { buffered_state_target_items, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, false, /* indexer */ - false, /* indexer async v2 */ ) } @@ -83,7 +79,6 @@ impl AptosDB { BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, false, /* indexer */ - false, /* indexer async v2 */ ) } diff --git a/storage/aptosdb/src/db/include/aptosdb_writer.rs b/storage/aptosdb/src/db/include/aptosdb_writer.rs index 6c6f8ec42af57..3f2e273d4fda1 100644 --- a/storage/aptosdb/src/db/include/aptosdb_writer.rs +++ b/storage/aptosdb/src/db/include/aptosdb_writer.rs @@ -198,47 +198,6 @@ impl DbWriter for AptosDB { Ok(()) }) } - - /// Open up dbwriter for table info indexing on indexer async v2 rocksdb - fn index_table_info( - &self, - db_reader: Arc, - first_version: Version, - write_sets: &[&WriteSet], - end_early_if_pending_on_empty: bool, - ) -> Result<()> { - gauged_api("index_table_info", || { - self.indexer_async_v2 - .as_ref() - .map(|indexer| { - indexer.index_table_info( - db_reader, - first_version, - write_sets, - end_early_if_pending_on_empty, - ) - }) - .unwrap_or(Ok(())) - }) - } - - fn cleanup_pending_on_items(&self) -> Result<()> { - gauged_api("cleanup_pending_on_items", || { - self.indexer_async_v2 - .as_ref() - .map(|indexer| indexer.cleanup_pending_on_items()) - .unwrap_or(Ok(())) - }) - } - - fn update_next_version(&self, end_version: u64) -> Result<()> { - gauged_api("update_next_version", || { - self.indexer_async_v2 - .as_ref() - .map(|indexer| indexer.update_next_version(end_version)) - .unwrap_or(Ok(())) - }) - } } impl AptosDB { diff --git a/storage/aptosdb/src/db/mod.rs b/storage/aptosdb/src/db/mod.rs index e209899cf27ec..3008f9025b88d 100644 --- a/storage/aptosdb/src/db/mod.rs +++ b/storage/aptosdb/src/db/mod.rs @@ -30,7 +30,7 @@ use aptos_config::config::{ PrunerConfig, RocksdbConfig, RocksdbConfigs, StorageDirPaths, NO_OP_STORAGE_PRUNER_CONFIG, }; use aptos_crypto::HashValue; -use aptos_db_indexer::{db_v2::IndexerAsyncV2, Indexer}; +use aptos_db_indexer::Indexer; use aptos_experimental_runtimes::thread_manager::{optimal_min_len, THREAD_MANAGER}; use aptos_logger::prelude::*; use aptos_metrics_core::TimerHelper; @@ -72,7 +72,6 @@ use aptos_types::{ write_set::WriteSet, }; use aptos_vm::data_cache::AsMoveResolver; -use dashmap::DashMap; use move_resource_viewer::MoveValueAnnotator; use rayon::prelude::*; use std::{ @@ -101,7 +100,6 @@ pub struct AptosDB { ledger_commit_lock: std::sync::Mutex<()>, indexer: Option, skip_index_and_usage: bool, - indexer_async_v2: Option, } // DbReader implementations and private functions used by them. @@ -123,7 +121,6 @@ impl AptosDB { enable_indexer: bool, buffered_state_target_items: usize, max_num_nodes_per_lru_cache_shard: usize, - enable_indexer_async_v2: bool, ) -> Result { Self::open_internal( &db_paths, @@ -134,7 +131,6 @@ impl AptosDB { buffered_state_target_items, max_num_nodes_per_lru_cache_shard, false, - enable_indexer_async_v2, ) } @@ -146,7 +142,6 @@ impl AptosDB { enable_indexer: bool, buffered_state_target_items: usize, max_num_nodes_per_lru_cache_shard: usize, - enable_indexer_async_v2: bool, ) -> Result { Self::open_internal( &db_paths, @@ -157,7 +152,6 @@ impl AptosDB { buffered_state_target_items, max_num_nodes_per_lru_cache_shard, true, - enable_indexer_async_v2, ) } diff --git a/storage/aptosdb/src/fast_sync_storage_wrapper.rs b/storage/aptosdb/src/fast_sync_storage_wrapper.rs index d191810c6b24d..d29bf307ef25e 100644 --- a/storage/aptosdb/src/fast_sync_storage_wrapper.rs +++ b/storage/aptosdb/src/fast_sync_storage_wrapper.rs @@ -49,7 +49,6 @@ impl FastSyncStorageWrapper { config.storage.enable_indexer, config.storage.buffered_state_target_items, config.storage.max_num_nodes_per_lru_cache_shard, - config.indexer_table_info.enabled, ) .map_err(|err| anyhow!("fast sync DB failed to open {}", err))?; @@ -76,7 +75,6 @@ impl FastSyncStorageWrapper { config.storage.enable_indexer, config.storage.buffered_state_target_items, config.storage.max_num_nodes_per_lru_cache_shard, - config.indexer_table_info.enabled, ) .map_err(|err| anyhow!("Secondary DB failed to open {}", err))?; diff --git a/storage/backup/backup-cli/src/utils/mod.rs b/storage/backup/backup-cli/src/utils/mod.rs index a3b9bf33ae150..f737d3d868b36 100644 --- a/storage/backup/backup-cli/src/utils/mod.rs +++ b/storage/backup/backup-cli/src/utils/mod.rs @@ -291,7 +291,6 @@ impl TryFrom for GlobalRestoreOptions { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ )?) .get_restore_handler(); diff --git a/storage/db-tool/src/bootstrap.rs b/storage/db-tool/src/bootstrap.rs index 74ce3cb605b3d..46aed10777957 100644 --- a/storage/db-tool/src/bootstrap.rs +++ b/storage/db-tool/src/bootstrap.rs @@ -57,7 +57,6 @@ impl Command { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ ) .expect("Failed to open DB."); let db = DbReaderWriter::new(db); diff --git a/storage/db-tool/src/replay_verify.rs b/storage/db-tool/src/replay_verify.rs index deafc78a6445e..21c1bd817e400 100644 --- a/storage/db-tool/src/replay_verify.rs +++ b/storage/db-tool/src/replay_verify.rs @@ -69,7 +69,6 @@ impl Opt { false, /* indexer */ BUFFERED_STATE_TARGET_ITEMS, DEFAULT_MAX_NUM_NODES_PER_LRU_CACHE_SHARD, - false, /* indexer async v2 */ )?) .get_restore_handler(); let ret = ReplayVerifyCoordinator::new( diff --git a/storage/indexer/src/db_ops.rs b/storage/indexer/src/db_ops.rs new file mode 100644 index 0000000000000..2f109bed876f0 --- /dev/null +++ b/storage/indexer/src/db_ops.rs @@ -0,0 +1,22 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::schema::column_families; +use anyhow::Result; +use aptos_config::config::RocksdbConfig; +use aptos_rocksdb_options::gen_rocksdb_options; +use aptos_schemadb::DB; +use std::{mem, path::Path}; + +pub fn open_db>(db_path: P, rocksdb_config: &RocksdbConfig) -> Result { + Ok(DB::open( + db_path, + "index_asnync_v2_db", + column_families(), + &gen_rocksdb_options(rocksdb_config, false), + )?) +} + +pub fn close_db(db: DB) { + mem::drop(db) +} diff --git a/storage/indexer/src/db_v2.rs b/storage/indexer/src/db_v2.rs index 7c60a758ff671..a21fcb7b435fe 100644 --- a/storage/indexer/src/db_v2.rs +++ b/storage/indexer/src/db_v2.rs @@ -7,13 +7,9 @@ /// and this file will be moved to /ecosystem/indexer-grpc/indexer-grpc-table-info. use crate::{ metadata::{MetadataKey, MetadataValue}, - schema::{ - column_families, indexer_metadata::IndexerMetadataSchema, table_info::TableInfoSchema, - }, + schema::{indexer_metadata::IndexerMetadataSchema, table_info::TableInfoSchema}, }; -use aptos_config::config::RocksdbConfig; use aptos_logger::info; -use aptos_rocksdb_options::gen_rocksdb_options; use aptos_schemadb::{SchemaBatch, DB}; use aptos_storage_interface::{ db_other_bail as bail, state_view::DbStateView, AptosDbError, DbReader, Result, @@ -39,6 +35,8 @@ use move_core_types::{ use move_resource_viewer::{AnnotatedMoveValue, MoveValueAnnotator}; use std::{ collections::{BTreeMap, HashMap}, + fs, + path::PathBuf, sync::{ atomic::{AtomicU64, Ordering}, Arc, @@ -46,12 +44,11 @@ use std::{ time::Duration, }; -pub const INDEX_ASYNC_V2_DB_NAME: &str = "index_indexer_async_v2_db"; const TABLE_INFO_RETRY_TIME_MILLIS: u64 = 10; #[derive(Debug)] pub struct IndexerAsyncV2 { - db: DB, + pub db: DB, // Next version to be processed next_version: AtomicU64, // It is used in the context of processing write ops and extracting table information. @@ -65,21 +62,7 @@ pub struct IndexerAsyncV2 { } impl IndexerAsyncV2 { - /// Opens up this rocksdb to get ready for read and write when bootstraping the aptosdb - pub fn open( - db_root_path: impl AsRef, - rocksdb_config: RocksdbConfig, - pending_on: DashMap>, - ) -> Result { - let db_path = db_root_path.as_ref().join(INDEX_ASYNC_V2_DB_NAME); - - let db = DB::open( - db_path, - "index_asnync_v2_db", - column_families(), - &gen_rocksdb_options(&rocksdb_config, false), - )?; - + pub fn new(db: DB) -> Result { let next_version = db .get::(&MetadataKey::LatestVersion)? .map_or(0, |v| v.expect_version()); @@ -87,7 +70,7 @@ impl IndexerAsyncV2 { Ok(Self { db, next_version: AtomicU64::new(next_version), - pending_on, + pending_on: DashMap::new(), }) } @@ -151,12 +134,10 @@ impl IndexerAsyncV2 { } pub fn update_next_version(&self, end_version: u64) -> Result<()> { - let batch = SchemaBatch::new(); - batch.put::( + self.db.put::( &MetadataKey::LatestVersion, &MetadataValue::Version(end_version - 1), )?; - self.db.write_schemas(batch)?; self.next_version.store(end_version, Ordering::Relaxed); Ok(()) } @@ -201,7 +182,10 @@ impl IndexerAsyncV2 { } pub fn next_version(&self) -> Version { - self.next_version.load(Ordering::Relaxed) + self.db + .get::(&MetadataKey::LatestVersion) + .unwrap() + .map_or(0, |v| v.expect_version()) } pub fn get_table_info(&self, handle: TableHandle) -> Result> { @@ -227,6 +211,11 @@ impl IndexerAsyncV2 { pub fn is_indexer_async_v2_pending_on_empty(&self) -> bool { self.pending_on.is_empty() } + + pub fn create_checkpoint(&self, path: &PathBuf) -> Result<()> { + fs::remove_dir_all(path).unwrap_or(()); + self.db.create_checkpoint(path) + } } struct TableInfoParser<'a, R> { diff --git a/storage/indexer/src/lib.rs b/storage/indexer/src/lib.rs index 5eebb36331880..b152baa1bb13d 100644 --- a/storage/indexer/src/lib.rs +++ b/storage/indexer/src/lib.rs @@ -3,9 +3,11 @@ /// TODO(jill): deprecate Indexer once Indexer Async V2 is ready mod db; +pub mod db_ops; pub mod db_v2; mod metadata; mod schema; +pub mod table_info_reader; use crate::{ db::INDEX_DB_NAME, diff --git a/storage/indexer/src/table_info_reader.rs b/storage/indexer/src/table_info_reader.rs new file mode 100644 index 0000000000000..f0ddcff4aa1ff --- /dev/null +++ b/storage/indexer/src/table_info_reader.rs @@ -0,0 +1,19 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::db_v2::IndexerAsyncV2; +use aptos_storage_interface::Result; +use aptos_types::state_store::table::{TableHandle, TableInfo}; + +/// Table info reader is to create a thin interface for other services to read the db data, +/// this standalone db is officially not part of the AptosDB anymore. +/// For services that need table info mapping, they need to acquire this reader in the FN bootstrapping stage. +pub trait TableInfoReader: Send + Sync { + fn get_table_info(&self, handle: TableHandle) -> Result>; +} + +impl TableInfoReader for IndexerAsyncV2 { + fn get_table_info(&self, handle: TableHandle) -> Result> { + self.get_table_info_with_retry(handle) + } +} diff --git a/storage/storage-interface/src/lib.rs b/storage/storage-interface/src/lib.rs index c6f4f567f2085..cebc7e7c276be 100644 --- a/storage/storage-interface/src/lib.rs +++ b/storage/storage-interface/src/lib.rs @@ -450,16 +450,6 @@ pub trait DbReader: Send + Sync { /// Returns whether the internal indexer DB has been enabled or not fn indexer_enabled(&self) -> bool; - /// Returns whether the internal indexer async v2 DB has been enabled or not - fn indexer_async_v2_enabled(&self) -> bool; - - /// Returns the next version which internal indexer async v2 DB should parse - fn get_indexer_async_v2_next_version(&self) -> Result; - - /// Returns boolean whether indexer async v2 pending on items are empty - /// if so, the whole batches are processed completely, if not, need to retry - fn is_indexer_async_v2_pending_on_empty(&self) -> Result; - /// Returns state storage usage at the end of an epoch. fn get_state_storage_usage(&self, version: Option) -> Result; ); // end delegated @@ -577,28 +567,6 @@ pub trait DbWriter: Send + Sync { ) -> Result<()> { unimplemented!() } - - /// Index table info mapping for the indexer async v2 rocksdb. - /// Called by the table info service when its constantly parsing the table info. - fn index_table_info( - &self, - db_reader: Arc, - first_version: Version, - write_sets: &[&WriteSet], - end_early_if_pending_on_empty: bool, - ) -> Result<()> { - unimplemented!() - } - - /// Clean up pending on items in the indexer async v2 rocksdb. - /// Called by the table info service when all threads finish processing. - fn cleanup_pending_on_items(&self) -> Result<()> { - unimplemented!() - } - - fn update_next_version(&self, end_version: u64) -> Result<()> { - unimplemented!() - } } #[derive(Clone)] From d6e00f1b323df445d749d89ef4ee682224b0c512 Mon Sep 17 00:00:00 2001 From: "Brian (Sunghoon) Cho" Date: Mon, 12 Feb 2024 14:10:19 -0800 Subject: [PATCH 059/328] [Quorom Store] enable BatchResponseV2 (#11546) ### Description Enable BatchResponseV2 which was introduced in #11162, but not enabled then for backwards compatibility. Do not add to 1.9 branch before deployment. --- consensus/src/network.rs | 2 +- .../src/quorum_store/quorum_store_builder.rs | 26 ++++++------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/consensus/src/network.rs b/consensus/src/network.rs index 7ef5d4ac1b910..ba998913dd460 100644 --- a/consensus/src/network.rs +++ b/consensus/src/network.rs @@ -457,7 +457,7 @@ impl QuorumStoreSender for NetworkSender { .send_rpc(recipient, msg, timeout) .await?; match response { - // TODO: deprecated, remove after two releases + // TODO: deprecated, remove after another release (likely v1.11) ConsensusMsg::BatchResponse(batch) => { batch.verify_with_digest(request_digest)?; Ok(BatchResponse::Batch(*batch)) diff --git a/consensus/src/quorum_store/quorum_store_builder.rs b/consensus/src/quorum_store/quorum_store_builder.rs index b0f0d2b002d53..572f120f53d88 100644 --- a/consensus/src/quorum_store/quorum_store_builder.rs +++ b/consensus/src/quorum_store/quorum_store_builder.rs @@ -377,8 +377,6 @@ impl InnerBuilder { Some(&counters::BATCH_RETRIEVAL_TASK_MSGS), ); let aptos_db_clone = self.aptos_db.clone(); - // TODO: Once v2 handler is released, remove this flag and always use v2 - let use_v2 = false; spawn_named!("batch_serve", async move { info!(epoch = epoch, "Batch retrieval task starts"); while let Some(rpc_request) = batch_retrieval_rx.next().await { @@ -398,23 +396,15 @@ impl InnerBuilder { }, } }; - let msg = if use_v2 { - Some(ConsensusMsg::BatchResponseV2(Box::new(response))) - } else if let BatchResponse::Batch(batch) = response { - Some(ConsensusMsg::BatchResponse(Box::new(batch))) - } else { - None - }; - if let Some(msg) = msg { - let bytes = rpc_request.protocol.to_bytes(&msg).unwrap(); - if let Err(e) = rpc_request - .response_sender - .send(Ok(bytes.into())) - .map_err(|_| anyhow::anyhow!("Failed to send block retrieval response")) - { - warn!(epoch = epoch, error = ?e, kind = error_kind(&e)); - } + let msg = ConsensusMsg::BatchResponseV2(Box::new(response)); + let bytes = rpc_request.protocol.to_bytes(&msg).unwrap(); + if let Err(e) = rpc_request + .response_sender + .send(Ok(bytes.into())) + .map_err(|_| anyhow::anyhow!("Failed to send block retrieval response")) + { + warn!(epoch = epoch, error = ?e, kind = error_kind(&e)); } } info!(epoch = epoch, "Batch retrieval task stops"); From d96938f63fec54bf4ad4daef304d7f7a9c3f33b6 Mon Sep 17 00:00:00 2001 From: Perry Randall Date: Mon, 12 Feb 2024 15:15:12 -0800 Subject: [PATCH 060/328] [gha] Add additional optional cache key Add an optional cache key for rust cache In some cases (like where we build the binary on a different base os in the same job) this automatic job based cache key is not specific enough so we need to further differentiate it. Test Plan: PR checks dont die --- .github/actions/rust-setup/action.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/actions/rust-setup/action.yaml b/.github/actions/rust-setup/action.yaml index 0cfd56b94999e..773dbbd27cd24 100644 --- a/.github/actions/rust-setup/action.yaml +++ b/.github/actions/rust-setup/action.yaml @@ -2,6 +2,10 @@ inputs: GIT_CREDENTIALS: description: "Optional credentials to pass to git" required: false + ADDITIONAL_KEY: + description: "An optional additional key to pass to rust-cache" + required: false + default: "" runs: using: composite @@ -15,6 +19,8 @@ runs: # https://github.com/Swatinem/rust-cache#cache-details - name: Run cargo cache uses: Swatinem/rust-cache@359a70e43a0bb8a13953b04a90f76428b4959bb6 # pin@v2.2.0 + with: + key: ${{ inputs.ADDITIONAL_KEY }} - name: install protoc and related tools shell: bash From b4fbf4cb55fd85bcd617ce33158db4fe40e7db35 Mon Sep 17 00:00:00 2001 From: Oliver He Date: Tue, 13 Feb 2024 07:55:01 +0800 Subject: [PATCH 061/328] Make training wheels signature optional in `SignedGroth16Zkp` (#11986) Co-authored-by: Alin Tomescu --- aptos-move/vm-genesis/src/lib.rs | 28 +++++++-- crates/aptos-crypto/Cargo.toml | 8 ++- crates/aptos-crypto/benches/zk.rs | 58 +++++++++++++++++++ crates/aptos-crypto/src/poseidon_bn254.rs | 8 ++- .../generate-format/tests/staged/api.yaml | 7 ++- .../generate-format/tests/staged/aptos.yaml | 7 ++- .../tests/staged/consensus.yaml | 7 ++- testsuite/smoke-test/src/zkid.rs | 13 +++-- types/src/transaction/authenticator.rs | 8 +-- types/src/zkid.rs | 24 ++++---- 10 files changed, 129 insertions(+), 39 deletions(-) create mode 100644 crates/aptos-crypto/benches/zk.rs diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index c68ada1f48899..bb57d71a1d36d 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -56,6 +56,7 @@ const GOVERNANCE_MODULE_NAME: &str = "aptos_governance"; const CODE_MODULE_NAME: &str = "code"; const VERSION_MODULE_NAME: &str = "version"; const ZKID_MODULE_NAME: &str = "zkid"; +const JWKS_MODULE_NAME: &str = "jwks"; const NUM_SECONDS_PER_YEAR: u64 = 365 * 24 * 60 * 60; const MICRO_SECONDS_PER_SECOND: u64 = 1_000_000; @@ -254,7 +255,7 @@ pub fn encode_genesis_change_set( if genesis_config.is_test { allow_core_resources_to_set_version(&mut session); } - initialize_zkid(&mut session); + initialize_zkid(&mut session, chain_id); set_genesis_end(&mut session); // Reconfiguration should happen after all on-chain invocations. @@ -531,7 +532,7 @@ fn initialize_on_chain_governance(session: &mut SessionExt, genesis_config: &Gen ); } -fn initialize_zkid(session: &mut SessionExt) { +fn initialize_zkid(session: &mut SessionExt, chain_id: ChainId) { let config = zkid::Configuration::new_for_devnet_and_testing(); exec_function( session, @@ -543,15 +544,30 @@ fn initialize_zkid(session: &mut SessionExt) { config.as_move_value(), ]), ); - let vk = Groth16VerificationKey::from(bn254_circom::DEVNET_VERIFYING_KEY.clone()); + if !chain_id.is_mainnet() { + let vk = Groth16VerificationKey::from(bn254_circom::DEVNET_VERIFYING_KEY.clone()); + exec_function( + session, + ZKID_MODULE_NAME, + "update_groth16_verification_key", + vec![], + serialize_values(&vec![ + MoveValue::Signer(CORE_CODE_ADDRESS), + vk.as_move_value(), + ]), + ); + } exec_function( session, - ZKID_MODULE_NAME, - "update_groth16_verification_key", + JWKS_MODULE_NAME, + "upsert_oidc_provider", vec![], serialize_values(&vec![ MoveValue::Signer(CORE_CODE_ADDRESS), - vk.as_move_value(), + "https://accounts.google.com".to_string().as_move_value(), + "https://accounts.google.com/.well-known/openid-configuration" + .to_string() + .as_move_value(), ]), ); } diff --git a/crates/aptos-crypto/Cargo.toml b/crates/aptos-crypto/Cargo.toml index bdd0e83a899c5..783984768a4d1 100644 --- a/crates/aptos-crypto/Cargo.toml +++ b/crates/aptos-crypto/Cargo.toml @@ -81,12 +81,16 @@ testing = [] name = "ark_bls12_381" harness = false +[[bench]] +name = "ark_bn254" +harness = false + [[bench]] name = "bls12381" harness = false [[bench]] -name = "ark_bn254" +name = "bulletproofs" harness = false [[bench]] @@ -110,5 +114,5 @@ name = "secp256k1" harness = false [[bench]] -name = "bulletproofs" +name = "zk" harness = false diff --git a/crates/aptos-crypto/benches/zk.rs b/crates/aptos-crypto/benches/zk.rs new file mode 100644 index 0000000000000..e6a12b0694410 --- /dev/null +++ b/crates/aptos-crypto/benches/zk.rs @@ -0,0 +1,58 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +#[macro_use] +extern crate criterion; + +use aptos_crypto::test_utils::random_bytes; +use ark_ff::PrimeField; +use criterion::{measurement::Measurement, BenchmarkGroup, BenchmarkId, Criterion, Throughput}; +use poseidon_ark::Poseidon; +use rand::thread_rng; + +/// Runs all the benchmarks. +fn bench_group(c: &mut Criterion) { + let mut group = c.benchmark_group("zk"); + + //let plot_config = PlotConfiguration::default().summary_scale(AxisScale::Logarithmic); + //group.plot_config(plot_config); + group.sample_size(50); + + for n in 1..=16 { + poseidon_bn254_ark(&mut group, n); + } + + group.finish(); +} + +fn poseidon_bn254_ark(g: &mut BenchmarkGroup, n: usize) { + let mut rng = thread_rng(); + + g.throughput(Throughput::Elements(n as u64)); + + let hash = Poseidon::new(); + + g.bench_function(BenchmarkId::new("poseidon-bn254-ark", n), move |b| { + b.iter_with_setup( + || { + (0..n) + .map(|_| { + let bytes = random_bytes(&mut rng, n); + ark_bn254::Fr::from_le_bytes_mod_order(bytes.as_slice()) + }) + .collect::>() + }, + |scalars| { + assert_eq!(scalars.len(), n); + + hash.hash(scalars).unwrap() + }, + ) + }); +} + +criterion_group!( + name = zk_benches; + config = Criterion::default(); //.measurement_time(Duration::from_secs(100)); + targets = bench_group); +criterion_main!(zk_benches); diff --git a/crates/aptos-crypto/src/poseidon_bn254.rs b/crates/aptos-crypto/src/poseidon_bn254.rs index 219122719c80e..33d0a2fb585ec 100644 --- a/crates/aptos-crypto/src/poseidon_bn254.rs +++ b/crates/aptos-crypto/src/poseidon_bn254.rs @@ -4,6 +4,7 @@ //! produces a single field element as output. use anyhow::bail; use ark_ff::PrimeField; +use once_cell::sync::Lazy; // TODO(zkid): Figure out the right library for Poseidon. use poseidon_ark::Poseidon; @@ -26,6 +27,9 @@ pub const BYTES_PACKED_PER_SCALAR: usize = 31; /// SNARK circuits would have to implement this more complicated packing). pub const MAX_NUM_INPUT_BYTES: usize = MAX_NUM_INPUT_SCALARS * BYTES_PACKED_PER_SCALAR; +/// Apparently, creating this object is rather slow, so we make it a global. +static HASHER: Lazy = Lazy::new(Poseidon::new); + /// Given an array of up to `MAX_NUM_INPUT_SCALARS` field elements (in the BN254 scalar field), hashes /// them using Poseidon-BN254 into a single field element. pub fn hash_scalars(inputs: Vec) -> anyhow::Result { @@ -36,9 +40,7 @@ pub fn hash_scalars(inputs: Vec) -> anyhow::Result ); } - let hash = Poseidon::new(); - - hash.hash(inputs).map_err(anyhow::Error::msg) + HASHER.hash(inputs).map_err(anyhow::Error::msg) } /// Given an string and `max_bytes`, it pads the byte array of the string with zeros up to size `max_bytes`, diff --git a/testsuite/generate-format/tests/staged/api.yaml b/testsuite/generate-format/tests/staged/api.yaml index f5bad867e9119..82f357fbe24a2 100644 --- a/testsuite/generate-format/tests/staged/api.yaml +++ b/testsuite/generate-format/tests/staged/api.yaml @@ -454,12 +454,13 @@ SignedGroth16Zkp: TYPENAME: Groth16Zkp - non_malleability_signature: TYPENAME: EphemeralSignature - - training_wheels_signature: - TYPENAME: EphemeralSignature + - exp_horizon_secs: U64 - extra_field: STR - override_aud_val: OPTION: STR - - exp_horizon_secs: U64 + - training_wheels_signature: + OPTION: + TYPENAME: EphemeralSignature SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/generate-format/tests/staged/aptos.yaml b/testsuite/generate-format/tests/staged/aptos.yaml index 0cadcf1f1be95..3b4d586ee507e 100644 --- a/testsuite/generate-format/tests/staged/aptos.yaml +++ b/testsuite/generate-format/tests/staged/aptos.yaml @@ -386,12 +386,13 @@ SignedGroth16Zkp: TYPENAME: Groth16Zkp - non_malleability_signature: TYPENAME: EphemeralSignature - - training_wheels_signature: - TYPENAME: EphemeralSignature + - exp_horizon_secs: U64 - extra_field: STR - override_aud_val: OPTION: STR - - exp_horizon_secs: U64 + - training_wheels_signature: + OPTION: + TYPENAME: EphemeralSignature SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/generate-format/tests/staged/consensus.yaml b/testsuite/generate-format/tests/staged/consensus.yaml index 1093b74174061..28978965358e3 100644 --- a/testsuite/generate-format/tests/staged/consensus.yaml +++ b/testsuite/generate-format/tests/staged/consensus.yaml @@ -745,12 +745,13 @@ SignedGroth16Zkp: TYPENAME: Groth16Zkp - non_malleability_signature: TYPENAME: EphemeralSignature - - training_wheels_signature: - TYPENAME: EphemeralSignature + - exp_horizon_secs: U64 - extra_field: STR - override_aud_val: OPTION: STR - - exp_horizon_secs: U64 + - training_wheels_signature: + OPTION: + TYPENAME: EphemeralSignature SignedTransaction: STRUCT: - raw_txn: diff --git a/testsuite/smoke-test/src/zkid.rs b/testsuite/smoke-test/src/zkid.rs index fd06332451309..c5eeffdb2925a 100644 --- a/testsuite/smoke-test/src/zkid.rs +++ b/testsuite/smoke-test/src/zkid.rs @@ -383,11 +383,12 @@ async fn test_zkid_groth16_verifies() { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephem_proof_sig, - training_wheels_signature: EphemeralSignature::ed25519(tw_sk.sign(&proof).unwrap()), - //training_wheels_signature: EphemeralSignature::ed25519(bad_sk.sign(&proof).unwrap()), extra_field: "\"family_name\":\"Straka\",".to_string(), - override_aud_val: None, exp_horizon_secs: config.max_exp_horizon_secs, + override_aud_val: None, + training_wheels_signature: Some(EphemeralSignature::ed25519( + tw_sk.sign(&proof).unwrap(), + )), }), jwt_header, exp_timestamp_secs: 1900255944, @@ -496,10 +497,12 @@ async fn test_zkid_groth16_signature_transaction_submission_proof_signature_chec sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephemeral_signature.clone(), // Wrong signature - training_wheels_signature: EphemeralSignature::ed25519(tw_sk.sign(&proof).unwrap()), extra_field: "\"family_name\":\"Straka\",".to_string(), - override_aud_val: None, exp_horizon_secs: config.max_exp_horizon_secs, + override_aud_val: None, + training_wheels_signature: Some(EphemeralSignature::ed25519( + tw_sk.sign(&proof).unwrap(), + )), }), jwt_header, exp_timestamp_secs: 1900255944, diff --git a/types/src/transaction/authenticator.rs b/types/src/transaction/authenticator.rs index 05483e7c0c10f..c7d03a88d716d 100644 --- a/types/src/transaction/authenticator.rs +++ b/types/src/transaction/authenticator.rs @@ -1802,12 +1802,12 @@ mod tests { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephem_proof_sig, - training_wheels_signature: EphemeralSignature::ed25519( - Ed25519Signature::dummy_signature(), - ), extra_field: "\"family_name\":\"Straka\",".to_string(), - override_aud_val: None, exp_horizon_secs: config.max_exp_horizon_secs, + override_aud_val: None, + training_wheels_signature: Some(EphemeralSignature::ed25519( + Ed25519Signature::dummy_signature(), + )), }), jwt_header: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_owned(), exp_timestamp_secs: 1900255944, diff --git a/types/src/zkid.rs b/types/src/zkid.rs index 4a6e5e6906fca..863c5cd65c280 100644 --- a/types/src/zkid.rs +++ b/types/src/zkid.rs @@ -313,16 +313,16 @@ pub struct SignedGroth16Zkp { pub proof: Groth16Zkp, /// A signature on the proof (via the ephemeral SK) to prevent malleability attacks. pub non_malleability_signature: EphemeralSignature, - /// A signature on the proof (via the training wheels SK) to mitigate against flaws in our circuit - pub training_wheels_signature: EphemeralSignature, + /// The expiration horizon that the circuit should enforce on the expiration date committed in the nonce. + /// This must be <= `Configuration::max_expiration_horizon_secs`. + pub exp_horizon_secs: u64, /// An extra field (e.g., `"":"") that will be matched publicly in the JWT pub extra_field: String, /// Will be set to the override `aud` value that the circuit should match, instead of the `aud` in the IDC. /// This will allow users to recover their zkID accounts derived by an application that is no longer online. pub override_aud_val: Option, - /// The expiration horizon that the circuit should enforce on the expiration date committed in the nonce. - /// This must be <= `Configuration::max_expiration_horizon_secs`. - pub exp_horizon_secs: u64, + /// A signature on the proof (via the training wheels SK) to mitigate against flaws in our circuit + pub training_wheels_signature: Option, } impl SignedGroth16Zkp { @@ -331,7 +331,11 @@ impl SignedGroth16Zkp { } pub fn verify_training_wheels_sig(&self, pub_key: &EphemeralPublicKey) -> Result<()> { - self.training_wheels_signature.verify(&self.proof, pub_key) + if let Some(training_wheels_signature) = &self.training_wheels_signature { + training_wheels_signature.verify(&self.proof, pub_key) + } else { + bail!("No training_wheels_signature found") + } } pub fn verify_proof( @@ -695,12 +699,12 @@ mod test { sig: ZkpOrOpenIdSig::Groth16Zkp(SignedGroth16Zkp { proof: proof.clone(), non_malleability_signature: ephem_proof_sig, - training_wheels_signature: EphemeralSignature::ed25519( - Ed25519Signature::dummy_signature(), - ), extra_field: "\"family_name\":\"Straka\",".to_string(), - override_aud_val: None, exp_horizon_secs: config.max_exp_horizon_secs, + override_aud_val: None, + training_wheels_signature: Some(EphemeralSignature::ed25519( + Ed25519Signature::dummy_signature(), + )), }), jwt_header: "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_owned(), exp_timestamp_secs: 1900255944, From b97a764327d47244c49dd3c9172fdb4a708f422e Mon Sep 17 00:00:00 2001 From: Rati Gelashvili Date: Mon, 12 Feb 2024 20:56:16 -0500 Subject: [PATCH 062/328] [Executor] [Delayed fields] Utilities clean-up / refactor (#11817) * [Executor] utilities clean-up --------- Co-authored-by: Igor --- .../aptos-aggregator/src/delta_change_set.rs | 10 +- aptos-move/aptos-aggregator/src/resolver.rs | 41 +- .../aptos-aggregator/src/tests/types.rs | 15 +- .../aptos-vm-types/src/abstract_write_op.rs | 33 +- aptos-move/aptos-vm-types/src/change_set.rs | 65 ++- aptos-move/aptos-vm-types/src/resolver.rs | 4 +- .../src/tests/test_change_set.rs | 9 +- aptos-move/aptos-vm-types/src/tests/utils.rs | 11 +- aptos-move/aptos-vm/src/block_executor/mod.rs | 37 +- aptos-move/aptos-vm/src/data_cache.rs | 17 +- .../src/move_vm_ext/respawned_session.rs | 11 +- aptos-move/aptos-vm/src/natives.rs | 15 +- .../block-executor/src/captured_reads.rs | 21 +- aptos-move/block-executor/src/executor.rs | 452 ++++-------------- .../block-executor/src/executor_utilities.rs | 289 +++++++++++ aptos-move/block-executor/src/lib.rs | 2 + .../src/proptest_types/types.rs | 26 +- aptos-move/block-executor/src/task.rs | 20 +- .../src/txn_last_input_output.rs | 118 ++--- .../block-executor/src/unit_tests/mod.rs | 2 +- .../block-executor/src/value_exchange.rs | 216 +++++++++ aptos-move/block-executor/src/view.rs | 403 +++++----------- .../e2e-move-tests/src/aggregator_v2.rs | 15 +- .../src/natives/aggregator_natives/context.rs | 17 +- aptos-move/mvhashmap/src/types.rs | 9 +- aptos-move/mvhashmap/src/unit_tests/mod.rs | 26 +- .../src/unit_tests/proptest_types.rs | 21 +- aptos-move/mvhashmap/src/unsync_map.rs | 12 +- aptos-move/mvhashmap/src/versioned_data.rs | 19 +- .../mvhashmap/src/versioned_group_data.rs | 18 +- types/src/write_set.rs | 54 +-- 31 files changed, 1044 insertions(+), 964 deletions(-) create mode 100644 aptos-move/block-executor/src/executor_utilities.rs create mode 100644 aptos-move/block-executor/src/value_exchange.rs diff --git a/aptos-move/aptos-aggregator/src/delta_change_set.rs b/aptos-move/aptos-aggregator/src/delta_change_set.rs index 8fe9d5b213e05..1f015d104b2a3 100644 --- a/aptos-move/aptos-aggregator/src/delta_change_set.rs +++ b/aptos-move/aptos-aggregator/src/delta_change_set.rs @@ -220,7 +220,10 @@ mod test { }; use aptos_types::{ delayed_fields::PanicError, - state_store::{state_key::StateKey, state_value::StateValue}, + state_store::{ + state_key::StateKey, + state_value::{StateValue, StateValueMetadata}, + }, write_set::WriteOp, }; use claims::{assert_err, assert_none, assert_ok, assert_ok_eq, assert_some_eq}; @@ -509,7 +512,6 @@ mod test { type Identifier = (); type ResourceGroupTag = (); type ResourceKey = (); - type ResourceValue = (); fn is_delayed_field_optimization_capable(&self) -> bool { unimplemented!("Irrelevant for the test") @@ -548,7 +550,7 @@ mod test { _delayed_write_set_keys: &HashSet, _skip: &HashSet, ) -> Result< - BTreeMap)>, + BTreeMap)>, PanicError, > { unimplemented!("Irrelevant for the test") @@ -558,7 +560,7 @@ mod test { &self, _delayed_write_set_keys: &HashSet, _skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { unimplemented!("Irrelevant for the test") } } diff --git a/aptos-move/aptos-aggregator/src/resolver.rs b/aptos-move/aptos-aggregator/src/resolver.rs index 4b5145255f365..7eca4b5d1b952 100644 --- a/aptos-move/aptos-aggregator/src/resolver.rs +++ b/aptos-move/aptos-aggregator/src/resolver.rs @@ -130,7 +130,6 @@ pub trait TDelayedFieldView { type Identifier; type ResourceKey; type ResourceGroupTag; - type ResourceValue; fn is_delayed_field_optimization_capable(&self) -> bool; @@ -177,34 +176,34 @@ pub trait TDelayedFieldView { /// 1. The resource is read during the transaction execution. /// 2. The resource is not present in write set of the VM Change Set. /// 3. The resource has a delayed field in it that is part of delayed field change set. - /// We get these resources and include them in the write set of the transaction output. + /// We get the keys of these resources and metadata to include them in the write set + /// of the transaction output after value exchange. fn get_reads_needing_exchange( &self, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result)>, PanicError>; + ) -> Result< + BTreeMap)>, + PanicError, + >; /// Returns the list of resource groups that satisfy all the following conditions: /// 1. At least one of the resource in the group is read during the transaction execution. /// 2. The resource group is not present in the write set of the VM Change Set. /// 3. At least one of the resources in the group has a delayed field in it that is part. /// of delayed field change set. - /// We get these resource groups and include them in the write set of the transaction output. - /// For each such resource group, this function outputs (resource key, (metadata op, resource group size)) + /// We get the keys of these resource groups and metadata to include them in the write set + /// of the transaction output after value exchange. For each such resource group, this function + /// outputs:(resource key, (metadata, resource group size)) fn get_group_reads_needing_exchange( &self, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result, PanicError>; + ) -> Result, PanicError>; } pub trait DelayedFieldResolver: - TDelayedFieldView< - Identifier = DelayedFieldID, - ResourceKey = StateKey, - ResourceGroupTag = StructTag, - ResourceValue = WriteOp, -> + TDelayedFieldView { } @@ -213,7 +212,6 @@ impl DelayedFieldResolver for T where Identifier = DelayedFieldID, ResourceKey = StateKey, ResourceGroupTag = StructTag, - ResourceValue = WriteOp, > { } @@ -225,7 +223,6 @@ where type Identifier = DelayedFieldID; type ResourceGroupTag = StructTag; type ResourceKey = StateKey; - type ResourceValue = WriteOp; fn is_delayed_field_optimization_capable(&self) -> bool { // For resolvers that are not capable, it cannot be enabled @@ -264,18 +261,20 @@ where fn get_reads_needing_exchange( &self, - _delayed_write_set_keys: &HashSet, + _delayed_write_set_ids: &HashSet, _skip: &HashSet, - ) -> Result)>, PanicError> - { + ) -> Result< + BTreeMap)>, + PanicError, + > { unimplemented!("get_reads_needing_exchange not implemented") } fn get_group_reads_needing_exchange( &self, - _delayed_write_set_keys: &HashSet, + _delayed_write_set_ids: &HashSet, _skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { unimplemented!("get_group_reads_needing_exchange not implemented") } } diff --git a/aptos-move/aptos-aggregator/src/tests/types.rs b/aptos-move/aptos-aggregator/src/tests/types.rs index b4befda3c6d04..ed45d92e41fa8 100644 --- a/aptos-move/aptos-aggregator/src/tests/types.rs +++ b/aptos-move/aptos-aggregator/src/tests/types.rs @@ -13,8 +13,10 @@ use crate::{ }; use aptos_types::{ delayed_fields::PanicError, - state_store::{state_key::StateKey, state_value::StateValue}, - write_set::WriteOp, + state_store::{ + state_key::StateKey, + state_value::{StateValue, StateValueMetadata}, + }, }; use move_binary_format::errors::PartialVMResult; use move_core_types::{language_storage::StructTag, value::MoveTypeLayout}; @@ -83,7 +85,6 @@ impl TDelayedFieldView for FakeAggregatorView { type Identifier = DelayedFieldID; type ResourceGroupTag = StructTag; type ResourceKey = StateKey; - type ResourceValue = WriteOp; fn is_delayed_field_optimization_capable(&self) -> bool { true @@ -145,8 +146,10 @@ impl TDelayedFieldView for FakeAggregatorView { &self, _delayed_write_set_keys: &HashSet, _skip: &HashSet, - ) -> Result)>, PanicError> - { + ) -> Result< + BTreeMap)>, + PanicError, + > { unimplemented!(); } @@ -154,7 +157,7 @@ impl TDelayedFieldView for FakeAggregatorView { &self, _delayed_write_set_keys: &HashSet, _skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { unimplemented!(); } } diff --git a/aptos-move/aptos-vm-types/src/abstract_write_op.rs b/aptos-move/aptos-vm-types/src/abstract_write_op.rs index 35572138724b4..7be8bf9442155 100644 --- a/aptos-move/aptos-vm-types/src/abstract_write_op.rs +++ b/aptos-move/aptos-vm-types/src/abstract_write_op.rs @@ -41,7 +41,7 @@ impl AbstractResourceWriteOp { pub fn materialized_size(&self) -> WriteOpSize { use AbstractResourceWriteOp::*; match self { - Write(write) => write.into(), + Write(write) => write.write_op_size(), WriteWithDelayedFields(WriteWithDelayedFieldsOp { write_op, materialized_size, @@ -85,12 +85,12 @@ impl AbstractResourceWriteOp { | WriteResourceGroup(GroupWrite { metadata_op: write_op, .. - }) + }) => write_op.get_metadata_mut(), + InPlaceDelayedFieldChange(InPlaceDelayedFieldChangeOp { metadata, .. }) | ResourceGroupInPlaceDelayedFieldChange(ResourceGroupInPlaceDelayedFieldChangeOp { - metadata_op: write_op, + metadata, .. - }) => write_op.get_metadata_mut(), - InPlaceDelayedFieldChange(InPlaceDelayedFieldChangeOp { metadata, .. }) => metadata, + }) => metadata, } } @@ -98,15 +98,16 @@ impl AbstractResourceWriteOp { write_op: WriteOp, maybe_layout: Option>, ) -> Self { - if let Some(layout) = maybe_layout { - let materialized_size = WriteOpSize::from(&write_op).write_len(); - Self::WriteWithDelayedFields(WriteWithDelayedFieldsOp { - write_op, - layout, - materialized_size, - }) - } else { - Self::Write(write_op) + match maybe_layout { + Some(layout) => { + let materialized_size = write_op.write_op_size().write_len(); + Self::WriteWithDelayedFields(WriteWithDelayedFieldsOp { + write_op, + layout, + materialized_size, + }) + }, + None => Self::Write(write_op), } } } @@ -180,6 +181,8 @@ impl GroupWrite { } #[derive(PartialEq, Eq, Clone, Debug)] +/// Note that write_op can be a Deletion, as long as the Move type layout contains +/// a delayed field. This simplifies squashing session outputs, in particular. pub struct WriteWithDelayedFieldsOp { pub write_op: WriteOp, pub layout: Arc, @@ -204,6 +207,6 @@ pub struct InPlaceDelayedFieldChangeOp { /// If future implementation needs those - they can be added. #[derive(PartialEq, Eq, Clone, Debug)] pub struct ResourceGroupInPlaceDelayedFieldChangeOp { - pub metadata_op: WriteOp, pub materialized_size: u64, + pub metadata: StateValueMetadata, } diff --git a/aptos-move/aptos-vm-types/src/change_set.rs b/aptos-move/aptos-vm-types/src/change_set.rs index d2b0a5180c853..3a3d18823c782 100644 --- a/aptos-move/aptos-vm-types/src/change_set.rs +++ b/aptos-move/aptos-vm-types/src/change_set.rs @@ -147,8 +147,11 @@ impl VMChangeSet { aggregator_v1_write_set: BTreeMap, aggregator_v1_delta_set: BTreeMap, delayed_field_change_set: BTreeMap>, - reads_needing_delayed_field_exchange: BTreeMap)>, - group_reads_needing_delayed_field_exchange: BTreeMap, + reads_needing_delayed_field_exchange: BTreeMap< + StateKey, + (StateValueMetadata, u64, Arc), + >, + group_reads_needing_delayed_field_exchange: BTreeMap, events: Vec<(ContractEvent, Option)>, checker: &dyn CheckChangeSet, ) -> PartialVMResult { @@ -166,39 +169,27 @@ impl VMChangeSet { .into_iter() .map(|(k, w)| Ok((k, AbstractResourceWriteOp::WriteResourceGroup(w)))), ) - .chain( - reads_needing_delayed_field_exchange - .into_iter() - .map(|(k, (w, layout))| { - Ok(( - k, - AbstractResourceWriteOp::InPlaceDelayedFieldChange( - InPlaceDelayedFieldChangeOp { - layout, - materialized_size: WriteOpSize::from(&w) - .write_len() - .ok_or_else(|| { - PartialVMError::new( - StatusCode::DELAYED_MATERIALIZATION_CODE_INVARIANT_ERROR, - ) - .with_message( - "Read with exchange cannot be a delete." - .to_string(), - ) - })?, - metadata: w.into_metadata(), - }, - ), - )) - }), - ) + .chain(reads_needing_delayed_field_exchange.into_iter().map( + |(k, (metadata, size, layout))| { + Ok(( + k, + AbstractResourceWriteOp::InPlaceDelayedFieldChange( + InPlaceDelayedFieldChangeOp { + layout, + materialized_size: size, + metadata, + }, + ), + )) + }, + )) .chain(group_reads_needing_delayed_field_exchange.into_iter().map( - |(k, (metadata_op, materialized_size))| { + |(k, (metadata, materialized_size))| { Ok(( k, AbstractResourceWriteOp::ResourceGroupInPlaceDelayedFieldChange( ResourceGroupInPlaceDelayedFieldChangeOp { - metadata_op, + metadata, materialized_size, }, ), @@ -361,7 +352,7 @@ impl VMChangeSet { self.module_write_set() .iter() .chain(self.aggregator_v1_write_set().iter()) - .map(|(k, v)| (k, WriteOpSize::from(v))), + .map(|(k, v)| (k, v.write_op_size())), ) } @@ -383,7 +374,7 @@ impl VMChangeSet { self.module_write_set .iter_mut() .chain(self.aggregator_v1_write_set.iter_mut()) - .map(|(k, v)| (k, WriteOpSize::from(v as &WriteOp), v.get_metadata_mut())), + .map(|(k, v)| (k, v.write_op_size(), v.get_metadata_mut())), ) } @@ -407,9 +398,9 @@ impl VMChangeSet { // Called by `into_transaction_output_with_materialized_writes` only. pub(crate) fn extend_resource_write_set( &mut self, - patched_resource_writes: impl Iterator, + materialized_resource_writes: impl Iterator, ) -> Result<(), PanicError> { - for (key, new_write) in patched_resource_writes { + for (key, new_write) in materialized_resource_writes { let abstract_write = self.resource_write_set.get_mut(&key).ok_or_else(|| { code_invariant_error(format!( "Cannot patch a resource which does not exist, for: {:?}.", @@ -424,7 +415,7 @@ impl VMChangeSet { ))); } - let new_length = WriteOpSize::from(&new_write).write_len(); + let new_length = new_write.write_op_size().write_len(); let old_length = abstract_write.materialized_size().write_len(); if new_length != old_length { return Err(code_invariant_error(format!( @@ -438,8 +429,8 @@ impl VMChangeSet { } /// The events are set to the input events. - pub(crate) fn set_events(&mut self, patched_events: impl Iterator) { - self.events = patched_events + pub(crate) fn set_events(&mut self, materialized_events: impl Iterator) { + self.events = materialized_events .map(|event| (event, None)) .collect::>(); } diff --git a/aptos-move/aptos-vm-types/src/resolver.rs b/aptos-move/aptos-vm-types/src/resolver.rs index 9c6084680f82d..4965a12f6c7ef 100644 --- a/aptos-move/aptos-vm-types/src/resolver.rs +++ b/aptos-move/aptos-vm-types/src/resolver.rs @@ -194,7 +194,7 @@ pub trait TExecutorView: TResourceView + TModuleView + TAggregatorV1View - + TDelayedFieldView + + TDelayedFieldView + StateStorageView { } @@ -203,7 +203,7 @@ impl TExecutorView for A where A: TResourceView + TModuleView + TAggregatorV1View - + TDelayedFieldView + + TDelayedFieldView + StateStorageView { } diff --git a/aptos-move/aptos-vm-types/src/tests/test_change_set.rs b/aptos-move/aptos-vm-types/src/tests/test_change_set.rs index 1869d0d911af5..a5ce86433d4af 100644 --- a/aptos-move/aptos-vm-types/src/tests/test_change_set.rs +++ b/aptos-move/aptos-vm-types/src/tests/test_change_set.rs @@ -20,7 +20,7 @@ use aptos_aggregator::{ use aptos_types::{ access_path::AccessPath, delayed_fields::{PanicError, SnapshotToStringFormula}, - state_store::state_key::StateKey, + state_store::{state_key::StateKey, state_value::StateValueMetadata}, transaction::ChangeSet as StorageChangeSet, write_set::{WriteOp, WriteSetMut}, }; @@ -622,7 +622,7 @@ fn test_resource_groups_squashing() { ExpandedVMChangeSetBuilder::new() .with_group_reads_needing_delayed_field_exchange(vec![( as_state_key!("1"), - (modification_metadata.clone(), 400) + (modification_metadata.metadata().clone(), 400) )]) .build(), &MockChangeSetChecker @@ -650,7 +650,8 @@ fn test_write_and_read_discrepancy_caught() { .with_reads_needing_delayed_field_exchange(vec![( as_state_key!("1"), ( - WriteOp::legacy_modification(as_bytes!(1).into()), + StateValueMetadata::none(), + 10, Arc::new(MoveTypeLayout::U64) ) )]) @@ -669,7 +670,7 @@ fn test_write_and_read_discrepancy_caught() { )]) .with_group_reads_needing_delayed_field_exchange(vec![( as_state_key!("1"), - (metadata_op, group_size) + (metadata_op.metadata().clone(), group_size) )]) .try_build()); } diff --git a/aptos-move/aptos-vm-types/src/tests/utils.rs b/aptos-move/aptos-vm-types/src/tests/utils.rs index a4bcbf4335234..0d5eee8ca441d 100644 --- a/aptos-move/aptos-vm-types/src/tests/utils.rs +++ b/aptos-move/aptos-vm-types/src/tests/utils.rs @@ -273,8 +273,9 @@ pub(crate) struct ExpandedVMChangeSetBuilder { aggregator_v1_write_set: BTreeMap, aggregator_v1_delta_set: BTreeMap, delayed_field_change_set: BTreeMap>, - reads_needing_delayed_field_exchange: BTreeMap)>, - group_reads_needing_delayed_field_exchange: BTreeMap, + reads_needing_delayed_field_exchange: + BTreeMap)>, + group_reads_needing_delayed_field_exchange: BTreeMap, events: Vec<(ContractEvent, Option)>, } @@ -355,7 +356,7 @@ impl ExpandedVMChangeSetBuilder { pub(crate) fn with_reads_needing_delayed_field_exchange( mut self, reads_needing_delayed_field_exchange: impl IntoIterator< - Item = (StateKey, (WriteOp, Arc)), + Item = (StateKey, (StateValueMetadata, u64, Arc)), >, ) -> Self { assert!(self.reads_needing_delayed_field_exchange.is_empty()); @@ -366,7 +367,9 @@ impl ExpandedVMChangeSetBuilder { pub(crate) fn with_group_reads_needing_delayed_field_exchange( mut self, - group_reads_needing_delayed_field_exchange: impl IntoIterator, + group_reads_needing_delayed_field_exchange: impl IntoIterator< + Item = (StateKey, (StateValueMetadata, u64)), + >, ) -> Self { assert!(self.group_reads_needing_delayed_field_exchange.is_empty()); self.group_reads_needing_delayed_field_exchange diff --git a/aptos-move/aptos-vm/src/block_executor/mod.rs b/aptos-move/aptos-vm/src/block_executor/mod.rs index 72685fc95beb5..e0dc90097387c 100644 --- a/aptos-move/aptos-vm/src/block_executor/mod.rs +++ b/aptos-move/aptos-vm/src/block_executor/mod.rs @@ -24,7 +24,7 @@ use aptos_types::{ delayed_fields::PanicError, executable::ExecutableTestType, fee_statement::FeeStatement, - state_store::{state_key::StateKey, StateView, StateViewId}, + state_store::{state_key::StateKey, state_value::StateValueMetadata, StateView, StateViewId}, transaction::{ signature_verified_transaction::SignatureVerifiedTransaction, BlockOutput, TransactionOutput, TransactionStatus, @@ -145,7 +145,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { } /// Should never be called after incorporating materialized output, as that consumes vm_output. - fn resource_write_set(&self) -> Vec<(StateKey, (WriteOp, Option>))> { + fn resource_write_set(&self) -> Vec<(StateKey, Arc, Option>)> { self.vm_output .lock() .as_ref() @@ -155,11 +155,12 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .iter() .flat_map(|(key, write)| match write { AbstractResourceWriteOp::Write(write_op) => { - Some((key.clone(), (write_op.clone(), None))) + Some((key.clone(), Arc::new(write_op.clone()), None)) }, AbstractResourceWriteOp::WriteWithDelayedFields(write) => Some(( key.clone(), - (write.write_op.clone(), Some(write.layout.clone())), + Arc::new(write.write_op.clone()), + Some(write.layout.clone()), )), _ => None, }) @@ -189,14 +190,16 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { } /// Should never be called after incorporating materialized output, as that consumes vm_output. - fn aggregator_v1_delta_set(&self) -> BTreeMap { + fn aggregator_v1_delta_set(&self) -> Vec<(StateKey, DeltaOp)> { self.vm_output .lock() .as_ref() .expect("Output must be set to get deltas") .change_set() .aggregator_v1_delta_set() - .clone() + .iter() + .map(|(key, op)| (key.clone(), *op)) + .collect() } /// Should never be called after incorporating materialized output, as that consumes vm_output. @@ -210,7 +213,9 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .clone() } - fn reads_needing_delayed_field_exchange(&self) -> Vec<(StateKey, Arc)> { + fn reads_needing_delayed_field_exchange( + &self, + ) -> Vec<(StateKey, StateValueMetadata, Arc)> { self.vm_output .lock() .as_ref() @@ -220,7 +225,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .iter() .flat_map(|(key, write)| { if let AbstractResourceWriteOp::InPlaceDelayedFieldChange(change) = write { - Some((key.clone(), change.layout.clone())) + Some((key.clone(), change.metadata.clone(), change.layout.clone())) } else { None } @@ -228,7 +233,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .collect() } - fn group_reads_needing_delayed_field_exchange(&self) -> Vec<(StateKey, WriteOp)> { + fn group_reads_needing_delayed_field_exchange(&self) -> Vec<(StateKey, StateValueMetadata)> { self.vm_output .lock() .as_ref() @@ -240,7 +245,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { if let AbstractResourceWriteOp::ResourceGroupInPlaceDelayedFieldChange(change) = write { - Some((key.clone(), change.metadata_op.clone())) + Some((key.clone(), change.metadata.clone())) } else { None } @@ -271,8 +276,8 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { fn incorporate_materialized_txn_output( &self, aggregator_v1_writes: Vec<(StateKey, WriteOp)>, - patched_resource_write_set: Vec<(StateKey, WriteOp)>, - patched_events: Vec, + materialized_resource_write_set: Vec<(StateKey, WriteOp)>, + materialized_events: Vec, ) -> Result<(), PanicError> { assert!( self.committed_output @@ -283,12 +288,12 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .expect("Output must be set to incorporate materialized data") .into_transaction_output_with_materialized_write_set( aggregator_v1_writes, - patched_resource_write_set, - patched_events, + materialized_resource_write_set, + materialized_events, )?, ) .is_ok(), - "Could not combine VMOutput with the patched resource and event data" + "Could not combine VMOutput with the materialized resource and event data" ); Ok(()) } @@ -305,7 +310,7 @@ impl BlockExecutorTransactionOutput for AptosTransactionOutput { .expect("We should be able to always convert to transaction output"), ) .is_ok(), - "Could not combine VMOutput with the patched resource and event data" + "Could not combine VMOutput with the materialized resource and event data" ); } diff --git a/aptos-move/aptos-vm/src/data_cache.rs b/aptos-move/aptos-vm/src/data_cache.rs index a41435432ae7c..fdc24fff76213 100644 --- a/aptos-move/aptos-vm/src/data_cache.rs +++ b/aptos-move/aptos-vm/src/data_cache.rs @@ -21,10 +21,12 @@ use aptos_types::{ delayed_fields::PanicError, on_chain_config::{ConfigStorage, Features, OnChainConfig}, state_store::{ - errors::StateviewError, state_key::StateKey, state_storage_usage::StateStorageUsage, - state_value::StateValue, StateView, StateViewId, + errors::StateviewError, + state_key::StateKey, + state_storage_usage::StateStorageUsage, + state_value::{StateValue, StateValueMetadata}, + StateView, StateViewId, }, - write_set::WriteOp, }; use aptos_vm_types::{ resolver::{ @@ -247,7 +249,6 @@ impl<'e, E: ExecutorView> TDelayedFieldView for StorageAdapter<'e, E> { type Identifier = DelayedFieldID; type ResourceGroupTag = StructTag; type ResourceKey = StateKey; - type ResourceValue = WriteOp; fn is_delayed_field_optimization_capable(&self) -> bool { self.executor_view.is_delayed_field_optimization_capable() @@ -286,8 +287,10 @@ impl<'e, E: ExecutorView> TDelayedFieldView for StorageAdapter<'e, E> { &self, delayed_write_set_keys: &HashSet, skip: &HashSet, - ) -> Result)>, PanicError> - { + ) -> Result< + BTreeMap)>, + PanicError, + > { self.executor_view .get_reads_needing_exchange(delayed_write_set_keys, skip) } @@ -296,7 +299,7 @@ impl<'e, E: ExecutorView> TDelayedFieldView for StorageAdapter<'e, E> { &self, delayed_write_set_keys: &HashSet, skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { self.executor_view .get_group_reads_needing_exchange(delayed_write_set_keys, skip) } diff --git a/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs b/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs index 05ebdf21d6414..31010a29fe513 100644 --- a/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs +++ b/aptos-move/aptos-vm/src/move_vm_ext/respawned_session.rs @@ -26,7 +26,7 @@ use aptos_types::{ state_value::{StateValue, StateValueMetadata}, StateViewId, }, - write_set::{TransactionWrite, WriteOp}, + write_set::TransactionWrite, }; use aptos_vm_types::{ abstract_write_op::{AbstractResourceWriteOp, WriteWithDelayedFieldsOp}, @@ -192,7 +192,6 @@ impl<'r> TDelayedFieldView for ExecutorViewWithChangeSet<'r> { type Identifier = DelayedFieldID; type ResourceGroupTag = StructTag; type ResourceKey = StateKey; - type ResourceValue = WriteOp; fn is_delayed_field_optimization_capable(&self) -> bool { self.base_executor_view @@ -279,8 +278,10 @@ impl<'r> TDelayedFieldView for ExecutorViewWithChangeSet<'r> { &self, delayed_write_set_keys: &HashSet, skip: &HashSet, - ) -> Result)>, PanicError> - { + ) -> Result< + BTreeMap)>, + PanicError, + > { self.base_executor_view .get_reads_needing_exchange(delayed_write_set_keys, skip) } @@ -289,7 +290,7 @@ impl<'r> TDelayedFieldView for ExecutorViewWithChangeSet<'r> { &self, delayed_write_set_keys: &HashSet, skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { self.base_executor_view .get_group_reads_needing_exchange(delayed_write_set_keys, skip) } diff --git a/aptos-move/aptos-vm/src/natives.rs b/aptos-move/aptos-vm/src/natives.rs index 4be6d9c6d051b..d093fcc399158 100644 --- a/aptos-move/aptos-vm/src/natives.rs +++ b/aptos-move/aptos-vm/src/natives.rs @@ -28,8 +28,10 @@ use aptos_types::{ use aptos_types::{ chain_id::ChainId, delayed_fields::PanicError, - state_store::{state_key::StateKey, state_value::StateValue}, - write_set::WriteOp, + state_store::{ + state_key::StateKey, + state_value::{StateValue, StateValueMetadata}, + }, }; #[cfg(feature = "testing")] use bytes::Bytes; @@ -81,7 +83,6 @@ impl TDelayedFieldView for AptosBlankStorage { type Identifier = DelayedFieldID; type ResourceGroupTag = StructTag; type ResourceKey = StateKey; - type ResourceValue = WriteOp; fn is_delayed_field_optimization_capable(&self) -> bool { false @@ -119,8 +120,10 @@ impl TDelayedFieldView for AptosBlankStorage { &self, _delayed_write_set_keys: &HashSet, _skip: &HashSet, - ) -> Result)>, PanicError> - { + ) -> Result< + BTreeMap)>, + PanicError, + > { unreachable!() } @@ -128,7 +131,7 @@ impl TDelayedFieldView for AptosBlankStorage { &self, _delayed_write_set_keys: &HashSet, _skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { unimplemented!() } } diff --git a/aptos-move/block-executor/src/captured_reads.rs b/aptos-move/block-executor/src/captured_reads.rs index 1abb8df59d6d1..d70a9bab34ed4 100644 --- a/aptos-move/block-executor/src/captured_reads.rs +++ b/aptos-move/block-executor/src/captured_reads.rs @@ -1,7 +1,7 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::types::InputOutputKey; +use crate::{types::InputOutputKey, value_exchange::filter_value_for_exchange}; use anyhow::bail; use aptos_aggregator::{ delta_math::DeltaHistory, @@ -32,7 +32,7 @@ use std::{ Entry, Entry::{Occupied, Vacant}, }, - HashMap, HashSet, + BTreeMap, HashMap, HashSet, }, sync::Arc, }; @@ -327,10 +327,23 @@ impl CapturedReads { // Return an iterator over the captured reads. pub(crate) fn get_read_values_with_delayed_fields( &self, - ) -> impl Iterator)> { + delayed_write_set_ids: &HashSet, + skip: &HashSet, + ) -> Result)>, PanicError> { self.data_reads .iter() - .filter(|(_, v)| matches!(v, DataRead::Versioned(_, _, Some(_)))) + .filter_map(|(key, data_read)| { + if skip.contains(key) { + return None; + } + + if let DataRead::Versioned(_version, value, Some(layout)) = data_read { + filter_value_for_exchange::(value, layout, delayed_write_set_ids, key) + } else { + None + } + }) + .collect() } // Return an iterator over the captured group reads that contain a delayed field diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index 20dbdade90590..d6d687c1e0591 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -9,6 +9,7 @@ use crate::{ TASK_VALIDATE_SECONDS, VM_INIT_SECONDS, WORK_WITH_TASK_SECONDS, }, errors::*, + executor_utilities::*, explicit_sync_wrapper::ExplicitSyncWrapper, limit_processor::BlockGasLimitProcessor, scheduler::{DependencyStatus, ExecutionTaskType, Scheduler, SchedulerTask, Wave}, @@ -26,18 +27,17 @@ use aptos_aggregator::{ use aptos_drop_helper::DEFAULT_DROPPER; use aptos_logger::{debug, error}; use aptos_mvhashmap::{ - types::{Incarnation, MVDataOutput, MVDelayedFieldsError, TxnIndex, ValueWithLayout}, + types::{Incarnation, MVDelayedFieldsError, TxnIndex, ValueWithLayout}, unsync_map::UnsyncMap, versioned_delayed_fields::CommitError, MVHashMap, }; use aptos_types::{ block_executor::config::BlockExecutorConfig, - contract_event::TransactionEvent, delayed_fields::PanicError, executable::Executable, on_chain_config::BlockGasLimitType, - state_store::TStateView, + state_store::{state_value::StateValue, TStateView}, transaction::{BlockExecutableTransaction as Transaction, BlockOutput}, write_set::{TransactionWrite, WriteOp}, }; @@ -49,7 +49,6 @@ use core::panic; use fail::fail_point; use move_core_types::value::MoveTypeLayout; use num_cpus; -use rand::{thread_rng, Rng}; use rayon::ThreadPool; use std::{ cell::RefCell, @@ -127,7 +126,10 @@ where // For tracking whether the recent execution wrote outside of the previous write/delta set. let mut updates_outside = false; - let mut apply_updates = |output: &E::Output| -> Result<(), PanicError> { + let mut apply_updates = |output: &E::Output| -> Result< + Vec<(T::Key, Arc, Option>)>, // Cached resource writes + PanicError, + > { for (group_key, group_metadata_op, group_ops) in output.resource_group_write_set().into_iter() { @@ -141,7 +143,8 @@ where idx_to_execute, incarnation, // Group metadata op needs no layout (individual resources in groups do). - (group_metadata_op, None), + Arc::new(group_metadata_op), + None, ); if versioned_cache.group_data().write( group_key, @@ -154,19 +157,21 @@ where } } + let resource_write_set = output.resource_write_set(); + // Then, process resource & aggregator_v1 & module writes. - for (k, v) in output.resource_write_set().into_iter().chain( + for (k, v, maybe_layout) in resource_write_set.clone().into_iter().chain( output .aggregator_v1_write_set() .into_iter() - .map(|(state_key, write_op)| (state_key, (write_op, None))), + .map(|(state_key, write_op)| (state_key, Arc::new(write_op), None)), ) { if prev_modified_keys.remove(&k).is_none() { updates_outside = true; } versioned_cache .data() - .write(k, idx_to_execute, incarnation, v); + .write(k, idx_to_execute, incarnation, v, maybe_layout); } for (k, v) in output.module_write_set().into_iter() { @@ -224,29 +229,32 @@ where }; } } - Ok(()) + Ok(resource_write_set) }; - let result = match execute_result { + let (result, resource_write_set) = match execute_result { // These statuses are the results of speculative execution, so even for // SkipRest (skip the rest of transactions) and Abort (abort execution with // user defined error), no immediate action is taken. Instead the statuses // are recorded and (final statuses) are analyzed when the block is executed. ExecutionStatus::Success(output) => { // Apply the writes/deltas to the versioned_data_cache. - apply_updates(&output)?; - ExecutionStatus::Success(output) + let resource_write_set = apply_updates(&output)?; + (ExecutionStatus::Success(output), resource_write_set) }, ExecutionStatus::SkipRest(output) => { // Apply the writes/deltas and record status indicating skip. - apply_updates(&output)?; - ExecutionStatus::SkipRest(output) + let resource_write_set = apply_updates(&output)?; + (ExecutionStatus::SkipRest(output), resource_write_set) }, ExecutionStatus::SpeculativeExecutionAbortError(msg) => { read_set.capture_delayed_field_read_error(&PanicOr::Or( MVDelayedFieldsError::DeltaApplicationFailure, )); - ExecutionStatus::SpeculativeExecutionAbortError(msg) + ( + ExecutionStatus::SpeculativeExecutionAbortError(msg), + Vec::new(), + ) }, ExecutionStatus::Abort(err) => { // Abort indicates an unrecoverable VM failure, and should not occur @@ -284,7 +292,7 @@ where versioned_cache.delayed_fields().remove(&id, idx_to_execute); } - if !last_input_output.record(idx_to_execute, read_set, result) { + if !last_input_output.record(idx_to_execute, read_set, result, resource_write_set) { return Err(PanicOr::Or( IntentionalFallbackToSequential::module_path_read_write( "Module read & write".into(), @@ -518,65 +526,27 @@ where } } - let process_finalized_group = - |finalized_group: anyhow::Result)>>, - metadata_is_deletion: bool| - -> Result<_, _> { - match finalized_group { - Ok(finalized_group) => { - // finalize_group already applies the deletions. - if finalized_group.is_empty() != metadata_is_deletion { - return Err(code_invariant_error(format!( - "Group is empty = {} but op is deletion = {} in parallel execution", - finalized_group.is_empty(), - metadata_is_deletion - ))); - } - Ok(finalized_group) - }, - Err(e) => Err(code_invariant_error(format!( - "Error committing resource group {:?}", - e - ))), - } - }; - - let group_metadata_ops = last_input_output.group_metadata_ops(txn_idx); - let mut finalized_groups = Vec::with_capacity(group_metadata_ops.len()); - for (group_key, metadata_op) in group_metadata_ops.into_iter() { - // finalize_group copies Arc of values and the Tags (TODO: optimize as needed). - let finalized_result = versioned_cache - .group_data() - .finalize_group(&group_key, txn_idx); - match process_finalized_group(finalized_result, metadata_op.is_deletion()) { - Ok(finalized_group) => { - finalized_groups.push((group_key, metadata_op, finalized_group)); - }, - Err(err) => { - return Err(err.into()); - }, - } - } - - if let Some(group_reads_needing_delayed_field_exchange) = - last_input_output.group_reads_needing_delayed_field_exchange(txn_idx) - { - for (group_key, metadata_op) in - group_reads_needing_delayed_field_exchange.into_iter() - { - let finalized_result = versioned_cache - .group_data() - .get_last_committed_group(&group_key); - match process_finalized_group(finalized_result, metadata_op.is_deletion()) { - Ok(finalized_group) => { - finalized_groups.push((group_key, metadata_op, finalized_group)); - }, - Err(err) => { - return Err(err.into()); - }, - } - } - } + let finalized_groups = groups_to_finalize!(last_input_output, txn_idx) + .map(|((group_key, metadata_op), is_read_needing_exchange)| { + // finalize_group copies Arc of values and the Tags (TODO: optimize as needed). + // TODO[agg_v2]: have a test that fails if we don't do the if. + let finalized_result = if is_read_needing_exchange { + versioned_cache + .group_data() + .get_last_committed_group(&group_key) + } else { + versioned_cache + .group_data() + .finalize_group(&group_key, txn_idx) + }; + map_finalized_group::( + group_key, + finalized_result, + metadata_op, + is_read_needing_exchange, + ) + }) + .collect::, _>>()?; last_input_output.record_finalized_group(txn_idx, finalized_groups); @@ -610,116 +580,6 @@ where Ok(()) } - // For each delayed field in resource write set, replace the identifiers with values. - fn map_id_to_values_in_write_set( - resource_write_set: Option>))>>, - latest_view: &LatestView, - ) -> BTreeMap { - let mut patched_resource_write_set = BTreeMap::new(); - if let Some(resource_write_set) = resource_write_set { - for (key, (write_op, layout)) in resource_write_set.into_iter() { - // layout is Some(_) if it contains a delayed field - if let Some(layout) = layout { - if !write_op.is_deletion() { - match write_op.bytes() { - // TODO[agg_v2](fix): propagate error - None => unreachable!(), - Some(write_op_bytes) => { - let patched_bytes = match latest_view - .replace_identifiers_with_values(write_op_bytes, &layout) - { - Ok((bytes, _)) => bytes, - Err(_) => { - unreachable!( - "Failed to replace identifiers with values, {layout:?}" - ) - }, - }; - let mut patched_write_op = write_op; - patched_write_op.set_bytes(patched_bytes); - patched_resource_write_set.insert(key, patched_write_op); - }, - } - } - } - } - } - patched_resource_write_set - } - - fn map_id_to_values_in_group_writes( - finalized_groups: Vec<(T::Key, T::Value, Vec<(T::Tag, ValueWithLayout)>)>, - latest_view: &LatestView, - ) -> Vec<(T::Key, T::Value, Vec<(T::Tag, Arc)>)> { - let mut patched_finalized_groups = Vec::with_capacity(finalized_groups.len()); - for (group_key, group_metadata_op, resource_vec) in finalized_groups.into_iter() { - let mut patched_resource_vec = Vec::with_capacity(resource_vec.len()); - for (tag, value_with_layout) in resource_vec.into_iter() { - let value = match value_with_layout { - ValueWithLayout::RawFromStorage(value) => value, - ValueWithLayout::Exchanged(value, None) => value, - ValueWithLayout::Exchanged(value, Some(layout)) => Arc::new( - Self::replace_ids_with_values(&value, layout.as_ref(), latest_view), - ), - }; - patched_resource_vec.push((tag, value)); - } - patched_finalized_groups.push((group_key, group_metadata_op, patched_resource_vec)); - } - patched_finalized_groups - } - - // Parse the input `value` and replace delayed field identifiers with - // corresponding values - fn replace_ids_with_values( - value: &T::Value, - layout: &MoveTypeLayout, - latest_view: &LatestView, - ) -> T::Value { - if let Some(mut value) = value.convert_read_to_modification() { - if let Some(value_bytes) = value.bytes() { - let (patched_bytes, _) = latest_view - .replace_identifiers_with_values(value_bytes, layout) - .unwrap(); - value.set_bytes(patched_bytes); - value - } else { - unreachable!("Value to be exchanged doesn't have bytes: {:?}", value) - } - } else { - unreachable!( - "Value to be exchanged cannot be transformed to modification: {:?}", - value - ); - } - } - - // For each delayed field in the event, replace delayed field identifier with value. - fn map_id_to_values_events( - events: Box)>>, - latest_view: &LatestView, - ) -> Vec { - let mut patched_events = vec![]; - for (event, layout) in events { - if let Some(layout) = layout { - let event_data = event.get_event_data(); - match latest_view - .replace_identifiers_with_values(&Bytes::from(event_data.to_vec()), &layout) - { - Ok((bytes, _)) => { - let mut patched_event = event; - patched_event.set_event_data(bytes.to_vec()); - patched_events.push(patched_event); - }, - Err(_) => unreachable!("Failed to replace identifiers with values in event"), - } - } else { - patched_events.push(event); - } - } - patched_events - } - fn materialize_aggregator_v1_delta_writes( txn_idx: TxnIndex, last_input_output: &TxnLastInputOutput, @@ -772,55 +632,6 @@ where aggregator_v1_delta_writes } - fn serialize_groups( - finalized_groups: Vec<(T::Key, T::Value, Vec<(T::Tag, Arc)>)>, - txn_idx: TxnIndex, - ) -> Result, PanicOr> { - fail_point!( - "fail-point-resource-group-serialization", - !finalized_groups.is_empty(), - |_| Err(PanicOr::Or( - IntentionalFallbackToSequential::ResourceGroupSerializationError - )) - ); - - finalized_groups - .into_iter() - .map(|(group_key, mut metadata_op, finalized_group)| { - let btree: BTreeMap = finalized_group - .into_iter() - // TODO[agg_v2](fix): Should anything be done using the layout here? - .map(|(resource_tag, arc_v)| { - let bytes = arc_v - .extract_raw_bytes() - .expect("Deletions should already be applied"); - (resource_tag, bytes) - }) - .collect(); - - let res = bcs::to_bytes(&btree) - .map_err(|e| { - PanicOr::Or( - IntentionalFallbackToSequential::resource_group_serialization_error( - format!("Unexpected resource group error {:?}", e), - txn_idx, - ), - ) - }) - .map(|group_bytes| { - metadata_op.set_bytes(group_bytes.into()); - (group_key, metadata_op) - }); - - if res.is_err() { - alert!("Failed to serialize resource group"); - } - - res - }) - .collect() - } - fn materialize_txn_commit( &self, txn_idx: TxnIndex, @@ -839,38 +650,23 @@ where shared_counter, ); let latest_view = LatestView::new(base_view, ViewState::Sync(parallel_state), txn_idx); - let resource_write_set = last_input_output.resource_write_set(txn_idx); let finalized_groups = last_input_output.take_finalized_group(txn_idx); + let materialized_finalized_groups = + map_id_to_values_in_group_writes(finalized_groups, &latest_view)?; + let serialized_groups = serialize_groups::(materialized_finalized_groups, txn_idx)?; - let mut patched_resource_write_set = - Self::map_id_to_values_in_write_set(resource_write_set, &latest_view); - - if let Some(reads_needing_delayed_field_exchange) = - last_input_output.reads_needing_delayed_field_exchange(txn_idx) - { - for (key, layout) in reads_needing_delayed_field_exchange.into_iter() { - if let Ok(MVDataOutput::Versioned( - _, - ValueWithLayout::Exchanged(value, existing_layout), - )) = versioned_cache.data().fetch_data(&key, txn_idx) - { - randomly_check_layout_matches( - existing_layout.as_deref(), - Some(layout.as_ref()), - )?; - patched_resource_write_set.insert( - key, - Self::replace_ids_with_values(&value, layout.as_ref(), &latest_view), - ); - } - } - } - - let patched_finalized_groups = - Self::map_id_to_values_in_group_writes(finalized_groups, &latest_view); + let resource_write_set = last_input_output.take_resource_write_set(txn_idx); + let resource_writes_to_materialize = resource_writes_to_materialize!( + resource_write_set, + last_input_output, + versioned_cache.data(), + txn_idx + )?; + let materialized_resource_write_set = + map_id_to_values_in_write_set(resource_writes_to_materialize, &latest_view)?; let events = last_input_output.events(txn_idx); - let patched_events = Self::map_id_to_values_events(events, &latest_view); + let materialized_events = map_id_to_values_events(events, &latest_view)?; let aggregator_v1_delta_writes = Self::materialize_aggregator_v1_delta_writes( txn_idx, last_input_output, @@ -878,16 +674,14 @@ where base_view, ); - let serialized_groups = Self::serialize_groups(patched_finalized_groups, txn_idx)?; - last_input_output.record_materialized_txn_output( txn_idx, aggregator_v1_delta_writes, - patched_resource_write_set + materialized_resource_write_set .into_iter() .chain(serialized_groups) .collect(), - patched_events, + materialized_events, )?; if let Some(txn_commit_listener) = &self.transaction_commit_hook { let txn_output = last_input_output.txn_output(txn_idx).unwrap(); @@ -1126,8 +920,9 @@ where fn apply_output_sequential( unsync_map: &UnsyncMap, output: &E::Output, + resource_write_set: Vec<(T::Key, Arc, Option>)>, ) -> Result<(), PanicOr> { - for (key, (write_op, layout)) in output.resource_write_set().into_iter() { + for (key, write_op, layout) in resource_write_set.into_iter() { unsync_map.write(key, write_op, layout); } @@ -1139,11 +934,11 @@ where code_invariant_error(format!("Unexpected resource group error {:?}", e)) })?; } - unsync_map.write(group_key, metadata_op, None); + unsync_map.write(group_key, Arc::new(metadata_op), None); } for (key, write_op) in output.aggregator_v1_write_set().into_iter() { - unsync_map.write(key, write_op, None); + unsync_map.write(key, Arc::new(write_op), None); } for (key, write_op) in output.module_write_set().into_iter() { @@ -1358,83 +1153,49 @@ where // Apply the writes. // TODO[agg_v2](fix): return code invariant error if dynamic change set optimizations disabled. - Self::apply_output_sequential(&unsync_map, &output)?; + let resource_write_set = output.resource_write_set(); + Self::apply_output_sequential( + &unsync_map, + &output, + resource_write_set.clone(), + )?; // If dynamic change set materialization part (indented for clarity/variable scope): { - let group_metadata_ops = output.resource_group_metadata_ops(); - let mut finalized_groups = Vec::with_capacity(group_metadata_ops.len()); - for (group_key, group_metadata_op) in group_metadata_ops.into_iter() { - let finalized_group: Vec<_> = - unsync_map.finalize_group(&group_key).collect(); - if finalized_group.is_empty() != group_metadata_op.is_deletion() { - // TODO[agg_v2](fix): code invariant error if dynamic change set optimizations disabled. - // TODO[agg_v2](fix): make sure this cannot be triggered by an user transaction - return Err(code_invariant_error(format!( - "Group is empty = {} but op is deletion = {} in sequential execution", - finalized_group.is_empty(), - group_metadata_op.is_deletion() - )).into()); - } - finalized_groups.push((group_key, group_metadata_op, finalized_group)); - } - - for (group_key, group_metadata_op) in - output.group_reads_needing_delayed_field_exchange() - { - let finalized_group: Vec<_> = - unsync_map.finalize_group(&group_key).collect(); - if finalized_group.is_empty() != group_metadata_op.is_deletion() { - return Err(code_invariant_error(format!( - "Group is empty = {} but op is deletion = {} in sequential execution", - finalized_group.is_empty(), - group_metadata_op.is_deletion() - )).into()); - } - finalized_groups.push((group_key, group_metadata_op, finalized_group)); - } + let finalized_groups = groups_to_finalize!(output,) + .map(|((group_key, metadata_op), is_read_needing_exchange)| { + let finalized_group = + Ok(unsync_map.finalize_group(&group_key).collect()); + map_finalized_group::( + group_key, + finalized_group, + metadata_op, + is_read_needing_exchange, + ) + }) + .collect::, _>>()?; + let materialized_finalized_groups = + map_id_to_values_in_group_writes(finalized_groups, &latest_view)?; + let serialized_groups = + serialize_groups::(materialized_finalized_groups, idx as TxnIndex) + .map_err(BlockExecutionError::FallbackToSequential)?; + let resource_writes_to_materialize = resource_writes_to_materialize!( + resource_write_set, + output, + unsync_map, + )?; // Replace delayed field id with values in resource write set and read set. - let resource_change_set = Some(output.resource_write_set()); - let mut patched_resource_write_set = - Self::map_id_to_values_in_write_set(resource_change_set, &latest_view); - - for (key, layout) in - output.reads_needing_delayed_field_exchange().into_iter() - { - if let Some(ValueWithLayout::Exchanged(value, _)) = - unsync_map.fetch_data(&key) - { - if patched_resource_write_set - .insert( - key, - Self::replace_ids_with_values( - &value, - layout.as_ref(), - &latest_view, - ), - ) - .is_some() - { - return Err(BlockExecutionError::FallbackToSequential(code_invariant_error( - "reads_needing_delayed_field_exchange already in the write set for key", - ).into())); - } - } - } - - let patched_finalized_groups = - Self::map_id_to_values_in_group_writes(finalized_groups, &latest_view); + let materialized_resource_write_set = map_id_to_values_in_write_set( + resource_writes_to_materialize, + &latest_view, + )?; // Replace delayed field id with values in events - let patched_events = Self::map_id_to_values_events( + let materialized_events = map_id_to_values_events( Box::new(output.get_events().into_iter()), &latest_view, - ); - - let serialized_groups = - Self::serialize_groups(patched_finalized_groups, idx as TxnIndex) - .map_err(BlockExecutionError::FallbackToSequential)?; + )?; output .incorporate_materialized_txn_output( @@ -1442,11 +1203,11 @@ where // They are already handled because we passed materialize_deltas=true // to execute_transaction. vec![], - patched_resource_write_set + materialized_resource_write_set .into_iter() .chain(serialized_groups.into_iter()) .collect(), - patched_events, + materialized_events, ) .map_err(PanicOr::from) .map_err(BlockExecutionError::FallbackToSequential)?; @@ -1582,14 +1343,3 @@ where ret } } - -fn gen_id_start_value(sequential: bool) -> u32 { - // IDs are ephemeral. Pick a random prefix, and different each time, - // in case exchange is mistakenly not performed - to more easily catch it. - // And in a bad case where it happens in prod, to and make sure incorrect - // block doesn't get committed, but chain halts. - // (take a different range from parallel execution, to even more easily differentiate) - - let offset = if sequential { 0 } else { 1000 }; - thread_rng().gen_range(1 + offset, 1000 + offset) * 1_000_000 -} diff --git a/aptos-move/block-executor/src/executor_utilities.rs b/aptos-move/block-executor/src/executor_utilities.rs new file mode 100644 index 0000000000000..93f7d85b552da --- /dev/null +++ b/aptos-move/block-executor/src/executor_utilities.rs @@ -0,0 +1,289 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::{errors::*, view::LatestView}; +use aptos_aggregator::types::{code_invariant_error, PanicOr}; +use aptos_logger::error; +use aptos_mvhashmap::types::{TxnIndex, ValueWithLayout}; +use aptos_types::{ + contract_event::TransactionEvent, delayed_fields::PanicError, executable::Executable, + state_store::TStateView, transaction::BlockExecutableTransaction as Transaction, + write_set::TransactionWrite, +}; +use aptos_vm_logging::{alert, prelude::*}; +use bytes::Bytes; +use fail::fail_point; +use move_core_types::value::MoveTypeLayout; +use rand::{thread_rng, Rng}; +use std::{collections::BTreeMap, sync::Arc}; + +// TODO(clean-up): refactor & replace these macros with functions for code clarity. Currently +// not possible due to type & API mismatch. +macro_rules! groups_to_finalize { + ($outputs:expr, $($txn_idx:expr),*) => {{ + let group_write_ops = $outputs.resource_group_metadata_ops($($txn_idx),*); + + group_write_ops.into_iter() + .map(|val| (val, false)) + .chain([()].into_iter().flat_map(|_| { + // Lazily evaluated only after iterating over group_write_ops. + $outputs.group_reads_needing_delayed_field_exchange($($txn_idx),*) + .into_iter() + .map(|(key, metadata)| + ((key, TransactionWrite::from_state_value( + Some(StateValue::new_with_metadata(Bytes::new(), metadata)))), true)) + })) + }}; +} + +// Selects and prepares resource writes that require ID replacement for delayed fields. +// - reads needing replacement: returns the error if data is not in Exchanged format. +// - normal resource writes: select writes that have layout set and are not a deletion. +// +// Since reads needing exchange also do not contain deletions (see 'does_value_need_exchange') +// logic in value_exchange.rs, it is guaranteed that no returned values is a deletion. +macro_rules! resource_writes_to_materialize { + ($writes:expr, $outputs:expr, $data_source:expr, $($txn_idx:expr),*) => {{ + $outputs + .reads_needing_delayed_field_exchange($($txn_idx),*) + .into_iter() + .map(|(key, metadata, layout)| { + match $data_source.fetch_exchanged_data(&key, $($txn_idx),*) { + Some((value, existing_layout)) => { + randomly_check_layout_matches( + Some(&existing_layout), + Some(layout.as_ref()), + )?; + let new_value = Arc::new(TransactionWrite::from_state_value(Some( + StateValue::new_with_metadata( + value.bytes().cloned().unwrap_or_else(Bytes::new), metadata) + ))); + Ok((key, new_value, layout)) + }, + None => { + Err(code_invariant_error( + "Read value needing exchange not in Exchanged format".to_string() + )) + } + }}).chain( + $writes.into_iter().filter_map(|(key, value, maybe_layout)| { + // layout is Some(_) if it contains a delayed field + if let Some(layout) = maybe_layout { + // No need to exchange anything if a resource with delayed field is deleted. + if !value.is_deletion() { + return Some(Ok((key, value, layout))) + } + } + None + })).collect::, _>>() + }}; +} + +pub(crate) use groups_to_finalize; +pub(crate) use resource_writes_to_materialize; + +pub(crate) fn map_finalized_group( + group_key: T::Key, + finalized_group: anyhow::Result)>>, + metadata_op: T::Value, + is_read_needing_exchange: bool, +) -> Result<(T::Key, T::Value, Vec<(T::Tag, ValueWithLayout)>), PanicError> { + let metadata_is_deletion = metadata_op.is_deletion(); + + match finalized_group { + Ok(finalized_group) => { + if is_read_needing_exchange && metadata_is_deletion { + // Value needed exchange but was not written / modified during the txn + // execution: may not be empty. + Err(code_invariant_error( + "Value only read and exchanged, but metadata op is Deletion".to_string(), + )) + } else if finalized_group.is_empty() != metadata_is_deletion { + // finalize_group already applies the deletions. + Err(code_invariant_error(format!( + "Group is empty = {} but op is deletion = {} in parallel execution", + finalized_group.is_empty(), + metadata_is_deletion + ))) + } else { + Ok((group_key, metadata_op, finalized_group)) + } + }, + Err(e) => Err(code_invariant_error(format!( + "Error committing resource group {:?}", + e + ))), + } +} + +pub(crate) fn serialize_groups( + finalized_groups: Vec<(T::Key, T::Value, Vec<(T::Tag, Arc)>)>, + txn_idx: TxnIndex, +) -> Result, PanicOr> { + fail_point!( + "fail-point-resource-group-serialization", + !finalized_groups.is_empty(), + |_| Err(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + )) + ); + + finalized_groups + .into_iter() + .map(|(group_key, mut metadata_op, finalized_group)| { + let btree: BTreeMap = finalized_group + .into_iter() + // TODO[agg_v2](fix): Should anything be done using the layout here? + .map(|(resource_tag, arc_v)| { + let bytes = arc_v + .extract_raw_bytes() + .expect("Deletions should already be applied"); + (resource_tag, bytes) + }) + .collect(); + + let res = bcs::to_bytes(&btree) + .map_err(|e| { + PanicOr::Or( + IntentionalFallbackToSequential::resource_group_serialization_error( + format!("Unexpected resource group error {:?}", e), + txn_idx, + ), + ) + }) + .map(|group_bytes| { + metadata_op.set_bytes(group_bytes.into()); + (group_key, metadata_op) + }); + + if res.is_err() { + alert!("Failed to serialize resource group"); + } + + res + }) + .collect() +} + +pub(crate) fn gen_id_start_value(sequential: bool) -> u32 { + // IDs are ephemeral. Pick a random prefix, and different each time, + // in case exchange is mistakenly not performed - to more easily catch it. + // And in a bad case where it happens in prod, to and make sure incorrect + // block doesn't get committed, but chain halts. + // (take a different range from parallel execution, to even more easily differentiate) + + let offset = if sequential { 0 } else { 1000 }; + thread_rng().gen_range(1 + offset, 1000 + offset) * 1_000_000 +} + +pub(crate) fn map_id_to_values_in_group_writes< + T: Transaction, + S: TStateView + Sync, + X: Executable + 'static, +>( + finalized_groups: Vec<(T::Key, T::Value, Vec<(T::Tag, ValueWithLayout)>)>, + latest_view: &LatestView, +) -> ::std::result::Result)>)>, PanicError> { + let mut patched_finalized_groups = Vec::with_capacity(finalized_groups.len()); + for (group_key, group_metadata_op, resource_vec) in finalized_groups.into_iter() { + let mut patched_resource_vec = Vec::with_capacity(resource_vec.len()); + for (tag, value_with_layout) in resource_vec.into_iter() { + let value = match value_with_layout { + ValueWithLayout::RawFromStorage(value) => value, + ValueWithLayout::Exchanged(value, None) => value, + ValueWithLayout::Exchanged(value, Some(layout)) => Arc::new( + replace_ids_with_values(&value, layout.as_ref(), latest_view)?, + ), + }; + patched_resource_vec.push((tag, value)); + } + patched_finalized_groups.push((group_key, group_metadata_op, patched_resource_vec)); + } + Ok(patched_finalized_groups) +} + +// For each delayed field in resource write set, replace the identifiers with values +// (ignoring other writes). Currently also checks the keys are unique. +pub(crate) fn map_id_to_values_in_write_set< + T: Transaction, + S: TStateView + Sync, + X: Executable + 'static, +>( + resource_write_set: Vec<(T::Key, Arc, Arc)>, + latest_view: &LatestView, +) -> Result, PanicError> { + resource_write_set + .into_iter() + .map(|(key, write_op, layout)| { + Ok::<_, PanicError>(( + key, + replace_ids_with_values(&write_op, &layout, latest_view)?, + )) + }) + .collect::>() +} + +// For each delayed field in the event, replace delayed field identifier with value. +pub(crate) fn map_id_to_values_events< + T: Transaction, + S: TStateView + Sync, + X: Executable + 'static, +>( + events: Box)>>, + latest_view: &LatestView, +) -> Result, PanicError> { + events + .map(|(event, layout)| { + if let Some(layout) = layout { + let event_data = event.get_event_data(); + latest_view + .replace_identifiers_with_values(&Bytes::from(event_data.to_vec()), &layout) + .map(|(bytes, _)| { + let mut patched_event = event; + patched_event.set_event_data(bytes.to_vec()); + patched_event + }) + .map_err(|_| { + code_invariant_error(format!( + "Failed to replace identifiers with values in an event {:?}", + layout + )) + }) + } else { + Ok(event) + } + }) + .collect::, PanicError>>() +} + +// Parse the input `value` and replace delayed field identifiers with corresponding values +fn replace_ids_with_values< + T: Transaction, + S: TStateView + Sync, + X: Executable + 'static, +>( + value: &Arc, + layout: &MoveTypeLayout, + latest_view: &LatestView, +) -> Result { + let mut value = (**value).clone(); + + if let Some(value_bytes) = value.bytes() { + let patched_bytes = latest_view + .replace_identifiers_with_values(value_bytes, layout) + .map_err(|_| { + code_invariant_error(format!( + "Failed to replace identifiers with values in a resource {:?}", + layout + )) + })? + .0; + value.set_bytes(patched_bytes); + Ok(value) + } else { + Err(code_invariant_error(format!( + "Value to be exchanged doesn't have bytes: {:?}", + value, + ))) + } +} diff --git a/aptos-move/block-executor/src/lib.rs b/aptos-move/block-executor/src/lib.rs index 3a16dff11cf0f..da4e34492d44d 100644 --- a/aptos-move/block-executor/src/lib.rs +++ b/aptos-move/block-executor/src/lib.rs @@ -143,6 +143,7 @@ mod captured_reads; pub mod counters; pub mod errors; pub mod executor; +mod executor_utilities; pub mod explicit_sync_wrapper; mod limit_processor; #[cfg(any(test, feature = "fuzzing"))] @@ -154,4 +155,5 @@ pub mod txn_last_input_output; pub mod types; #[cfg(test)] mod unit_tests; +mod value_exchange; pub mod view; diff --git a/aptos-move/block-executor/src/proptest_types/types.rs b/aptos-move/block-executor/src/proptest_types/types.rs index cf831b54786ab..ea816bcd7a901 100644 --- a/aptos-move/block-executor/src/proptest_types/types.rs +++ b/aptos-move/block-executor/src/proptest_types/types.rs @@ -297,13 +297,6 @@ impl TransactionWrite for ValueType { fn set_bytes(&mut self, bytes: Bytes) { self.bytes = bytes.into(); } - - fn convert_read_to_modification(&self) -> Option - where - Self: Sized, - { - Some(self.clone()) - } } #[derive(Clone, Copy)] @@ -1011,12 +1004,12 @@ where // TODO[agg_v2](tests): Assigning MoveTypeLayout as None for all the writes for now. // That means, the resources do not have any DelayedFields embedded in them. // Change it to test resources with DelayedFields as well. - fn resource_write_set(&self) -> Vec<(K, (ValueType, Option>))> { + fn resource_write_set(&self) -> Vec<(K, Arc, Option>)> { self.writes .iter() .filter(|(k, _)| k.module_path().is_none()) .cloned() - .map(|(k, v)| (k, (v, None))) + .map(|(k, v)| (k, Arc::new(v), None)) .collect() } @@ -1034,8 +1027,8 @@ where BTreeMap::new() } - fn aggregator_v1_delta_set(&self) -> BTreeMap { - self.deltas.iter().cloned().collect() + fn aggregator_v1_delta_set(&self) -> Vec<(K, DeltaOp)> { + self.deltas.clone() } fn delayed_field_change_set( @@ -1050,17 +1043,18 @@ where fn reads_needing_delayed_field_exchange( &self, - ) -> Vec<(::Key, Arc)> { + ) -> Vec<( + ::Key, + StateValueMetadata, + Arc, + )> { // TODO[agg_v2](tests): add aggregators V2 to the proptest? Vec::new() } fn group_reads_needing_delayed_field_exchange( &self, - ) -> Vec<( - ::Key, - ::Value, - )> { + ) -> Vec<(::Key, StateValueMetadata)> { // TODO[agg_v2](tests): add aggregators V2 to the proptest? Vec::new() } diff --git a/aptos-move/block-executor/src/task.rs b/aptos-move/block-executor/src/task.rs index 127d37d3efb75..5e78c28c9e1d7 100644 --- a/aptos-move/block-executor/src/task.rs +++ b/aptos-move/block-executor/src/task.rs @@ -9,6 +9,7 @@ use aptos_aggregator::{ use aptos_mvhashmap::types::TxnIndex; use aptos_types::{ delayed_fields::PanicError, fee_statement::FeeStatement, + state_store::state_value::StateValueMetadata, transaction::BlockExecutableTransaction as Transaction, write_set::WriteOp, }; use aptos_vm_types::resolver::{TExecutorView, TResourceGroupView}; @@ -95,10 +96,8 @@ pub trait TransactionOutput: Send + Sync + Debug { &self, ) -> Vec<( ::Key, - ( - ::Value, - Option>, - ), + Arc<::Value>, + Option>, )>; fn module_write_set( @@ -110,7 +109,7 @@ pub trait TransactionOutput: Send + Sync + Debug { ) -> BTreeMap<::Key, ::Value>; /// Get the aggregator V1 deltas of a transaction from its output. - fn aggregator_v1_delta_set(&self) -> BTreeMap<::Key, DeltaOp>; + fn aggregator_v1_delta_set(&self) -> Vec<(::Key, DeltaOp)>; /// Get the delayed field changes of a transaction from its output. fn delayed_field_change_set( @@ -122,15 +121,16 @@ pub trait TransactionOutput: Send + Sync + Debug { fn reads_needing_delayed_field_exchange( &self, - ) -> Vec<(::Key, Arc)>; - - fn group_reads_needing_delayed_field_exchange( - &self, ) -> Vec<( ::Key, - ::Value, + StateValueMetadata, + Arc, )>; + fn group_reads_needing_delayed_field_exchange( + &self, + ) -> Vec<(::Key, StateValueMetadata)>; + /// Get the events of a transaction from its output. fn get_events(&self) -> Vec<(::Event, Option)>; diff --git a/aptos-move/block-executor/src/txn_last_input_output.rs b/aptos-move/block-executor/src/txn_last_input_output.rs index f524ee20607f6..37c9a2d7b84ab 100644 --- a/aptos-move/block-executor/src/txn_last_input_output.rs +++ b/aptos-move/block-executor/src/txn_last_input_output.rs @@ -12,6 +12,7 @@ use aptos_aggregator::types::{code_invariant_error, PanicOr}; use aptos_mvhashmap::types::{TxnIndex, ValueWithLayout}; use aptos_types::{ delayed_fields::PanicError, fee_statement::FeeStatement, + state_store::state_value::StateValueMetadata, transaction::BlockExecutableTransaction as Transaction, write_set::WriteOp, }; use arc_swap::ArcSwapOption; @@ -27,6 +28,20 @@ use std::{ type TxnInput = CapturedReads; +macro_rules! forward_on_success_or_skip_rest { + ($self:ident, $txn_idx:ident, $f:ident) => {{ + $self.outputs[$txn_idx as usize] + .load() + .as_ref() + .map_or(vec![], |txn_output| match &txn_output.output_status { + ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => t.$f(), + ExecutionStatus::Abort(_) + | ExecutionStatus::SpeculativeExecutionAbortError(_) + | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => vec![], + }) + }}; +} + // When a transaction is committed, the output delta writes must be populated by // the WriteOps corresponding to the deltas in the corresponding outputs. #[derive(Debug)] @@ -60,7 +75,14 @@ pub struct TxnLastInputOutput, E: >, >, + // TODO: Consider breaking down the outputs when storing (avoid traversals, cache below). outputs: Vec>>>, // txn_idx -> output. + // Cache to avoid expensive clones of data. + // TODO(clean-up): be consistent with naming resource writes: here it means specifically + // individual writes, but in some contexts it refers to all writes (e.g. including group writes) + arced_resource_writes: Vec< + CachePadded, Option>)>>>, + >, // Record all writes and reads to access paths corresponding to modules (code) in any // (speculative) executions. Used to avoid a potential race with module publishing and @@ -80,6 +102,9 @@ impl, E: Debug + Send + Clone> outputs: (0..num_txns) .map(|_| CachePadded::new(ArcSwapOption::empty())) .collect(), + arced_resource_writes: (0..num_txns) + .map(|_| CachePadded::new(ExplicitSyncWrapper::>::new(vec![]))) + .collect(), finalized_groups: (0..num_txns) .map(|_| CachePadded::new(ExplicitSyncWrapper::>::new(vec![]))) .collect(), @@ -121,6 +146,7 @@ impl, E: Debug + Send + Clone> txn_idx: TxnIndex, input: CapturedReads, output: ExecutionStatus>, + arced_resource_writes: Vec<(T::Key, Arc, Option>)>, ) -> bool { let written_modules = match &output { ExecutionStatus::Success(output) | ExecutionStatus::SkipRest(output) => { @@ -137,6 +163,7 @@ impl, E: Debug + Send + Clone> return false; } + *self.arced_resource_writes[txn_idx as usize].acquire() = arced_resource_writes; self.inputs[txn_idx as usize].store(Some(Arc::new(input))); self.outputs[txn_idx as usize].store(Some(Arc::new(TxnOutput::from_output_status(output)))); @@ -235,7 +262,7 @@ impl, E: Debug + Send + Clone> output_status: ExecutionStatus::SkipRest(output), }))); } else { - unreachable!("Unexpected status"); + unreachable!("Unexpected status, must be Success"); } } @@ -255,9 +282,14 @@ impl, E: Debug + Send + Clone> ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => Some( t.resource_write_set() .into_iter() - .map(|(k, _)| k) + .map(|(k, _, _)| k) .chain(t.aggregator_v1_write_set().into_keys()) - .chain(t.aggregator_v1_delta_set().into_keys()) + .chain( + t.aggregator_v1_delta_set() + .into_iter() + .map(|(k, _)| k) + .collect::>(), + ) .map(|k| (k, KeyKind::Resource)) .chain( t.module_write_set() @@ -276,22 +308,6 @@ impl, E: Debug + Send + Clone> }) } - pub(crate) fn resource_write_set( - &self, - txn_idx: TxnIndex, - ) -> Option>))>> { - self.outputs[txn_idx as usize] - .load_full() - .and_then(|txn_output| match &txn_output.output_status { - ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => { - Some(t.resource_write_set()) - }, - ExecutionStatus::Abort(_) - | ExecutionStatus::SpeculativeExecutionAbortError(_) - | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => None, - }) - } - pub(crate) fn delayed_field_keys( &self, txn_idx: TxnIndex, @@ -312,63 +328,26 @@ impl, E: Debug + Send + Clone> pub(crate) fn reads_needing_delayed_field_exchange( &self, txn_idx: TxnIndex, - ) -> Option)>> { - self.outputs[txn_idx as usize] - .load() - .as_ref() - .and_then(|txn_output| match &txn_output.output_status { - ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => { - Some(t.reads_needing_delayed_field_exchange()) - }, - ExecutionStatus::Abort(_) - | ExecutionStatus::SpeculativeExecutionAbortError(_) - | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => None, - }) + ) -> Vec<(T::Key, StateValueMetadata, Arc)> { + forward_on_success_or_skip_rest!(self, txn_idx, reads_needing_delayed_field_exchange) } pub(crate) fn group_reads_needing_delayed_field_exchange( &self, txn_idx: TxnIndex, - ) -> Option> { - self.outputs[txn_idx as usize] - .load() - .as_ref() - .and_then(|txn_output| match &txn_output.output_status { - ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => { - Some(t.group_reads_needing_delayed_field_exchange()) - }, - ExecutionStatus::Abort(_) - | ExecutionStatus::SpeculativeExecutionAbortError(_) - | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => None, - }) + ) -> Vec<(T::Key, StateValueMetadata)> { + forward_on_success_or_skip_rest!(self, txn_idx, group_reads_needing_delayed_field_exchange) } pub(crate) fn aggregator_v1_delta_keys(&self, txn_idx: TxnIndex) -> Vec { - self.outputs[txn_idx as usize].load().as_ref().map_or( - vec![], - |txn_output| match &txn_output.output_status { - ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => { - t.aggregator_v1_delta_set().into_keys().collect() - }, - ExecutionStatus::Abort(_) - | ExecutionStatus::SpeculativeExecutionAbortError(_) - | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => vec![], - }, - ) + forward_on_success_or_skip_rest!(self, txn_idx, aggregator_v1_delta_set) + .into_iter() + .map(|(k, _)| k) + .collect() } - pub(crate) fn group_metadata_ops(&self, txn_idx: TxnIndex) -> Vec<(T::Key, T::Value)> { - self.outputs[txn_idx as usize].load().as_ref().map_or( - vec![], - |txn_output| match &txn_output.output_status { - ExecutionStatus::Success(t) | ExecutionStatus::SkipRest(t) => { - t.resource_group_metadata_ops() - }, - ExecutionStatus::Abort(_) - | ExecutionStatus::SpeculativeExecutionAbortError(_) - | ExecutionStatus::DelayedFieldsCodeInvariantError(_) => vec![], - }, - ) + pub(crate) fn resource_group_metadata_ops(&self, txn_idx: TxnIndex) -> Vec<(T::Key, T::Value)> { + forward_on_success_or_skip_rest!(self, txn_idx, resource_group_metadata_ops) } pub(crate) fn events( @@ -406,6 +385,13 @@ impl, E: Debug + Send + Clone> std::mem::take(&mut self.finalized_groups[txn_idx as usize].acquire()) } + pub(crate) fn take_resource_write_set( + &self, + txn_idx: TxnIndex, + ) -> Vec<(T::Key, Arc, Option>)> { + std::mem::take(&mut self.arced_resource_writes[txn_idx as usize].acquire()) + } + // Called when a transaction is committed to record WriteOps for materialized aggregator values // corresponding to the (deltas) in the recorded final output of the transaction, as well as // finalized group updates. diff --git a/aptos-move/block-executor/src/unit_tests/mod.rs b/aptos-move/block-executor/src/unit_tests/mod.rs index 60d1d9c25a8c4..7501f7f52f727 100644 --- a/aptos-move/block-executor/src/unit_tests/mod.rs +++ b/aptos-move/block-executor/src/unit_tests/mod.rs @@ -106,7 +106,7 @@ fn resource_group_bcs_fallback() { assert!(!txn_outputs[2].writes.is_empty()); assert!(!txn_outputs[1].group_writes.is_empty()); }, - Err(_) => unreachable!("Must succeed: failpoint not yet set up"), + Err(e) => unreachable!("Must succeed, but {:?}: failpoint not yet set up", e), }; // Set up and sanity check failpoint. diff --git a/aptos-move/block-executor/src/value_exchange.rs b/aptos-move/block-executor/src/value_exchange.rs new file mode 100644 index 0000000000000..d9a7bec95094d --- /dev/null +++ b/aptos-move/block-executor/src/value_exchange.rs @@ -0,0 +1,216 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use crate::view::{LatestView, ViewState}; +use aptos_aggregator::{ + resolver::TDelayedFieldView, + types::{ + code_invariant_error, DelayedFieldValue, PanicError, ReadPosition, TryFromMoveValue, + TryIntoMoveValue, + }, +}; +use aptos_mvhashmap::{types::TxnIndex, versioned_delayed_fields::TVersionedDelayedFieldView}; +use aptos_types::{ + executable::Executable, + state_store::{state_value::StateValueMetadata, TStateView}, + transaction::BlockExecutableTransaction as Transaction, + write_set::TransactionWrite, +}; +use bytes::Bytes; +use move_core_types::value::{IdentifierMappingKind, MoveTypeLayout}; +use move_vm_types::{ + value_transformation::{ + deserialize_and_replace_values_with_ids, TransformationError, TransformationResult, + ValueToIdentifierMapping, + }, + values::Value, +}; +use std::{cell::RefCell, collections::HashSet, sync::Arc}; + +pub(crate) struct TemporaryValueToIdentifierMapping< + 'a, + T: Transaction, + S: TStateView, + X: Executable, +> { + latest_view: &'a LatestView<'a, T, S, X>, + txn_idx: TxnIndex, + // These are the delayed field keys that were touched when utilizing this mapping + // to replace ids with values or values with ids + delayed_field_ids: RefCell>, +} + +impl<'a, T: Transaction, S: TStateView, X: Executable> + TemporaryValueToIdentifierMapping<'a, T, S, X> +{ + pub fn new(latest_view: &'a LatestView<'a, T, S, X>, txn_idx: TxnIndex) -> Self { + Self { + latest_view, + txn_idx, + delayed_field_ids: RefCell::new(HashSet::new()), + } + } + + fn generate_delayed_field_id(&self, width: u32) -> T::Identifier { + self.latest_view.generate_delayed_field_id(width) + } + + pub fn into_inner(self) -> HashSet { + self.delayed_field_ids.into_inner() + } +} + +// For aggregators V2, values are replaced with identifiers at deserialization time, +// and are replaced back when the value is serialized. The "lifted" values are cached +// by the `LatestView` in the aggregators multi-version data structure. +impl<'a, T: Transaction, S: TStateView, X: Executable> ValueToIdentifierMapping + for TemporaryValueToIdentifierMapping<'a, T, S, X> +{ + fn value_to_identifier( + &self, + kind: &IdentifierMappingKind, + layout: &MoveTypeLayout, + value: Value, + ) -> TransformationResult { + let (base_value, width) = DelayedFieldValue::try_from_move_value(layout, value, kind)?; + let id = self.generate_delayed_field_id(width); + match &self.latest_view.latest_view { + ViewState::Sync(state) => state.set_delayed_field_value(id, base_value), + ViewState::Unsync(state) => { + state.set_delayed_field_value(id, base_value); + }, + }; + self.delayed_field_ids.borrow_mut().insert(id); + id.try_into_move_value(layout) + .map_err(|e| TransformationError(format!("{:?}", e))) + } + + fn identifier_to_value( + &self, + layout: &MoveTypeLayout, + identifier_value: Value, + ) -> TransformationResult { + let (id, width) = T::Identifier::try_from_move_value(layout, identifier_value, &()) + .map_err(|e| TransformationError(format!("{:?}", e)))?; + self.delayed_field_ids.borrow_mut().insert(id); + Ok(match &self.latest_view.latest_view { + ViewState::Sync(state) => state + .versioned_map + .delayed_fields() + .read_latest_committed_value(&id, self.txn_idx, ReadPosition::AfterCurrentTxn) + .expect("Committed value for ID must always exist"), + ViewState::Unsync(state) => state + .read_delayed_field(id) + .expect("Delayed field value for ID must always exist in sequential execution"), + } + .try_into_move_value(layout, width)?) + } +} + +struct TemporaryExtractIdentifiersMapping { + // These are the delayed field keys that were touched when utilizing this mapping + // to replace ids with values or values with ids + delayed_field_ids: RefCell>, +} + +impl TemporaryExtractIdentifiersMapping { + pub fn new() -> Self { + Self { + delayed_field_ids: RefCell::new(HashSet::new()), + } + } + + pub fn into_inner(self) -> HashSet { + self.delayed_field_ids.into_inner() + } +} + +impl ValueToIdentifierMapping for TemporaryExtractIdentifiersMapping { + fn value_to_identifier( + &self, + _kind: &IdentifierMappingKind, + layout: &MoveTypeLayout, + value: Value, + ) -> TransformationResult { + let (id, _) = T::Identifier::try_from_move_value(layout, value, &()) + .map_err(|e| TransformationError(format!("{:?}", e)))?; + self.delayed_field_ids.borrow_mut().insert(id); + id.try_into_move_value(layout) + .map_err(|e| TransformationError(format!("{:?}", e))) + } + + fn identifier_to_value( + &self, + layout: &MoveTypeLayout, + identifier_value: Value, + ) -> TransformationResult { + let (id, _) = T::Identifier::try_from_move_value(layout, identifier_value, &()) + .map_err(|e| TransformationError(format!("{:?}", e)))?; + self.delayed_field_ids.borrow_mut().insert(id); + id.try_into_move_value(layout) + .map_err(|e| TransformationError(format!("{:?}", e))) + } +} + +// Given a Bytes, where values were already exchanged with identifiers, +// return a list of identifiers present in it. +// TODO[agg_v2](cleanup): store list of identifiers with the exchanged value (like layout), +// and remove this method. +fn extract_identifiers_from_value( + bytes: &Bytes, + layout: &MoveTypeLayout, +) -> Result, PanicError> { + let mapping = TemporaryExtractIdentifiersMapping::::new(); + // TODO[agg_v2](cleanup) rename deserialize_and_replace_values_with_ids to not be specific + // to mapping trait implementation. + let _patched_value = deserialize_and_replace_values_with_ids(bytes.as_ref(), layout, &mapping) + .ok_or_else(|| { + code_invariant_error("Failed to deserialize a value to extract identifiers") + })?; + Ok(mapping.into_inner()) +} + +// Deletion returns a PanicError. +pub(crate) fn does_value_need_exchange( + value: &T::Value, + layout: &MoveTypeLayout, + delayed_write_set_ids: &HashSet, +) -> Result { + if let Some(bytes) = value.bytes() { + extract_identifiers_from_value::(bytes, layout) + .map(|identifiers_in_read| !delayed_write_set_ids.is_disjoint(&identifiers_in_read)) + } else { + // Deletion returns an error. + Err(code_invariant_error( + "Delete shouldn't be in values considered for exchange", + )) + } +} + +// Exclude deletions, and values that do not contain any delayed field IDs that were written to. +pub(crate) fn filter_value_for_exchange( + value: &T::Value, + layout: &Arc, + delayed_write_set_ids: &HashSet, + key: &T::Key, +) -> Option)), PanicError>> { + if value.is_deletion() { + None + } else { + does_value_need_exchange::(value, layout, delayed_write_set_ids).map_or_else( + |e| Some(Err(e)), + |needs_exchange| { + needs_exchange.then(|| { + Ok(( + key.clone(), + ( + value.as_state_value_metadata().unwrap().clone(), + value.write_op_size().write_len().unwrap(), + layout.clone(), + ), + )) + }) + }, + ) + } +} diff --git a/aptos-move/block-executor/src/view.rs b/aptos-move/block-executor/src/view.rs index b14973296e8ea..e5b7a78f2d672 100644 --- a/aptos-move/block-executor/src/view.rs +++ b/aptos-move/block-executor/src/view.rs @@ -10,6 +10,9 @@ use crate::{ }, counters, scheduler::{DependencyResult, DependencyStatus, Scheduler, TWaitForDependency}, + value_exchange::{ + does_value_need_exchange, filter_value_for_exchange, TemporaryValueToIdentifierMapping, + }, }; use aptos_aggregator::{ bounded_math::{ok_overflow, BoundedMath, SignedU128}, @@ -18,7 +21,7 @@ use aptos_aggregator::{ resolver::{TAggregatorV1View, TDelayedFieldView}, types::{ code_invariant_error, expect_ok, DelayedFieldValue, DelayedFieldsSpeculativeError, PanicOr, - ReadPosition, TryFromMoveValue, TryIntoMoveValue, + ReadPosition, }, }; use aptos_logger::error; @@ -51,14 +54,10 @@ use aptos_vm_types::resolver::{ use bytes::Bytes; use claims::assert_ok; use move_binary_format::errors::{PartialVMError, PartialVMResult}; -use move_core_types::{ - value::{IdentifierMappingKind, MoveTypeLayout}, - vm_status::StatusCode, -}; +use move_core_types::{value::MoveTypeLayout, vm_status::StatusCode}; use move_vm_types::{ value_transformation::{ deserialize_and_replace_values_with_ids, serialize_and_replace_ids_with_values, - TransformationError, TransformationResult, ValueToIdentifierMapping, }, values::Value, }; @@ -156,7 +155,7 @@ trait ResourceGroupState { } pub(crate) struct ParallelState<'a, T: Transaction, X: Executable> { - versioned_map: &'a MVHashMap, + pub(crate) versioned_map: &'a MVHashMap, scheduler: &'a Scheduler, start_counter: u32, counter: &'a AtomicU32, @@ -453,7 +452,7 @@ impl<'a, T: Transaction, X: Executable> ParallelState<'a, T, X> { } } - fn set_delayed_field_value(&self, id: T::Identifier, base_value: DelayedFieldValue) { + pub(crate) fn set_delayed_field_value(&self, id: T::Identifier, base_value: DelayedFieldValue) { self.versioned_map .delayed_fields() .set_base_value(id, base_value) @@ -777,11 +776,11 @@ impl<'a, T: Transaction, X: Executable> SequentialState<'a, T, X> { } } - fn set_delayed_field_value(&self, id: T::Identifier, base_value: DelayedFieldValue) { + pub(crate) fn set_delayed_field_value(&self, id: T::Identifier, base_value: DelayedFieldValue) { self.unsync_map.write_delayed_field(id, base_value) } - fn read_delayed_field(&self, id: T::Identifier) -> Option { + pub(crate) fn read_delayed_field(&self, id: T::Identifier) -> Option { self.unsync_map.fetch_delayed_field(&id) } } @@ -948,7 +947,7 @@ impl<'a, T: Transaction, X: Executable> ViewState<'a, T, X> { /// must be set according to the latest transaction that the worker was / is executing. pub(crate) struct LatestView<'a, T: Transaction, S: TStateView, X: Executable> { base_view: &'a S, - latest_view: ViewState<'a, T, X>, + pub(crate) latest_view: ViewState<'a, T, X>, txn_idx: TxnIndex, } @@ -1115,88 +1114,35 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< Ok((patched_bytes, mapping.into_inner())) } - // Given a bytes, where values were already exchanged with idnetifiers, - // return a list of identifiers present in it. - fn extract_identifiers_from_value( - &self, - bytes: &Bytes, - layout: &MoveTypeLayout, - ) -> anyhow::Result> { - let mapping = TemporaryExtractIdentifiersMapping::::new(); - // TODO[agg_v2](cleanup) rename deserialize_and_replace_values_with_ids to not be specific to mapping trait implementation - // TODO[agg_v2](cleanup) provide traversal method, that doesn't create unnecessary patched value. - let _patched_value = - deserialize_and_replace_values_with_ids(bytes.as_ref(), layout, &mapping).ok_or_else( - || anyhow::anyhow!("Failed to deserialize resource during id replacement"), - )?; - Ok(mapping.into_inner()) - } - - fn does_value_need_exchange( - &self, - value: &T::Value, - layout: &Arc, - delayed_write_set_keys: &HashSet, - key: &T::Key, - ) -> Option)), PanicError>> { - if let Some(bytes) = value.bytes() { - let identifiers_in_read_result = self.extract_identifiers_from_value(bytes, layout); - - match identifiers_in_read_result { - Ok(identifiers_in_read) => { - if !delayed_write_set_keys.is_disjoint(&identifiers_in_read) { - return Some(Ok((key.clone(), (value.clone(), layout.clone())))); - } - }, - Err(e) => { - return Some(Err(code_invariant_error(format!("Cannot extract identifiers from value that identifiers were exchanged into before {:?}", e)))) - } - } - } - None - } - - fn get_reads_needing_exchange_parallel( - &self, - read_set: &CapturedReads, - delayed_write_set_keys: &HashSet, - skip: &HashSet, - ) -> Result)>, PanicError> { - read_set - .get_read_values_with_delayed_fields() - .filter(|(key, _)| !skip.contains(key)) - .flat_map(|(key, data_read)| { - if let DataRead::Versioned(_version, value, Some(layout)) = data_read { - return self.does_value_need_exchange( - value, - layout, - delayed_write_set_keys, - key, - ); - } - None - }) - .collect() - } - fn get_reads_needing_exchange_sequential( &self, read_set: &HashSet, unsync_map: &UnsyncMap, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result)>, PanicError> { + ) -> Result)>, PanicError> { read_set .iter() - .filter(|key| !skip.contains(key)) - .flat_map(|key| match unsync_map.fetch_data(key) { - Some(ValueWithLayout::Exchanged(value, Some(layout))) => self - .does_value_need_exchange(value.as_ref(), &layout, delayed_write_set_keys, key), - Some(ValueWithLayout::Exchanged(_, None)) => None, - Some(ValueWithLayout::RawFromStorage(_)) => Some(Err(code_invariant_error( - "Cannot exchange value that was not exchanged before", - ))), - None => None, + .filter_map(|key| { + if skip.contains(key) { + return None; + } + + match unsync_map.fetch_data(key) { + Some(ValueWithLayout::Exchanged(value, Some(layout))) => { + filter_value_for_exchange::( + value.as_ref(), + &layout, + delayed_write_set_ids, + key, + ) + }, + Some(ValueWithLayout::Exchanged(_, None)) => None, + Some(ValueWithLayout::RawFromStorage(_)) => Some(Err(code_invariant_error( + "Cannot exchange value that was not exchanged before", + ))), + None => None, + } }) .collect() } @@ -1204,9 +1150,9 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< fn get_group_reads_needing_exchange_parallel( &self, parallel_state: &ParallelState<'a, T, X>, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { let reads_with_delayed_fields = parallel_state .captured_reads .borrow() @@ -1218,18 +1164,27 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< .into_iter() .flat_map(|(key, group_read)| { let GroupRead { inner_reads, .. } = group_read; + + // TODO[agg_v2](clean-up): Once ids can be extracted without possible failure, + // the following is just an any call on iterator (same for resource reads). let mut resources_needing_delayed_field_exchange = false; for data_read in inner_reads.values() { if let DataRead::Versioned(_version, value, Some(layout)) = data_read { - if let Some(bytes) = value.bytes() { - let identifiers_in_read = self - .extract_identifiers_from_value(bytes, layout.as_ref()) - .unwrap(); - if !delayed_write_set_keys.is_disjoint(&identifiers_in_read) { - // TODO[agg_v2](optimize): Is it possible to avoid clones here? - resources_needing_delayed_field_exchange = true; - break; - } + // TODO[agg_v2](optimize): Is it possible to avoid clones here? + match does_value_need_exchange::( + value, + layout.as_ref(), + delayed_write_set_ids, + ) { + Ok(needs_exchange) => { + if needs_exchange { + resources_needing_delayed_field_exchange = true; + break; + } + }, + Err(e) => { + return Some(Err(e)); + }, } } } @@ -1238,20 +1193,18 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< } if let Ok(Some(metadata)) = self.get_resource_state_value_metadata(&key) { - let metadata = Some(StateValue::new_with_metadata(Bytes::new(), metadata)); - if let Ok(GroupReadResult::Size(group_size)) = - parallel_state.read_group_size(&key, self.txn_idx) - { - let metadata_op: T::Value = TransactionWrite::from_state_value(metadata); - if let Some(metadata_op) = metadata_op.convert_read_to_modification() { - return Some(Ok((key.clone(), (metadata_op, group_size.get())))); - } - } else { - return Some(Err(code_invariant_error(format!( - "Cannot compute metadata op size for the group read {:?}", - key - )))); - } + return Some( + if let Ok(GroupReadResult::Size(group_size)) = + parallel_state.read_group_size(&key, self.txn_idx) + { + Ok((key.clone(), (metadata, group_size.get()))) + } else { + Err(code_invariant_error(format!( + "Cannot compute metadata op size for the group read {:?}", + key + ))) + }, + ); } Some(Err(code_invariant_error(format!( "Cannot compute metadata op for the group read {:?}", @@ -1265,9 +1218,9 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< &self, group_read_set: &HashMap>, unsync_map: &UnsyncMap, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { group_read_set .iter() .filter(|(key, _tags)| !skip.contains(key)) @@ -1280,18 +1233,21 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< if let ValueWithLayout::Exchanged(value, Some(layout)) = value_with_layout { - if let Some(bytes) = value.bytes() { - let identifiers_in_read = self - .extract_identifiers_from_value(bytes, layout.as_ref()) - .unwrap(); - if !delayed_write_set_keys.is_disjoint(&identifiers_in_read) { - resources_needing_delayed_field_exchange = true; - break; - } - } else { - return Some(Err(code_invariant_error( - "Delete shouldn't be in get_group_reads_needing_exchange_sequential", - ))); + // TODO[agg_v2](optimize): Is it possible to avoid clones here? + match does_value_need_exchange::( + &value, + layout.as_ref(), + delayed_write_set_ids, + ) { + Ok(needs_exchange) => { + if needs_exchange { + resources_needing_delayed_field_exchange = true; + break; + } + }, + Err(e) => { + return Some(Err(e)); + }, } } } @@ -1299,16 +1255,11 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> LatestView< if !resources_needing_delayed_field_exchange { return None; } - if let Some(metadata) = unsync_map.fetch_data(key) { + if let Ok(Some(metadata)) = self.get_resource_state_value_metadata(key) { if let Ok(GroupReadResult::Size(group_size)) = unsync_map.get_group_size(key) { - if let Some(metadata_op) = metadata - .extract_value_no_layout() - .convert_read_to_modification() - { - return Some(Ok((key.clone(), (metadata_op, group_size.get())))); - } + return Some(Ok((key.clone(), (metadata, group_size.get())))); } else { // TODO[agg_v2](fix): `get_group_size` can fail on group tag serialization. Do // we want to propagate this error? This is somewhat an invariant @@ -1651,7 +1602,6 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TDelayedFie type Identifier = T::Identifier; type ResourceGroupTag = T::Tag; type ResourceKey = T::Key; - type ResourceValue = T::Value; fn is_delayed_field_optimization_capable(&self) -> bool { match &self.latest_view { @@ -1767,34 +1717,25 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TDelayedFie Ok(result) } - // TODO[agg_v2](cleanup) - update comment. - // For each resource that satisfies the following conditions, - // 1. Resource is in read set - // 2. Resource is not in write set - // replace the delayed field identifiers in the resource with corresponding values. - // If any of the delayed field identifiers in the resource are part of delayed_field_write_set, - // then include the resource in the write set. fn get_reads_needing_exchange( &self, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result)>, PanicError> - { + ) -> Result< + BTreeMap)>, + PanicError, + > { match &self.latest_view { - ViewState::Sync(state) => { - let captured_reads = state.captured_reads.borrow(); - self.get_reads_needing_exchange_parallel( - &captured_reads, - delayed_write_set_keys, - skip, - ) - }, + ViewState::Sync(state) => state + .captured_reads + .borrow() + .get_read_values_with_delayed_fields(delayed_write_set_ids, skip), ViewState::Unsync(state) => { let read_set = state.read_set.borrow(); self.get_reads_needing_exchange_sequential( &read_set.resource_reads, state.unsync_map, - delayed_write_set_keys, + delayed_write_set_ids, skip, ) }, @@ -1803,19 +1744,19 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TDelayedFie fn get_group_reads_needing_exchange( &self, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet, - ) -> Result, PanicError> { + ) -> Result, PanicError> { match &self.latest_view { ViewState::Sync(state) => { - self.get_group_reads_needing_exchange_parallel(state, delayed_write_set_keys, skip) + self.get_group_reads_needing_exchange_parallel(state, delayed_write_set_ids, skip) }, ViewState::Unsync(state) => { let read_set = state.read_set.borrow(); self.get_group_reads_needing_exchange_sequential( &read_set.group_reads, state.unsync_map, - delayed_write_set_keys, + delayed_write_set_ids, skip, ) }, @@ -1823,131 +1764,6 @@ impl<'a, T: Transaction, S: TStateView, X: Executable> TDelayedFie } } -struct TemporaryValueToIdentifierMapping< - 'a, - T: Transaction, - S: TStateView, - X: Executable, -> { - latest_view: &'a LatestView<'a, T, S, X>, - txn_idx: TxnIndex, - // These are the delayed field keys that were touched when utilizing this mapping - // to replace ids with values or values with ids - delayed_field_keys: RefCell>, -} - -impl<'a, T: Transaction, S: TStateView, X: Executable> - TemporaryValueToIdentifierMapping<'a, T, S, X> -{ - pub fn new(latest_view: &'a LatestView<'a, T, S, X>, txn_idx: TxnIndex) -> Self { - Self { - latest_view, - txn_idx, - delayed_field_keys: RefCell::new(HashSet::new()), - } - } - - fn generate_delayed_field_id(&self, width: u32) -> T::Identifier { - self.latest_view.generate_delayed_field_id(width) - } - - pub fn into_inner(self) -> HashSet { - self.delayed_field_keys.into_inner() - } -} - -// For aggregators V2, values are replaced with identifiers at deserialization time, -// and are replaced back when the value is serialized. The "lifted" values are cached -// by the `LatestView` in the aggregators multi-version data structure. -impl<'a, T: Transaction, S: TStateView, X: Executable> ValueToIdentifierMapping - for TemporaryValueToIdentifierMapping<'a, T, S, X> -{ - fn value_to_identifier( - &self, - kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - value: Value, - ) -> TransformationResult { - let (base_value, width) = DelayedFieldValue::try_from_move_value(layout, value, kind)?; - let id = self.generate_delayed_field_id(width); - match &self.latest_view.latest_view { - ViewState::Sync(state) => state.set_delayed_field_value(id, base_value), - ViewState::Unsync(state) => { - state.set_delayed_field_value(id, base_value); - }, - }; - self.delayed_field_keys.borrow_mut().insert(id); - id.try_into_move_value(layout) - .map_err(|e| TransformationError(format!("{:?}", e))) - } - - fn identifier_to_value( - &self, - layout: &MoveTypeLayout, - identifier_value: Value, - ) -> TransformationResult { - let (id, width) = T::Identifier::try_from_move_value(layout, identifier_value, &()) - .map_err(|e| TransformationError(format!("{:?}", e)))?; - self.delayed_field_keys.borrow_mut().insert(id); - Ok(match &self.latest_view.latest_view { - ViewState::Sync(state) => state - .versioned_map - .delayed_fields() - .read_latest_committed_value(&id, self.txn_idx, ReadPosition::AfterCurrentTxn) - .expect("Committed value for ID must always exist"), - ViewState::Unsync(state) => state - .read_delayed_field(id) - .expect("Delayed field value for ID must always exist in sequential execution"), - } - .try_into_move_value(layout, width)?) - } -} - -struct TemporaryExtractIdentifiersMapping { - // These are the delayed field keys that were touched when utilizing this mapping - // to replace ids with values or values with ids - delayed_field_keys: RefCell>, -} - -impl TemporaryExtractIdentifiersMapping { - pub fn new() -> Self { - Self { - delayed_field_keys: RefCell::new(HashSet::new()), - } - } - - pub fn into_inner(self) -> HashSet { - self.delayed_field_keys.into_inner() - } -} - -impl ValueToIdentifierMapping for TemporaryExtractIdentifiersMapping { - fn value_to_identifier( - &self, - _kind: &IdentifierMappingKind, - layout: &MoveTypeLayout, - value: Value, - ) -> TransformationResult { - let (id, _) = T::Identifier::try_from_move_value(layout, value, &()) - .map_err(|e| TransformationError(format!("{:?}", e)))?; - self.delayed_field_keys.borrow_mut().insert(id); - id.try_into_move_value(layout) - .map_err(|e| TransformationError(format!("{:?}", e))) - } - - fn identifier_to_value( - &self, - layout: &MoveTypeLayout, - identifier_value: Value, - ) -> TransformationResult { - let (id, _) = T::Identifier::try_from_move_value(layout, identifier_value, &()) - .map_err(|e| TransformationError(format!("{:?}", e)))?; - self.delayed_field_keys.borrow_mut().insert(id); - id.try_into_move_value(layout) - .map_err(|e| TransformationError(format!("{:?}", e))) - } -} - #[cfg(test)] mod test { // @@ -2991,25 +2807,28 @@ mod test { fn get_reads_needing_exchange( &self, - delayed_write_set_keys: &HashSet, + delayed_write_set_ids: &HashSet, skip: &HashSet>, - ) -> Result, (ValueType, Arc)>, PanicError> { + ) -> Result< + BTreeMap, (StateValueMetadata, u64, Arc)>, + PanicError, + > { let seq = self .latest_view_seq - .get_reads_needing_exchange(delayed_write_set_keys, skip); + .get_reads_needing_exchange(delayed_write_set_ids, skip); let par = self .latest_view_par - .get_reads_needing_exchange(delayed_write_set_keys, skip); + .get_reads_needing_exchange(delayed_write_set_ids, skip); self.assert_res_eq( seq.as_ref().map(|m| { m.iter() - .map(|(k, (v, l))| (*k, (v.as_state_value(), l.clone()))) + .map(|(k, (metadata, size, layout))| (*k, (metadata, size, layout.clone()))) .collect::>() }), par.as_ref().map(|m| { m.iter() - .map(|(k, (v, l))| (*k, (v.as_state_value(), l.clone()))) + .map(|(k, (metadata, size, layout))| (*k, (metadata, size, layout.clone()))) .collect::>() }), ) @@ -3232,14 +3051,16 @@ mod test { let captured_reads = views.latest_view_par.take_parallel_reads(); assert!(captured_reads.validate_data_reads(holder.versioned_map.data(), 1)); - let read_set_with_delayed_fields = captured_reads.get_read_values_with_delayed_fields(); + // TODO(aggr_v2): what's up with this test case? + let _read_set_with_delayed_fields = + captured_reads.get_read_values_with_delayed_fields(&HashSet::new(), &HashSet::new()); // TODO[agg_v2](fix): This prints // read: (KeyType(4, false), Versioned(Err(StorageVersion), Some(Struct(Runtime([Struct(Runtime([Tagged(IdentifierMapping(Aggregator), U64), U64]))]))))) // read: (KeyType(2, false), Versioned(Err(StorageVersion), Some(Struct(Runtime([Struct(Runtime([Tagged(IdentifierMapping(Aggregator), U64), U64]))]))))) - for read in read_set_with_delayed_fields { - println!("read: {:?}", read); - } + // for read in read_set_with_delayed_fields { + // println!("read: {:?}", read); + // } // TODO[agg_v2](fix): This assertion fails. // let data_read = DataRead::Versioned(Ok((1,0)), Arc::new(TransactionWrite::from_state_value(Some(state_value_4))), Some(Arc::new(layout))); diff --git a/aptos-move/e2e-move-tests/src/aggregator_v2.rs b/aptos-move/e2e-move-tests/src/aggregator_v2.rs index c0f9fa33e5173..f086ee1339628 100644 --- a/aptos-move/e2e-move-tests/src/aggregator_v2.rs +++ b/aptos-move/e2e-move-tests/src/aggregator_v2.rs @@ -45,7 +45,7 @@ pub fn initialize_enabled_disabled_comparison( let mut agg_harness = AggV2TestHarness { harness: harness_base, - comparison_harnesses: vec![harness_comp], + comparison_harnesses: vec![(harness_comp, "aggregator_execution_enabled".to_string())], account: account_base, txn_accounts: vec![], txn_index: 0, @@ -87,7 +87,7 @@ fn initialize_harness( pub struct AggV2TestHarness { pub harness: MoveHarness, - pub comparison_harnesses: Vec, + pub comparison_harnesses: Vec<(MoveHarness, String)>, pub account: Account, pub txn_accounts: Vec, pub txn_index: usize, @@ -179,14 +179,9 @@ impl AggV2TestHarness { .harness .run_block_in_parts_and_check(block_split, txn_block.clone()); - for (idx, h) in self.comparison_harnesses.iter_mut().enumerate() { + for (h, name) in self.comparison_harnesses.iter_mut() { let new_result = h.run_block_in_parts_and_check(block_split, txn_block.clone()); - assert_outputs_equal( - &result, - "baseline", - &new_result, - &format!("comparison {}", idx), - ); + assert_outputs_equal(&result, "baseline", &new_result, name); } } @@ -204,7 +199,7 @@ impl AggV2TestHarness { let result = self.harness.store_and_fund_account(&acc, balance, seq_num); - for h in self.comparison_harnesses.iter_mut() { + for (h, _name) in self.comparison_harnesses.iter_mut() { h.store_and_fund_account(&acc, balance, seq_num); } diff --git a/aptos-move/framework/src/natives/aggregator_natives/context.rs b/aptos-move/framework/src/natives/aggregator_natives/context.rs index aa20f28b322a0..7b9ab4a0fe976 100644 --- a/aptos-move/framework/src/natives/aggregator_natives/context.rs +++ b/aptos-move/framework/src/natives/aggregator_natives/context.rs @@ -11,7 +11,8 @@ use aptos_aggregator::{ types::DelayedFieldID, }; use aptos_types::{ - delayed_fields::PanicError, state_store::state_key::StateKey, write_set::WriteOp, + delayed_fields::PanicError, + state_store::{state_key::StateKey, state_value::StateValueMetadata}, }; use better_any::{Tid, TidAble}; use move_core_types::value::MoveTypeLayout; @@ -38,8 +39,8 @@ pub enum AggregatorChangeV1 { pub struct AggregatorChangeSet { pub aggregator_v1_changes: BTreeMap, pub delayed_field_changes: BTreeMap>, - pub reads_needing_exchange: BTreeMap)>, - pub group_reads_needing_exchange: BTreeMap, + pub reads_needing_exchange: BTreeMap)>, + pub group_reads_needing_exchange: BTreeMap, } /// Native context that can be attached to VM `NativeContextExtensions`. @@ -116,7 +117,7 @@ impl<'a> NativeAggregatorContext<'a> { } let delayed_field_changes = delayed_field_data.into_inner().into(); - let delayed_write_set_keys = delayed_field_changes + let delayed_write_set_ids = delayed_field_changes .keys() .cloned() .collect::>(); @@ -126,17 +127,17 @@ impl<'a> NativeAggregatorContext<'a> { // is_empty check covers both whether delayed fields are enabled or not, as well as whether there // are any changes that would require computing reads needing exchange. // TODO[agg_v2](optimize) we only later compute the the write set, so cannot pass the correct skip values here. - reads_needing_exchange: if delayed_write_set_keys.is_empty() { + reads_needing_exchange: if delayed_write_set_ids.is_empty() { BTreeMap::new() } else { self.delayed_field_resolver - .get_reads_needing_exchange(&delayed_write_set_keys, &HashSet::new())? + .get_reads_needing_exchange(&delayed_write_set_ids, &HashSet::new())? }, - group_reads_needing_exchange: if delayed_write_set_keys.is_empty() { + group_reads_needing_exchange: if delayed_write_set_ids.is_empty() { BTreeMap::new() } else { self.delayed_field_resolver - .get_group_reads_needing_exchange(&delayed_write_set_keys, &HashSet::new())? + .get_group_reads_needing_exchange(&delayed_write_set_ids, &HashSet::new())? }, }) } diff --git a/aptos-move/mvhashmap/src/types.rs b/aptos-move/mvhashmap/src/types.rs index 9ab180e67923d..c5c8b0938e541 100644 --- a/aptos-move/mvhashmap/src/types.rs +++ b/aptos-move/mvhashmap/src/types.rs @@ -364,17 +364,10 @@ pub(crate) mod test { fn set_bytes(&mut self, bytes: Bytes) { self.bytes = bytes; } - - fn convert_read_to_modification(&self) -> Option - where - Self: Sized, - { - Some(self.clone()) - } } // Generate a Vec deterministically based on txn_idx and incarnation. - pub(crate) fn value_for(txn_idx: TxnIndex, incarnation: Incarnation) -> TestValue { + fn value_for(txn_idx: TxnIndex, incarnation: Incarnation) -> TestValue { TestValue::new(vec![txn_idx * 5, txn_idx + incarnation, incarnation * 5]) } diff --git a/aptos-move/mvhashmap/src/unit_tests/mod.rs b/aptos-move/mvhashmap/src/unit_tests/mod.rs index b0da112a956ca..728c3d4adc7c9 100644 --- a/aptos-move/mvhashmap/src/unit_tests/mod.rs +++ b/aptos-move/mvhashmap/src/unit_tests/mod.rs @@ -4,7 +4,7 @@ use super::{ types::{ - test::{arc_value_for, u128_for, value_for, KeyType, TestValue}, + test::{arc_value_for, u128_for, KeyType, TestValue}, MVDataError, MVDataOutput, }, unsync_map::UnsyncMap, @@ -42,16 +42,16 @@ fn unsync_map_data_basic() { assert_none!(map.fetch_data(&ap)); // Ensure write registers the new value. //TODO[agg_v2](tests): Hardocoding layout to None. Test when layout is Some(.) as well. - map.write(ap.clone(), value_for(10, 1), None); + map.write(ap.clone(), arc_value_for(10, 1), None); assert_some_eq!( map.fetch_data(&ap), - ValueWithLayout::Exchanged(Arc::new(value_for(10, 1)), None) + ValueWithLayout::Exchanged(arc_value_for(10, 1), None) ); // Ensure the next write overwrites the value. - map.write(ap.clone(), value_for(14, 1), None); + map.write(ap.clone(), arc_value_for(14, 1), None); assert_some_eq!( map.fetch_data(&ap), - ValueWithLayout::Exchanged(Arc::new(value_for(14, 1)), None) + ValueWithLayout::Exchanged(arc_value_for(14, 1), None) ); } @@ -74,7 +74,7 @@ fn create_write_read_placeholder_struct() { // Write by txn 10. mvtbl .data() - .write(ap1.clone(), 10, 1, (value_for(10, 1), None)); + .write(ap1.clone(), 10, 1, arc_value_for(10, 1), None); // Reads that should go the DB return Err(Uninitialized) let r_db = mvtbl.data().fetch_data(&ap1, 9); @@ -111,10 +111,10 @@ fn create_write_read_placeholder_struct() { // More writes. mvtbl .data() - .write(ap1.clone(), 12, 0, (value_for(12, 0), None)); + .write(ap1.clone(), 12, 0, arc_value_for(12, 0), None); mvtbl .data() - .write(ap1.clone(), 8, 3, (value_for(8, 3), None)); + .write(ap1.clone(), 8, 3, arc_value_for(8, 3), None); // Verify reads. let r_12 = mvtbl.data().fetch_data(&ap1, 15); @@ -151,7 +151,7 @@ fn create_write_read_placeholder_struct() { mvtbl.data().remove(&ap1, 10); mvtbl .data() - .write(ap2.clone(), 10, 2, (value_for(10, 2), None)); + .write(ap2.clone(), 10, 2, arc_value_for(10, 2), None); // Read by txn 11 no longer observes entry from txn 10. let r_8 = mvtbl.data().fetch_data(&ap1, 11); @@ -166,10 +166,10 @@ fn create_write_read_placeholder_struct() { // Reads, writes for ap2 and ap3. mvtbl .data() - .write(ap2.clone(), 5, 0, (value_for(5, 0), None)); + .write(ap2.clone(), 5, 0, arc_value_for(5, 0), None); mvtbl .data() - .write(ap3.clone(), 20, 4, (value_for(20, 4), None)); + .write(ap3.clone(), 20, 4, arc_value_for(20, 4), None); let r_5 = mvtbl.data().fetch_data(&ap2, 10); assert_eq!( Ok(Versioned( @@ -216,10 +216,10 @@ fn create_write_read_placeholder_struct() { let r_33 = mvtbl.data().fetch_data(&ap1, 33); assert_eq!(Err(DeltaApplicationFailure), r_33); - let val = value_for(10, 3); + let val = arc_value_for(10, 3); // sub base sub_for for which should underflow. let sub_base = val.as_u128().unwrap().unwrap(); - mvtbl.data().write(ap2.clone(), 10, 3, (val, None)); + mvtbl.data().write(ap2.clone(), 10, 3, val, None); mvtbl .data() .add_delta(ap2.clone(), 30, delta_sub(30 + sub_base, u128::MAX)); diff --git a/aptos-move/mvhashmap/src/unit_tests/proptest_types.rs b/aptos-move/mvhashmap/src/unit_tests/proptest_types.rs index 10512fe80665d..09c532229d584 100644 --- a/aptos-move/mvhashmap/src/unit_tests/proptest_types.rs +++ b/aptos-move/mvhashmap/src/unit_tests/proptest_types.rs @@ -20,7 +20,10 @@ use std::{ collections::{BTreeMap, HashMap}, fmt::Debug, hash::Hash, - sync::atomic::{AtomicUsize, Ordering}, + sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, + }, }; const DEFAULT_TIMEOUT: u64 = 30; @@ -83,14 +86,6 @@ impl> + Clone + Debug> TransactionWrite for Value { fn set_bytes(&mut self, bytes: Bytes) { self.maybe_bytes = Some(bytes); } - - fn convert_read_to_modification(&self) -> Option - where - Self: Sized, - { - // If we have no bytes, no modification can be created. - self.maybe_bytes.as_ref().map(|_| self.clone()) - } } enum Data { @@ -249,7 +244,7 @@ where .write(key.clone(), idx, 0, vec![(5, (value, None))]); map.group_data().mark_estimate(&key, idx); } else { - map.data().write(key.clone(), idx, 0, (value, None)); + map.data().write(key.clone(), idx, 0, Arc::new(value), None); map.data().mark_estimate(&key, idx); } } @@ -357,7 +352,8 @@ where map.group_data() .write(key, idx as TxnIndex, 1, vec![(5, (value, None))]); } else { - map.data().write(key, idx as TxnIndex, 1, (value, None)); + map.data() + .write(key, idx as TxnIndex, 1, Arc::new(value), None); } }, Operator::Insert(v) => { @@ -367,7 +363,8 @@ where map.group_data() .write(key, idx as TxnIndex, 1, vec![(5, (value, None))]); } else { - map.data().write(key, idx as TxnIndex, 1, (value, None)); + map.data() + .write(key, idx as TxnIndex, 1, Arc::new(value), None); } }, Operator::Update(delta) => { diff --git a/aptos-move/mvhashmap/src/unsync_map.rs b/aptos-move/mvhashmap/src/unsync_map.rs index abcb30f094314..9e3e9d34f31f7 100644 --- a/aptos-move/mvhashmap/src/unsync_map.rs +++ b/aptos-move/mvhashmap/src/unsync_map.rs @@ -189,6 +189,14 @@ impl< self.resource_map.borrow().get(key).cloned() } + pub fn fetch_exchanged_data(&self, key: &K) -> Option<(Arc, Arc)> { + if let Some(ValueWithLayout::Exchanged(value, Some(layout))) = self.fetch_data(key) { + Some((value, layout)) + } else { + None + } + } + pub fn fetch_group_data(&self, key: &K) -> Option, ValueWithLayout)>> { self.group_cache.borrow().get(key).map(|group_map| { group_map @@ -224,10 +232,10 @@ impl< self.delayed_field_map.borrow().get(id).cloned() } - pub fn write(&self, key: K, value: V, layout: Option>) { + pub fn write(&self, key: K, value: Arc, layout: Option>) { self.resource_map .borrow_mut() - .insert(key, ValueWithLayout::Exchanged(Arc::new(value), layout)); + .insert(key, ValueWithLayout::Exchanged(value, layout)); } pub fn write_module(&self, key: K, value: V) { diff --git a/aptos-move/mvhashmap/src/versioned_data.rs b/aptos-move/mvhashmap/src/versioned_data.rs index 67e937a4e6b2c..17ba970476a62 100644 --- a/aptos-move/mvhashmap/src/versioned_data.rs +++ b/aptos-move/mvhashmap/src/versioned_data.rs @@ -256,6 +256,20 @@ impl VersionedData { .unwrap_or(Err(MVDataError::Uninitialized)) } + pub fn fetch_exchanged_data( + &self, + key: &K, + txn_idx: TxnIndex, + ) -> Option<(Arc, Arc)> { + if let Ok(MVDataOutput::Versioned(_, ValueWithLayout::Exchanged(value, Some(layout)))) = + self.fetch_data(key, txn_idx) + { + Some((value, layout)) + } else { + None + } + } + pub fn set_base_value(&self, key: K, value: ValueWithLayout) { let mut v = self.values.entry(key).or_default(); // For base value, incarnation is irrelevant, and is always set to 0. @@ -308,14 +322,15 @@ impl VersionedData { key: K, txn_idx: TxnIndex, incarnation: Incarnation, - data: (V, Option>), + data: Arc, + maybe_layout: Option>, ) { let mut v = self.values.entry(key).or_default(); let prev_entry = v.versioned_map.insert( ShiftedTxnIndex::new(txn_idx), CachePadded::new(Entry::new_write_from( incarnation, - ValueWithLayout::Exchanged(Arc::new(data.0), data.1), + ValueWithLayout::Exchanged(data, maybe_layout), )), ); diff --git a/aptos-move/mvhashmap/src/versioned_group_data.rs b/aptos-move/mvhashmap/src/versioned_group_data.rs index 7bf380b579123..e722f1753d262 100644 --- a/aptos-move/mvhashmap/src/versioned_group_data.rs +++ b/aptos-move/mvhashmap/src/versioned_group_data.rs @@ -197,7 +197,7 @@ impl VersionedGro if at_base_version { // base version is from storage and final - immediately treat as committed. - self.commit_idx(zero_idx) + self.commit_idx(zero_idx, true) .expect("Marking storage version as committed must succeed"); } @@ -246,7 +246,11 @@ impl VersionedGro } // Records the latest committed op for each tag in the group (removed tags ar excluded). - fn commit_idx(&mut self, shifted_idx: ShiftedTxnIndex) -> anyhow::Result<()> { + fn commit_idx( + &mut self, + shifted_idx: ShiftedTxnIndex, + allow_new_modification: bool, + ) -> anyhow::Result<()> { use std::collections::hash_map::Entry::*; use WriteOpKind::*; @@ -265,14 +269,16 @@ impl VersionedGro (Vacant(entry), Creation) => { entry.insert(v.clone()); }, + (Vacant(entry), Modification) if allow_new_modification => { + entry.insert(v.clone()); + }, (Occupied(mut entry), Creation) if entry.get().write_op_kind() == Deletion => { entry.insert(v.clone()); }, - (_, _) => { + (e, _) => { bail!( - "WriteOp kind {:?} not consistent with previous value at tag {:?}", + "[{shifted_idx:?}] WriteOp kind {:?} not consistent with previous value at tag {tag:?}, value: {e:?}", v.write_op_kind(), - tag ); }, } @@ -479,7 +485,7 @@ impl< ) -> anyhow::Result)>> { let mut v = self.group_values.get_mut(key).expect("Path must exist"); - v.commit_idx(ShiftedTxnIndex::new(txn_idx))?; + v.commit_idx(ShiftedTxnIndex::new(txn_idx), false)?; Ok(v.get_committed_group()) } diff --git a/types/src/write_set.rs b/types/src/write_set.rs index 7c21e69df4e54..5c01d87c556dd 100644 --- a/types/src/write_set.rs +++ b/types/src/write_set.rs @@ -286,21 +286,6 @@ pub enum WriteOpSize { Deletion, } -impl From<&WriteOp> for WriteOpSize { - fn from(value: &WriteOp) -> Self { - use WriteOp::*; - match value { - Creation { data, .. } => WriteOpSize::Creation { - write_len: data.len() as u64, - }, - Modification { data, .. } => WriteOpSize::Modification { - write_len: data.len() as u64, - }, - Deletion { .. } => WriteOpSize::Deletion, - } - } -} - impl WriteOpSize { pub fn write_len(&self) -> Option { match self { @@ -329,9 +314,10 @@ pub trait TransactionWrite: Debug { // Often, the contents of W:TransactionWrite are converted to Option, e.g. // to emulate reading from storage after W has been applied. However, in some contexts, // it is also helpful to convert a StateValue to a potential instance of W that would - // have the desired effect. This allows e.g. to store certain sentinel elements of - // type W in data-structures (happens in MVHashMap). If there are several instances of - // W that correspond to maybe_state_value, an arbitrary one may be provided. + // have the desired effect. This allows e.g. storing sentinel elements of type W in + // data-structures (notably in MVHashMap). The kind of W will be Modification and not + // Creation, but o.w. if there are several instances of W that correspond to the + // provided maybe_state_value, an arbitrary one may be provided. fn from_state_value(maybe_state_value: Option) -> Self; fn extract_raw_bytes(&self) -> Option { @@ -361,12 +347,18 @@ pub trait TransactionWrite: Debug { fn set_bytes(&mut self, bytes: Bytes); - /// Convert a `self`, which was read (containing DelayedField exchanges) in a current - /// transaction, to a modification write, in which we can then exchange DelayedField - /// identifiers into their final values, to produce a write operation. - fn convert_read_to_modification(&self) -> Option - where - Self: Sized; + fn write_op_size(&self) -> WriteOpSize { + use WriteOpKind::*; + match self.write_op_kind() { + Creation => WriteOpSize::Creation { + write_len: self.bytes().unwrap().len() as u64, + }, + Modification => WriteOpSize::Modification { + write_len: self.bytes().unwrap().len() as u64, + }, + Deletion { .. } => WriteOpSize::Deletion, + } + } } impl TransactionWrite for WriteOp { @@ -390,7 +382,7 @@ impl TransactionWrite for WriteOp { None => Self::legacy_deletion(), Some(state_value) => { let (metadata, data) = state_value.unpack(); - Self::Creation { data, metadata } + Self::Modification { data, metadata } }, } } @@ -412,18 +404,6 @@ impl TransactionWrite for WriteOp { Deletion { .. } => (), } } - - fn convert_read_to_modification(&self) -> Option { - use WriteOp::*; - - match self.clone() { - Creation { data, metadata } | Modification { data, metadata } => { - Some(Modification { data, metadata }) - }, - // Deletion don't have data to become modification. - Deletion { .. } => None, - } - } } #[allow(clippy::format_collect)] From d7e68325c39dafa88dca0744f2b5a87e217b43e3 Mon Sep 17 00:00:00 2001 From: igor-aptos <110557261+igor-aptos@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:09:51 -0800 Subject: [PATCH 063/328] [agg_v2] e2e test with module publish (#11973) * [agg_v2] e2e test with module publish * adding allow_fallback to local config in block executor, to allow tests to assert no fallback happened, when it shouldn't otherwise if there is bug in parallel executor, fallback hides it * cleanup --------- --- aptos-move/aptos-vm/src/aptos_vm.rs | 1 + .../sharded_executor_service.rs | 5 +- aptos-move/block-executor/src/executor.rs | 82 ++++++++++--------- .../e2e-move-tests/src/aggregator_v2.rs | 26 ++++-- .../e2e-move-tests/src/resource_groups.rs | 4 +- .../e2e-move-tests/src/tests/aggregator_v2.rs | 66 +++++++++++++-- aptos-move/e2e-tests/src/executor.rs | 45 ++++++---- types/src/block_executor/config.rs | 11 ++- 8 files changed, 170 insertions(+), 70 deletions(-) diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index f0162c8b1ff8c..421a5404030ca 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -2193,6 +2193,7 @@ impl VMExecutor for AptosVM { BlockExecutorConfig { local: BlockExecutorLocalConfig { concurrency_level: Self::get_concurrency_level(), + allow_fallback: true, }, onchain: onchain_config, }, 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 9ae61f5d7d22f..b48b4f07adec0 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 @@ -142,7 +142,10 @@ impl ShardedExecutorService { &signature_verified_transactions, aggr_overridden_state_view.as_ref(), BlockExecutorConfig { - local: BlockExecutorLocalConfig { concurrency_level }, + local: BlockExecutorLocalConfig { + concurrency_level, + allow_fallback: true, + }, onchain: onchain_config, }, cross_shard_commit_sender, diff --git a/aptos-move/block-executor/src/executor.rs b/aptos-move/block-executor/src/executor.rs index d6d687c1e0591..4ea07119f9a59 100644 --- a/aptos-move/block-executor/src/executor.rs +++ b/aptos-move/block-executor/src/executor.rs @@ -1287,57 +1287,63 @@ where ) }; - let mut resource_group_bcs_fallback = matches!( - ret, - Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( - IntentionalFallbackToSequential::ResourceGroupSerializationError - ))) - ); + if self.config.local.allow_fallback { + let mut resource_group_bcs_fallback = matches!( + ret, + Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + ))) + ); - if self.config.local.concurrency_level > 1 && !resource_group_bcs_fallback { - // Sequential execution fallback, only worth doing if we did a different pass before, - // i.e. parallel. This fallback does not handle resource group serialization issues. + if self.config.local.concurrency_level > 1 && !resource_group_bcs_fallback { + // Sequential execution fallback, only worth doing if we did a different pass before, + // i.e. parallel. This fallback does not handle resource group serialization issues. - if let Err(BlockExecutionError::FallbackToSequential(_)) = &ret { - // Any error logs are already written at appropriate levels. - debug!("Sequential_fallback occurred"); + if let Err(BlockExecutionError::FallbackToSequential(_)) = &ret { + // Any error logs are already written at appropriate levels. + debug!("Sequential_fallback occurred"); - // All logs from the parallel execution should be cleared and not reported. - // Clear by re-initializing the speculative logs. - init_speculative_logs(signature_verified_block.len()); + // All logs from the parallel execution should be cleared and not reported. + // Clear by re-initializing the speculative logs. + init_speculative_logs(signature_verified_block.len()); + ret = self.execute_transactions_sequential( + executor_arguments, + signature_verified_block, + base_view, + false, + ); + resource_group_bcs_fallback = matches!( + ret, + Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( + IntentionalFallbackToSequential::ResourceGroupSerializationError + ))) + ); + } + } + + if resource_group_bcs_fallback { + alert!("Resource group serialization fallback"); + init_speculative_logs(signature_verified_block.len()); ret = self.execute_transactions_sequential( executor_arguments, signature_verified_block, base_view, - false, - ); - resource_group_bcs_fallback = matches!( - ret, - Err(BlockExecutionError::FallbackToSequential(PanicOr::Or( - IntentionalFallbackToSequential::ResourceGroupSerializationError - ))) + true, ); } - } - - if resource_group_bcs_fallback { - alert!("Resource group serialization fallback"); - init_speculative_logs(signature_verified_block.len()); - ret = self.execute_transactions_sequential( - executor_arguments, - signature_verified_block, - base_view, - true, - ); - } - // If after trying available fallbacks, we still are askign to do a fallback, - // something unrecoverable went wrong. - if let Err(BlockExecutionError::FallbackToSequential(e)) = &ret { + // If after trying available fallbacks, we still are askign to do a fallback, + // something unrecoverable went wrong. + if let Err(BlockExecutionError::FallbackToSequential(e)) = &ret { + // TODO[agg_v2][fix] make sure this can never happen - we have sequential raising + // this error often when something that should never happen goes wrong + panic!("Sequential execution failed with {:?}", e); + } + } else if let Err(BlockExecutionError::FallbackToSequential(e)) = &ret { // TODO[agg_v2][fix] make sure this can never happen - we have sequential raising // this error often when something that should never happen goes wrong - panic!("Sequential execution failed with {:?}", e); + panic!("Fallback disabled, execution failed due to {:?}", e); } ret diff --git a/aptos-move/e2e-move-tests/src/aggregator_v2.rs b/aptos-move/e2e-move-tests/src/aggregator_v2.rs index f086ee1339628..7697ad45d957a 100644 --- a/aptos-move/e2e-move-tests/src/aggregator_v2.rs +++ b/aptos-move/e2e-move-tests/src/aggregator_v2.rs @@ -20,15 +20,20 @@ pub fn initialize( mode: ExecutorMode, aggregator_execution_enabled: bool, txns: usize, + allow_block_executor_fallback: bool, ) -> AggV2TestHarness { - let (harness, account) = initialize_harness(mode, aggregator_execution_enabled, path); - + let (mut harness, account) = + initialize_harness(mode, aggregator_execution_enabled, path.clone()); + if !allow_block_executor_fallback { + harness.executor.disable_block_executor_fallback(); + } let mut result = AggV2TestHarness { harness, comparison_harnesses: vec![], account, txn_accounts: vec![], txn_index: 0, + path, }; result.initialize_issuer_accounts(txns); @@ -39,16 +44,21 @@ pub fn initialize_enabled_disabled_comparison( path: PathBuf, mode: ExecutorMode, txns: usize, + allow_block_executor_fallback: bool, ) -> AggV2TestHarness { - let (harness_base, account_base) = initialize_harness(mode, false, path.clone()); - let (harness_comp, _account_comp) = initialize_harness(mode, true, path); - + let (mut harness_base, account_base) = initialize_harness(mode, false, path.clone()); + let (mut harness_comp, _account_comp) = initialize_harness(mode, true, path.clone()); + if !allow_block_executor_fallback { + harness_base.executor.disable_block_executor_fallback(); + harness_comp.executor.disable_block_executor_fallback(); + } let mut agg_harness = AggV2TestHarness { harness: harness_base, comparison_harnesses: vec![(harness_comp, "aggregator_execution_enabled".to_string())], account: account_base, txn_accounts: vec![], txn_index: 0, + path, }; agg_harness.initialize_issuer_accounts(txns); @@ -91,6 +101,7 @@ pub struct AggV2TestHarness { pub account: Account, pub txn_accounts: Vec, pub txn_index: usize, + pub path: PathBuf, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -226,6 +237,11 @@ impl AggV2TestHarness { ) } + pub fn republish(&mut self) -> SignedTransaction { + self.harness + .create_publish_package_cache_building(&self.account, &self.path, |_| {}) + } + fn create_entry_agg_func_with_args( &mut self, name: &str, diff --git a/aptos-move/e2e-move-tests/src/resource_groups.rs b/aptos-move/e2e-move-tests/src/resource_groups.rs index 9e151d104609d..6c249dd5ea70a 100644 --- a/aptos-move/e2e-move-tests/src/resource_groups.rs +++ b/aptos-move/e2e-move-tests/src/resource_groups.rs @@ -16,7 +16,9 @@ pub fn initialize( resource_group_charge_as_sum_enabled: bool, txns: usize, ) -> ResourceGroupsTestHarness { - let (harness, account) = initialize_harness(mode, resource_group_charge_as_sum_enabled, path); + let (mut harness, account) = + initialize_harness(mode, resource_group_charge_as_sum_enabled, path); + harness.executor.disable_block_executor_fallback(); let mut rg_harness = ResourceGroupsTestHarness { harness, diff --git a/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs b/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs index b9d831586efe8..10107653b93c0 100644 --- a/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs +++ b/aptos-move/e2e-move-tests/src/tests/aggregator_v2.rs @@ -19,21 +19,53 @@ const EAGGREGATOR_UNDERFLOW: u64 = 0x02_0002; const DEFAULT_EXECUTOR_MODE: ExecutorMode = ExecutorMode::SequentialOnly; -fn setup( +fn _setup( executor_mode: ExecutorMode, aggregator_execution_mode: AggregatorMode, txns: usize, + allow_block_executor_fallback: bool, ) -> AggV2TestHarness { let path = common::test_dir_path("aggregator_v2.data/pack"); match aggregator_execution_mode { - AggregatorMode::EnabledOnly => initialize(path, executor_mode, true, txns), - AggregatorMode::DisabledOnly => initialize(path, executor_mode, false, txns), - AggregatorMode::BothComparison => { - initialize_enabled_disabled_comparison(path, executor_mode, txns) - }, + AggregatorMode::EnabledOnly => initialize( + path, + executor_mode, + true, + txns, + allow_block_executor_fallback, + ), + AggregatorMode::DisabledOnly => initialize( + path, + executor_mode, + false, + txns, + allow_block_executor_fallback, + ), + AggregatorMode::BothComparison => initialize_enabled_disabled_comparison( + path, + executor_mode, + txns, + allow_block_executor_fallback, + ), } } +fn setup( + executor_mode: ExecutorMode, + aggregator_execution_mode: AggregatorMode, + txns: usize, +) -> AggV2TestHarness { + _setup(executor_mode, aggregator_execution_mode, txns, false) +} + +fn setup_allow_fallback( + executor_mode: ExecutorMode, + aggregator_execution_mode: AggregatorMode, + txns: usize, +) -> AggV2TestHarness { + _setup(executor_mode, aggregator_execution_mode, txns, true) +} + #[cfg(test)] mod test_cases { use super::*; @@ -382,6 +414,28 @@ proptest! { ); } + #[test] + fn test_aggregator_with_republish(test_env in arb_test_env(6), element_type in arb_agg_type(), use_type in arb_use_type()) { + println!("Testing test_aggregator_overflow {:?}", test_env); + let mut h = setup_allow_fallback(test_env.executor_mode, test_env.aggregator_execution_mode, 3); + + let agg_loc = AggregatorLocation::new(*h.account.address(), element_type, use_type, 0); + + let txns = vec![ + (SUCCESS, h.init(None, use_type, element_type, StructType::Aggregator)), + (SUCCESS, h.new_add(&agg_loc, 600, 400)), + (SUCCESS, h.add(&agg_loc, 1)), + (SUCCESS, h.republish()), + (EAGGREGATOR_OVERFLOW, h.add(&agg_loc, 200)), + (SUCCESS, h.add(&agg_loc, 1)), + ]; + + h.run_block_in_parts_and_check( + test_env.block_split, + txns, + ); + } + #[test] fn test_aggregator_materialize_overflow(test_env in arb_test_env(3)) { println!("Testing test_aggregator_materialize_overflow {:?}", test_env); diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 76b94ce0e98c6..8ae1697e59354 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -57,7 +57,7 @@ use aptos_vm::{ block_executor::{AptosTransactionOutput, BlockAptosVM}, data_cache::AsMoveResolver, move_vm_ext::{MoveVmExt, SessionId}, - verifier, AptosVM, VMExecutor, VMValidator, + verifier, AptosVM, VMValidator, }; use aptos_vm_genesis::{generate_genesis_change_set_for_testing_with_count, GenesisOptions}; use aptos_vm_logging::log_schema::AdapterLogSchema; @@ -128,6 +128,7 @@ pub struct FakeExecutor { executor_mode: Option, features: Features, chain_id: u8, + allow_block_executor_fallback: bool, } pub enum GasMeterType { @@ -155,6 +156,7 @@ impl FakeExecutor { executor_mode: None, features: Features::default(), chain_id: chain_id.id(), + allow_block_executor_fallback: true, }; executor.apply_write_set(write_set); // As a set effect, also allow module bundle txns. TODO: Remove @@ -179,6 +181,10 @@ impl FakeExecutor { self.set_executor_mode(ExecutorMode::BothComparison) } + pub fn disable_block_executor_fallback(&mut self) { + self.allow_block_executor_fallback = false; + } + /// Creates an executor from the genesis file GENESIS_FILE_LOCATION pub fn from_head_genesis() -> Self { Self::from_genesis(GENESIS_CHANGE_SET_HEAD.clone().write_set(), ChainId::test()) @@ -236,6 +242,7 @@ impl FakeExecutor { executor_mode: None, features: Features::default(), chain_id: ChainId::test().id(), + allow_block_executor_fallback: true, } } @@ -470,21 +477,28 @@ impl FakeExecutor { } } - pub fn execute_transaction_block_parallel( + fn execute_transaction_block_impl( &self, txn_block: &[SignatureVerifiedTransaction], onchain_config: BlockExecutorConfigFromOnchain, + sequential: bool, ) -> Result, VMStatus> { + let config = BlockExecutorConfig { + local: BlockExecutorLocalConfig { + concurrency_level: if sequential { + 1 + } else { + usize::min(4, num_cpus::get()) + }, + allow_fallback: self.allow_block_executor_fallback, + }, + onchain: onchain_config, + }; BlockAptosVM::execute_block::<_, NoOpTransactionCommitHook>( self.executor_thread_pool.clone(), txn_block, &self.data_store, - BlockExecutorConfig { - local: BlockExecutorLocalConfig { - concurrency_level: usize::min(4, num_cpus::get()), - }, - onchain: onchain_config, - }, + config, None, ).map(BlockOutput::into_transaction_outputs_forced) } @@ -520,20 +534,17 @@ impl FakeExecutor { let onchain_config = BlockExecutorConfigFromOnchain::on_but_large_for_test(); let sequential_output = if mode != ExecutorMode::ParallelOnly { - Some( - AptosVM::execute_block( - &sig_verified_block, - &self.data_store, - onchain_config.clone(), - ) - .map(BlockOutput::into_transaction_outputs_forced), - ) + Some(self.execute_transaction_block_impl( + &sig_verified_block, + onchain_config.clone(), + true, + )) } else { None }; let parallel_output = if mode != ExecutorMode::SequentialOnly { - Some(self.execute_transaction_block_parallel(&sig_verified_block, onchain_config)) + Some(self.execute_transaction_block_impl(&sig_verified_block, onchain_config, false)) } else { None }; diff --git a/types/src/block_executor/config.rs b/types/src/block_executor/config.rs index 2ae51eb88daff..ba37ff3531840 100644 --- a/types/src/block_executor/config.rs +++ b/types/src/block_executor/config.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; #[derive(Clone, Debug)] pub struct BlockExecutorLocalConfig { pub concurrency_level: usize, + pub allow_fallback: bool, } /// Configuration from on-chain configuration, that is @@ -62,7 +63,10 @@ pub struct BlockExecutorConfig { impl BlockExecutorConfig { pub fn new_no_block_limit(concurrency_level: usize) -> Self { Self { - local: BlockExecutorLocalConfig { concurrency_level }, + local: BlockExecutorLocalConfig { + concurrency_level, + allow_fallback: true, + }, onchain: BlockExecutorConfigFromOnchain::new_no_block_limit(), } } @@ -72,7 +76,10 @@ impl BlockExecutorConfig { maybe_block_gas_limit: Option, ) -> Self { Self { - local: BlockExecutorLocalConfig { concurrency_level }, + local: BlockExecutorLocalConfig { + concurrency_level, + allow_fallback: true, + }, onchain: BlockExecutorConfigFromOnchain::new_maybe_block_limit(maybe_block_gas_limit), } } From d3915a7f1e1930db084b3a252767f4c1d99e3f56 Mon Sep 17 00:00:00 2001 From: Oliver He Date: Tue, 13 Feb 2024 23:33:05 +0800 Subject: [PATCH 064/328] Fix zkid smoke tests (#11994) * Fix zkid smoke tests * remove print * fix * remove more print * reset swarm number --- testsuite/smoke-test/src/zkid.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/testsuite/smoke-test/src/zkid.rs b/testsuite/smoke-test/src/zkid.rs index c5eeffdb2925a..3946fc8cf2520 100644 --- a/testsuite/smoke-test/src/zkid.rs +++ b/testsuite/smoke-test/src/zkid.rs @@ -91,8 +91,8 @@ async fn test_zkid_oidc_signature_transaction_submission() { let epk_blinder = vec![0u8; 31]; let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); - let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiIxYlFsNF9YYzUtSXBDcFViS19BZVhwZ2Q2R1o0MGxVVjN1YjN5b19FTHhrIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcwNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); - let jwt_sig = "oBdOiIUc-ioG2-sHV1hWDLjgk4NrVf3z6V-HmgbOrVAz3PV1CwdfyTXsmVaCqLzOHzcbFB6ZRDxShs3aR7PsqdlhI0Dh8WrfU8kBkyk1FAmx2nST4SoSJROXsnusaOpNFpgSl96Rq3SXgr-yPBE9dEwTfD00vq2gH_fH1JAIeJJhc6WicMcsEZ7iONT1RZOid_9FlDrg1GxlGtNmpn4nEAmIxqnT0JrCESiRvzmuuXUibwx9xvHgIxhyVuAA9amlzaD1DL6jEc5B_0YnGKN7DO_l2Hkj9MbQZvU0beR-Lfcz8jxCjojODTYmWgbtu5E7YWIyC6dsjiBnTxc-svCsmQ".to_string(); + let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiJHRTJSNWtpSjN1QUZORGNVLTdFZWlRUVE2ZzhITXlTX3VFSERuV0V4NndJIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcyNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); + let jwt_sig = "VjBhIlbIP7SmF-ra7GMgcWNghU1Ew8U7ZeGBukJ7NHUfjQkPsG2cMfZD_WwZoLJBk3HjjZJyItVq67XIUqdbIM30pVem-QPDX-bjaGEyRlHUkHonKT8JjOMUtKN9NQA9ikqd-DJCxT5UfpotJ_9n7D4kf2cO9wpITyVFHT_BP8yJoJEWT61bvqIzVuNNE3umMwL29lICnvnUa20KjDIyk2BOlUOvNJfjPdJHPuzFDuqjv8cRSTJqjd2N-E31-R7VvCtQ75WNfWu1mPY3IDfu7uiS5zqXNJzWq1GLe8K3o2_BP9_xP7loDyCYAcmX-gFSNCEc4gbpYEq_5vBYfwG7Vg".to_string(); let openid_signature = OpenIdSig { jwt_sig, @@ -106,7 +106,7 @@ async fn test_zkid_oidc_signature_transaction_submission() { let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::OpenIdSig(openid_signature), jwt_header, - exp_timestamp_secs: 1707812836, + exp_timestamp_secs: 1727812836, ephemeral_pubkey: ephemeral_public_key, ephemeral_signature, }; @@ -175,7 +175,7 @@ async fn test_zkid_oidc_signature_transaction_submission_fails_jwt_verification( let epk_blinder = vec![0u8; 31]; let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); - let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiIxYlFsNF9YYzUtSXBDcFViS19BZVhwZ2Q2R1o0MGxVVjN1YjN5b19FTHhrIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcwNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); + let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiJHRTJSNWtpSjN1QUZORGNVLTdFZWlRUVE2ZzhITXlTX3VFSERuV0V4NndJIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcyNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); let jwt_sig = "bad_signature".to_string(); let openid_signature = OpenIdSig { @@ -190,7 +190,7 @@ async fn test_zkid_oidc_signature_transaction_submission_fails_jwt_verification( let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::OpenIdSig(openid_signature), jwt_header, - exp_timestamp_secs: 1707812836, + exp_timestamp_secs: 1727812836, ephemeral_pubkey: ephemeral_public_key, ephemeral_signature, }; @@ -260,8 +260,8 @@ async fn test_zkid_oidc_signature_transaction_submission_epk_expired() { let epk_blinder = vec![0u8; 31]; let jwt_header = "eyJhbGciOiJSUzI1NiIsImtpZCI6InRlc3RfandrIiwidHlwIjoiSldUIn0".to_string(); - let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiIxYlFsNF9YYzUtSXBDcFViS19BZVhwZ2Q2R1o0MGxVVjN1YjN5b19FTHhrIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcwNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); - let jwt_sig = "oBdOiIUc-ioG2-sHV1hWDLjgk4NrVf3z6V-HmgbOrVAz3PV1CwdfyTXsmVaCqLzOHzcbFB6ZRDxShs3aR7PsqdlhI0Dh8WrfU8kBkyk1FAmx2nST4SoSJROXsnusaOpNFpgSl96Rq3SXgr-yPBE9dEwTfD00vq2gH_fH1JAIeJJhc6WicMcsEZ7iONT1RZOid_9FlDrg1GxlGtNmpn4nEAmIxqnT0JrCESiRvzmuuXUibwx9xvHgIxhyVuAA9amlzaD1DL6jEc5B_0YnGKN7DO_l2Hkj9MbQZvU0beR-Lfcz8jxCjojODTYmWgbtu5E7YWIyC6dsjiBnTxc-svCsmQ".to_string(); + let jwt_payload = "eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdWQiOiJ0ZXN0X2NsaWVudF9pZCIsInN1YiI6InRlc3RfYWNjb3VudCIsImVtYWlsIjoidGVzdEBnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibm9uY2UiOiJHRTJSNWtpSjN1QUZORGNVLTdFZWlRUVE2ZzhITXlTX3VFSERuV0V4NndJIiwibmJmIjoxNzAyODA4OTM2LCJpYXQiOjE3MDQ5MDkyMzYsImV4cCI6MTcyNzgxMjgzNiwianRpIjoiZjEwYWZiZjBlN2JiOTcyZWI4ZmE2M2YwMjQ5YjBhMzRhMjMxZmM0MCJ9".to_string(); + let jwt_sig = "VjBhIlbIP7SmF-ra7GMgcWNghU1Ew8U7ZeGBukJ7NHUfjQkPsG2cMfZD_WwZoLJBk3HjjZJyItVq67XIUqdbIM30pVem-QPDX-bjaGEyRlHUkHonKT8JjOMUtKN9NQA9ikqd-DJCxT5UfpotJ_9n7D4kf2cO9wpITyVFHT_BP8yJoJEWT61bvqIzVuNNE3umMwL29lICnvnUa20KjDIyk2BOlUOvNJfjPdJHPuzFDuqjv8cRSTJqjd2N-E31-R7VvCtQ75WNfWu1mPY3IDfu7uiS5zqXNJzWq1GLe8K3o2_BP9_xP7loDyCYAcmX-gFSNCEc4gbpYEq_5vBYfwG7Vg".to_string(); let openid_signature = OpenIdSig { jwt_sig, @@ -275,7 +275,7 @@ async fn test_zkid_oidc_signature_transaction_submission_epk_expired() { let zk_sig = ZkIdSignature { sig: ZkpOrOpenIdSig::OpenIdSig(openid_signature), jwt_header, - exp_timestamp_secs: 1704909236, + exp_timestamp_secs: 1, // Expired timestamp ephemeral_pubkey: ephemeral_public_key, ephemeral_signature, }; From ba5914b3d1e30b48da23e51479aa672ff3189c78 Mon Sep 17 00:00:00 2001 From: George Mitenkov Date: Tue, 13 Feb 2024 18:06:14 +0100 Subject: [PATCH 065/328] [vm] Remove module bundle (#11781) - Module bundle payload has never been used --- Cargo.lock | 1 + api/doc/spec.json | 33 +- api/doc/spec.yaml | 27 +- api/src/transactions.rs | 11 +- api/types/src/convert.rs | 29 +- api/types/src/lib.rs | 8 +- api/types/src/transaction.rs | 30 +- .../aptos-debugger/src/aptos_debugger.rs | 11 +- .../Cargo.toml | 1 + .../src/aptos_test_harness.rs | 72 +- .../aptos_test_harness/borrow_in_loop.exp | 2 +- .../aptos_test_harness/call_function.exp | 14 +- .../aptos_test_harness/call_function.move | 3 +- .../aptos_test_harness/diamond_clicker.exp | 2 +- .../tests/v2-tests/smoke_test.exp | 16 +- .../tests/v2-tests/smoke_test.move | 3 +- aptos-move/aptos-vm/src/aptos_vm.rs | 162 +- .../aptos-vm/src/transaction_metadata.rs | 3 +- .../aptos-vm/src/transaction_validation.rs | 39 +- .../src/tests/access_path_test.rs | 12 +- ...__tests__data_store__borrow_after_move.exp | 29 - ...__tests__data_store__change_after_move.exp | 29 - ...s__data_store__move_from_across_blocks.exp | 29 - ...led_transaction_cleanup_test_version_4.exp | 0 ...n_tests__non_existent_sender_version_4.exp | 18 - ...s__mint__mint_to_new_account_version_4.exp | 66 - ..._module_publishing__bad_module_address.exp | 37 - ...s__module_publishing__duplicate_module.exp | 58 - ...e_publishing__layout_compatible_module.exp | 58 - ...incompatible_module_with_changed_field.exp | 58 - ...out_incompatible_module_with_new_field.exp | 58 - ...incompatible_module_with_removed_field.exp | 58 - ...ncompatible_module_with_removed_struct.exp | 58 - ..._publishing__linking_compatible_module.exp | 58 - ...g_incompatible_module_with_added_param.exp | 58 - ...incompatible_module_with_changed_param.exp | 58 - ...ncompatible_module_with_removed_pub_fn.exp | 58 - ...lishing__test_publishing_allow_modules.exp | 29 - ...test_publishing_modules_invalid_sender.exp | 29 - ..._test_publishing_modules_proper_sender.exp | 29 - ...op_txn_after_reconfiguration_version_4.exp | 130 - ...nfigs__initial_aptos_version_version_4.exp | 118 - ...uite__tests__package_publishing__basic.exp | 70 - ...ackage_publishing__upgrade_fail_compat.exp | 74 - ...age_publishing__upgrade_fail_immutable.exp | 73 - ...shing__upgrade_fail_overlapping_module.exp | 73 - ...age_publishing__upgrade_success_compat.exp | 82 - ..._publishing__upgrade_success_no_compat.exp | 82 - ...cle_peer_to_peer_multi_block_version_4.exp | 2720 ----------------- ..._to_peer__cycle_peer_to_peer_version_4.exp | 2704 ---------------- ..._few_peer_to_peer_with_event_version_4.exp | 112 - ...er__many_to_one_peer_to_peer_version_4.exp | 2654 ---------------- ...er__one_to_many_peer_to_peer_version_4.exp | 2654 ---------------- ...ngle_peer_to_peer_with_event_version_4.exp | 31 - ...tate_key__rotate_ed25519_key_version_4.exp | 62 - ..._rotate_ed25519_multisig_key_version_4.exp | 66 - ...t_module_dependency_fails_verification.exp | 37 - ...ansitive_dependency_fails_verification.exp | 37 - ...ests__verify_txn__test_open_publishing.exp | 37 - ...__test_open_publishing_invalid_address.exp | 37 - ..._verify_txn__verify_chain_id_version_4.exp | 18 - ..._txn__verify_expiration_time_version_4.exp | 36 - ...__verify_max_sequence_number_version_4.exp | 18 - ..._txn__verify_reserved_sender_version_4.exp | 18 - ...verify_txn__verify_signature_version_4.exp | 18 - ...y_txn__verify_simple_payment_version_4.exp | 230 -- aptos-move/e2e-tests/src/account.rs | 9 +- aptos-move/e2e-tests/src/executor.rs | 8 +- .../e2e-testsuite/src/tests/data_store.rs | 86 +- aptos-move/e2e-testsuite/src/tests/mod.rs | 1 - .../src/tests/module_publishing.rs | 357 --- .../e2e-testsuite/src/tests/verify_txn.rs | 214 +- .../doc/transaction_validation.md | 56 +- .../sources/transaction_validation.move | 16 +- .../sources/transaction_validation.spec.move | 15 - .../indexer-grpc-fullnode/src/convert.rs | 17 +- .../executor/src/components/chunk_output.rs | 6 +- execution/executor/src/mock_vm/mod.rs | 4 +- .../aptos/transaction/v1/transaction.proto | 8 +- .../aptos/transaction/v1/transaction_pb2.py | 178 +- .../aptos/transaction/v1/transaction_pb2.pyi | 14 - protos/rust/src/pb/aptos.transaction.v1.rs | 1523 +++++---- .../rust/src/pb/aptos.transaction.v1.serde.rs | 108 - .../src/aptos/transaction/v1/transaction.ts | 128 - .../move/aptosvm_publish_and_run.rs | 56 +- .../generate-format/tests/staged/api.yaml | 13 +- .../generate-format/tests/staged/aptos.yaml | 13 +- .../tests/staged/consensus.yaml | 13 +- types/src/proptest_types.rs | 36 +- .../test_helpers/transaction_test_helpers.rs | 26 +- types/src/transaction/mod.rs | 134 +- 91 files changed, 1089 insertions(+), 15495 deletions(-) delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__failed_transaction_cleanup_test_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__non_existent_sender_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__mint__mint_to_new_account_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__bad_module_address.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__duplicate_module.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_compatible_module.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_changed_field.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_new_field.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_field.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_struct.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_compatible_module.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_added_param.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_changed_param.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_removed_pub_fn.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_allow_modules.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_invalid_sender.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_proper_sender.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__drop_txn_after_reconfiguration_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__initial_aptos_version_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__basic.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_compat.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_immutable.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_overlapping_module.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_compat.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_no_compat.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_multi_block_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__few_peer_to_peer_with_event_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__many_to_one_peer_to_peer_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__one_to_many_peer_to_peer_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__single_peer_to_peer_with_event_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_key_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_multisig_key_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_dependency_fails_verification.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_transitive_dependency_fails_verification.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing_invalid_address.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_chain_id_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_expiration_time_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_max_sequence_number_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_reserved_sender_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_signature_version_4.exp delete mode 100644 aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_simple_payment_version_4.exp delete mode 100644 aptos-move/e2e-testsuite/src/tests/module_publishing.rs diff --git a/Cargo.lock b/Cargo.lock index 2be34d423d123..5dc023ca063db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4099,6 +4099,7 @@ dependencies = [ "datatest-stable", "hex", "move-binary-format", + "move-bytecode-verifier", "move-command-line-common", "move-compiler", "move-core-types", diff --git a/api/doc/spec.json b/api/doc/spec.json index 574e57a2cbee2..01743f5643b0f 100644 --- a/api/doc/spec.json +++ b/api/doc/spec.json @@ -12533,6 +12533,9 @@ } } }, + "DeprecatedModuleBundlePayload": { + "type": "object" + }, "DirectWriteSet": { "type": "object", "required": [ @@ -12938,20 +12941,6 @@ } } }, - "ModuleBundlePayload": { - "type": "object", - "required": [ - "modules" - ], - "properties": { - "modules": { - "type": "array", - "items": { - "$ref": "#/components/schemas/MoveModuleBytecode" - } - } - } - }, "MoveAbility": { "type": "string" }, @@ -13752,7 +13741,7 @@ "$ref": "#/components/schemas/TransactionPayload_ScriptPayload" }, { - "$ref": "#/components/schemas/TransactionPayload_ModuleBundlePayload" + "$ref": "#/components/schemas/TransactionPayload_DeprecatedModuleBundlePayload" }, { "$ref": "#/components/schemas/TransactionPayload_MultisigPayload" @@ -13763,12 +13752,12 @@ "mapping": { "entry_function_payload": "#/components/schemas/TransactionPayload_EntryFunctionPayload", "script_payload": "#/components/schemas/TransactionPayload_ScriptPayload", - "module_bundle_payload": "#/components/schemas/TransactionPayload_ModuleBundlePayload", + "module_bundle_payload": "#/components/schemas/TransactionPayload_DeprecatedModuleBundlePayload", "multisig_payload": "#/components/schemas/TransactionPayload_MultisigPayload" } } }, - "TransactionPayload_EntryFunctionPayload": { + "TransactionPayload_DeprecatedModuleBundlePayload": { "allOf": [ { "type": "object", @@ -13778,16 +13767,16 @@ "properties": { "type": { "type": "string", - "example": "entry_function_payload" + "example": "module_bundle_payload" } } }, { - "$ref": "#/components/schemas/EntryFunctionPayload" + "$ref": "#/components/schemas/DeprecatedModuleBundlePayload" } ] }, - "TransactionPayload_ModuleBundlePayload": { + "TransactionPayload_EntryFunctionPayload": { "allOf": [ { "type": "object", @@ -13797,12 +13786,12 @@ "properties": { "type": { "type": "string", - "example": "module_bundle_payload" + "example": "entry_function_payload" } } }, { - "$ref": "#/components/schemas/ModuleBundlePayload" + "$ref": "#/components/schemas/EntryFunctionPayload" } ] }, diff --git a/api/doc/spec.yaml b/api/doc/spec.yaml index ee95d4880a813..d24bc416dcde1 100644 --- a/api/doc/spec.yaml +++ b/api/doc/spec.yaml @@ -9383,6 +9383,8 @@ components: key_type: type: string description: Deleted key type + DeprecatedModuleBundlePayload: + type: object DirectWriteSet: type: object required: @@ -9682,15 +9684,6 @@ components: format: uint8 signature: $ref: '#/components/schemas/Signature' - ModuleBundlePayload: - type: object - required: - - modules - properties: - modules: - type: array - items: - $ref: '#/components/schemas/MoveModuleBytecode' MoveAbility: type: string MoveFunction: @@ -10325,16 +10318,16 @@ components: oneOf: - $ref: '#/components/schemas/TransactionPayload_EntryFunctionPayload' - $ref: '#/components/schemas/TransactionPayload_ScriptPayload' - - $ref: '#/components/schemas/TransactionPayload_ModuleBundlePayload' + - $ref: '#/components/schemas/TransactionPayload_DeprecatedModuleBundlePayload' - $ref: '#/components/schemas/TransactionPayload_MultisigPayload' discriminator: propertyName: type mapping: entry_function_payload: '#/components/schemas/TransactionPayload_EntryFunctionPayload' script_payload: '#/components/schemas/TransactionPayload_ScriptPayload' - module_bundle_payload: '#/components/schemas/TransactionPayload_ModuleBundlePayload' + module_bundle_payload: '#/components/schemas/TransactionPayload_DeprecatedModuleBundlePayload' multisig_payload: '#/components/schemas/TransactionPayload_MultisigPayload' - TransactionPayload_EntryFunctionPayload: + TransactionPayload_DeprecatedModuleBundlePayload: allOf: - type: object required: @@ -10342,9 +10335,9 @@ components: properties: type: type: string - example: entry_function_payload - - $ref: '#/components/schemas/EntryFunctionPayload' - TransactionPayload_ModuleBundlePayload: + example: module_bundle_payload + - $ref: '#/components/schemas/DeprecatedModuleBundlePayload' + TransactionPayload_EntryFunctionPayload: allOf: - type: object required: @@ -10352,8 +10345,8 @@ components: properties: type: type: string - example: module_bundle_payload - - $ref: '#/components/schemas/ModuleBundlePayload' + example: entry_function_payload + - $ref: '#/components/schemas/EntryFunctionPayload' TransactionPayload_MultisigPayload: allOf: - type: object diff --git a/api/src/transactions.rs b/api/src/transactions.rs index 5726064112feb..cf7a46db2a49c 100644 --- a/api/src/transactions.rs +++ b/api/src/transactions.rs @@ -941,8 +941,15 @@ impl TransactionsApi { } }, - // Deprecated. Will be removed in the future. - TransactionPayload::ModuleBundle(_) => {}, + // Deprecated. To avoid panics when malicios users submit this + // payload, return an error. + TransactionPayload::ModuleBundle(_) => { + return Err(SubmitTransactionError::bad_request_with_code( + "Module bundle payload has been removed", + AptosErrorCode::InvalidInput, + ledger_info, + )) + }, } // TODO: Verify script args? diff --git a/api/types/src/convert.rs b/api/types/src/convert.rs index b9f3a45f78712..6368d90f9ce89 100644 --- a/api/types/src/convert.rs +++ b/api/types/src/convert.rs @@ -5,9 +5,8 @@ use crate::{ transaction::{ DecodedTableData, DeleteModule, DeleteResource, DeleteTableItem, DeletedTableData, - ModuleBundlePayload, MultisigPayload, MultisigTransactionPayload, - StateCheckpointTransaction, UserTransactionRequestInner, WriteModule, WriteResource, - WriteTableItem, + MultisigPayload, MultisigTransactionPayload, StateCheckpointTransaction, + UserTransactionRequestInner, WriteModule, WriteResource, WriteTableItem, }, view::{ViewFunction, ViewRequest}, Bytecode, DirectWriteSet, EntryFunctionId, EntryFunctionPayload, Event, HexEncodedBytes, @@ -29,8 +28,7 @@ use aptos_types::{ table::{TableHandle, TableInfo}, }, transaction::{ - EntryFunction, ExecutionStatus, ModuleBundle, Multisig, RawTransaction, Script, - SignedTransaction, + EntryFunction, ExecutionStatus, Multisig, RawTransaction, Script, SignedTransaction, }, vm_status::AbortLocation, write_set::WriteOp, @@ -269,13 +267,8 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { }) }, - // Deprecated. Will be removed in the future. - ModuleBundle(modules) => TransactionPayload::ModuleBundlePayload(ModuleBundlePayload { - modules: modules - .into_iter() - .map(|module| MoveModuleBytecode::from(module).try_parse_abi()) - .collect::>>()?, - }), + // Deprecated. + ModuleBundle(_) => bail!("Module bundle payload has been removed"), }; Ok(ret) } @@ -701,15 +694,9 @@ impl<'a, R: ModuleResolver + ?Sized> MoveConverter<'a, R> { }) }, - // Deprecated. Will be removed in the future. - TransactionPayload::ModuleBundlePayload(payload) => { - Target::ModuleBundle(ModuleBundle::new( - payload - .modules - .into_iter() - .map(|m| m.bytecode.into()) - .collect(), - )) + // Deprecated. + TransactionPayload::ModuleBundlePayload(_) => { + bail!("Module bundle payload has been removed") }, }; Ok(ret) diff --git a/api/types/src/lib.rs b/api/types/src/lib.rs index 9021adf06d86e..4b81155e80718 100644 --- a/api/types/src/lib.rs +++ b/api/types/src/lib.rs @@ -48,10 +48,10 @@ pub use transaction::{ AccountSignature, BlockMetadataTransaction, DeleteModule, DeleteResource, DeleteTableItem, DirectWriteSet, Ed25519Signature, EncodeSubmissionRequest, EntryFunctionPayload, Event, FeePayerSignature, GasEstimation, GasEstimationBcs, GenesisPayload, GenesisTransaction, - ModuleBundlePayload, MultiAgentSignature, MultiEd25519Signature, MultiKeySignature, - MultisigPayload, MultisigTransactionPayload, PendingTransaction, PublicKey, ScriptPayload, - ScriptWriteSet, Signature, SingleKeySignature, SubmitTransactionRequest, Transaction, - TransactionData, TransactionId, TransactionInfo, TransactionOnChainData, TransactionPayload, + MultiAgentSignature, MultiEd25519Signature, MultiKeySignature, MultisigPayload, + MultisigTransactionPayload, PendingTransaction, PublicKey, ScriptPayload, ScriptWriteSet, + Signature, SingleKeySignature, SubmitTransactionRequest, Transaction, TransactionData, + TransactionId, TransactionInfo, TransactionOnChainData, TransactionPayload, TransactionSignature, TransactionSigningMessage, TransactionsBatchSingleSubmissionFailure, TransactionsBatchSubmissionResult, UserCreateSigningMessageRequest, UserTransaction, UserTransactionRequest, VersionedEvent, WriteModule, WriteResource, WriteSet, WriteSetChange, diff --git a/api/types/src/transaction.rs b/api/types/src/transaction.rs index 9ec1dde2c07ad..efc164df1f751 100755 --- a/api/types/src/transaction.rs +++ b/api/types/src/transaction.rs @@ -654,8 +654,11 @@ pub enum GenesisPayload { pub enum TransactionPayload { EntryFunctionPayload(EntryFunctionPayload), ScriptPayload(ScriptPayload), - // Deprecated. Will be removed in the future. - ModuleBundlePayload(ModuleBundlePayload), + + // Deprecated. We cannot remove the enum variant because it breaks the + // ordering, unfortunately. + ModuleBundlePayload(DeprecatedModuleBundlePayload), + MultisigPayload(MultisigPayload), } @@ -665,26 +668,19 @@ impl VerifyInput for TransactionPayload { TransactionPayload::EntryFunctionPayload(inner) => inner.verify(), TransactionPayload::ScriptPayload(inner) => inner.verify(), TransactionPayload::MultisigPayload(inner) => inner.verify(), - // Deprecated. Will be removed in the future. - TransactionPayload::ModuleBundlePayload(inner) => inner.verify(), + + // Deprecated. + TransactionPayload::ModuleBundlePayload(_) => { + bail!("Module bundle payload has been removed") + }, } } } +// We cannot remove enum variant, but at least we can remove the logic +// and keep a deprecate name here to avoid further usage. #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Object)] -pub struct ModuleBundlePayload { - pub modules: Vec, -} - -impl VerifyInput for ModuleBundlePayload { - fn verify(&self) -> anyhow::Result<()> { - for module in self.modules.iter() { - module.verify()?; - } - - Ok(()) - } -} +pub struct DeprecatedModuleBundlePayload; /// Payload which runs a single entry function #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Object)] diff --git a/aptos-move/aptos-debugger/src/aptos_debugger.rs b/aptos-move/aptos-debugger/src/aptos_debugger.rs index 2da001b843616..6cc92f8508520 100644 --- a/aptos-move/aptos-debugger/src/aptos_debugger.rs +++ b/aptos-move/aptos-debugger/src/aptos_debugger.rs @@ -80,6 +80,11 @@ impl AptosDebugger { let resolver = state_view.as_move_resolver(); let vm = AptosVM::new(&resolver); + // Module bundle is deprecated! + if let TransactionPayload::ModuleBundle(_) = txn.payload() { + anyhow::bail!("Module bundle payload has been removed") + } + let (status, output, gas_profiler) = vm.execute_user_transaction_with_custom_gas_meter( &resolver, &txn, @@ -100,8 +105,12 @@ impl AptosDebugger { entry_func.function().to_owned(), entry_func.ty_args().to_vec(), ), - TransactionPayload::ModuleBundle(..) => unreachable!("not supported"), TransactionPayload::Multisig(..) => unimplemented!("not supported yet"), + + // Deprecated. + TransactionPayload::ModuleBundle(..) => { + unreachable!("Module bundle payload has already been checked") + }, }; Ok(gas_profiler) }, diff --git a/aptos-move/aptos-transactional-test-harness/Cargo.toml b/aptos-move/aptos-transactional-test-harness/Cargo.toml index a461ab5c82925..819565c5e933c 100644 --- a/aptos-move/aptos-transactional-test-harness/Cargo.toml +++ b/aptos-move/aptos-transactional-test-harness/Cargo.toml @@ -28,6 +28,7 @@ bcs = { workspace = true } clap = { workspace = true } hex = { workspace = true } move-binary-format = { workspace = true, features = [ "fuzzing" ] } +move-bytecode-verifier = { workspace = true } move-command-line-common = { workspace = true } move-compiler = { workspace = true } move-core-types = { workspace = true, features = [ "fuzzing" ] } diff --git a/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs b/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs index 9a25a4cabf246..cfcedc563db01 100644 --- a/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs +++ b/aptos-move/aptos-transactional-test-harness/src/aptos_test_harness.rs @@ -22,15 +22,15 @@ use aptos_types::{ state_store::{state_key::StateKey, table::TableHandle, TStateView}, transaction::{ signature_verified_transaction::into_signature_verified_block, - EntryFunction as TransactionEntryFunction, ExecutionStatus, Module as TransactionModule, - RawTransaction, Script as TransactionScript, Transaction, TransactionOutput, - TransactionStatus, + EntryFunction as TransactionEntryFunction, ExecutionStatus, RawTransaction, + Script as TransactionScript, Transaction, TransactionOutput, TransactionStatus, }, }; use aptos_vm::{data_cache::AsMoveResolver, AptosVM, VMExecutor}; use aptos_vm_genesis::GENESIS_KEYPAIR; use clap::Parser; use move_binary_format::file_format::{CompiledModule, CompiledScript}; +use move_bytecode_verifier::verify_module; use move_command_line_common::{ address::ParsedAddress, files::verify_and_create_named_address_mapping, }; @@ -449,20 +449,17 @@ impl<'a> AptosTestAdapter<'a> { let max_number_of_gas_units = TransactionGasParameters::initial().maximum_number_of_gas_units; let gas_unit_price = gas_unit_price.unwrap_or(1000); - let max_gas_amount = match max_gas_amount { - Some(max_gas_amount) => max_gas_amount, - None => { - if gas_unit_price == 0 { - u64::from(max_number_of_gas_units) - } else { - let account_balance = self.fetch_account_balance(signer_addr).unwrap(); - std::cmp::min( - u64::from(max_number_of_gas_units), - account_balance / gas_unit_price, - ) - } - }, - }; + let max_gas_amount = max_gas_amount.unwrap_or_else(|| { + if gas_unit_price == 0 { + u64::from(max_number_of_gas_units) + } else { + let account_balance = self.fetch_account_balance(signer_addr).unwrap(); + std::cmp::min( + u64::from(max_number_of_gas_units), + account_balance / gas_unit_price, + ) + } + }); let expiration_timestamp_secs = expiration_time.unwrap_or(40000); Ok(TransactionParameters { @@ -653,35 +650,27 @@ impl<'a> MoveTestAdapter<'a> for AptosTestAdapter<'a> { &mut self, module: CompiledModule, mut named_addr_opt: Option, - gas_budget: Option, + _gas_budget: Option, extra_args: Self::ExtraPublishArgs, ) -> Result<(Option, CompiledModule)> { - let module_id = module.self_id(); - // TODO: hack to allow the signer to be overridden. // See if we can implement it in a cleaner way. - let signer = match extra_args.override_signer { + let address = match extra_args.override_signer { Some(addr) => { if let ParsedAddress::Named(named_addr) = &addr { named_addr_opt = Some(Identifier::new(named_addr.clone()).unwrap()) } self.compiled_state().resolve_address(&addr) }, - None => *module_id.address(), + None => *module.self_id().address(), }; - - let params = self.fetch_transaction_parameters( - &signer, - extra_args.sequence_number, - extra_args.expiration_time, - extra_args.gas_unit_price, - gas_budget, - )?; + let module_id = ModuleId::new(address, module.self_id().name().to_owned()); let mut module_blob = vec![]; module.serialize(&mut module_blob).unwrap(); - let private_key = match (extra_args.private_key, named_addr_opt) { + // TODO: Do we still need this? + let _private_key = match (extra_args.private_key, named_addr_opt) { (Some(private_key), _) => self.resolve_private_key(&private_key), (None, Some(named_addr)) => match self .private_key_mapping @@ -693,20 +682,11 @@ impl<'a> MoveTestAdapter<'a> for AptosTestAdapter<'a> { (None, None) => panic_missing_private_key("publish"), }; - let txn = RawTransaction::new_module( - signer, - params.sequence_number, - TransactionModule::new(module_blob), - params.max_gas_amount, - params.gas_unit_price, - params.expiration_timestamp_secs, - ChainId::test(), - ) - .sign(&private_key, Ed25519PublicKey::from(&private_key))? - .into_inner(); - - self.run_transaction(Transaction::UserTransaction(txn))?; - + // TODO: HACK! This allows us to publish a module without any checks and bypassing publishing + // through native context. Implement in a cleaner way, and simply run the bytecode verifier + // for now. + verify_module(&module)?; + self.storage.add_module(&module_id, module_blob); Ok((None, module)) } @@ -995,7 +975,5 @@ pub fn run_aptos_test_with_config( path: &Path, config: TestRunConfig, ) -> Result<(), Box> { - // TODO: remove once bundles removed - aptos_vm::aptos_vm::allow_module_bundle_for_test(); run_test_impl::(config, path, Some(&*PRECOMPILED_APTOS_FRAMEWORK)) } diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp index 3de40356eb68b..f7386474fbc02 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/borrow_in_loop.exp @@ -1,7 +1,7 @@ processed 4 tasks task 1 'publish'. lines 4-26: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(STLOC_UNSAFE_TO_DESTROY_ERROR)) +Error: VMError with status STLOC_UNSAFE_TO_DESTROY_ERROR at location Module ModuleId { address: f75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6, name: Identifier("m") } at index 0 for function definition at code offset 11 in function definition 0 task 2 'run'. lines 28-28: Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(LINKER_ERROR)) diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.exp index 30820d3de1b30..24e4a98414a62 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.exp @@ -1,6 +1,14 @@ -processed 4 tasks +processed 5 tasks -task 2 'run'. lines 33-33: +task 2 'run'. lines 32-32: +Events: +{ + type: 0x1::transaction_fee::FeeStatement + data: "36000000000000000300000000000000010000000000000050c30000000000000000000000000000" +}mutable inputs after call: local#0: 0 +return values: 0 + +task 3 'run'. lines 34-34: Events: { type: 0x1::transaction_fee::FeeStatement @@ -8,7 +16,7 @@ Events: }mutable inputs after call: local#0: 0 return values: 0 -task 3 'view'. lines 35-35: +task 4 'view'. lines 36-36: store key 0xf75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6::hello_world::ModuleData { global_counter: 0 state: copy drop store 0x1::string::String { diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.move b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.move index 06571b5f5fc98..2e955cc6c04be 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.move +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/call_function.move @@ -13,7 +13,7 @@ module Alice::hello_world { state: String, } - fun init_module(sender: &signer) { + public entry fun initialize(sender: &signer) { move_to( sender, ModuleData { global_counter: 0, state: string::utf8(b"init") } @@ -29,6 +29,7 @@ module Alice::hello_world { } } +//# run --signers Alice --show-events -- Alice::hello_world::initialize //# run --signers Alice --args x"68656C6C6F20776F726C64" --show-events -- Alice::hello_world::hi diff --git a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp index 1c0972a5089cf..1a1568423f326 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp +++ b/aptos-move/aptos-transactional-test-harness/tests/aptos_test_harness/diamond_clicker.exp @@ -1,7 +1,7 @@ processed 3 tasks task 1 'publish'. lines 4-35: -Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(CALL_TYPE_MISMATCH_ERROR)) +Error: VMError with status CALL_TYPE_MISMATCH_ERROR at location Module ModuleId { address: f75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6, name: Identifier("game") } at index 0 for function definition at code offset 25 in function definition 0 task 2 'run'. lines 37-37: Error: Failed to execute transaction. ExecutionStatus: MiscellaneousError(Some(LINKER_ERROR)) diff --git a/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.exp b/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.exp index 9f346bae872bc..73cea4f9847d5 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.exp +++ b/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.exp @@ -1,6 +1,14 @@ -processed 5 tasks +processed 6 tasks -task 2 'run'. lines 37-37: +task 2 'run'. lines 36-36: +Events: +{ + type: 0x1::transaction_fee::FeeStatement + data: "36000000000000000300000000000000010000000000000050c30000000000000000000000000000" +}mutable inputs after call: local#0: 0 +return values: 0 + +task 3 'run'. lines 38-38: Events: { type: 0x1::transaction_fee::FeeStatement @@ -8,7 +16,7 @@ Events: }mutable inputs after call: local#0: 0 return values: 0 -task 3 'view'. lines 39-39: +task 4 'view'. lines 40-40: store key 0xf75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6::hello_world::ModuleData { global_counter: 0 state: copy drop store 0x1::string::String { @@ -16,5 +24,5 @@ store key 0xf75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6::he } } -task 4 'run'. lines 41-41: +task 5 'run'. lines 42-42: Error: Failed to execute transaction. ExecutionStatus: MoveAbort { location: f75daa73fc071f93593335eb9033da804777eb94491650dd3f095ce6f778acb6::hello_world, code: 12, info: None } diff --git a/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.move b/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.move index a2af0a018d96f..f5a194a5de2ab 100644 --- a/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.move +++ b/aptos-move/aptos-transactional-test-harness/tests/v2-tests/smoke_test.move @@ -13,7 +13,7 @@ module Alice::hello_world { state: String, } - fun init_module(sender: &signer) { + public entry fun initialize(sender: &signer) { move_to( sender, ModuleData { global_counter: 0, state: string::utf8(b"init") } @@ -33,6 +33,7 @@ module Alice::hello_world { } } +//# run --signers Alice --show-events -- Alice::hello_world::initialize //# run --signers Alice --args x"68656C6C6F20776F726C64" --show-events -- Alice::hello_world::hi diff --git a/aptos-move/aptos-vm/src/aptos_vm.rs b/aptos-move/aptos-vm/src/aptos_vm.rs index 421a5404030ca..f9bd3a21600b2 100644 --- a/aptos-move/aptos-vm/src/aptos_vm.rs +++ b/aptos-move/aptos-vm/src/aptos_vm.rs @@ -46,14 +46,9 @@ use aptos_types::{ }, state_store::StateView, transaction::{ - authenticator::AnySignature, - signature_verified_transaction::SignatureVerifiedTransaction, + authenticator::AnySignature, signature_verified_transaction::SignatureVerifiedTransaction, BlockOutput, EntryFunction, ExecutionError, ExecutionStatus, ModuleBundle, Multisig, MultisigTransactionPayload, SignatureCheckedTransaction, SignedTransaction, Transaction, - Transaction::{ - BlockMetadata as BlockMetadataTransaction, GenesisTransaction, StateCheckpoint, - UserTransaction, - }, TransactionOutput, TransactionPayload, TransactionStatus, VMValidatorResult, ViewFunctionOutput, WriteSetPayload, }, @@ -75,9 +70,9 @@ use move_binary_format::{ access::ModuleAccess, compatibility::Compatibility, deserializer::DeserializerConfig, - errors::{verification_error, Location, PartialVMError, PartialVMResult, VMError, VMResult}, + errors::{Location, PartialVMError, PartialVMResult, VMError, VMResult}, file_format_common::{IDENTIFIER_SIZE_MAX, LEGACY_IDENTIFIER_SIZE_MAX}, - CompiledModule, IndexKind, + CompiledModule, }; use move_core_types::{ account_address::AccountAddress, @@ -97,10 +92,7 @@ use std::{ cmp::{max, min}, collections::{BTreeMap, BTreeSet}, marker::Sync, - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, + sync::Arc, }; static EXECUTION_CONCURRENCY_LEVEL: OnceCell = OnceCell::new(); @@ -121,10 +113,13 @@ pub static RAYON_EXEC_POOL: Lazy> = Lazy::new(|| { ) }); -/// Remove this once the bundle is removed from the code. -static MODULE_BUNDLE_DISALLOWED: AtomicBool = AtomicBool::new(true); -pub fn allow_module_bundle_for_test() { - MODULE_BUNDLE_DISALLOWED.store(false, Ordering::Relaxed); +macro_rules! deprecated_module_bundle { + () => { + VMStatus::error( + StatusCode::FEATURE_UNDER_GATING, + Some("Module bundle payload has been removed".to_string()), + ) + }; } macro_rules! unwrap_or_discard { @@ -426,7 +421,7 @@ impl AptosVM { // The transaction should be kept. Run the appropriate post transaction workflows // including epilogue. This runs a new session that ignores any side effects that // might abort the execution (e.g., spending additional funds needed to pay for - // gas). Eeven if the previous failure occurred while running the epilogue, it + // gas). Even if the previous failure occurred while running the epilogue, it // should not fail now. If it somehow fails here, there is no choice but to // discard the transaction. let txn_output = match self.finish_aborted_transaction( @@ -1071,32 +1066,6 @@ impl AptosVM { Ok(respawned_session) } - fn verify_module_bundle( - session: &mut SessionExt, - module_bundle: &ModuleBundle, - ) -> VMResult<()> { - for module_blob in module_bundle.iter() { - match CompiledModule::deserialize_with_config( - module_blob.code(), - &session.get_vm_config().deserializer_config, - ) { - Ok(module) => { - // verify the module doesn't exist - if session.load_module(&module.self_id()).is_ok() { - return Err(verification_error( - StatusCode::DUPLICATE_MODULE_NAME, - IndexKind::AddressIdentifier, - module.self_handle_idx().0, - ) - .finish(Location::Undefined)); - } - }, - Err(err) => return Err(err.finish(Location::Undefined)), - } - } - Ok(()) - } - /// Execute all module initializers. fn execute_module_initialization( &self, @@ -1169,73 +1138,6 @@ impl AptosVM { Ok(result) } - /// Execute a module bundle load request. - /// TODO: this is going to be deprecated and removed in favor of code publishing via - /// NativeCodeContext - fn execute_modules( - &self, - resolver: &impl AptosMoveResolver, - mut session: SessionExt, - gas_meter: &mut impl AptosGasMeter, - txn_data: &TransactionMetadata, - modules: &ModuleBundle, - log_context: &AdapterLogSchema, - new_published_modules_loaded: &mut bool, - change_set_configs: &ChangeSetConfigs, - ) -> Result<(VMStatus, VMOutput), VMStatus> { - if MODULE_BUNDLE_DISALLOWED.load(Ordering::Relaxed) { - return Err(VMStatus::error(StatusCode::FEATURE_UNDER_GATING, None)); - } - fail_point!("move_adapter::execute_module", |_| { - Err(VMStatus::error( - StatusCode::UNKNOWN_INVARIANT_VIOLATION_ERROR, - None, - )) - }); - - gas_meter.charge_intrinsic_gas_for_transaction(txn_data.transaction_size())?; - - Self::verify_module_bundle(&mut session, modules)?; - session.publish_module_bundle_with_compat_config( - modules.clone().into_inner(), - txn_data.sender(), - gas_meter, - Compatibility::new( - true, - true, - !self - .features - .is_enabled(FeatureFlag::TREAT_FRIEND_AS_PRIVATE), - ), - )?; - - // call init function of the each module - self.execute_module_initialization( - &mut session, - gas_meter, - &self.deserialize_module_bundle(modules)?, - BTreeSet::new(), - &[txn_data.sender()], - new_published_modules_loaded, - )?; - - let respawned_session = self.charge_change_set_and_respawn_session( - session, - resolver, - gas_meter, - change_set_configs, - txn_data, - )?; - - self.success_transaction_cleanup( - respawned_session, - gas_meter, - txn_data, - log_context, - change_set_configs, - ) - } - /// Resolve a pending code publish request registered via the NativeCodeContext. fn resolve_pending_code_publish( &self, @@ -1560,17 +1462,13 @@ impl AptosVM { } }, - // Deprecated. Will be removed in the future. - TransactionPayload::ModuleBundle(m) => self.execute_modules( - resolver, - session, - gas_meter, - &txn_data, - m, - log_context, - &mut new_published_modules_loaded, - &storage_gas_params.change_set_configs, - ), + // Deprecated. We cannot make this `unreachable!` because a malicious + // validator can craft this transaction and cause the node to panic. + TransactionPayload::ModuleBundle(_) => { + let vm_status = deprecated_module_bundle!(); + let discarded_output = discarded_output(vm_status.status_code()); + return (vm_status, discarded_output); + }, }; let gas_usage = txn_data @@ -1973,13 +1871,6 @@ impl AptosVM { txn_data: &TransactionMetadata, log_context: &AdapterLogSchema, ) -> Result<(), VMStatus> { - // Deprecated. Will be removed in the future. - if matches!(payload, TransactionPayload::ModuleBundle(_)) - && MODULE_BUNDLE_DISALLOWED.load(Ordering::Relaxed) - { - return Err(VMStatus::error(StatusCode::FEATURE_UNDER_GATING, None)); - } - check_gas( get_or_vm_startup_failure(&self.gas_params, log_context)?, self.gas_feature_version, @@ -2012,10 +1903,9 @@ impl AptosVM { Ok(()) } }, - // Deprecated. Will be removed in the future. - TransactionPayload::ModuleBundle(_module) => { - transaction_validation::run_module_prologue(session, txn_data, log_context) - }, + + // Deprecated. + TransactionPayload::ModuleBundle(_) => Err(deprecated_module_bundle!()), } } @@ -2045,7 +1935,7 @@ impl AptosVM { } Ok(match txn.expect_valid() { - BlockMetadataTransaction(block_metadata) => { + Transaction::BlockMetadata(block_metadata) => { fail_point!("aptos_vm::execution::block_metadata"); let (vm_status, output) = self.process_block_prologue(resolver, block_metadata.clone(), log_context)?; @@ -2060,7 +1950,7 @@ impl AptosVM { )?; (vm_status, output, Some("block_prologue_ext".to_string())) }, - GenesisTransaction(write_set_payload) => { + Transaction::GenesisTransaction(write_set_payload) => { let (vm_status, output) = self.process_waypoint_change_set( resolver, write_set_payload.clone(), @@ -2068,7 +1958,7 @@ impl AptosVM { )?; (vm_status, output, Some("waypoint_write_set".to_string())) }, - UserTransaction(txn) => { + Transaction::UserTransaction(txn) => { fail_point!("aptos_vm::execution::user_transaction"); let sender = txn.sender().to_hex(); let _timer = TXN_TOTAL_SECONDS.start_timer(); @@ -2143,7 +2033,7 @@ impl AptosVM { } (vm_status, output, Some(sender)) }, - StateCheckpoint(_) => { + Transaction::StateCheckpoint(_) => { let status = TransactionStatus::Keep(ExecutionStatus::Success); let output = VMOutput::empty_with_status(status); (VMStatus::Executed, output, Some("state_checkpoint".into())) diff --git a/aptos-move/aptos-vm/src/transaction_metadata.rs b/aptos-move/aptos-vm/src/transaction_metadata.rs index 909859ed95d6d..bd39cc629c822 100644 --- a/aptos-move/aptos-vm/src/transaction_metadata.rs +++ b/aptos-move/aptos-vm/src/transaction_metadata.rs @@ -56,7 +56,8 @@ impl TransactionMetadata { TransactionPayload::EntryFunction(_) => vec![], TransactionPayload::Multisig(_) => vec![], - // Deprecated. Will be removed in the future. + // Deprecated. Return an empty vec because we cannot do anything + // else here, only `unreachable!` otherwise. TransactionPayload::ModuleBundle(_) => vec![], }, script_size: match txn.payload() { diff --git a/aptos-move/aptos-vm/src/transaction_validation.rs b/aptos-move/aptos-vm/src/transaction_validation.rs index 0aac37c8d438f..cb4ca1a0a558c 100644 --- a/aptos-move/aptos-vm/src/transaction_validation.rs +++ b/aptos-move/aptos-vm/src/transaction_validation.rs @@ -30,7 +30,6 @@ use move_core_types::{ use move_vm_runtime::logging::expect_no_verification_errors; use move_vm_types::gas::UnmeteredGasMeter; use once_cell::sync::Lazy; -use serde::{Deserialize, Serialize}; pub static APTOS_TRANSACTION_VALIDATION: Lazy = Lazy::new(|| TransactionValidation { @@ -38,20 +37,18 @@ pub static APTOS_TRANSACTION_VALIDATION: Lazy = module_name: Identifier::new("transaction_validation").unwrap(), fee_payer_prologue_name: Identifier::new("fee_payer_script_prologue").unwrap(), script_prologue_name: Identifier::new("script_prologue").unwrap(), - module_prologue_name: Identifier::new("module_prologue").unwrap(), multi_agent_prologue_name: Identifier::new("multi_agent_script_prologue").unwrap(), user_epilogue_name: Identifier::new("epilogue").unwrap(), user_epilogue_gas_payer_name: Identifier::new("epilogue_gas_payer").unwrap(), }); /// On-chain functions used to validate transactions -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Debug)] pub struct TransactionValidation { pub module_addr: AccountAddress, pub module_name: Identifier, pub fee_payer_prologue_name: Identifier, pub script_prologue_name: Identifier, - pub module_prologue_name: Identifier, pub multi_agent_prologue_name: Identifier, pub user_epilogue_name: Identifier, pub user_epilogue_gas_payer_name: Identifier, @@ -150,40 +147,6 @@ pub(crate) fn run_script_prologue( .or_else(|err| convert_prologue_error(err, log_context)) } -// Deprecated (see ModuleBundle). -pub(crate) fn run_module_prologue( - session: &mut SessionExt, - txn_data: &TransactionMetadata, - log_context: &AdapterLogSchema, -) -> Result<(), VMStatus> { - let txn_sequence_number = txn_data.sequence_number(); - let txn_authentication_key = txn_data.authentication_key(); - let txn_gas_price = txn_data.gas_unit_price(); - let txn_max_gas_units = txn_data.max_gas_amount(); - let txn_expiration_timestamp_secs = txn_data.expiration_timestamp_secs(); - let chain_id = txn_data.chain_id(); - let mut gas_meter = UnmeteredGasMeter; - session - .execute_function_bypass_visibility( - &APTOS_TRANSACTION_VALIDATION.module_id(), - &APTOS_TRANSACTION_VALIDATION.module_prologue_name, - vec![], - serialize_values(&vec![ - MoveValue::Signer(txn_data.sender), - MoveValue::U64(txn_sequence_number), - MoveValue::vector_u8(txn_authentication_key.to_vec()), - MoveValue::U64(txn_gas_price.into()), - MoveValue::U64(txn_max_gas_units.into()), - MoveValue::U64(txn_expiration_timestamp_secs), - MoveValue::U8(chain_id.id()), - ]), - &mut gas_meter, - ) - .map(|_return_vals| ()) - .map_err(expect_no_verification_errors) - .or_else(|err| convert_prologue_error(err, log_context)) -} - /// Run the prologue for a multisig transaction. This needs to verify that: /// 1. The the multisig tx exists /// 2. It has received enough approvals to meet the signature threshold of the multisig account diff --git a/aptos-move/e2e-move-tests/src/tests/access_path_test.rs b/aptos-move/e2e-move-tests/src/tests/access_path_test.rs index 5a068c1c26bd5..895c38c1c52ba 100644 --- a/aptos-move/e2e-move-tests/src/tests/access_path_test.rs +++ b/aptos-move/e2e-move-tests/src/tests/access_path_test.rs @@ -1,11 +1,9 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::{assert_success, MoveHarness}; +use crate::MoveHarness; use aptos_types::{ - account_address::AccountAddress, - move_utils::MemberId, - transaction::{ExecutionStatus, ModuleBundle, TransactionPayload}, + account_address::AccountAddress, move_utils::MemberId, transaction::ExecutionStatus, }; use move_binary_format::{ file_format::{ @@ -99,11 +97,7 @@ fn access_path_panic() { let mut h = MoveHarness::new(); let acc = h.new_account_at(addr); - let publish_tx_res = h.create_transaction_payload( - &acc, - TransactionPayload::ModuleBundle(ModuleBundle::singleton(module_bytes)), - ); - assert_success!(h.run(publish_tx_res)); + h.executor.add_module(&cm.self_id(), module_bytes); let res = h.run_entry_function( &acc, diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp index 51c45c78d8bd3..3cbbb2c13121f 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__borrow_after_move.exp @@ -1,32 +1,3 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000090100040204040308190521140735420877400ab701050cbc014f0d8b020200000101000208000003000100000402010000050001000006000100010800040001060c0002060c03010608000105010708000103014d067369676e657202543109626f72726f775f7431096368616e67655f74310972656d6f76655f74310a7075626c6973685f743101760a616464726573735f6f66f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000000000000000000000000000000000010002010703000100010003050b0011042b000c0102010100010005090b0011042a000c020b010b020f001502020100010006060b0011042c0013000c01020301000001050b0006030000000000000012002d0002000000, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) Ok( [ TransactionOutput { diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp index b47d321dced8a..95dbaf44731f2 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__change_after_move.exp @@ -1,32 +1,3 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000090100040204040308190521140735420877400ab701050cbc014f0d8b020200000101000208000003000100000402010000050001000006000100010800040001060c0002060c03010608000105010708000103014d067369676e657202543109626f72726f775f7431096368616e67655f74310972656d6f76655f74310a7075626c6973685f743101760a616464726573735f6f66f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000000000000000000000000000000000010002010703000100010003050b0011042b000c0102010100010005090b0011042a000c020b010b020f001502020100010006060b0011042c0013000c01020301000001050b0006030000000000000012002d0002000000, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) Ok( [ TransactionOutput { diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp index a1e1e6b120a76..9e21b72f293fc 100644 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp +++ b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__data_store__move_from_across_blocks.exp @@ -1,32 +1,3 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000090100040204040308190521140735420877400ab701050cbc014f0d8b020200000101000208000003000100000402010000050001000006000100010800040001060c0002060c03010608000105010708000103014d067369676e657202543109626f72726f775f7431096368616e67655f74310972656d6f76655f74310a7075626c6973685f743101760a616464726573735f6f66f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000000000000000000000000000000000010002010703000100010003050b0011042b000c0102010100010005090b0011042a000c020b010b020f001502020100010006060b0011042c0013000c01020301000001050b0006030000000000000012002d0002000000, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) Ok( [ TransactionOutput { diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__failed_transaction_cleanup_test_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__failed_transaction_cleanup_test_version_4.exp deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__non_existent_sender_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__non_existent_sender_version_4.exp deleted file mode 100644 index 0f133e3cf2294..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__failed_transaction_tests__non_existent_sender_version_4.exp +++ /dev/null @@ -1,18 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - SENDING_ACCOUNT_DOES_NOT_EXIST, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__mint__mint_to_new_account_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__mint__mint_to_new_account_version_4.exp deleted file mode 100644 index f83568b70da8d..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__mint__mint_to_new_account_version_4.exp +++ /dev/null @@ -1,66 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000000000000000000000000000000000000000000000000000000000a550c18, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201304972f9242cbc3528a1e286323471ab891baa37e0053b85651693a79854a000100000000000000040000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a550c1800000000000000000100000000000000000000000000000000000000000000000000000000000000000000000a550c180000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20a10700000000000001000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - TableItem { - handle: TableHandle( - 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, - ), - key: [ - 6, - 25, - 220, - 41, - 160, - 170, - 200, - 250, - 20, - 103, - 20, - 5, - 142, - 141, - 214, - 210, - 208, - 243, - 189, - 245, - 246, - 51, - 25, - 7, - 191, - 145, - 243, - 172, - 216, - 30, - 105, - 53, - ], - }: Modification(1f82fd05000000000100000000000000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "20a1070000000000" }, - ], - gas_used: 439, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__bad_module_address.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__bad_module_address.exp deleted file mode 100644 index 7bca678b8ffb2..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__bad_module_address.exp +++ /dev/null @@ -1,37 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xd88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: "Resource(0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>)" }, - hash: OnceCell(Uninit), - }: Modification(3d420f00000000000000000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: AccessPath { address: 0xd88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380b00000000000000000000000000000000000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000100000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380000, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: TableItem { handle: 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, key: 0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935 }, - hash: OnceCell(Uninit), - }: Modification(fce0f505000000000100000000000000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - MODULE_ADDRESS_DOES_NOT_MATCH_SENDER, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__duplicate_module.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__duplicate_module.exp deleted file mode 100644 index 6796da0e574f7..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__duplicate_module.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000008010002020204030605050b01070c060812200a32050c3707000000010000000200000000014d01540166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100020102030001000000010200, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_compatible_module.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_compatible_module.exp deleted file mode 100644 index dbcbbe7cb3418..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_compatible_module.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000030100020702020804200000014df5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_changed_field.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_changed_field.exp deleted file mode 100644 index e1bd11888a305..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_changed_field.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000005010002020204070606080c200a2c05000000010000014d01540166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1000201020300, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_new_field.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_new_field.exp deleted file mode 100644 index e1bd11888a305..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_new_field.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000005010002020204070606080c200a2c05000000010000014d01540166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1000201020300, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_field.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_field.exp deleted file mode 100644 index e1bd11888a305..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_field.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000005010002020204070606080c200a2c05000000010000014d01540166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1000201020300, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_struct.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_struct.exp deleted file mode 100644 index e1bd11888a305..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__layout_incompatible_module_with_removed_struct.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000005010002020204070606080c200a2c05000000010000014d01540166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1000201020300, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_compatible_module.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_compatible_module.exp deleted file mode 100644 index dbcbbe7cb3418..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_compatible_module.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000030100020702020804200000014df5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_added_param.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_added_param.exp deleted file mode 100644 index 5cc2fce35b2e5..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_added_param.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000006010002030205050701070804080c200c2c070000000100000000014d0166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001000000010200, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_changed_param.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_changed_param.exp deleted file mode 100644 index ce02953eb881e..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_changed_param.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000006010002030205050703070a04080e200c2e0700000001000100010300014d0166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001000001010200, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_removed_pub_fn.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_removed_pub_fn.exp deleted file mode 100644 index 5cc2fce35b2e5..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__linking_incompatible_module_with_removed_pub_fn.exp +++ /dev/null @@ -1,58 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b0600000006010002030205050701070804080c200c2c070000000100000000014d0166f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001000000010200, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - DUPLICATE_MODULE_NAME, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_allow_modules.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_allow_modules.exp deleted file mode 100644 index a4509c64732ee..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_allow_modules.exp +++ /dev/null @@ -1,29 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000030100020702020804200000014df5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_invalid_sender.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_invalid_sender.exp deleted file mode 100644 index e36ddad8f2592..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_invalid_sender.exp +++ /dev/null @@ -1,29 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - MODULE_ADDRESS_DOES_NOT_MATCH_SENDER, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_proper_sender.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_proper_sender.exp deleted file mode 100644 index 234d916d46d5b..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__module_publishing__test_publishing_modules_proper_sender.exp +++ /dev/null @@ -1,29 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xa550c18, path: "Code(000000000000000000000000000000000000000000000000000000000a550c18::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b06000000030100020702020804200000014d000000000000000000000000000000000000000000000000000000000a550c1800, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 0, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xa550c18, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(201304972f9242cbc3528a1e286323471ab891baa37e0053b85651693a79854a000100000000000000040000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a550c1800000000000000000100000000000000000000000000000000000000000000000000000000000000000000000a550c180000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000010000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__drop_txn_after_reconfiguration_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__drop_txn_after_reconfiguration_version_4.exp deleted file mode 100644 index a8926f5554c9b..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__drop_txn_after_reconfiguration_version_4.exp +++ /dev/null @@ -1,130 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 01000000000000000000000000000000000000000000000000000000000000000105626c6f636b0d426c6f636b5265736f7572636500 }, - ): Modification(010000000000000000a493d600000000020000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000001), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b651456616c696461746f72506572666f726d616e636500 }, - ): Modification(0101000000000000000000000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010974696d657374616d701743757272656e7454696d654d6963726f7365636f6e647300 }, - ): Modification(0100000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010d73746174655f73746f7261676511537461746553746f72616765557361676500 }, - ): Modification(010000000000000000000000000000000000000000000000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 3, account_address: 0000000000000000000000000000000000000000000000000000000000000001 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("block"), name: Identifier("NewBlockEvent"), type_params: [] }), event_data: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36000100000000000000" }, - ], - gas_used: 0, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b650c56616c696461746f7253657400 }, - ): Modification(0001d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3675e5f505000000003086fb211f41a07c6399ccc6ab3a8fe568fb0f574ce1b811896c44c6da4f267d543c6cac9fb8f4e9b92a3b809eefb91cbd00000000000000000000000075e5f50500000000000000000000000000000000000000000000000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b651456616c696461746f72506572666f726d616e636500 }, - ): Modification(0100000000000000000000000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201304972f9242cbc3528a1e286323471ab891baa37e0053b85651693a79854a00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010776657273696f6e0756657273696f6e00 }, - ): Modification(0500000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010b73746f726167655f6761730a53746f7261676547617300 }, - ): Modification(803801000000000080841e0000000000801a0600000000002800000000000000e803000000000000c800000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010f7265636f6e66696775726174696f6e0d436f6e66696775726174696f6e00 }, - ): Modification(02000000000000000100000000000000020000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000001), - AccessPath( - AccessPath { address: d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b65095374616b65506f6f6c00 }, - ): Modification(75e5f50500000000000000000000000000000000000000000000000000000000201c000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000400000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000500000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000600000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000700000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000800000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000900000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000a00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000b00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000c00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000d00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000e00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000f00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36), - AccessPath( - AccessPath { address: d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b650f56616c696461746f72436f6e66696700 }, - ): Modification(3086fb211f41a07c6399ccc6ab3a8fe568fb0f574ce1b811896c44c6da4f267d543c6cac9fb8f4e9b92a3b809eefb91cbd00000000000000000000), - TableItem { - handle: TableHandle( - 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, - ), - key: [ - 6, - 25, - 220, - 41, - 160, - 170, - 200, - 250, - 20, - 103, - 20, - 5, - 142, - 141, - 214, - 210, - 208, - 243, - 189, - 245, - 246, - 51, - 25, - 7, - 191, - 145, - 243, - 172, - 216, - 30, - 105, - 53, - ], - }: Modification(74e5f505000000000100000000000000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 12, account_address: d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("stake"), name: Identifier("DistributeRewardsEvent"), type_params: [] }), event_data: "d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c367504000000000000" }, - ContractEvent { key: EventKey { creation_number: 2, account_address: 0000000000000000000000000000000000000000000000000000000000000001 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("reconfiguration"), name: Identifier("NewEpochEvent"), type_params: [] }), event_data: "0200000000000000" }, - ], - gas_used: 2191, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Retry, - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__initial_aptos_version_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__initial_aptos_version_version_4.exp deleted file mode 100644 index 93458c7f6d6e5..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__on_chain_configs__initial_aptos_version_version_4.exp +++ /dev/null @@ -1,118 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 01000000000000000000000000000000000000000000000000000000000000000105626c6f636b0d426c6f636b5265736f7572636500 }, - ): Modification(010000000000000000a493d600000000020000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000001), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b651456616c696461746f72506572666f726d616e636500 }, - ): Modification(0101000000000000000000000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010974696d657374616d701743757272656e7454696d654d6963726f7365636f6e647300 }, - ): Modification(0100000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010d73746174655f73746f7261676511537461746553746f72616765557361676500 }, - ): Modification(010000000000000000000000000000000000000000000000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 3, account_address: 0000000000000000000000000000000000000000000000000000000000000001 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("block"), name: Identifier("NewBlockEvent"), type_params: [] }), event_data: "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36000100000000000000" }, - ], - gas_used: 0, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b650c56616c696461746f7253657400 }, - ): Modification(0001d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3675e5f505000000003086fb211f41a07c6399ccc6ab3a8fe568fb0f574ce1b811896c44c6da4f267d543c6cac9fb8f4e9b92a3b809eefb91cbd00000000000000000000000075e5f50500000000000000000000000000000000000000000000000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b651456616c696461746f72506572666f726d616e636500 }, - ): Modification(0100000000000000000000000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201304972f9242cbc3528a1e286323471ab891baa37e0053b85651693a79854a00010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010776657273696f6e0756657273696f6e00 }, - ): Modification(0500000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010b73746f726167655f6761730a53746f7261676547617300 }, - ): Modification(803801000000000080841e0000000000801a0600000000002800000000000000e803000000000000c800000000000000), - AccessPath( - AccessPath { address: 0000000000000000000000000000000000000000000000000000000000000001, path: 0100000000000000000000000000000000000000000000000000000000000000010f7265636f6e66696775726174696f6e0d436f6e66696775726174696f6e00 }, - ): Modification(02000000000000000100000000000000020000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000001), - AccessPath( - AccessPath { address: d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b65095374616b65506f6f6c00 }, - ): Modification(75e5f50500000000000000000000000000000000000000000000000000000000201c000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000400000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000500000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000600000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000700000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000800000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000900000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000a00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000b00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3601000000000000000c00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000d00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000e00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c3600000000000000000f00000000000000d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36), - AccessPath( - AccessPath { address: d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36, path: 010000000000000000000000000000000000000000000000000000000000000001057374616b650f56616c696461746f72436f6e66696700 }, - ): Modification(3086fb211f41a07c6399ccc6ab3a8fe568fb0f574ce1b811896c44c6da4f267d543c6cac9fb8f4e9b92a3b809eefb91cbd00000000000000000000), - TableItem { - handle: TableHandle( - 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, - ), - key: [ - 6, - 25, - 220, - 41, - 160, - 170, - 200, - 250, - 20, - 103, - 20, - 5, - 142, - 141, - 214, - 210, - 208, - 243, - 189, - 245, - 246, - 51, - 25, - 7, - 191, - 145, - 243, - 172, - 216, - 30, - 105, - 53, - ], - }: Modification(74e5f505000000000100000000000000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 12, account_address: d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c36 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("stake"), name: Identifier("DistributeRewardsEvent"), type_params: [] }), event_data: "d1126ce48bd65fb72190dbd9a6eaa65ba973f1e1664ac0cfba4db1d071fd0c367504000000000000" }, - ContractEvent { key: EventKey { creation_number: 2, account_address: 0000000000000000000000000000000000000000000000000000000000000001 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("reconfiguration"), name: Identifier("NewEpochEvent"), type_params: [] }), event_data: "0200000000000000" }, - ], - gas_used: 2191, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__basic.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__basic.exp deleted file mode 100644 index b4f4800c696df..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__basic.exp +++ /dev/null @@ -1,70 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b000001066d795f6d6f64d6010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f28733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(00300f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0d0818200c38070000000100010001060c00066d795f6d6f640568656c6c6ff5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4672, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(a72d0f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ], - }, - ), - events: [], - gas_used: 601, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_compat.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_compat.exp deleted file mode 100644 index 0f455a8b5064c..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_compat.exp +++ /dev/null @@ -1,74 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b010001066d795f6d6f64d7010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f3128733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(fa2f0f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0e0819200c39070000000100010001060c00066d795f6d6f640668656c6c6f31f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4678, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(62200f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ], - }, - ), - events: [], - gas_used: 3992, - status: Keep( - MiscellaneousError( - Some( - BACKWARD_INCOMPATIBLE_MODULE_UPDATE, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_immutable.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_immutable.exp deleted file mode 100644 index c5da2e81ffd9f..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_immutable.exp +++ /dev/null @@ -1,73 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b020001066d795f6d6f64d6010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f28733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(00300f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0d0818200c38070000000100010001060c00066d795f6d6f640568656c6c6ff5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4672, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(2e240f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ], - }, - ), - events: [], - gas_used: 3026, - status: Keep( - MoveAbort { - location: 0000000000000000000000000000000000000000000000000000000000000001::code, - code: 65538, - }, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_overlapping_module.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_overlapping_module.exp deleted file mode 100644 index ba961ca2c827a..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_fail_overlapping_module.exp +++ /dev/null @@ -1,73 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b000001066d795f6d6f64d6010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f28733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(00300f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0d0818200c38070000000100010001060c00066d795f6d6f640568656c6c6ff5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4672, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(491b0f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ], - }, - ), - events: [], - gas_used: 5303, - status: Keep( - MoveAbort { - location: 0000000000000000000000000000000000000000000000000000000000000001::code, - code: 524289, - }, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_compat.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_compat.exp deleted file mode 100644 index 8bfe075dcbd81..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_compat.exp +++ /dev/null @@ -1,82 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b010001066d795f6d6f64d7010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f3028733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(fa2f0f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0e0819200c39070000000100010001060c00066d795f6d6f640668656c6c6f30f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4678, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b010001066d795f6d6f64b8020a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f3028733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20207075626c696320656e7472792068656c6c6f3128733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(a51e0f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b050000000601000203020a050c040710150825200c450e00000001000100000200010001060c00066d795f6d6f640668656c6c6f300668656c6c6f31f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1000104000101020101040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4437, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_no_compat.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_no_compat.exp deleted file mode 100644 index 94e1fee90359d..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__package_publishing__upgrade_success_no_compat.exp +++ /dev/null @@ -1,82 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b000001066d795f6d6f64d7010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f3128733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(fa2f0f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0e0819200c39070000000100010001060c00066d795f6d6f640668656c6c6f31f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 4678, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: WriteSet( - WriteSetMut { - write_set: [ - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ), - Value(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f64650f5061636b616765526567697374727900 }, - ), - Value(01076d795f7061636b000001066d795f6d6f64d7010a20202020202020206d6f64756c65203078463542394436463031413939453734433739304532463333304330393246413035343535413831393346314446433142313133454343353444303637414645312e6d795f6d6f64207b0a202020202020202020207075626c696320656e7472792068656c6c6f3228733a20267369676e657229207b0a20202020202020202020202020206c6162656c206c303a0a202020202020202020202020202072657475726e3b0a202020202020202020202020207d0a20202020202020207d0a20202020202020200000), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ), - Value(62200f000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - ), - ( - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 00f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1066d795f6d6f64 }, - ), - Value(a11ceb0b0500000006010002030205050704070b0e0819200c39070000000100010001060c00066d795f6d6f640668656c6c6f32f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001040001010200), - ), - ], - }, - ), - events: [], - gas_used: 3992, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_multi_block_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_multi_block_version_4.exp deleted file mode 100644 index 122c075664f20..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_multi_block_version_4.exp +++ /dev/null @@ -1,2720 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62), - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013801000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380b00000000000000000000000000000000000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000100000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7), - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62), - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620b0000000000000000000000000000000000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000000000000000010000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7), - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb70b000000000000000000000000000000000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7000000000000000001000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb70000), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c00000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c01000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c0b00000000000000000000000000000000000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c00000000000000000100000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd), - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0b0000000000000000000000000000000000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000000000000000010000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589900000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a00000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589901000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf58990b00000000000000000000000000000000000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589900000000000000000100000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf58990000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a01000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a), - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a0b00000000000000000000000000000000000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a00000000000000000100000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a0000), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a00000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52500000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a01000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a0b00000000000000000000000000000000000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a00000000000000000100000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52501000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525), - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca5250b00000000000000000000000000000000000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52500000000000000000100000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca5250000), - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d00000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d01000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d), - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d0b00000000000000000000000000000000000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d00000000000000000100000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d0000), - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde), - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde0b000000000000000000000000000000000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde000000000000000001000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde0000), - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67100000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67101000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671), - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e6710b00000000000000000000000000000000000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67100000000000000000100000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e6710000), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78300000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78301000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a7830b00000000000000000000000000000000000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78300000000000000000100000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a7830000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1), - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae10b000000000000000000000000000000000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1000000000000000001000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae10000), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e00000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e01000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e0b00000000000000000000000000000000000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e00000000000000000100000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20), - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860), - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac638600b00000000000000000000000000000000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386000000000000000000100000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac638600000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20), - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c200b000000000000000000000000000000000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20000000000000000001000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c200000), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da00000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952700000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da01000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da0b00000000000000000000000000000000000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da00000000000000000100000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952701000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527), - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb295270b00000000000000000000000000000000000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952700000000000000000100000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb295270000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080), - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924101000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241), - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe992410b00000000000000000000000000000000000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924100000000000000000100000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe992410000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080), - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff8189930800b00000000000000000000000000000000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308000000000000000000100000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff8189930800000), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca00000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca01000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca0b00000000000000000000000000000000000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca00000000000000000100000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a), - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a), - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a0b000000000000000000000000000000000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a000000000000000001000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a), - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0b0000000000000000000000000000000000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000000000000000010000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000), - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6), - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f60b000000000000000000000000000000000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6000000000000000001000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f60000), - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb), - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0b0000000000000000000000000000000000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000000000000000010000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403100000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403101000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec450640310b00000000000000000000000000000000000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403100000000000000000100000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec450640310000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2), - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06), - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f060b000000000000000000000000000000000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06000000000000000001000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f060000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2), - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20b0000000000000000000000000000000000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000000000000000010000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070b0000000000000000000000000000000000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000000000000000010000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a), - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a0b000000000000000000000000000000000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a000000000000000001000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a0000), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93900000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f00000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93901000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d9390b00000000000000000000000000000000000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93900000000000000000100000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d9390000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f01000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f), - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f0b00000000000000000000000000000000000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f00000000000000000100000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f0000), - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71), - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe710b000000000000000000000000000000000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71000000000000000001000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe710000), - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f), - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f0b000000000000000000000000000000000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f000000000000000001000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f0000), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490900000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490901000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced4549090b00000000000000000000000000000000000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490900000000000000000100000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced4549090000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed), - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(200d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed0b000000000000000000000000000000000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed000000000000000001000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed0000), - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9), - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90b0000000000000000000000000000000000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000000000000000010000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37100000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924101000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37101000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb3710b00000000000000000000000000000000000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37100000000000000000100000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb3710000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1), - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10b0000000000000000000000000000000000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000000000000000010000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b400000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b401000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b40b00000000000000000000000000000000000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b400000000000000000100000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3), - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf), - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(208b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf0b000000000000000000000000000000000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf000000000000000001000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3), - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de30b000000000000000000000000000000000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3000000000000000001000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de30000), - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925), - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c39250b000000000000000000000000000000000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925000000000000000001000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c39250000), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc66730b000000000000000000000000000000000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673000000000000000001000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc66730000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479), - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790b0000000000000000000000000000000000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000000000000000010000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(207b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b80b000000000000000000000000000000000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8000000000000000001000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b80000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e), - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e0b000000000000000000000000000000000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e000000000000000001000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e0000), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e500000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e501000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e50b00000000000000000000000000000000000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e500000000000000000100000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e50000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1401000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140b00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f00000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f01000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f0b00000000000000000000000000000000000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f00000000000000000100000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f0000), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6500000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f00000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6501000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e650b00000000000000000000000000000000000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6500000000000000000100000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e650000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f01000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f0b00000000000000000000000000000000000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f00000000000000000100000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33), - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(207fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b330b000000000000000000000000000000000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33000000000000000001000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b330000), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de00000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e00000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de01000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de0b00000000000000000000000000000000000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de00000000000000000100000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70500000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e01000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e0b00000000000000000000000000000000000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e00000000000000000100000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70501000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705), - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e7050b00000000000000000000000000000000000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70500000000000000000100000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e7050000), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a400000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd100000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a401000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a40b00000000000000000000000000000000000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a400000000000000000100000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1), - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd101000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1), - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd10b00000000000000000000000000000000000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd100000000000000000100000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce500000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c01000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c0b00000000000000000000000000000000000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c00000000000000000100000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce501000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce50b00000000000000000000000000000000000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce500000000000000000100000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce50000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8), - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76), - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba760b000000000000000000000000000000000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76000000000000000001000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba760000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8), - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae80b000000000000000000000000000000000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8000000000000000001000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae80000), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b00000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e100000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b01000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b0b00000000000000000000000000000000000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b00000000000000000100000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e101000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e10b00000000000000000000000000000000000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e100000000000000000100000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559), - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f), - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0b0000000000000000000000000000000000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000000000000000010000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559), - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a5590b000000000000000000000000000000000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559000000000000000001000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a5590000), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b00000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2800000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b01000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b0b00000000000000000000000000000000000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b00000000000000000100000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad), - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2801000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28), - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be280b00000000000000000000000000000000000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2800000000000000000100000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be280000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad), - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0b0000000000000000000000000000000000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000000000000000010000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe100000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe101000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe10b00000000000000000000000000000000000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe100000000000000000100000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe10000), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0400000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df00000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0401000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d040b00000000000000000000000000000000000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0400000000000000000100000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d040000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df01000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df), - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df0b00000000000000000000000000000000000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df00000000000000000100000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df0000), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c30b000000000000000000000000000000000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3000000000000000001000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c30000), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817200000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817201000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac781720b00000000000000000000000000000000000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817200000000000000000100000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac781720000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8), - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e80b000000000000000000000000000000000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8000000000000000001000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e80000), - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c), - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c0b000000000000000000000000000000000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c000000000000000001000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c0000), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378100000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4200000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378101000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f9ff3690146bbcd9388221112019585859153db829a26325a230334314c437810b00000000000000000000000000000000000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378100000000000000000100000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c437810000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4201000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42), - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce420b00000000000000000000000000000000000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4200000000000000000100000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce420000), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c01000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c01000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c), - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c0b00000000000000000000000000000000000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c00000000000000000100000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c0000), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1600000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f00000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1601000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d160b00000000000000000000000000000000000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1600000000000000000100000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d160000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f01000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f), - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f0b00000000000000000000000000000000000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f00000000000000000100000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f0000), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f20b000000000000000000000000000000000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2000000000000000001000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f20000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888), - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05), - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba050b000000000000000000000000000000000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05000000000000000001000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba050000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888), - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880b0000000000000000000000000000000000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000000000000000010000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c00000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914800000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c01000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c0b00000000000000000000000000000000000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c00000000000000000100000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914801000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb91480b00000000000000000000000000000000000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914800000000000000000100000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb91480000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c), - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c0b000000000000000000000000000000000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c000000000000000001000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c0000), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a600000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a601000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a60b00000000000000000000000000000000000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a600000000000000000100000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a60000), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410600000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410601000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e741060b00000000000000000000000000000000000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410600000000000000000100000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e741060000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17), - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(200deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff170b000000000000000000000000000000000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17000000000000000001000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff170000), - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf00000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf01000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf), - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf0b00000000000000000000000000000000000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf00000000000000000100000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf0000), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c400000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c401000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c40b00000000000000000000000000000000000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c400000000000000000100000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca), - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a), - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0b0000000000000000000000000000000000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000000000000000010000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca), - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca0b000000000000000000000000000000000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca000000000000000001000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca0000), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0500000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0501000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab050b00000000000000000000000000000000000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0500000000000000000100000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab050000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1), - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10b0000000000000000000000000000000000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000000000000000010000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f0000000000000100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f000000000000010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f0000000000000100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0b0000000000000000000000000000000000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000000000000000010000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f000000000000010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29), - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a290b000000000000000000000000000000000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29000000000000000001000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a290000), - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40420f00000000000001000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c01000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_version_4.exp deleted file mode 100644 index 0cbccbe720c04..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__cycle_peer_to_peer_version_4.exp +++ /dev/null @@ -1,2704 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(98801e00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62), - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013801000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380b00000000000000000000000000000000000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000100000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7), - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62), - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620b0000000000000000000000000000000000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000000000000000010000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7), - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb70b000000000000000000000000000000000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7000000000000000001000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb70000), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c00000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c01000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c0b00000000000000000000000000000000000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c00000000000000000100000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd), - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0b0000000000000000000000000000000000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000000000000000010000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589900000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a00000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589901000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf58990b00000000000000000000000000000000000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589900000000000000000100000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf58990000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a01000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a), - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a0b00000000000000000000000000000000000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a00000000000000000100000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a0000), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a00000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52500000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a01000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a0b00000000000000000000000000000000000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a00000000000000000100000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52501000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525), - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca5250b00000000000000000000000000000000000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52500000000000000000100000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca5250000), - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d00000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d01000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d), - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d0b00000000000000000000000000000000000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d00000000000000000100000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d0000), - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde), - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde0b000000000000000000000000000000000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde000000000000000001000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde0000), - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67100000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67101000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671), - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e6710b00000000000000000000000000000000000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67100000000000000000100000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e6710000), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78300000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78301000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a7830b00000000000000000000000000000000000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78300000000000000000100000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a7830000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1), - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae10b000000000000000000000000000000000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1000000000000000001000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae10000), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e00000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e01000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e0b00000000000000000000000000000000000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e00000000000000000100000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20), - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860), - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac638600b00000000000000000000000000000000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386000000000000000000100000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac638600000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20), - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c200b000000000000000000000000000000000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20000000000000000001000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c200000), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da00000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952700000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da01000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da0b00000000000000000000000000000000000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da00000000000000000100000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924100000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241), - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952701000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527), - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb295270b00000000000000000000000000000000000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952700000000000000000100000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb295270000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080), - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924101000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241), - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe992410b00000000000000000000000000000000000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924100000000000000000100000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe992410000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080), - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff8189930800b00000000000000000000000000000000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308000000000000000000100000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff8189930800000), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca00000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca01000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca0b00000000000000000000000000000000000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca00000000000000000100000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a), - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a), - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a0b000000000000000000000000000000000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a000000000000000001000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a), - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0b0000000000000000000000000000000000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000000000000000010000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000), - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6), - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f60b000000000000000000000000000000000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6000000000000000001000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f60000), - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb), - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0b0000000000000000000000000000000000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000000000000000010000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403100000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403101000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec450640310b00000000000000000000000000000000000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403100000000000000000100000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec450640310000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2), - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06), - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f060b000000000000000000000000000000000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06000000000000000001000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f060000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2), - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20b0000000000000000000000000000000000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000000000000000010000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070b0000000000000000000000000000000000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000000000000000010000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a), - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a0b000000000000000000000000000000000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a000000000000000001000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a0000), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93900000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f00000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93901000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d9390b00000000000000000000000000000000000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93900000000000000000100000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d9390000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f01000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f), - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f0b00000000000000000000000000000000000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f00000000000000000100000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f0000), - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71), - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe710b000000000000000000000000000000000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71000000000000000001000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe710000), - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f), - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f0b000000000000000000000000000000000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f000000000000000001000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f0000), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490900000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490901000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced4549090b00000000000000000000000000000000000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490900000000000000000100000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced4549090000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed), - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(200d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed0b000000000000000000000000000000000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed000000000000000001000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed0000), - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9), - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90b0000000000000000000000000000000000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000000000000000010000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37100000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37101000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb3710b00000000000000000000000000000000000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37100000000000000000100000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb3710000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1), - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10b0000000000000000000000000000000000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000000000000000010000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b400000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b401000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b40b00000000000000000000000000000000000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b400000000000000000100000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3), - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf), - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(208b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf0b000000000000000000000000000000000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf000000000000000001000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3), - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de30b000000000000000000000000000000000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3000000000000000001000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de30000), - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925), - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c39250b000000000000000000000000000000000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925000000000000000001000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c39250000), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc66730b000000000000000000000000000000000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673000000000000000001000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc66730000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479), - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790b0000000000000000000000000000000000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000000000000000010000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(207b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b80b000000000000000000000000000000000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8000000000000000001000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b80000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e), - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e0b000000000000000000000000000000000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e000000000000000001000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e0000), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e500000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e501000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e50b00000000000000000000000000000000000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e500000000000000000100000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e50000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1401000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140b00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f00000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f01000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f0b00000000000000000000000000000000000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f00000000000000000100000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f0000), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6500000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f00000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6501000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e650b00000000000000000000000000000000000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6500000000000000000100000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e650000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f01000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f0b00000000000000000000000000000000000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f00000000000000000100000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33), - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(207fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b330b000000000000000000000000000000000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33000000000000000001000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b330000), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de00000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e00000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de01000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de0b00000000000000000000000000000000000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de00000000000000000100000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70500000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e01000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e0b00000000000000000000000000000000000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e00000000000000000100000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70501000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705), - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e7050b00000000000000000000000000000000000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70500000000000000000100000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e7050000), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a400000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd100000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a401000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a40b00000000000000000000000000000000000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a400000000000000000100000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd101000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1), - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd10b00000000000000000000000000000000000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd100000000000000000100000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd10000), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c00000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce500000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c01000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c0b00000000000000000000000000000000000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c00000000000000000100000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce501000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce50b00000000000000000000000000000000000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce500000000000000000100000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce50000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8), - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76), - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba760b000000000000000000000000000000000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76000000000000000001000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba760000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8), - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae80b000000000000000000000000000000000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8000000000000000001000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae80000), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b00000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e100000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b01000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b0b00000000000000000000000000000000000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b00000000000000000100000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e101000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e10b00000000000000000000000000000000000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e100000000000000000100000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559), - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f), - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0b0000000000000000000000000000000000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000000000000000010000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559), - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a5590b000000000000000000000000000000000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559000000000000000001000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a5590000), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b00000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2800000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b01000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b0b00000000000000000000000000000000000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b00000000000000000100000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad), - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2801000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28), - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be280b00000000000000000000000000000000000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2800000000000000000100000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be280000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad), - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0b0000000000000000000000000000000000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000000000000000010000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe100000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe101000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe10b00000000000000000000000000000000000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe100000000000000000100000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe10000), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0400000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df00000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0401000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d040b00000000000000000000000000000000000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0400000000000000000100000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d040000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df01000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df), - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df0b00000000000000000000000000000000000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df00000000000000000100000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df0000), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c30b000000000000000000000000000000000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3000000000000000001000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c30000), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817200000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817201000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac781720b00000000000000000000000000000000000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817200000000000000000100000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac781720000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8), - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e80b000000000000000000000000000000000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8000000000000000001000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e80000), - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c), - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c0b000000000000000000000000000000000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c000000000000000001000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c0000), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378100000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4200000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378101000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f9ff3690146bbcd9388221112019585859153db829a26325a230334314c437810b00000000000000000000000000000000000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378100000000000000000100000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c437810000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c00000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c), - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4201000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42), - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce420b00000000000000000000000000000000000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4200000000000000000100000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce420000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c01000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c), - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c0b00000000000000000000000000000000000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c00000000000000000100000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c0000), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1600000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f00000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1601000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d160b00000000000000000000000000000000000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1600000000000000000100000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d160000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f01000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f), - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f0b00000000000000000000000000000000000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f00000000000000000100000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f0000), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f20b000000000000000000000000000000000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2000000000000000001000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f20000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888), - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05), - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba050b000000000000000000000000000000000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05000000000000000001000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba050000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888), - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880b0000000000000000000000000000000000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000000000000000010000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c00000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914800000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c01000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c0b00000000000000000000000000000000000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c00000000000000000100000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914801000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb91480b00000000000000000000000000000000000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914800000000000000000100000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb91480000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c), - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c0b000000000000000000000000000000000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c000000000000000001000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c0000), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a600000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a601000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a60b00000000000000000000000000000000000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a600000000000000000100000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a60000), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410600000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410601000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e741060b00000000000000000000000000000000000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410600000000000000000100000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e741060000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17), - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(200deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff170b000000000000000000000000000000000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17000000000000000001000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff170000), - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf00000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf01000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf), - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf0b00000000000000000000000000000000000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf00000000000000000100000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf0000), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c400000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c401000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c40b00000000000000000000000000000000000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c400000000000000000100000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca), - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a), - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0b0000000000000000000000000000000000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000000000000000010000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca), - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca0b000000000000000000000000000000000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca000000000000000001000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca0000), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e00000000000001000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0500000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0501000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab050b00000000000000000000000000000000000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0500000000000000000100000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab050000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1), - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10b0000000000000000000000000000000000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000000000000000010000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e0000000000000100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68881e000000000000010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e0000000000000100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0b0000000000000000000000000000000000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000000000000000010000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e000000000000010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29), - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a290b000000000000000000000000000000000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29000000000000000001000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a290000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80841e00000000000001000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__few_peer_to_peer_with_event_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__few_peer_to_peer_with_event_version_4.exp deleted file mode 100644 index 905d530dd742b..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__few_peer_to_peer_with_event_version_4.exp +++ /dev/null @@ -1,112 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8ca2d00000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d8c22d00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(90ce2d00000000000002000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0be2d00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe102000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(78d22d00000000000003000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08bb2d00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe103000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10d00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 2, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 2, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(60d62d00000000000004000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20b72d00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe104000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10e00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 3, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 3, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__many_to_one_peer_to_peer_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__many_to_one_peer_to_peer_version_4.exp deleted file mode 100644 index 196792a90a80b..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__many_to_one_peer_to_peer_version_4.exp +++ /dev/null @@ -1,2654 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013801000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380b00000000000000000000000000000000000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000100000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb91786801380000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62), - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620b0000000000000000000000000000000000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000000000000000010000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(104a0f00000000000002000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7), - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb70b000000000000000000000000000000000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7000000000000000001000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb70000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f84d0f00000000000003000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 2, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c01000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c), - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c0b00000000000000000000000000000000000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c00000000000000000100000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e0510f00000000000004000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 3, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd), - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0b0000000000000000000000000000000000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000000000000000010000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c8550f00000000000005000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 4, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589901000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899), - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf58990b00000000000000000000000000000000000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589900000000000000000100000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf58990000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b0590f00000000000006000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 5, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a01000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a), - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a0b00000000000000000000000000000000000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a00000000000000000100000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(985d0f00000000000007000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 6, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a01000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a), - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a0b00000000000000000000000000000000000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a00000000000000000100000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80610f00000000000008000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 7, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52501000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525), - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca5250b00000000000000000000000000000000000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52500000000000000000100000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca5250000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68650f00000000000009000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 8, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d01000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d), - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d0b00000000000000000000000000000000000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d00000000000000000100000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(50690f0000000000000a000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 9, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde), - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde0b000000000000000000000000000000000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde000000000000000001000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(386d0f0000000000000b000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 10, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67101000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671), - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e6710b00000000000000000000000000000000000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67100000000000000000100000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e6710000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20710f0000000000000c000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 11, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08750f0000000000000d000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78301000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a7830b00000000000000000000000000000000000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78300000000000000000100000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a7830000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 12, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1), - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae10b000000000000000000000000000000000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1000000000000000001000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae10000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0780f0000000000000e000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 13, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e01000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e), - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e0b00000000000000000000000000000000000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e00000000000000000100000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d87c0f0000000000000f000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 14, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860), - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac638600b00000000000000000000000000000000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386000000000000000000100000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac638600000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c0800f00000000000010000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 15, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20), - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c200b000000000000000000000000000000000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20000000000000000001000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c200000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8840f00000000000011000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 16, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da01000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da), - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da0b00000000000000000000000000000000000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da00000000000000000100000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(90880f00000000000012000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 17, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952701000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527), - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb295270b00000000000000000000000000000000000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952700000000000000000100000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb295270000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(788c0f00000000000013000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 18, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924101000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241), - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe992410b00000000000000000000000000000000000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924100000000000000000100000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe992410000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(60900f00000000000014000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 19, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080), - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff8189930800b00000000000000000000000000000000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308000000000000000000100000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff8189930800000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(48940f00000000000015000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 20, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca01000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca), - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca0b00000000000000000000000000000000000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca00000000000000000100000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(30980f00000000000016000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 21, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a), - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a0b000000000000000000000000000000000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a000000000000000001000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(189c0f00000000000017000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 22, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a), - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0b0000000000000000000000000000000000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000000000000000010000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(00a00f00000000000018000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 23, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6), - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f60b000000000000000000000000000000000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6000000000000000001000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f60000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8a30f00000000000019000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 24, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb), - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0b0000000000000000000000000000000000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000000000000000010000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d0a70f0000000000001a000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 25, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b8ab0f0000000000001b000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403101000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec450640310b00000000000000000000000000000000000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403100000000000000000100000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec450640310000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 26, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06), - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f060b000000000000000000000000000000000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06000000000000000001000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f060000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a0af0f0000000000001c000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 27, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2), - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20b0000000000000000000000000000000000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000000000000000010000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(88b30f0000000000001d000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 28, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807), - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070b0000000000000000000000000000000000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000000000000000010000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(70b70f0000000000001e000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 29, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a), - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a0b000000000000000000000000000000000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a000000000000000001000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(58bb0f0000000000001f000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 30, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93901000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939), - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d9390b00000000000000000000000000000000000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93900000000000000000100000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d9390000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40bf0f00000000000020000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 31, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f01000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f), - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f0b00000000000000000000000000000000000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f00000000000000000100000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28c30f00000000000021000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 32, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71), - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe710b000000000000000000000000000000000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71000000000000000001000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe710000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(10c70f00000000000022000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 33, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f), - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f0b000000000000000000000000000000000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f000000000000000001000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f8ca0f00000000000023000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 34, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490901000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909), - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced4549090b00000000000000000000000000000000000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490900000000000000000100000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced4549090000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e0ce0f00000000000024000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 35, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed), - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(200d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed0b000000000000000000000000000000000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed000000000000000001000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c8d20f00000000000025000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 36, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9), - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90b0000000000000000000000000000000000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000000000000000010000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b0d60f00000000000026000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 37, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37101000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371), - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb3710b00000000000000000000000000000000000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37100000000000000000100000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb3710000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(98da0f00000000000027000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 38, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1), - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10b0000000000000000000000000000000000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000000000000000010000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80de0f00000000000028000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 39, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b401000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4), - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b40b00000000000000000000000000000000000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b400000000000000000100000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b40000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68e20f00000000000029000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 40, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf), - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(208b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf0b000000000000000000000000000000000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf000000000000000001000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(50e60f0000000000002a000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 41, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3), - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de30b000000000000000000000000000000000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3000000000000000001000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de30000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(38ea0f0000000000002b000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 42, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925), - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c39250b000000000000000000000000000000000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925000000000000000001000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c39250000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20ee0f0000000000002c000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 43, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673), - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc66730b000000000000000000000000000000000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673000000000000000001000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc66730000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08f20f0000000000002d000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 44, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479), - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790b0000000000000000000000000000000000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000000000000000010000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0f50f0000000000002e000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 45, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8), - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(207b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b80b000000000000000000000000000000000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8000000000000000001000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b80000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d8f90f0000000000002f000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 46, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e), - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e0b000000000000000000000000000000000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e000000000000000001000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e0000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c0fd0f00000000000030000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 47, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e501000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5), - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e50b00000000000000000000000000000000000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e500000000000000000100000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e50000), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8011000000000000031000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 48, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28460f00000000000001000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f01000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f0b00000000000000000000000000000000000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f00000000000000000100000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(104a0f00000000000002000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6501000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e650b00000000000000000000000000000000000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6500000000000000000100000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e650000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f84d0f00000000000003000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f01000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f0b00000000000000000000000000000000000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f00000000000000000100000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 2, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e0510f00000000000004000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33), - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(207fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b330b000000000000000000000000000000000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33000000000000000001000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b330000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 3, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c8550f00000000000005000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de01000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de0b00000000000000000000000000000000000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de00000000000000000100000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 4, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b0590f00000000000006000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e01000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e0b00000000000000000000000000000000000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e00000000000000000100000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 5, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70501000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705), - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e7050b00000000000000000000000000000000000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70500000000000000000100000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e7050000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(985d0f00000000000007000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 6, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80610f00000000000008000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a401000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a40b00000000000000000000000000000000000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a400000000000000000100000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 7, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd101000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1), - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd10b00000000000000000000000000000000000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd100000000000000000100000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd10000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68650f00000000000009000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 8, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(50690f0000000000000a000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c01000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c0b00000000000000000000000000000000000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c00000000000000000100000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 9, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(386d0f0000000000000b000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce501000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce50b00000000000000000000000000000000000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce500000000000000000100000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce50000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 10, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76), - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba760b000000000000000000000000000000000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76000000000000000001000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba760000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20710f0000000000000c000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 11, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8), - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae80b000000000000000000000000000000000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8000000000000000001000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae80000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08750f0000000000000d000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 12, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0780f0000000000000e000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b01000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b0b00000000000000000000000000000000000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b00000000000000000100000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 13, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d87c0f0000000000000f000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e101000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e10b00000000000000000000000000000000000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e100000000000000000100000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 14, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f), - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0b0000000000000000000000000000000000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000000000000000010000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c0800f00000000000010000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 15, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559), - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a5590b000000000000000000000000000000000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559000000000000000001000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a5590000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8840f00000000000011000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 16, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(90880f00000000000012000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b01000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b0b00000000000000000000000000000000000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b00000000000000000100000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 17, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2801000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28), - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be280b00000000000000000000000000000000000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2800000000000000000100000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be280000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(788c0f00000000000013000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 18, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad), - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0b0000000000000000000000000000000000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000000000000000010000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(60900f00000000000014000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 19, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(48940f00000000000015000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe101000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe10b00000000000000000000000000000000000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe100000000000000000100000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 20, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(30980f00000000000016000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0401000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d040b00000000000000000000000000000000000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0400000000000000000100000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d040000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 21, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df01000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df), - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df0b00000000000000000000000000000000000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df00000000000000000100000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(189c0f00000000000017000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 22, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(00a00f00000000000018000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(209b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c30b000000000000000000000000000000000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3000000000000000001000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c30000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 23, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8a30f00000000000019000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817201000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac781720b00000000000000000000000000000000000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817200000000000000000100000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac781720000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 24, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8), - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(201233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e80b000000000000000000000000000000000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8000000000000000001000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e80000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d0a70f0000000000001a000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 25, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c), - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(203b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c0b000000000000000000000000000000000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c000000000000000001000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b8ab0f0000000000001b000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 26, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a0af0f0000000000001c000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378101000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f9ff3690146bbcd9388221112019585859153db829a26325a230334314c437810b00000000000000000000000000000000000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378100000000000000000100000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c437810000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 27, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(88b30f0000000000001d000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4201000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42), - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce420b00000000000000000000000000000000000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4200000000000000000100000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce420000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 28, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(70b70f0000000000001e000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c01000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c), - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c0b00000000000000000000000000000000000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c00000000000000000100000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 29, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(58bb0f0000000000001f000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1601000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d160b00000000000000000000000000000000000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1600000000000000000100000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d160000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 30, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f01000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f), - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f0b00000000000000000000000000000000000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f00000000000000000100000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(40bf0f00000000000020000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 31, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2), - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f20b000000000000000000000000000000000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2000000000000000001000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f20000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(28c30f00000000000021000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 32, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05), - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(206784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba050b000000000000000000000000000000000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05000000000000000001000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba050000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(10c70f00000000000022000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 33, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888), - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880b0000000000000000000000000000000000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000000000000000010000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f8ca0f00000000000023000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 34, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e0ce0f00000000000024000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c01000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c0b00000000000000000000000000000000000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c00000000000000000100000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c0000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 35, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c8d20f00000000000025000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914801000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb91480b00000000000000000000000000000000000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914800000000000000000100000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb91480000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 36, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c), - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(202c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c0b000000000000000000000000000000000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c000000000000000001000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b0d60f00000000000026000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 37, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(98da0f00000000000027000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a601000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a60b00000000000000000000000000000000000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a600000000000000000100000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a60000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 38, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80de0f00000000000028000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410601000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e741060b00000000000000000000000000000000000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410600000000000000000100000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e741060000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 39, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17), - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(200deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff170b000000000000000000000000000000000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17000000000000000001000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff170000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68e20f00000000000029000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 40, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf01000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf), - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf0b00000000000000000000000000000000000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf00000000000000000100000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(50e60f0000000000002a000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 41, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(38ea0f0000000000002b000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c401000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c40b00000000000000000000000000000000000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c400000000000000000100000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c40000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 42, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a), - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0b0000000000000000000000000000000000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000000000000000010000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20ee0f0000000000002c000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 43, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca), - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(204a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca0b000000000000000000000000000000000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca000000000000000001000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08f20f0000000000002d000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 44, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0f50f0000000000002e000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0501000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab050b00000000000000000000000000000000000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0500000000000000000100000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab050000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 45, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1), - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10b0000000000000000000000000000000000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000000000000000010000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d8f90f0000000000002f000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 46, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f0000000000000000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d), - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(2066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0b0000000000000000000000000000000000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000000000000000010000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c0fd0f00000000000030000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 47, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f000000000000000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29), - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(205ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a290b000000000000000000000000000000000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29000000000000000001000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a290000), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8011000000000000031000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 48, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__one_to_many_peer_to_peer_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__one_to_many_peer_to_peer_version_4.exp deleted file mode 100644 index 02e45feae8d32..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__one_to_many_peer_to_peer_version_4.exp +++ /dev/null @@ -1,2654 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(18ddf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add620000000000000000000000000000000060fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(30d9f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe102000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 60fd3e46986c9411f7fc6ccce1ac4ad4bd7274c6b2a874f316af7b0b1a1add62 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7000000000000000000000000000000003a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(48d5f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe103000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10d00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 2, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a7660127b0d4d5813c9c47ca99693be18da06a3cf5e1d6075fa744eebd32fb7 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c00000000000000000000000000000000ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(60d1f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe104000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10e00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 3, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ed7f9bbda84ca34619971897d744b7db94713995e6e80e20e8478b613c5d0a1c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd0000000000000000000000000000000099564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(78cdf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe105000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10f00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 4, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 99564e392e1b66cfc4cc132dee4260af3eaa3cd380f64d53a9774c807ed24edd }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf589900000000000000000000000000000000a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(90c9f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe106000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11000000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 5, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: a968f3bbde7dfdeee91e900b40d5dc9aadbd34af209df0d2405a410ac1cf5899 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a00000000000000000000000000000000700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8c5f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe107000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11100000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 6, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 700d63590df528affe6468249273db0a8a19a2e1b098c8751c40062f1b9fdc0a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a00000000000000000000000000000000f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c0c1f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe108000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11200000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 7, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f3487802e7529d97a2d15e64247e4cf0ed8203a4f08409faa853fe075dda380a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca52500000000000000000000000000000000420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d8bdf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe109000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 8, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 420a2e51feec470742c0edfb09116b3e1b90d2c4f35d14315a3cd0a479cca525 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d00000000000000000000000000000000425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0b9f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10a000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 9, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 425b2e8f85238a3a9891c3e5708efbccef0fcf810ddae697b22f7f55fb0e129d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde000000000000000000000000000000005955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08b6f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11500000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 10, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5955b4e2d80a99d8e468385a502cdd1979b8a091728e922cf5e95193d6059bde }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e67100000000000000000000000000000000bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20b2f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10c000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11600000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 11, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc72d0d28fa1602d67834afdfbab476e0c20cd359a7c1d7969894aa18fc7e671 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(38aef505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10d000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11700000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - AccessPath( - AccessPath { address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a78300000000000000000000000000000000fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 12, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fa6451c6cf7b3fc64443a3479dbd1db129bb56db24ab8d1cce6c6adbd153a783 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1000000000000000000000000000000003f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(50aaf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10e000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11800000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 13, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3f993bafbc6af2c3e90974fb5d042306260fa2ad9ca38b504e1777068e898ae1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e00000000000000000000000000000000deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68a6f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10f000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11900000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 14, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: deb91349d35a7230d55a45015b354447e88fb52e5cf15cc0930d4c1875826b9e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac6386000000000000000000000000000000000b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80a2f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe110000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11a00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 15, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: b37c74ada403d58f5da406e7a81d97946aa7a4136fedb0739cf6f1477ac63860 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20000000000000000000000000000000001a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(989ef505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe111000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 16, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1a3fe2f45f16b96b5ccc4e57b144f2c361873a394a612d7855d4759d7c414c20 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da00000000000000000000000000000000f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b09af505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe112000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11c00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 17, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f16dea2553779dec8cd23a56692988415d7559ad559f58c2e432441243aa23da }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb2952700000000000000000000000000000000d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c896f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe113000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11d00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 18, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d2c6307eb821535463bb174ebd937438d9fbbaadbad9a031d0fe0f592cb29527 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe9924100000000000000000000000000000000baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e092f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe114000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11e00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 19, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: baac25d982278cf7c59a189ccf07822d0be47417b8a0d45cf5612162bfe99241 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff81899308000000000000000000000000000000000206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f88ef505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe115000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11f00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 20, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 206c65bf1702a005f5fbf5e5f72cc5736b7e8c5bdf9c0176fb0c5ff818993080 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca00000000000000000000000000000000bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(108bf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe116000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12000000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 21, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc038750080396e9da363f7387291ae669686b4b87d6428785bb5673256caeca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a000000000000000000000000000000006ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(2887f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe117000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12100000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 22, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6ce0e682f4683e6f790c2cf17a9cad3e0aa90b6e45e43b08c8e9e54155bba25a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a0000000000000000000000000000000022538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(4083f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe118000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12200000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 23, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 22538bc10d28186b1d67e4a9e70a22f4bda1fabdfdb41ee558aa750114ef9f8a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6000000000000000000000000000000002586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(587ff505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe119000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 24, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2586c1c33917645df426dae013e51ec90d7292bbbe2668b668d8c41db71289f6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb0000000000000000000000000000000057911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(707bf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11a000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 25, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 57911e723641a53969561209b10d55f9f7729d87a5feee44c2de1719f15897cb }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(8877f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11b000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12500000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - AccessPath( - AccessPath { address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec4506403100000000000000000000000000000000f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 26, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f6e3e34896f9e9a69f8c47f5a76f995e8c748ecf43f8a7b81657b2ec45064031 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06000000000000000000000000000000005fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a073f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11c000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12600000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 27, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5fecb137832d1c9472e42bd0ecf15b72a9bcd9b71da6dfabe0dcb58f3a549f06 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f20000000000000000000000000000000008ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b86ff505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11d000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12700000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 28, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 08ddebf23921e2a611f7e908d12fd0922c84eeb61d1e68f453ca71985d10f6f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea8070000000000000000000000000000000080e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d06bf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11e000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12800000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 29, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 80e15fe49bf4ff07f4dc329c9da66fa8fb825bbe1d45b1d59c545fadcf3ea807 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a000000000000000000000000000000001afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e867f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe11f000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12900000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 30, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1afa290c4dc192f121e1d63ea39570a407b551af18fb0a9a29d76510e385076a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d93900000000000000000000000000000000c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(0064f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe120000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12a00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 31, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c8b3338dd3176802eacc9e3e03e1eb8e22427c7f32111b7f6db7ec8685d4d939 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f00000000000000000000000000000000108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(1860f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe121000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 32, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 108a16ec3c36b81144b56bcd95e7d918efea1a9a890a41b863c82372962aee1f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71000000000000000000000000000000004a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(305cf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe122000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12c00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 33, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a21d175ea2e97a695b663bf53c841a635cc01d14f3f98920c9e175d34f0fe71 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f000000000000000000000000000000009a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(4858f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe123000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12d00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 34, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9a6f5e638ae34edd8d58ffd5a0168b25751fde96a4324046f314a0e6e3e5003f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced45490900000000000000000000000000000000d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(6054f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe124000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12e00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 35, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d32f91c41851e95256e7fc8a2af02026e8290c44403f4dfdd53a952ced454909 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed000000000000000000000000000000000d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(7850f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe125000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12f00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 36, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 0d7ccfd3e1e9eb7cbc4f9bc5c1efb251d85197f810ece92b30c74c725df246ed }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d90000000000000000000000000000000078c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(904cf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe126000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13000000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 37, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78c17b32f5629cbd8220459219ac5516942ffa09d513cf6cb237d0d56f93c8d9 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb37100000000000000000000000000000000cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a848f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe127000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13100000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 38, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: cc6cd5aec6bf56d89b64ab25699880cf8fbaa3076d9b39b8e9f5279516fbb371 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba10000000000000000000000000000000046fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c044f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe128000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13200000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 39, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 46fdaea743be387a7932f5af65a940cfc6daac0308c0998af86967dc877feba1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b400000000000000000000000000000000f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d840f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe129000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13300000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 40, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f2968b6cbdca36419b62fca6d88f6fbeb462db060d37fb076603bc0ecd18c9b4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf000000000000000000000000000000008b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f03cf505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12a000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13400000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 41, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 8b075c3c7b2a72118e6fb5db606bcf181e8d662a08070a2481416e992fd010bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3000000000000000000000000000000002f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(0839f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12b000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13500000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 42, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2f75a821f2b34f8aca1fb99979ddce8a7515842c1f2ebc82111ad756aee02de3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925000000000000000000000000000000006bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(2035f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12c000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13600000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 43, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6bf26914bb51b074e88d39ec266a2423d13fc3ec93da44c2f5f25e9e683c3925 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673000000000000000000000000000000009d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(3831f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12d000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13700000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 44, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9d3e2917d1d9aebd688acbe059d9d352d4c322dd3ff3e381d216809a5bbc6673 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c4790000000000000000000000000000000002f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(502df505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12e000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13800000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 45, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 02f44d7d0052946fbee9fe7161117f2fa6ec09a5ab949f718bb346d2ccc3c479 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8000000000000000000000000000000007b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(6829f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe12f000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13900000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 46, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 7b84066600ac7ab30afbbd6c74b82101320f0abd774da4f29d8e3dc38dc4d3b8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e000000000000000000000000000000004990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(8025f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe130000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13a00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 47, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4990a2a717bd5995b66b79903348e1a6974c1264ab4930fc501eac9859a5456e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e500000000000000000000000000000000ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(9821f505000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe131000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe13b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 48, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ce1227563c894533d99d9531acfaca6527af2c1e0297a29792b6e2adb90e66e5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(18ddf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1401000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140b00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f00000000000000000000000000000000d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d23cdb70c4ecd2e8d9475d1ef86df1eb8fcac8f60395bd154a7dce263158975f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(30d9f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1402000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140c00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e6500000000000000000000000000000000e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 1, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: e4a312d8f4f1363dbb02fd5d96860b3e8031d6b041f23daa9501c11a35145e65 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(48d5f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1403000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140d00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f00000000000000000000000000000000c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 2, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c30cb7560427c19158903b1e72950a66f2f44d0632c87242b7efcfe58bc3303f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(60d1f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1404000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140e00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33000000000000000000000000000000007fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 3, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 7fafa9a4eb0c367d4e325389b6f3244f2dfc87af8b151803a1b2f8f9a7020b33 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(78cdf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1405000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140f00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de00000000000000000000000000000000d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 4, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d127f7530b4f6ec33dfa17f6fdeb872e13089ea0a50f1945acc5cb56bdc3e7de }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(90c9f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1406000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141000000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e00000000000000000000000000000000bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 5, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bad256bab31519774f2ccea1e722279cecdd42a647ec1c13a8a3424ab281ca0e }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e70500000000000000000000000000000000579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a8c5f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1407000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141100000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 6, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 579797ba4d6db98d5a60eddce8ff70d2cee4c5dd50f7a3018d771de13906e705 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c0c1f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1408000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141200000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a400000000000000000000000000000000bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 7, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bb67f9aba825ea91273e81a5514f32e4641035b1277b13993c513e82e1f043a4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd100000000000000000000000000000000479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d8bdf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1409000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141300000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 8, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 479aaceffe1e6880a8b42c12dbce4b503276d99d93e6af57edd286e3cb86bfd1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f0b9f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140a000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141400000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c00000000000000000000000000000000eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 9, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: eb89e3188800b3d2c488653e9bf32ed94bc635f47956cc91dbd61f890af4cc3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(08b6f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140b000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141500000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce500000000000000000000000000000000d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 10, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d753df922e304ccf5946697675333d2aa8650a3db064920a9cfc86775a275ce5 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76000000000000000000000000000000003a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(20b2f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140c000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141600000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 11, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3a5768cdd3296943da5acbdadf3a4a0315fb2ee6dd32b4a40be4934ce877ba76 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8000000000000000000000000000000001500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(38aef505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140d000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141700000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 12, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1500f931617fbc474169be676ccd2171c2fc3862f090d81c96cb837ede1daae8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(50aaf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140e000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141800000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b00000000000000000000000000000000a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 13, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: a3bb6ac591f1aff5737d4ab760395d440ad14dc38e2a320b18e3f58744c9866b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(68a6f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140f000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141900000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e100000000000000000000000000000000960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 14, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 960255ae3ddf18e425e44359c36553f7dedc471cc667f57ade1401d88f9cb1e1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f0000000000000000000000000000000078f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(80a2f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1410000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141a00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 15, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78f8069cbc15648b9c9f771db516f8a1a7848325e7f0283a3a28a43aa794948f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559000000000000000000000000000000002d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(989ef505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1411000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141b00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 16, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2d9137739fded47a9ecbe60aa1fa4846f534a1da1859b244123b38994a15a559 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b09af505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1412000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141c00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b00000000000000000000000000000000e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 17, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: e2a94b801782b4393313593f96707c10d2abfb464a84c2fdec8db04488b8fb4b }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be2800000000000000000000000000000000764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c896f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1413000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141d00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 18, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 764a76c84995dc08a1395c9d66a6ed2ba0cce55154e14ffa642ff2e2db66be28 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad0000000000000000000000000000000028f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e092f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1414000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141e00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 19, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 28f9841a7236c9efceb267f545694a95c6a203d9fe8ca20107904467a804d6ad }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f88ef505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1415000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141f00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe100000000000000000000000000000000ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 20, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ade5cfb08640d0e74b74af2348673a3caba344b7b6824bebe5e283d7aedd3fe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(108bf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1416000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142000000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d0400000000000000000000000000000000bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 21, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc6681dfba31269d18ca4d8df7a3cfe16301c6a8ce09a0e611369b4cce570d04 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df00000000000000000000000000000000135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(2887f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1417000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142100000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 22, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 135069356a81e973d50c2ba0c1aaa3977e9863ae2a5041292f7f0ef7f07b49df }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(4083f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1418000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142200000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3000000000000000000000000000000009b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 23, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 9b718105a84f8d380c494fea6a1bb73a2d98df246ca39979a715098bbae4d0c3 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(587ff505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1419000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142300000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac7817200000000000000000000000000000000ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 24, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: ce36d15e4fac797dda674984c4af25288e97dad540508eaaf2fa95f18ac78172 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8000000000000000000000000000000001233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(707bf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141a000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142400000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 25, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 1233806acfe93258f7221cd01c6d0b896fb561c14a1ada4a620475204af444e8 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c000000000000000000000000000000003b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(8877f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141b000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142500000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 26, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 3b371dda97935cfe2477c8e0d458303fbb7095613fded735c73b6ea01d82795c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a073f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141c000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142600000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c4378100000000000000000000000000000000f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 27, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: f9ff3690146bbcd9388221112019585859153db829a26325a230334314c43781 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(b86ff505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141d000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142700000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce4200000000000000000000000000000000de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 28, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: de9649bed43934e319d80e400e6105036357402f230d73d2daae9d8c2025ce42 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d06bf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141e000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142800000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c00000000000000000000000000000000db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 29, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: db163a88112c6000052e51228358e8a5c9793c4c6eba9dd6c88e2d0657dc204c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e867f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f141f000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142900000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d1600000000000000000000000000000000dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 30, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: dfbc85dc5398c2c704180e629e705f076bb8cf30dec210eb26166e9b2ec59d16 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f00000000000000000000000000000000000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(0064f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1420000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142a00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 31, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 000e9ec609c12eb27d7c88e71d13ebebf134249305d490328cd19fc6a9fd977f }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2000000000000000000000000000000006d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(1860f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1421000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142b00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 32, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6d811ca4511b3d34af7edd8e492a4a4c9f5e416aa52df7d31e6bbb268d1d98f2 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05000000000000000000000000000000006784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(305cf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1422000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142c00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 33, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 6784da0210304c98e22385cee60681a57ed71f407e45ab01f93cf14abbdeba05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b8880000000000000000000000000000000006314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(4858f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1423000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142d00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 34, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 06314919f08caec879f26260704d59e5ea8a5a120e3ffcc011aae1349b98b888 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(6054f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1424000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142e00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c00000000000000000000000000000000fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 35, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fbd9fe69a85104bda9514f959eacc169d4a022f19d261a6935f5a7149d92ab3c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(7850f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1425000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142f00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb914800000000000000000000000000000000b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 36, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: b4981bcf96483454d47a6f28e2b03b9a7e22b1232a3a6e87a8ae384369bb9148 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c000000000000000000000000000000002c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(904cf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1426000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143000000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 37, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 2c5e693a491591189a26146af5c6c07116c328b69d73147c0daa70c63554420c }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(a848f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1427000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143100000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a600000000000000000000000000000000d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 38, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d86695e1a2577a6b7d04ae60eb1321ada659bcdda9e3e90d119b68b46ec9d7a6 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(c044f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1428000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143200000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e7410600000000000000000000000000000000fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 39, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: fc46659281b4980234a51e3b7b57a0cdeeffc42ef4d2275b088cefd590e74106 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17000000000000000000000000000000000deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(d840f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1429000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143300000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 40, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 0deafa362c90faa218564facfe34d575be4c5b4957203f4f24de4354f109ff17 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf00000000000000000000000000000000598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(f03cf505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142a000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143400000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 41, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 598ca23a5cc5e58067d49de822c0741e6d0f9ea969c71b2525ac8dfcd91599bf }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(0839f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142b000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143500000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c400000000000000000000000000000000bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 42, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: bc53de0ba0c448a681b7dee01d18d701ff0789d8e693706fbaa50096279d05c4 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a0000000000000000000000000000000078ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(2035f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142c000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143600000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 43, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 78ce8931064bd4458ddbda43d36857dd1b1995ec87323d5b5d014b61be7fd88a }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca000000000000000000000000000000004a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(3831f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142d000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143700000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 44, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 4a34024ccd17559d8bd6f89f41e2bba7dff528dad529f572bb6929c960430aca }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(502df505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142e000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143800000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - AccessPath( - AccessPath { address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f505000000000001000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab0500000000000000000000000000000000c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 45, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: c9d10c763ab08627dcf893cebb6805b4a4fe308978f53467bdc37b0b2869ab05 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c10000000000000000000000000000000012713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(6829f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f142f000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143900000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 46, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 12713e2c81c52b05a90d0a8a3446e6f6fdff7332fde6980607bdb90b31e115c1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f50500000000000100000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d0000000000000000000000000000000066eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(8025f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1430000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143a00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 47, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 66eade2c6f7314032c1ee9e167b5704680f7084fb3d18db2c73276255c8a994d }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(e8e4f5050000000000010000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29000000000000000000000000000000005ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(9821f505000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1431000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14), - AccessPath( - AccessPath { address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f143b00000000000000000000000000000000000000000000000000000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f1400000000000000000100000000000000792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f140000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: 792bae4346bd4f1f99ed8117e8272a43ddf9e60becd5a7974bb5bb589b211f14 }, index: 48, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: 5ddebccf021ca445c6bafc6185b4a5d5a478174ca5ddc82fa03b6401eeda0a29 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__single_peer_to_peer_with_event_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__single_peer_to_peer_with_event_version_4.exp deleted file mode 100644 index b413306f68a3d..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__peer_to_peer__single_peer_to_peer_with_event_version_4.exp +++ /dev/null @@ -1,31 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(888a0100000000000001000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb917868013800000000000000000000000000000000d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(583e0f00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe101000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [ - ContractEvent { key: EventKey { creation_number: 0, account_address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("WithdrawEvent"), type_params: [] }), event_data: "e803000000000000" }, - ContractEvent { key: EventKey { creation_number: 0, account_address: d88e78203e6688f0587d58ad01b0232da2a4b23f5916b324c365bb9178680138 }, index: 0, type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("coin"), name: Identifier("DepositEvent"), type_params: [] }), event_data: "e803000000000000" }, - ], - gas_used: 696, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_key_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_key_version_4.exp deleted file mode 100644 index 08b358ee2725f..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_key_version_4.exp +++ /dev/null @@ -1,62 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(208e0d19280063fa870fe4dbb85cc724091a398451c5c11e1e76e64cdc7b5885100b0000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [], - gas_used: 1, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - INVALID_AUTH_KEY, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(208e0d19280063fa870fe4dbb85cc724091a398451c5c11e1e76e64cdc7b5885100c0000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [], - gas_used: 1, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_multisig_key_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_multisig_key_version_4.exp deleted file mode 100644 index 7b3cf24f9ddd4..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__rotate_key__rotate_ed25519_multisig_key_version_4.exp +++ /dev/null @@ -1,66 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c3719640b67074ec5aad6545c1e5b9a7f9f2ac468efe35ee53476a1fbb9a2e6c0b0000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [], - gas_used: 1, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c3719640b67074ec5aad6545c1e5b9a7f9f2ac468efe35ee53476a1fbb9a2e6c0c0000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [], - gas_used: 1, - status: Keep( - Success, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20c3719640b67074ec5aad6545c1e5b9a7f9f2ac468efe35ee53476a1fbb9a2e6c0d0000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - }, - }, - ), - ), - events: [], - gas_used: 1, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_dependency_fails_verification.exp deleted file mode 100644 index fa4553cbb6cda..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_dependency_fails_verification.exp +++ /dev/null @@ -1,37 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>)" }, - hash: OnceCell(Uninit), - }: Modification(3d420f00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: TableItem { handle: 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, key: 0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935 }, - hash: OnceCell(Uninit), - }: Modification(fce0f505000000000100000000000000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - UNEXPECTED_VERIFIER_ERROR, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_transitive_dependency_fails_verification.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_transitive_dependency_fails_verification.exp deleted file mode 100644 index fa4553cbb6cda..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_module_transitive_dependency_fails_verification.exp +++ /dev/null @@ -1,37 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>)" }, - hash: OnceCell(Uninit), - }: Modification(3d420f00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: TableItem { handle: 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, key: 0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935 }, - hash: OnceCell(Uninit), - }: Modification(fce0f505000000000100000000000000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - UNEXPECTED_VERIFIER_ERROR, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing.exp deleted file mode 100644 index fbed942bfe6bb..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing.exp +++ /dev/null @@ -1,37 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Code(f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1::M)" }, - hash: OnceCell(Uninit), - }: Creation(a11ceb0b060000000601000203020a050c0607120a081c200c3c23000000010001000002000100020303010300014d036d61780373756df5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10001000002080a000a012403060a01020a00020101000001060a000a01160c020a020200, metadata:StateValueMetadata { inner: Some(StateValueMetadataInner { slot_deposit: 50000, bytes_deposit: 0, creation_time_usecs: 0 }) }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>)" }, - hash: OnceCell(Uninit), - }: Modification(84059a3b000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: TableItem { handle: 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, key: 0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935 }, - hash: OnceCell(Uninit), - }: Modification(831cf505000000000100000000000000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "f7010000000000000300000000000000010000000000000050c30000000000000000000000000000" }, - ], - gas_used: 503, - status: Keep( - Success, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing_invalid_address.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing_invalid_address.exp deleted file mode 100644 index d543e5268596e..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__test_open_publishing_invalid_address.exp +++ /dev/null @@ -1,37 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::coin::CoinStore<0x1::aptos_coin::AptosCoin>)" }, - hash: OnceCell(Uninit), - }: Modification(3d420f00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: AccessPath { address: 0xf5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: "Resource(0x1::account::Account)" }, - hash: OnceCell(Uninit), - }: Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000, metadata:StateValueMetadata { inner: None }), - StateKey { - inner: TableItem { handle: 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, key: 0619dc29a0aac8fa146714058e8dd6d2d0f3bdf5f6331907bf91f3acd81e6935 }, - hash: OnceCell(Uninit), - }: Modification(fce0f505000000000100000000000000, metadata:StateValueMetadata { inner: None }), - }, - }, - ), - ), - events: [ - ModuleEvent { type: Struct(StructTag { address: 0000000000000000000000000000000000000000000000000000000000000001, module: Identifier("transaction_fee"), name: Identifier("FeeStatement"), type_params: [] }), event_data: "03000000000000000300000000000000000000000000000000000000000000000000000000000000" }, - ], - gas_used: 3, - status: Keep( - MiscellaneousError( - Some( - MODULE_ADDRESS_DOES_NOT_MATCH_SENDER, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_chain_id_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_chain_id_version_4.exp deleted file mode 100644 index 1224b6a442605..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_chain_id_version_4.exp +++ /dev/null @@ -1,18 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - BAD_CHAIN_ID, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_expiration_time_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_expiration_time_version_4.exp deleted file mode 100644 index c30f3c8502219..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_expiration_time_version_4.exp +++ /dev/null @@ -1,36 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - TRANSACTION_EXPIRED, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - TRANSACTION_EXPIRED, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_max_sequence_number_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_max_sequence_number_version_4.exp deleted file mode 100644 index c9444d2c2a499..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_max_sequence_number_version_4.exp +++ /dev/null @@ -1,18 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - SEQUENCE_NUMBER_TOO_BIG, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_reserved_sender_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_reserved_sender_version_4.exp deleted file mode 100644 index 0f133e3cf2294..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_reserved_sender_version_4.exp +++ /dev/null @@ -1,18 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - SENDING_ACCOUNT_DOES_NOT_EXIST, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_signature_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_signature_version_4.exp deleted file mode 100644 index 709b8e9eba644..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_signature_version_4.exp +++ /dev/null @@ -1,18 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - INVALID_SIGNATURE, - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_simple_payment_version_4.exp b/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_simple_payment_version_4.exp deleted file mode 100644 index 63918e9da0799..0000000000000 --- a/aptos-move/e2e-tests/goldens/language_e2e_testsuite__tests__verify_txn__verify_simple_payment_version_4.exp +++ /dev/null @@ -1,230 +0,0 @@ -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - INVALID_AUTH_KEY, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - SEQUENCE_NUMBER_TOO_OLD, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - SEQUENCE_NUMBER_TOO_NEW, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - INSUFFICIENT_BALANCE_FOR_TRANSACTION_FEE, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - SENDING_ACCOUNT_DOES_NOT_EXIST, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - GAS_UNIT_PRICE_ABOVE_MAX_BOUND, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - MAX_GAS_UNITS_BELOW_MIN_TRANSACTION_GAS_UNITS, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - MAX_GAS_UNITS_EXCEEDS_MAX_GAS_UNITS_BOUND, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: {}, - }, - ), - ), - events: [], - gas_used: 0, - status: Discard( - EXCEEDED_MAX_TRANSACTION_SIZE, - ), - }, - ], -) -Ok( - [ - TransactionOutput { - write_set: V0( - WriteSetV0( - WriteSetMut { - write_set: { - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 01000000000000000000000000000000000000000000000000000000000000000104636f696e09436f696e53746f7265010700000000000000000000000000000000000000000000000000000000000000010a6170746f735f636f696e094170746f73436f696e00 }, - ): Modification(0abb0d00000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1), - AccessPath( - AccessPath { address: f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe1, path: 010000000000000000000000000000000000000000000000000000000000000001076163636f756e74074163636f756e7400 }, - ): Modification(20f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10b00000000000000000000000000000000000000000000000000000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe100000000000000000100000000000000f5b9d6f01a99e74c790e2f330c092fa05455a8193f1dfc1b113ecc54d067afe10000), - TableItem { - handle: TableHandle( - 1b854694ae746cdbd8d44186ca4929b2b337df21d1c74633be19b2710552fdca, - ), - key: [ - 6, - 25, - 220, - 41, - 160, - 170, - 200, - 250, - 20, - 103, - 20, - 5, - 142, - 141, - 214, - 210, - 208, - 243, - 189, - 245, - 246, - 51, - 25, - 7, - 191, - 145, - 243, - 172, - 216, - 30, - 105, - 53, - ], - }: Modification(69e0f505000000000100000000000000), - }, - }, - ), - ), - events: [], - gas_used: 150, - status: Keep( - MiscellaneousError( - Some( - NUMBER_OF_ARGUMENTS_MISMATCH, - ), - ), - ), - }, - ], -) diff --git a/aptos-move/e2e-tests/src/account.rs b/aptos-move/e2e-tests/src/account.rs index 71fdf07d3fc82..306b6800e3f1f 100644 --- a/aptos-move/e2e-tests/src/account.rs +++ b/aptos-move/e2e-tests/src/account.rs @@ -15,8 +15,8 @@ use aptos_types::{ event::{EventHandle, EventKey}, state_store::state_key::StateKey, transaction::{ - authenticator::AuthenticationKey, EntryFunction, Module, ModuleBundle, RawTransaction, - Script, SignedTransaction, TransactionPayload, + authenticator::AuthenticationKey, EntryFunction, RawTransaction, Script, SignedTransaction, + TransactionPayload, }, write_set::{WriteOp, WriteSet, WriteSetMut}, }; @@ -217,11 +217,6 @@ impl TransactionBuilder { self } - pub fn module(mut self, m: Module) -> Self { - self.program = Some(TransactionPayload::ModuleBundle(ModuleBundle::from(m))); - self - } - pub fn max_gas_amount(mut self, max_gas_amount: u64) -> Self { self.max_gas_amount = Some(max_gas_amount); self diff --git a/aptos-move/e2e-tests/src/executor.rs b/aptos-move/e2e-tests/src/executor.rs index 8ae1697e59354..ee2215f89c5ed 100644 --- a/aptos-move/e2e-tests/src/executor.rs +++ b/aptos-move/e2e-tests/src/executor.rs @@ -159,8 +159,6 @@ impl FakeExecutor { allow_block_executor_fallback: true, }; executor.apply_write_set(write_set); - // As a set effect, also allow module bundle txns. TODO: Remove - aptos_vm::aptos_vm::allow_module_bundle_for_test(); executor } @@ -638,8 +636,12 @@ impl FakeExecutor { entry_func.function().to_owned(), entry_func.ty_args().to_vec(), ), - TransactionPayload::ModuleBundle(..) => unreachable!("not supported"), TransactionPayload::Multisig(..) => unimplemented!("not supported yet"), + + // Deprecated. + TransactionPayload::ModuleBundle(..) => { + unreachable!("Module bundle payload has been removed") + }, }; Ok(gas_profiler) }, diff --git a/aptos-move/e2e-testsuite/src/tests/data_store.rs b/aptos-move/e2e-testsuite/src/tests/data_store.rs index 66d7e201d3003..a25c1590e8f4c 100644 --- a/aptos-move/e2e-testsuite/src/tests/data_store.rs +++ b/aptos-move/e2e-testsuite/src/tests/data_store.rs @@ -3,11 +3,13 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_language_e2e_tests::{ - account::AccountData, compile::compile_script, current_function_name, executor::FakeExecutor, + account::AccountData, compile::compile_script, current_function_name, + data_store::FakeDataStore, executor::FakeExecutor, }; use aptos_types::transaction::{ - ExecutionStatus, Module, SignedTransaction, Transaction, TransactionStatus, + ExecutionStatus, SignedTransaction, Transaction, TransactionStatus, }; +use claims::assert_matches; use move_binary_format::CompiledModule; use move_bytecode_verifier::verify_module; use move_ir_compiler::Compiler; @@ -16,21 +18,20 @@ use move_ir_compiler::Compiler; fn move_from_across_blocks() { let mut executor = FakeExecutor::from_head_genesis(); executor.set_golden_file(current_function_name!()); - let sender = executor.create_raw_account_data(1_000_000, 10); + let sender = executor.create_raw_account_data(1_000_000, 11); executor.add_account_data(&sender); // publish module with add and remove resource - let (module, txn) = add_module_txn(&sender, 10); - executor.execute_and_apply(txn); + let module = add_module(executor.data_store_mut(), &sender); // remove resource fails given no resource were published let rem_txn = remove_resource_txn(&sender, 11, vec![module.clone()]); let output = executor.execute_transaction(rem_txn); - assert!(matches!( + assert_matches!( output.status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); executor.apply_write_set(output.write_set()); // publish resource @@ -48,21 +49,21 @@ fn move_from_across_blocks() { // remove resource fails given it was removed already let rem_txn = remove_resource_txn(&sender, 15, vec![module.clone()]); let output = executor.execute_transaction(rem_txn); - assert!(matches!( + assert_matches!( output.status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); executor.apply_write_set(output.write_set()); // borrow resource fail given it was removed let borrow_txn = borrow_resource_txn(&sender, 16, vec![module.clone()]); let output = executor.execute_transaction(borrow_txn); - assert!(matches!( + assert_matches!( output.status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); executor.apply_write_set(output.write_set()); // publish resource again @@ -81,11 +82,11 @@ fn move_from_across_blocks() { output[0].status(), &TransactionStatus::Keep(ExecutionStatus::Success) ); - assert!(matches!( + assert_matches!( output[1].status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); for out in output { executor.apply_write_set(out.write_set()); } @@ -95,21 +96,20 @@ fn move_from_across_blocks() { fn borrow_after_move() { let mut executor = FakeExecutor::from_head_genesis(); executor.set_golden_file(current_function_name!()); - let sender = executor.create_raw_account_data(1_000_000, 10); + let sender = executor.create_raw_account_data(1_000_000, 11); executor.add_account_data(&sender); // publish module with add and remove resource - let (module, txn) = add_module_txn(&sender, 10); - executor.execute_and_apply(txn); + let module = add_module(executor.data_store_mut(), &sender); // remove resource fails given no resource were published let rem_txn = remove_resource_txn(&sender, 11, vec![module.clone()]); let output = executor.execute_transaction(rem_txn); - assert!(matches!( + assert_matches!( output.status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); executor.apply_write_set(output.write_set()); // publish resource @@ -132,11 +132,11 @@ fn borrow_after_move() { output[0].status(), &TransactionStatus::Keep(ExecutionStatus::Success) ); - assert!(matches!( + assert_matches!( output[1].status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); for out in output { executor.apply_write_set(out.write_set()); } @@ -146,21 +146,20 @@ fn borrow_after_move() { fn change_after_move() { let mut executor = FakeExecutor::from_head_genesis(); executor.set_golden_file(current_function_name!()); - let sender = executor.create_raw_account_data(1_000_000, 10); + let sender = executor.create_raw_account_data(1_000_000, 11); executor.add_account_data(&sender); // publish module with add and remove resource - let (module, txn) = add_module_txn(&sender, 10); - executor.execute_and_apply(txn); + let module = add_module(executor.data_store_mut(), &sender); // remove resource fails given no resource were published let rem_txn = remove_resource_txn(&sender, 11, vec![module.clone()]); let output = executor.execute_transaction(rem_txn); - assert!(matches!( + assert_matches!( output.status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); executor.apply_write_set(output.write_set()); // publish resource @@ -183,11 +182,11 @@ fn change_after_move() { output[0].status(), &TransactionStatus::Keep(ExecutionStatus::Success) ); - assert!(matches!( + assert_matches!( output[1].status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); for out in output { executor.apply_write_set(out.write_set()); } @@ -195,16 +194,16 @@ fn change_after_move() { // borrow resource let borrow_txn = borrow_resource_txn(&sender, 16, vec![module]); let output = executor.execute_transaction(borrow_txn); - assert!(matches!( + assert_matches!( output.status().status(), // StatusCode::MISSING_DATA Ok(ExecutionStatus::ExecutionFailure { .. }) - )); + ); executor.apply_write_set(output.write_set()); } -fn add_module_txn(sender: &AccountData, seq_num: u64) -> (CompiledModule, SignedTransaction) { - let module_code = format!( +fn add_module(data_store: &mut FakeDataStore, sender: &AccountData) -> CompiledModule { + let code = format!( " module 0x{}.M {{ import 0x1.signer; @@ -247,22 +246,17 @@ fn add_module_txn(sender: &AccountData, seq_num: u64) -> (CompiledModule, Signed deps: framework_modules.iter().collect(), }; let module = compiler - .into_compiled_module(module_code.as_str()) + .into_compiled_module(code.as_str()) .expect("Module compilation failed"); - let mut module_blob = vec![]; + verify_module(&module).expect("Module must verify"); + + let mut module_bytes = vec![]; module - .serialize(&mut module_blob) + .serialize(&mut module_bytes) .expect("Module must serialize"); - verify_module(&module).expect("Module must verify"); - ( - module, - sender - .account() - .transaction() - .module(Module::new(module_blob)) - .sequence_number(seq_num) - .sign(), - ) + + data_store.add_module(&module.self_id(), module_bytes); + module } fn add_resource_txn( @@ -283,11 +277,11 @@ fn add_resource_txn( sender.address().to_hex(), ); - let module = compile_script(&program, extra_deps); + let script = compile_script(&program, extra_deps); sender .account() .transaction() - .script(module) + .script(script) .sequence_number(seq_num) .sign() } diff --git a/aptos-move/e2e-testsuite/src/tests/mod.rs b/aptos-move/e2e-testsuite/src/tests/mod.rs index 7a1f974008f52..03f411f1bd17c 100644 --- a/aptos-move/e2e-testsuite/src/tests/mod.rs +++ b/aptos-move/e2e-testsuite/src/tests/mod.rs @@ -22,7 +22,6 @@ mod genesis_initializations; mod invariant_violation; mod loader; mod mint; -mod module_publishing; mod on_chain_configs; mod peer_to_peer; mod scripts; diff --git a/aptos-move/e2e-testsuite/src/tests/module_publishing.rs b/aptos-move/e2e-testsuite/src/tests/module_publishing.rs deleted file mode 100644 index 6f153558392d3..0000000000000 --- a/aptos-move/e2e-testsuite/src/tests/module_publishing.rs +++ /dev/null @@ -1,357 +0,0 @@ -// Copyright © Aptos Foundation -// Parts of the project are originally copyright © Meta Platforms, Inc. -// SPDX-License-Identifier: Apache-2.0 - -use aptos_language_e2e_tests::{ - account::Account, compile::compile_module, current_function_name, executor::FakeExecutor, - transaction_status_eq, -}; -use aptos_types::transaction::{ExecutionStatus, TransactionStatus}; -use move_core_types::vm_status::StatusCode; - -// TODO: ignoring most tests for now as bundle publishing is no longer available. Want to resurrect -// or rewrite for new publishin approach - -// A module with an address different from the sender's address should be rejected -#[test] -fn bad_module_address() { - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // create a transaction trying to publish a new module. - let account1 = executor.create_raw_account_data(1_000_000, 10); - let account2 = executor.create_raw_account_data(1_000_000, 10); - - executor.add_account_data(&account1); - executor.add_account_data(&account2); - - let program = format!( - " - module 0x{}.M {{ - }} - ", - account1.address().to_hex() - ); - - // compile with account 1's address - let compiled_module = compile_module(&program).1; - // send with account 2's address - let txn = account2 - .account() - .transaction() - .module(compiled_module) - .sequence_number(10) - .gas_unit_price(1) - .sign(); - - // TODO: This is not verified for now. - // verify and fail because the addresses don't match - // let vm_status = executor.verify_transaction(txn.clone()).status().unwrap(); - // assert!(vm_status.is(StatusType::Verification)); - // assert!(vm_status.major_status == StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER); - - // execute and fail for the same reason - let output = executor.execute_transaction(txn); - match output.status() { - TransactionStatus::Keep(status) => { - assert!( - status - == &ExecutionStatus::MiscellaneousError(Some( - StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER - )) - ); - // assert!(status.status_code() == StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER); - }, - vm_status => panic!("Unexpected verification status: {:?}", vm_status), - }; -} - -macro_rules! module_republish_test { - ($name:ident, $prog1:literal, $prog2:literal) => { - #[test] - fn $name() { - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - let sequence_number = 2; - let account = executor.create_raw_account_data(1_000_000, sequence_number); - executor.add_account_data(&account); - - let program1 = String::from($prog1).replace("##ADDRESS##", &account.address().to_hex()); - let compiled_module1 = compile_module(&program1).1; - - let txn1 = account - .account() - .transaction() - .module(compiled_module1.clone()) - .sequence_number(sequence_number) - .sign(); - - let program2 = String::from($prog2).replace("##ADDRESS##", &account.address().to_hex()); - let compiled_module2 = compile_module(&program2).1; - - let txn2 = account - .account() - .transaction() - .module(compiled_module2) - .sequence_number(sequence_number + 1) - .sign(); - - let output1 = executor.execute_transaction(txn1); - executor.apply_write_set(output1.write_set()); - // first tx should allways succeed - assert!(transaction_status_eq( - &output1.status(), - &TransactionStatus::Keep(ExecutionStatus::Success), - )); - - let output2 = executor.execute_transaction(txn2); - println!("{:?}", output2.status()); - // second tx should always fail, module republish is not allowed - assert!(transaction_status_eq( - &output2.status(), - &TransactionStatus::Keep(ExecutionStatus::MiscellaneousError(Some( - StatusCode::DUPLICATE_MODULE_NAME - ))), - )); - } - }; -} - -// Publishing a module named M under the same address twice is OK (a module is self-compatible) -module_republish_test!( - duplicate_module, - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - public f() { label b0: return; } - } - ", - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - public f() { label b0: return; } - } - " // ExecutionStatus::Success -); - -// Republishing a module named M under the same address with a superset of the structs is OK -module_republish_test!( - layout_compatible_module, - " - module 0x##ADDRESS##.M { - } - ", - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - } - " // ExecutionStatus::Success -); - -// Republishing a module named M under the same address with a superset of public functions is OK -module_republish_test!( - linking_compatible_module, - " - module 0x##ADDRESS##.M { - } - ", - " - module 0x##ADDRESS##.M { - public f() { label b0: return; } - } - " // ExecutionStatus::Success -); - -// Republishing a module named M under the same address that breaks data layout should be rejected -module_republish_test!( - layout_incompatible_module_with_new_field, - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - } - ", - " - module 0x##ADDRESS##.M { - struct T { f: u64, g: bool } - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -module_republish_test!( - layout_incompatible_module_with_changed_field, - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - } - ", - " - module 0x##ADDRESS##.M { - struct T { f: bool } - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -module_republish_test!( - layout_incompatible_module_with_removed_field, - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - } - ", - " - module 0x##ADDRESS##.M { - struct T {} - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -module_republish_test!( - layout_incompatible_module_with_removed_struct, - " - module 0x##ADDRESS##.M { - struct T { f: u64 } - } - ", - " - module 0x##ADDRESS##.M { - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -// Republishing a module named M under the same address that breaks linking should be rejected -module_republish_test!( - linking_incompatible_module_with_added_param, - " - module 0x##ADDRESS##.M { - public f() { label b0: return; } - } - ", - " - module 0x##ADDRESS##.M { - public f(_a: u64) { label b0: return; } - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -module_republish_test!( - linking_incompatible_module_with_changed_param, - " - module 0x##ADDRESS##.M { - public f(_a: u64) { label b0: return; } - } - ", - " - module 0x##ADDRESS##.M { - public f(_a: bool) { label b0: return; } - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -module_republish_test!( - linking_incompatible_module_with_removed_pub_fn, - " - module 0x##ADDRESS##.M { - public f() { label b0: return; } - } - ", - " - module 0x##ADDRESS##.M { - } - " // ExecutionStatus::MiscellaneousError(Some(StatusCode::BACKWARD_INCOMPATIBLE_MODULE_UPDATE)) -); - -#[test] -pub fn test_publishing_modules_proper_sender() { - // create a FakeExecutor with a genesis from file - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // create a transaction trying to publish a new module. - let sender = Account::new_aptos_root(); - - let program = format!( - " - module 0x{}.M {{ - }} - ", - sender.address().to_hex(), - ); - - let random_script = compile_module(&program).1; - let txn = sender - .transaction() - .module(random_script) - .sequence_number(0) - .sign(); - assert_eq!(executor.verify_transaction(txn.clone()).status(), None); - assert_eq!( - executor.execute_transaction(txn).status(), - &TransactionStatus::Keep(ExecutionStatus::Success) - ); -} - -#[test] -pub fn test_publishing_modules_invalid_sender() { - // create a FakeExecutor with a genesis from file - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // create a transaction trying to publish a new module. - let sender = executor.create_raw_account_data(1_000_000, 10); - executor.add_account_data(&sender); - - let program = String::from( - " - module 0x1.M { - } - ", - ); - - let random_script = compile_module(&program).1; - let txn = sender - .account() - .transaction() - .module(random_script) - .sequence_number(10) - .sign(); - assert_eq!( - executor.execute_transaction(txn).status(), - // this should be MODULE_ADDRESS_DOES_NOT_MATCH_SENDER but we don't do this check in prologue now - &TransactionStatus::Keep(ExecutionStatus::MiscellaneousError(Some( - StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER - ))), - ); -} - -#[test] -pub fn test_publishing_allow_modules() { - // create a FakeExecutor with a genesis from file - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // create a transaction trying to publish a new module. - let sender = executor.create_raw_account_data(1_000_000, 10); - executor.add_account_data(&sender); - - let program = format!( - " - module 0x{}.M {{ - }} - ", - sender.address().to_hex(), - ); - - let random_script = compile_module(&program).1; - let txn = sender - .account() - .transaction() - .module(random_script) - .sequence_number(10) - .sign(); - assert_eq!(executor.verify_transaction(txn.clone()).status(), None); - assert_eq!( - executor.execute_transaction(txn).status(), - &TransactionStatus::Keep(ExecutionStatus::Success) - ); -} diff --git a/aptos-move/e2e-testsuite/src/tests/verify_txn.rs b/aptos-move/e2e-testsuite/src/tests/verify_txn.rs index 28645fe586e91..1d03cf1d53609 100644 --- a/aptos-move/e2e-testsuite/src/tests/verify_txn.rs +++ b/aptos-move/e2e-testsuite/src/tests/verify_txn.rs @@ -8,7 +8,7 @@ use aptos_gas_algebra::Gas; use aptos_gas_schedule::{InitialGasSchedule, TransactionGasParameters}; use aptos_language_e2e_tests::{ assert_prologue_disparity, assert_prologue_parity, common_transactions::EMPTY_SCRIPT, - compile::compile_module, current_function_name, executor::FakeExecutor, transaction_status_eq, + current_function_name, executor::FakeExecutor, transaction_status_eq, }; use aptos_types::{ account_address::AccountAddress, @@ -23,7 +23,6 @@ use move_core_types::{ gas_algebra::GasQuantity, identifier::Identifier, language_storage::{StructTag, TypeTag}, - vm_status::StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER, }; use move_ir_compiler::Compiler; @@ -512,120 +511,6 @@ fn verify_max_sequence_number() { ); } -#[test] -pub fn test_open_publishing_invalid_address() { - // create a FakeExecutor with a genesis from file - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // create a transaction trying to publish a new module. - let sender = executor.create_raw_account_data(1_000_000, 10); - let receiver = executor.create_raw_account_data(1_000_000, 10); - executor.add_account_data(&sender); - executor.add_account_data(&receiver); - - let module = format!( - " - module 0x{}.M {{ - public max(a: u64, b: u64): u64 {{ - label b0: - jump_if (copy(a) > copy(b)) b2; - label b1: - return copy(b); - label b2: - return copy(a); - }} - - public sum(a: u64, b: u64): u64 {{ - let c: u64; - label b0: - c = copy(a) + copy(b); - return copy(c); - }} - }} - ", - receiver.address().to_hex(), - ); - - let random_module = compile_module(&module).1; - let txn = sender - .account() - .transaction() - .module(random_module) - .sequence_number(10) - .max_gas_amount(100_000) - .gas_unit_price(1) - .sign(); - - // TODO: This is not verified for now. - // verify and fail because the addresses don't match - // let vm_status = executor.verify_transaction(txn.clone()).status().unwrap(); - - // assert!(vm_status.is(StatusType::Verification)); - // assert!(vm_status.major_status == StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER); - - // execute and fail for the same reason - let output = executor.execute_transaction(txn); - if let TransactionStatus::Keep(status) = output.status() { - // assert!(status.status_code() == StatusCode::MODULE_ADDRESS_DOES_NOT_MATCH_SENDER) - assert!( - status - == &ExecutionStatus::MiscellaneousError(Some(MODULE_ADDRESS_DOES_NOT_MATCH_SENDER)) - ); - } else { - panic!("Unexpected execution status: {:?}", output) - }; -} - -#[test] -pub fn test_open_publishing() { - // create a FakeExecutor with a genesis from file - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // create a transaction trying to publish a new module. - let sender = executor.create_raw_account_data(10_0000_0000, 10); - executor.add_account_data(&sender); - - let program = format!( - " - module 0x{}.M {{ - public max(a: u64, b: u64): u64 {{ - label b0: - jump_if (copy(a) > copy(b)) b2; - label b1: - return copy(b); - label b2: - return copy(a); - }} - - public sum(a: u64, b: u64): u64 {{ - let c: u64; - label b0: - c = copy(a) + copy(b); - return copy(c); - }} - }} - ", - sender.address().to_hex(), - ); - - let random_module = compile_module(&program).1; - let txn = sender - .account() - .transaction() - .module(random_module) - .sequence_number(10) - .max_gas_amount(100_000) - .gas_unit_price(100) - .sign(); - assert_eq!(executor.verify_transaction(txn.clone()).status(), None); - assert_eq!( - executor.execute_transaction(txn).status(), - &TransactionStatus::Keep(ExecutionStatus::Success) - ); -} - fn bad_module() -> (CompiledModule, Vec) { let bad_module_code = " module 0x1.Test { @@ -736,42 +621,6 @@ fn test_script_dependency_fails_verification() { } } -#[test] -fn test_module_dependency_fails_verification() { - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // Get a module that fails verification into the store. - let (bad_module, bad_module_bytes) = bad_module(); - executor.add_module(&bad_module.self_id(), bad_module_bytes); - - // Create a transaction that tries to use that module. - let sender = executor.create_raw_account_data(1_000_000, 10); - executor.add_account_data(&sender); - let good_module = { - let (_, serialized_module) = good_module_uses_bad(*sender.address(), bad_module); - aptos_types::transaction::Module::new(serialized_module) - }; - - let txn = sender - .account() - .transaction() - .module(good_module) - .sequence_number(10) - .max_gas_amount(100_000) - .gas_unit_price(1) - .sign(); - // As of now, we verify module/script dependencies. This will result in an - // invariant violation as we try to load `Test` - assert_eq!(executor.verify_transaction(txn.clone()).status(), None); - match executor.execute_transaction(txn).status() { - TransactionStatus::Keep(ExecutionStatus::MiscellaneousError(status)) => { - assert_eq!(status, &Some(StatusCode::UNEXPECTED_VERIFIER_ERROR)); - }, - _ => panic!("Kept transaction with an invariant violation!"), - } -} - #[test] fn test_type_tag_dependency_fails_verification() { let mut executor = FakeExecutor::from_head_genesis(); @@ -875,67 +724,6 @@ fn test_script_transitive_dependency_fails_verification() { } } -#[test] -fn test_module_transitive_dependency_fails_verification() { - let mut executor = FakeExecutor::from_head_genesis(); - executor.set_golden_file(current_function_name!()); - - // Get a module that fails verification into the store. - let (bad_module, bad_module_bytes) = bad_module(); - executor.add_module(&bad_module.self_id(), bad_module_bytes); - - // Create a module that tries to use that module. - let (good_module, good_module_bytes) = - good_module_uses_bad(account_config::CORE_CODE_ADDRESS, bad_module); - executor.add_module(&good_module.self_id(), good_module_bytes); - - // Create a transaction that tries to use that module. - let sender = executor.create_raw_account_data(1_000_000, 10); - executor.add_account_data(&sender); - - let module_code = format!( - " - module 0x{}.Test3 {{ - import 0x1.Test2; - public bar() {{ - label b0: - Test2.bar(); - return; - }} - }} - ", - sender.address().to_hex() - ); - let module = { - let compiler = Compiler { - deps: vec![&good_module], - }; - aptos_types::transaction::Module::new( - compiler - .into_module_blob(module_code.as_str()) - .expect("Module compilation failed"), - ) - }; - - let txn = sender - .account() - .transaction() - .module(module) - .sequence_number(10) - .max_gas_amount(100_000) - .gas_unit_price(1) - .sign(); - // As of now, we verify module/script dependencies. This will result in an - // invariant violation as we try to load `Test` - assert_eq!(executor.verify_transaction(txn.clone()).status(), None); - match executor.execute_transaction(txn).status() { - TransactionStatus::Keep(ExecutionStatus::MiscellaneousError(status)) => { - assert_eq!(status, &Some(StatusCode::UNEXPECTED_VERIFIER_ERROR)); - }, - _ => panic!("Kept transaction with an invariant violation!"), - } -} - #[test] fn test_type_tag_transitive_dependency_fails_verification() { let mut executor = FakeExecutor::from_head_genesis(); diff --git a/aptos-move/framework/aptos-framework/doc/transaction_validation.md b/aptos-move/framework/aptos-framework/doc/transaction_validation.md index 42975346aced9..66e6f1746abb0 100644 --- a/aptos-move/framework/aptos-framework/doc/transaction_validation.md +++ b/aptos-move/framework/aptos-framework/doc/transaction_validation.md @@ -9,7 +9,6 @@ - [Constants](#@Constants_0) - [Function `initialize`](#0x1_transaction_validation_initialize) - [Function `prologue_common`](#0x1_transaction_validation_prologue_common) -- [Function `module_prologue`](#0x1_transaction_validation_module_prologue) - [Function `script_prologue`](#0x1_transaction_validation_script_prologue) - [Function `multi_agent_script_prologue`](#0x1_transaction_validation_multi_agent_script_prologue) - [Function `multi_agent_common_prologue`](#0x1_transaction_validation_multi_agent_common_prologue) @@ -21,7 +20,6 @@ - [Module-level Specification](#module-level-spec) - [Function `initialize`](#@Specification_1_initialize) - [Function `prologue_common`](#@Specification_1_prologue_common) - - [Function `module_prologue`](#@Specification_1_module_prologue) - [Function `script_prologue`](#@Specification_1_script_prologue) - [Function `multi_agent_script_prologue`](#@Specification_1_multi_agent_script_prologue) - [Function `multi_agent_common_prologue`](#@Specification_1_multi_agent_common_prologue) @@ -241,6 +239,7 @@ Only called during genesis to initialize system resources for this module.
public(friend) fun initialize(
     aptos_framework: &signer,
     script_prologue_name: vector<u8>,
+    // module_prologue_name is deprecated and not used.
     module_prologue_name: vector<u8>,
     multi_agent_prologue_name: vector<u8>,
     user_epilogue_name: vector<u8>,
@@ -251,6 +250,7 @@ Only called during genesis to initialize system resources for this module.
         module_addr: @aptos_framework,
         module_name: b"transaction_validation",
         script_prologue_name,
+        // module_prologue_name is deprecated and not used.
         module_prologue_name,
         multi_agent_prologue_name,
         user_epilogue_name,
@@ -348,39 +348,6 @@ Only called during genesis to initialize system resources for this module.
 
 
 
-
-
-
-
-## Function `module_prologue`
-
-
-
-
fun module_prologue(sender: signer, txn_sequence_number: u64, txn_public_key: vector<u8>, txn_gas_price: u64, txn_max_gas_units: u64, txn_expiration_time: u64, chain_id: u8)
-
- - - -
-Implementation - - -
fun module_prologue(
-    sender: signer,
-    txn_sequence_number: u64,
-    txn_public_key: vector<u8>,
-    txn_gas_price: u64,
-    txn_max_gas_units: u64,
-    txn_expiration_time: u64,
-    chain_id: u8,
-) {
-    let gas_payer = signer::address_of(&sender);
-    prologue_common(sender, gas_payer, txn_sequence_number, txn_public_key, txn_gas_price, txn_max_gas_units, txn_expiration_time, chain_id)
-}
-
- - -
@@ -812,25 +779,6 @@ Give some constraints that may abort according to the conditions. - - -### Function `module_prologue` - - -
fun module_prologue(sender: signer, txn_sequence_number: u64, txn_public_key: vector<u8>, txn_gas_price: u64, txn_max_gas_units: u64, txn_expiration_time: u64, chain_id: u8)
-
- - - - -
include PrologueCommonAbortsIf {
-    gas_payer: signer::address_of(sender),
-    txn_authentication_key: txn_public_key
-};
-
- - - ### Function `script_prologue` diff --git a/aptos-move/framework/aptos-framework/sources/transaction_validation.move b/aptos-move/framework/aptos-framework/sources/transaction_validation.move index 085bea28c8a63..1997aafdb7b4f 100644 --- a/aptos-move/framework/aptos-framework/sources/transaction_validation.move +++ b/aptos-move/framework/aptos-framework/sources/transaction_validation.move @@ -21,6 +21,7 @@ module aptos_framework::transaction_validation { module_addr: address, module_name: vector, script_prologue_name: vector, + // module_prologue_name is deprecated and not used. module_prologue_name: vector, multi_agent_prologue_name: vector, user_epilogue_name: vector, @@ -51,6 +52,7 @@ module aptos_framework::transaction_validation { public(friend) fun initialize( aptos_framework: &signer, script_prologue_name: vector, + // module_prologue_name is deprecated and not used. module_prologue_name: vector, multi_agent_prologue_name: vector, user_epilogue_name: vector, @@ -61,6 +63,7 @@ module aptos_framework::transaction_validation { module_addr: @aptos_framework, module_name: b"transaction_validation", script_prologue_name, + // module_prologue_name is deprecated and not used. module_prologue_name, multi_agent_prologue_name, user_epilogue_name, @@ -135,19 +138,6 @@ module aptos_framework::transaction_validation { assert!(balance >= max_transaction_fee, error::invalid_argument(PROLOGUE_ECANT_PAY_GAS_DEPOSIT)); } - fun module_prologue( - sender: signer, - txn_sequence_number: u64, - txn_public_key: vector, - txn_gas_price: u64, - txn_max_gas_units: u64, - txn_expiration_time: u64, - chain_id: u8, - ) { - let gas_payer = signer::address_of(&sender); - prologue_common(sender, gas_payer, txn_sequence_number, txn_public_key, txn_gas_price, txn_max_gas_units, txn_expiration_time, chain_id) - } - fun script_prologue( sender: signer, txn_sequence_number: u64, diff --git a/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move b/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move index 82d9c2636af97..cc5d0ce6f2624 100644 --- a/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move +++ b/aptos-move/framework/aptos-framework/sources/transaction_validation.spec.move @@ -111,21 +111,6 @@ spec aptos_framework::transaction_validation { include PrologueCommonAbortsIf; } - spec module_prologue( - sender: signer, - txn_sequence_number: u64, - txn_public_key: vector, - txn_gas_price: u64, - txn_max_gas_units: u64, - txn_expiration_time: u64, - chain_id: u8, - ) { - include PrologueCommonAbortsIf { - gas_payer: signer::address_of(sender), - txn_authentication_key: txn_public_key - }; - } - spec script_prologue( sender: signer, txn_sequence_number: u64, diff --git a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs index 604dec90a1801..888608260fe36 100644 --- a/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs +++ b/ecosystem/indexer-grpc/indexer-grpc-fullnode/src/convert.rs @@ -171,20 +171,9 @@ pub fn convert_transaction_payload( )), }, - // Deprecated. Will be removed in the future. - TransactionPayload::ModuleBundlePayload(mbp) => transaction::TransactionPayload { - r#type: transaction::transaction_payload::Type::ModuleBundlePayload as i32, - payload: Some( - transaction::transaction_payload::Payload::ModuleBundlePayload( - transaction::ModuleBundlePayload { - modules: mbp - .modules - .iter() - .map(convert_move_module_bytecode) - .collect(), - }, - ), - ), + // Deprecated. + TransactionPayload::ModuleBundlePayload(_) => { + unreachable!("Module bundle payload has been removed") }, } } diff --git a/execution/executor/src/components/chunk_output.rs b/execution/executor/src/components/chunk_output.rs index 520bed20602a7..824e86048fbdc 100644 --- a/execution/executor/src/components/chunk_output.rs +++ b/execution/executor/src/components/chunk_output.rs @@ -388,10 +388,10 @@ pub fn update_counters_for_processed_chunk( .inc(); }, - // Deprecated. Will be removed in the future. - aptos_types::transaction::TransactionPayload::ModuleBundle(_module) => { + // Deprecated. + aptos_types::transaction::TransactionPayload::ModuleBundle(_) => { metrics::APTOS_PROCESSED_USER_TRANSACTIONS_PAYLOAD_TYPE - .with_label_values(&[process_type, "module", state]) + .with_label_values(&[process_type, "deprecated_module_bundle", state]) .inc(); }, } diff --git a/execution/executor/src/mock_vm/mod.rs b/execution/executor/src/mock_vm/mod.rs index bfae749dc6bb2..45e1a74df3a45 100644 --- a/execution/executor/src/mock_vm/mod.rs +++ b/execution/executor/src/mock_vm/mod.rs @@ -411,9 +411,9 @@ fn decode_transaction(txn: &SignedTransaction) -> MockVMTransaction { TransactionPayload::Multisig(_) => { unimplemented!("MockVM does not support multisig transaction payload.") }, - // Deprecated. Will be removed in the future. + // Deprecated. TransactionPayload::ModuleBundle(_) => { - unimplemented!("MockVM does not support Module transaction payload.") + unreachable!("Module bundle payload has been removed") }, } } diff --git a/protos/proto/aptos/transaction/v1/transaction.proto b/protos/proto/aptos/transaction/v1/transaction.proto index eeefb3c3d8a19..a0ff966c12247 100644 --- a/protos/proto/aptos/transaction/v1/transaction.proto +++ b/protos/proto/aptos/transaction/v1/transaction.proto @@ -231,9 +231,9 @@ message TransactionPayload { TYPE_UNSPECIFIED = 0; TYPE_ENTRY_FUNCTION_PAYLOAD = 1; TYPE_SCRIPT_PAYLOAD = 2; - TYPE_MODULE_BUNDLE_PAYLOAD = 3; TYPE_WRITE_SET_PAYLOAD = 4; TYPE_MULTISIG_PAYLOAD = 5; + reserved 3; } Type type = 1; @@ -241,10 +241,10 @@ message TransactionPayload { oneof payload { EntryFunctionPayload entry_function_payload = 2; ScriptPayload script_payload = 3; - ModuleBundlePayload module_bundle_payload = 4; WriteSetPayload write_set_payload = 5; MultisigPayload multisig_payload = 6; } + reserved 4; } message EntryFunctionPayload { @@ -283,10 +283,6 @@ message MultisigTransactionPayload { } } -message ModuleBundlePayload { - repeated MoveModuleBytecode modules = 1; -} - message MoveModuleBytecode { bytes bytecode = 1; MoveModule abi = 2; diff --git a/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.py b/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.py index b177483c37930..224d757905835 100644 --- a/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.py +++ b/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.py @@ -17,7 +17,7 @@ ) DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile( - b'\n&aptos/transaction/v1/transaction.proto\x12\x14\x61ptos.transaction.v1\x1a$aptos/util/timestamp/timestamp.proto"\x9a\x01\n\x05\x42lock\x12\x32\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1f.aptos.util.timestamp.Timestamp\x12\x12\n\x06height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x37\n\x0ctransactions\x18\x03 \x03(\x0b\x32!.aptos.transaction.v1.Transaction\x12\x10\n\x08\x63hain_id\x18\x04 \x01(\r"\xad\x06\n\x0bTransaction\x12\x32\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1f.aptos.util.timestamp.Timestamp\x12\x13\n\x07version\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x33\n\x04info\x18\x03 \x01(\x0b\x32%.aptos.transaction.v1.TransactionInfo\x12\x11\n\x05\x65poch\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x0c\x62lock_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12?\n\x04type\x18\x06 \x01(\x0e\x32\x31.aptos.transaction.v1.Transaction.TransactionType\x12H\n\x0e\x62lock_metadata\x18\x07 \x01(\x0b\x32..aptos.transaction.v1.BlockMetadataTransactionH\x00\x12;\n\x07genesis\x18\x08 \x01(\x0b\x32(.aptos.transaction.v1.GenesisTransactionH\x00\x12L\n\x10state_checkpoint\x18\t \x01(\x0b\x32\x30.aptos.transaction.v1.StateCheckpointTransactionH\x00\x12\x35\n\x04user\x18\n \x01(\x0b\x32%.aptos.transaction.v1.UserTransactionH\x00\x12?\n\tvalidator\x18\x15 \x01(\x0b\x32*.aptos.transaction.v1.ValidatorTransactionH\x00"\xd8\x01\n\x0fTransactionType\x12 \n\x1cTRANSACTION_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18TRANSACTION_TYPE_GENESIS\x10\x01\x12#\n\x1fTRANSACTION_TYPE_BLOCK_METADATA\x10\x02\x12%\n!TRANSACTION_TYPE_STATE_CHECKPOINT\x10\x03\x12\x19\n\x15TRANSACTION_TYPE_USER\x10\x04\x12\x1e\n\x1aTRANSACTION_TYPE_VALIDATOR\x10\x14\x42\n\n\x08txn_data"\xbe\x01\n\x18\x42lockMetadataTransaction\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\x05round\x18\x02 \x01(\x04\x42\x02\x30\x01\x12+\n\x06\x65vents\x18\x03 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event\x12#\n\x1bprevious_block_votes_bitvec\x18\x04 \x01(\x0c\x12\x10\n\x08proposer\x18\x05 \x01(\t\x12\x1f\n\x17\x66\x61iled_proposer_indices\x18\x06 \x03(\r"r\n\x12GenesisTransaction\x12/\n\x07payload\x18\x01 \x01(\x0b\x32\x1e.aptos.transaction.v1.WriteSet\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event"\x1c\n\x1aStateCheckpointTransaction"\x16\n\x14ValidatorTransaction"}\n\x0fUserTransaction\x12=\n\x07request\x18\x01 \x01(\x0b\x32,.aptos.transaction.v1.UserTransactionRequest\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event"\x9f\x01\n\x05\x45vent\x12+\n\x03key\x18\x01 \x01(\x0b\x32\x1e.aptos.transaction.v1.EventKey\x12\x1b\n\x0fsequence_number\x18\x02 \x01(\x04\x42\x02\x30\x01\x12,\n\x04type\x18\x03 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12\x10\n\x08type_str\x18\x05 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\t"\xa1\x02\n\x0fTransactionInfo\x12\x0c\n\x04hash\x18\x01 \x01(\x0c\x12\x19\n\x11state_change_hash\x18\x02 \x01(\x0c\x12\x17\n\x0f\x65vent_root_hash\x18\x03 \x01(\x0c\x12"\n\x15state_checkpoint_hash\x18\x04 \x01(\x0cH\x00\x88\x01\x01\x12\x14\n\x08gas_used\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x07success\x18\x06 \x01(\x08\x12\x11\n\tvm_status\x18\x07 \x01(\t\x12\x1d\n\x15\x61\x63\x63umulator_root_hash\x18\x08 \x01(\x0c\x12\x35\n\x07\x63hanges\x18\t \x03(\x0b\x32$.aptos.transaction.v1.WriteSetChangeB\x18\n\x16_state_checkpoint_hash"@\n\x08\x45ventKey\x12\x1b\n\x0f\x63reation_number\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0f\x61\x63\x63ount_address\x18\x02 \x01(\t"\xb0\x02\n\x16UserTransactionRequest\x12\x0e\n\x06sender\x18\x01 \x01(\t\x12\x1b\n\x0fsequence_number\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0emax_gas_amount\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0egas_unit_price\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x42\n\x19\x65xpiration_timestamp_secs\x18\x05 \x01(\x0b\x32\x1f.aptos.util.timestamp.Timestamp\x12\x39\n\x07payload\x18\x06 \x01(\x0b\x32(.aptos.transaction.v1.TransactionPayload\x12\x32\n\tsignature\x18\x07 \x01(\x0b\x32\x1f.aptos.transaction.v1.Signature"\xda\x02\n\x08WriteSet\x12\x43\n\x0ewrite_set_type\x18\x01 \x01(\x0e\x32+.aptos.transaction.v1.WriteSet.WriteSetType\x12@\n\x10script_write_set\x18\x02 \x01(\x0b\x32$.aptos.transaction.v1.ScriptWriteSetH\x00\x12@\n\x10\x64irect_write_set\x18\x03 \x01(\x0b\x32$.aptos.transaction.v1.DirectWriteSetH\x00"x\n\x0cWriteSetType\x12\x1e\n\x1aWRITE_SET_TYPE_UNSPECIFIED\x10\x00\x12#\n\x1fWRITE_SET_TYPE_SCRIPT_WRITE_SET\x10\x01\x12#\n\x1fWRITE_SET_TYPE_DIRECT_WRITE_SET\x10\x02\x42\x0b\n\twrite_set"Y\n\x0eScriptWriteSet\x12\x12\n\nexecute_as\x18\x01 \x01(\t\x12\x33\n\x06script\x18\x02 \x01(\x0b\x32#.aptos.transaction.v1.ScriptPayload"}\n\x0e\x44irectWriteSet\x12>\n\x10write_set_change\x18\x01 \x03(\x0b\x32$.aptos.transaction.v1.WriteSetChange\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event"\x89\x05\n\x0eWriteSetChange\x12\x37\n\x04type\x18\x01 \x01(\x0e\x32).aptos.transaction.v1.WriteSetChange.Type\x12;\n\rdelete_module\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.DeleteModuleH\x00\x12?\n\x0f\x64\x65lete_resource\x18\x03 \x01(\x0b\x32$.aptos.transaction.v1.DeleteResourceH\x00\x12\x42\n\x11\x64\x65lete_table_item\x18\x04 \x01(\x0b\x32%.aptos.transaction.v1.DeleteTableItemH\x00\x12\x39\n\x0cwrite_module\x18\x05 \x01(\x0b\x32!.aptos.transaction.v1.WriteModuleH\x00\x12=\n\x0ewrite_resource\x18\x06 \x01(\x0b\x32#.aptos.transaction.v1.WriteResourceH\x00\x12@\n\x10write_table_item\x18\x07 \x01(\x0b\x32$.aptos.transaction.v1.WriteTableItemH\x00"\xb5\x01\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12TYPE_DELETE_MODULE\x10\x01\x12\x18\n\x14TYPE_DELETE_RESOURCE\x10\x02\x12\x1a\n\x16TYPE_DELETE_TABLE_ITEM\x10\x03\x12\x15\n\x11TYPE_WRITE_MODULE\x10\x04\x12\x17\n\x13TYPE_WRITE_RESOURCE\x10\x05\x12\x19\n\x15TYPE_WRITE_TABLE_ITEM\x10\x06\x42\x08\n\x06\x63hange"k\n\x0c\x44\x65leteModule\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x32\n\x06module\x18\x03 \x01(\x0b\x32".aptos.transaction.v1.MoveModuleId"~\n\x0e\x44\x65leteResource\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x31\n\x04type\x18\x03 \x01(\x0b\x32#.aptos.transaction.v1.MoveStructTag\x12\x10\n\x08type_str\x18\x04 \x01(\t"{\n\x0f\x44\x65leteTableItem\x12\x16\n\x0estate_key_hash\x18\x01 \x01(\x0c\x12\x0e\n\x06handle\x18\x02 \x01(\t\x12\x0b\n\x03key\x18\x03 \x01(\t\x12\x33\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32%.aptos.transaction.v1.DeleteTableData"0\n\x0f\x44\x65leteTableData\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x10\n\x08key_type\x18\x02 \x01(\t"n\n\x0bWriteModule\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x36\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32(.aptos.transaction.v1.MoveModuleBytecode"\x8b\x01\n\rWriteResource\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x31\n\x04type\x18\x03 \x01(\x0b\x32#.aptos.transaction.v1.MoveStructTag\x12\x10\n\x08type_str\x18\x04 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x05 \x01(\t"R\n\x0eWriteTableData\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x10\n\x08key_type\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\t\x12\x12\n\nvalue_type\x18\x04 \x01(\t"y\n\x0eWriteTableItem\x12\x16\n\x0estate_key_hash\x18\x01 \x01(\x0c\x12\x0e\n\x06handle\x18\x02 \x01(\t\x12\x0b\n\x03key\x18\x03 \x01(\t\x12\x32\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32$.aptos.transaction.v1.WriteTableData"\xec\x04\n\x12TransactionPayload\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.aptos.transaction.v1.TransactionPayload.Type\x12L\n\x16\x65ntry_function_payload\x18\x02 \x01(\x0b\x32*.aptos.transaction.v1.EntryFunctionPayloadH\x00\x12=\n\x0escript_payload\x18\x03 \x01(\x0b\x32#.aptos.transaction.v1.ScriptPayloadH\x00\x12J\n\x15module_bundle_payload\x18\x04 \x01(\x0b\x32).aptos.transaction.v1.ModuleBundlePayloadH\x00\x12\x42\n\x11write_set_payload\x18\x05 \x01(\x0b\x32%.aptos.transaction.v1.WriteSetPayloadH\x00\x12\x41\n\x10multisig_payload\x18\x06 \x01(\x0b\x32%.aptos.transaction.v1.MultisigPayloadH\x00"\xad\x01\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bTYPE_ENTRY_FUNCTION_PAYLOAD\x10\x01\x12\x17\n\x13TYPE_SCRIPT_PAYLOAD\x10\x02\x12\x1e\n\x1aTYPE_MODULE_BUNDLE_PAYLOAD\x10\x03\x12\x1a\n\x16TYPE_WRITE_SET_PAYLOAD\x10\x04\x12\x19\n\x15TYPE_MULTISIG_PAYLOAD\x10\x05\x42\t\n\x07payload"\xb9\x01\n\x14\x45ntryFunctionPayload\x12\x37\n\x08\x66unction\x18\x01 \x01(\x0b\x32%.aptos.transaction.v1.EntryFunctionId\x12\x36\n\x0etype_arguments\x18\x02 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12\x11\n\targuments\x18\x03 \x03(\t\x12\x1d\n\x15\x65ntry_function_id_str\x18\x04 \x01(\t"W\n\x12MoveScriptBytecode\x12\x10\n\x08\x62ytecode\x18\x01 \x01(\x0c\x12/\n\x03\x61\x62i\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.MoveFunction"\x92\x01\n\rScriptPayload\x12\x36\n\x04\x63ode\x18\x01 \x01(\x0b\x32(.aptos.transaction.v1.MoveScriptBytecode\x12\x36\n\x0etype_arguments\x18\x02 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12\x11\n\targuments\x18\x03 \x03(\t"\x97\x01\n\x0fMultisigPayload\x12\x18\n\x10multisig_address\x18\x01 \x01(\t\x12R\n\x13transaction_payload\x18\x02 \x01(\x0b\x32\x30.aptos.transaction.v1.MultisigTransactionPayloadH\x00\x88\x01\x01\x42\x16\n\x14_transaction_payload"\xf9\x01\n\x1aMultisigTransactionPayload\x12\x43\n\x04type\x18\x01 \x01(\x0e\x32\x35.aptos.transaction.v1.MultisigTransactionPayload.Type\x12L\n\x16\x65ntry_function_payload\x18\x02 \x01(\x0b\x32*.aptos.transaction.v1.EntryFunctionPayloadH\x00"=\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bTYPE_ENTRY_FUNCTION_PAYLOAD\x10\x01\x42\t\n\x07payload"P\n\x13ModuleBundlePayload\x12\x39\n\x07modules\x18\x01 \x03(\x0b\x32(.aptos.transaction.v1.MoveModuleBytecode"U\n\x12MoveModuleBytecode\x12\x10\n\x08\x62ytecode\x18\x01 \x01(\x0c\x12-\n\x03\x61\x62i\x18\x02 \x01(\x0b\x32 .aptos.transaction.v1.MoveModule"\xd2\x01\n\nMoveModule\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x33\n\x07\x66riends\x18\x03 \x03(\x0b\x32".aptos.transaction.v1.MoveModuleId\x12=\n\x11\x65xposed_functions\x18\x04 \x03(\x0b\x32".aptos.transaction.v1.MoveFunction\x12\x31\n\x07structs\x18\x05 \x03(\x0b\x32 .aptos.transaction.v1.MoveStruct"\x92\x03\n\x0cMoveFunction\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x41\n\nvisibility\x18\x02 \x01(\x0e\x32-.aptos.transaction.v1.MoveFunction.Visibility\x12\x10\n\x08is_entry\x18\x03 \x01(\x08\x12O\n\x13generic_type_params\x18\x04 \x03(\x0b\x32\x32.aptos.transaction.v1.MoveFunctionGenericTypeParam\x12.\n\x06params\x18\x05 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12.\n\x06return\x18\x06 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType"n\n\nVisibility\x12\x1a\n\x16VISIBILITY_UNSPECIFIED\x10\x00\x12\x16\n\x12VISIBILITY_PRIVATE\x10\x01\x12\x15\n\x11VISIBILITY_PUBLIC\x10\x02\x12\x15\n\x11VISIBILITY_FRIEND\x10\x03"\xe9\x01\n\nMoveStruct\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tis_native\x18\x02 \x01(\x08\x12\x34\n\tabilities\x18\x03 \x03(\x0e\x32!.aptos.transaction.v1.MoveAbility\x12M\n\x13generic_type_params\x18\x04 \x03(\x0b\x32\x30.aptos.transaction.v1.MoveStructGenericTypeParam\x12\x35\n\x06\x66ields\x18\x05 \x03(\x0b\x32%.aptos.transaction.v1.MoveStructField"h\n\x1aMoveStructGenericTypeParam\x12\x36\n\x0b\x63onstraints\x18\x01 \x03(\x0e\x32!.aptos.transaction.v1.MoveAbility\x12\x12\n\nis_phantom\x18\x02 \x01(\x08"M\n\x0fMoveStructField\x12\x0c\n\x04name\x18\x01 \x01(\t\x12,\n\x04type\x18\x02 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveType"V\n\x1cMoveFunctionGenericTypeParam\x12\x36\n\x0b\x63onstraints\x18\x01 \x03(\x0e\x32!.aptos.transaction.v1.MoveAbility"\xf8\x02\n\x08MoveType\x12-\n\x04type\x18\x01 \x01(\x0e\x32\x1f.aptos.transaction.v1.MoveTypes\x12\x30\n\x06vector\x18\x03 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveTypeH\x00\x12\x35\n\x06struct\x18\x04 \x01(\x0b\x32#.aptos.transaction.v1.MoveStructTagH\x00\x12"\n\x18generic_type_param_index\x18\x05 \x01(\rH\x00\x12\x41\n\treference\x18\x06 \x01(\x0b\x32,.aptos.transaction.v1.MoveType.ReferenceTypeH\x00\x12\x14\n\nunparsable\x18\x07 \x01(\tH\x00\x1aL\n\rReferenceType\x12\x0f\n\x07mutable\x18\x01 \x01(\x08\x12*\n\x02to\x18\x02 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveTypeB\t\n\x07\x63ontent"D\n\x0fWriteSetPayload\x12\x31\n\twrite_set\x18\x01 \x01(\x0b\x32\x1e.aptos.transaction.v1.WriteSet"S\n\x0f\x45ntryFunctionId\x12\x32\n\x06module\x18\x01 \x01(\x0b\x32".aptos.transaction.v1.MoveModuleId\x12\x0c\n\x04name\x18\x02 \x01(\t"-\n\x0cMoveModuleId\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"{\n\rMoveStructTag\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0e\n\x06module\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12;\n\x13generic_type_params\x18\x04 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType"\x9b\x04\n\tSignature\x12\x32\n\x04type\x18\x01 \x01(\x0e\x32$.aptos.transaction.v1.Signature.Type\x12\x39\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x02 \x01(\x0b\x32&.aptos.transaction.v1.Ed25519SignatureH\x00\x12\x44\n\rmulti_ed25519\x18\x03 \x01(\x0b\x32+.aptos.transaction.v1.MultiEd25519SignatureH\x00\x12@\n\x0bmulti_agent\x18\x04 \x01(\x0b\x32).aptos.transaction.v1.MultiAgentSignatureH\x00\x12<\n\tfee_payer\x18\x05 \x01(\x0b\x32\'.aptos.transaction.v1.FeePayerSignatureH\x00\x12;\n\rsingle_sender\x18\x07 \x01(\x0b\x32".aptos.transaction.v1.SingleSenderH\x00"\x8e\x01\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x16\n\x12TYPE_MULTI_ED25519\x10\x02\x12\x14\n\x10TYPE_MULTI_AGENT\x10\x03\x12\x12\n\x0eTYPE_FEE_PAYER\x10\x04\x12\x16\n\x12TYPE_SINGLE_SENDER\x10\x06"\x04\x08\x05\x10\x05\x42\x0b\n\tsignature"9\n\x10\x45\x64\x32\x35\x35\x31\x39Signature\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c"o\n\x15MultiEd25519Signature\x12\x13\n\x0bpublic_keys\x18\x01 \x03(\x0c\x12\x12\n\nsignatures\x18\x02 \x03(\x0c\x12\x11\n\tthreshold\x18\x03 \x01(\r\x12\x1a\n\x12public_key_indices\x18\x04 \x03(\r"\xb4\x01\n\x13MultiAgentSignature\x12\x36\n\x06sender\x18\x01 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature\x12"\n\x1asecondary_signer_addresses\x18\x02 \x03(\t\x12\x41\n\x11secondary_signers\x18\x03 \x03(\x0b\x32&.aptos.transaction.v1.AccountSignature"\x8f\x02\n\x11\x46\x65\x65PayerSignature\x12\x36\n\x06sender\x18\x01 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature\x12"\n\x1asecondary_signer_addresses\x18\x02 \x03(\t\x12\x41\n\x11secondary_signers\x18\x03 \x03(\x0b\x32&.aptos.transaction.v1.AccountSignature\x12\x19\n\x11\x66\x65\x65_payer_address\x18\x04 \x01(\t\x12@\n\x10\x66\x65\x65_payer_signer\x18\x05 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature"\xcc\x01\n\x0c\x41nyPublicKey\x12\x35\n\x04type\x18\x01 \x01(\x0e\x32\'.aptos.transaction.v1.AnyPublicKey.Type\x12\x12\n\npublic_key\x18\x02 \x01(\x0c"q\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x18\n\x14TYPE_SECP256K1_ECDSA\x10\x02\x12\x18\n\x14TYPE_SECP256R1_ECDSA\x10\x03\x12\r\n\tTYPE_ZKID\x10\x04"\x91\x03\n\x0c\x41nySignature\x12\x35\n\x04type\x18\x01 \x01(\x0e\x32\'.aptos.transaction.v1.AnySignature.Type\x12\x30\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x02 \x01(\x0b\x32\x1d.aptos.transaction.v1.Ed25519H\x00\x12?\n\x0fsecp256k1_ecdsa\x18\x03 \x01(\x0b\x32$.aptos.transaction.v1.Secp256k1EcdsaH\x00\x12\x32\n\x08webauthn\x18\x04 \x01(\x0b\x32\x1e.aptos.transaction.v1.WebAuthnH\x00\x12*\n\x04zkid\x18\x05 \x01(\x0b\x32\x1a.aptos.transaction.v1.ZkIdH\x00"j\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x18\n\x14TYPE_SECP256K1_ECDSA\x10\x02\x12\x11\n\rTYPE_WEBAUTHN\x10\x03\x12\r\n\tTYPE_ZKID\x10\x04\x42\x0b\n\tsignature"\x1c\n\x07\x45\x64\x32\x35\x35\x31\x39\x12\x11\n\tsignature\x18\x01 \x01(\x0c"#\n\x0eSecp256k1Ecdsa\x12\x11\n\tsignature\x18\x01 \x01(\x0c"\x1d\n\x08WebAuthn\x12\x11\n\tsignature\x18\x01 \x01(\x0c"\x19\n\x04ZkId\x12\x11\n\tsignature\x18\x01 \x01(\x0c"\x83\x01\n\x12SingleKeySignature\x12\x36\n\npublic_key\x18\x01 \x01(\x0b\x32".aptos.transaction.v1.AnyPublicKey\x12\x35\n\tsignature\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.AnySignature"X\n\x10IndexedSignature\x12\r\n\x05index\x18\x01 \x01(\r\x12\x35\n\tsignature\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.AnySignature"\xa5\x01\n\x11MultiKeySignature\x12\x37\n\x0bpublic_keys\x18\x01 \x03(\x0b\x32".aptos.transaction.v1.AnyPublicKey\x12:\n\nsignatures\x18\x02 \x03(\x0b\x32&.aptos.transaction.v1.IndexedSignature\x12\x1b\n\x13signatures_required\x18\x03 \x01(\r"F\n\x0cSingleSender\x12\x36\n\x06sender\x18\x01 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature"\xe4\x03\n\x10\x41\x63\x63ountSignature\x12\x39\n\x04type\x18\x01 \x01(\x0e\x32+.aptos.transaction.v1.AccountSignature.Type\x12\x39\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x02 \x01(\x0b\x32&.aptos.transaction.v1.Ed25519SignatureH\x00\x12\x44\n\rmulti_ed25519\x18\x03 \x01(\x0b\x32+.aptos.transaction.v1.MultiEd25519SignatureH\x00\x12H\n\x14single_key_signature\x18\x05 \x01(\x0b\x32(.aptos.transaction.v1.SingleKeySignatureH\x00\x12\x46\n\x13multi_key_signature\x18\x06 \x01(\x0b\x32\'.aptos.transaction.v1.MultiKeySignatureH\x00"u\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x16\n\x12TYPE_MULTI_ED25519\x10\x02\x12\x13\n\x0fTYPE_SINGLE_KEY\x10\x04\x12\x12\n\x0eTYPE_MULTI_KEY\x10\x05"\x04\x08\x03\x10\x03\x42\x0b\n\tsignature*\xea\x02\n\tMoveTypes\x12\x1a\n\x16MOVE_TYPES_UNSPECIFIED\x10\x00\x12\x13\n\x0fMOVE_TYPES_BOOL\x10\x01\x12\x11\n\rMOVE_TYPES_U8\x10\x02\x12\x12\n\x0eMOVE_TYPES_U16\x10\x0c\x12\x12\n\x0eMOVE_TYPES_U32\x10\r\x12\x12\n\x0eMOVE_TYPES_U64\x10\x03\x12\x13\n\x0fMOVE_TYPES_U128\x10\x04\x12\x13\n\x0fMOVE_TYPES_U256\x10\x0e\x12\x16\n\x12MOVE_TYPES_ADDRESS\x10\x05\x12\x15\n\x11MOVE_TYPES_SIGNER\x10\x06\x12\x15\n\x11MOVE_TYPES_VECTOR\x10\x07\x12\x15\n\x11MOVE_TYPES_STRUCT\x10\x08\x12!\n\x1dMOVE_TYPES_GENERIC_TYPE_PARAM\x10\t\x12\x18\n\x14MOVE_TYPES_REFERENCE\x10\n\x12\x19\n\x15MOVE_TYPES_UNPARSABLE\x10\x0b*\x87\x01\n\x0bMoveAbility\x12\x1c\n\x18MOVE_ABILITY_UNSPECIFIED\x10\x00\x12\x15\n\x11MOVE_ABILITY_COPY\x10\x01\x12\x15\n\x11MOVE_ABILITY_DROP\x10\x02\x12\x16\n\x12MOVE_ABILITY_STORE\x10\x03\x12\x14\n\x10MOVE_ABILITY_KEY\x10\x04\x62\x06proto3' + b'\n&aptos/transaction/v1/transaction.proto\x12\x14\x61ptos.transaction.v1\x1a$aptos/util/timestamp/timestamp.proto"\x9a\x01\n\x05\x42lock\x12\x32\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1f.aptos.util.timestamp.Timestamp\x12\x12\n\x06height\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x37\n\x0ctransactions\x18\x03 \x03(\x0b\x32!.aptos.transaction.v1.Transaction\x12\x10\n\x08\x63hain_id\x18\x04 \x01(\r"\xad\x06\n\x0bTransaction\x12\x32\n\ttimestamp\x18\x01 \x01(\x0b\x32\x1f.aptos.util.timestamp.Timestamp\x12\x13\n\x07version\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x33\n\x04info\x18\x03 \x01(\x0b\x32%.aptos.transaction.v1.TransactionInfo\x12\x11\n\x05\x65poch\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x18\n\x0c\x62lock_height\x18\x05 \x01(\x04\x42\x02\x30\x01\x12?\n\x04type\x18\x06 \x01(\x0e\x32\x31.aptos.transaction.v1.Transaction.TransactionType\x12H\n\x0e\x62lock_metadata\x18\x07 \x01(\x0b\x32..aptos.transaction.v1.BlockMetadataTransactionH\x00\x12;\n\x07genesis\x18\x08 \x01(\x0b\x32(.aptos.transaction.v1.GenesisTransactionH\x00\x12L\n\x10state_checkpoint\x18\t \x01(\x0b\x32\x30.aptos.transaction.v1.StateCheckpointTransactionH\x00\x12\x35\n\x04user\x18\n \x01(\x0b\x32%.aptos.transaction.v1.UserTransactionH\x00\x12?\n\tvalidator\x18\x15 \x01(\x0b\x32*.aptos.transaction.v1.ValidatorTransactionH\x00"\xd8\x01\n\x0fTransactionType\x12 \n\x1cTRANSACTION_TYPE_UNSPECIFIED\x10\x00\x12\x1c\n\x18TRANSACTION_TYPE_GENESIS\x10\x01\x12#\n\x1fTRANSACTION_TYPE_BLOCK_METADATA\x10\x02\x12%\n!TRANSACTION_TYPE_STATE_CHECKPOINT\x10\x03\x12\x19\n\x15TRANSACTION_TYPE_USER\x10\x04\x12\x1e\n\x1aTRANSACTION_TYPE_VALIDATOR\x10\x14\x42\n\n\x08txn_data"\xbe\x01\n\x18\x42lockMetadataTransaction\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\x05round\x18\x02 \x01(\x04\x42\x02\x30\x01\x12+\n\x06\x65vents\x18\x03 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event\x12#\n\x1bprevious_block_votes_bitvec\x18\x04 \x01(\x0c\x12\x10\n\x08proposer\x18\x05 \x01(\t\x12\x1f\n\x17\x66\x61iled_proposer_indices\x18\x06 \x03(\r"r\n\x12GenesisTransaction\x12/\n\x07payload\x18\x01 \x01(\x0b\x32\x1e.aptos.transaction.v1.WriteSet\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event"\x1c\n\x1aStateCheckpointTransaction"\x16\n\x14ValidatorTransaction"}\n\x0fUserTransaction\x12=\n\x07request\x18\x01 \x01(\x0b\x32,.aptos.transaction.v1.UserTransactionRequest\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event"\x9f\x01\n\x05\x45vent\x12+\n\x03key\x18\x01 \x01(\x0b\x32\x1e.aptos.transaction.v1.EventKey\x12\x1b\n\x0fsequence_number\x18\x02 \x01(\x04\x42\x02\x30\x01\x12,\n\x04type\x18\x03 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12\x10\n\x08type_str\x18\x05 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x04 \x01(\t"\xa1\x02\n\x0fTransactionInfo\x12\x0c\n\x04hash\x18\x01 \x01(\x0c\x12\x19\n\x11state_change_hash\x18\x02 \x01(\x0c\x12\x17\n\x0f\x65vent_root_hash\x18\x03 \x01(\x0c\x12"\n\x15state_checkpoint_hash\x18\x04 \x01(\x0cH\x00\x88\x01\x01\x12\x14\n\x08gas_used\x18\x05 \x01(\x04\x42\x02\x30\x01\x12\x0f\n\x07success\x18\x06 \x01(\x08\x12\x11\n\tvm_status\x18\x07 \x01(\t\x12\x1d\n\x15\x61\x63\x63umulator_root_hash\x18\x08 \x01(\x0c\x12\x35\n\x07\x63hanges\x18\t \x03(\x0b\x32$.aptos.transaction.v1.WriteSetChangeB\x18\n\x16_state_checkpoint_hash"@\n\x08\x45ventKey\x12\x1b\n\x0f\x63reation_number\x18\x01 \x01(\x04\x42\x02\x30\x01\x12\x17\n\x0f\x61\x63\x63ount_address\x18\x02 \x01(\t"\xb0\x02\n\x16UserTransactionRequest\x12\x0e\n\x06sender\x18\x01 \x01(\t\x12\x1b\n\x0fsequence_number\x18\x02 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0emax_gas_amount\x18\x03 \x01(\x04\x42\x02\x30\x01\x12\x1a\n\x0egas_unit_price\x18\x04 \x01(\x04\x42\x02\x30\x01\x12\x42\n\x19\x65xpiration_timestamp_secs\x18\x05 \x01(\x0b\x32\x1f.aptos.util.timestamp.Timestamp\x12\x39\n\x07payload\x18\x06 \x01(\x0b\x32(.aptos.transaction.v1.TransactionPayload\x12\x32\n\tsignature\x18\x07 \x01(\x0b\x32\x1f.aptos.transaction.v1.Signature"\xda\x02\n\x08WriteSet\x12\x43\n\x0ewrite_set_type\x18\x01 \x01(\x0e\x32+.aptos.transaction.v1.WriteSet.WriteSetType\x12@\n\x10script_write_set\x18\x02 \x01(\x0b\x32$.aptos.transaction.v1.ScriptWriteSetH\x00\x12@\n\x10\x64irect_write_set\x18\x03 \x01(\x0b\x32$.aptos.transaction.v1.DirectWriteSetH\x00"x\n\x0cWriteSetType\x12\x1e\n\x1aWRITE_SET_TYPE_UNSPECIFIED\x10\x00\x12#\n\x1fWRITE_SET_TYPE_SCRIPT_WRITE_SET\x10\x01\x12#\n\x1fWRITE_SET_TYPE_DIRECT_WRITE_SET\x10\x02\x42\x0b\n\twrite_set"Y\n\x0eScriptWriteSet\x12\x12\n\nexecute_as\x18\x01 \x01(\t\x12\x33\n\x06script\x18\x02 \x01(\x0b\x32#.aptos.transaction.v1.ScriptPayload"}\n\x0e\x44irectWriteSet\x12>\n\x10write_set_change\x18\x01 \x03(\x0b\x32$.aptos.transaction.v1.WriteSetChange\x12+\n\x06\x65vents\x18\x02 \x03(\x0b\x32\x1b.aptos.transaction.v1.Event"\x89\x05\n\x0eWriteSetChange\x12\x37\n\x04type\x18\x01 \x01(\x0e\x32).aptos.transaction.v1.WriteSetChange.Type\x12;\n\rdelete_module\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.DeleteModuleH\x00\x12?\n\x0f\x64\x65lete_resource\x18\x03 \x01(\x0b\x32$.aptos.transaction.v1.DeleteResourceH\x00\x12\x42\n\x11\x64\x65lete_table_item\x18\x04 \x01(\x0b\x32%.aptos.transaction.v1.DeleteTableItemH\x00\x12\x39\n\x0cwrite_module\x18\x05 \x01(\x0b\x32!.aptos.transaction.v1.WriteModuleH\x00\x12=\n\x0ewrite_resource\x18\x06 \x01(\x0b\x32#.aptos.transaction.v1.WriteResourceH\x00\x12@\n\x10write_table_item\x18\x07 \x01(\x0b\x32$.aptos.transaction.v1.WriteTableItemH\x00"\xb5\x01\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x16\n\x12TYPE_DELETE_MODULE\x10\x01\x12\x18\n\x14TYPE_DELETE_RESOURCE\x10\x02\x12\x1a\n\x16TYPE_DELETE_TABLE_ITEM\x10\x03\x12\x15\n\x11TYPE_WRITE_MODULE\x10\x04\x12\x17\n\x13TYPE_WRITE_RESOURCE\x10\x05\x12\x19\n\x15TYPE_WRITE_TABLE_ITEM\x10\x06\x42\x08\n\x06\x63hange"k\n\x0c\x44\x65leteModule\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x32\n\x06module\x18\x03 \x01(\x0b\x32".aptos.transaction.v1.MoveModuleId"~\n\x0e\x44\x65leteResource\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x31\n\x04type\x18\x03 \x01(\x0b\x32#.aptos.transaction.v1.MoveStructTag\x12\x10\n\x08type_str\x18\x04 \x01(\t"{\n\x0f\x44\x65leteTableItem\x12\x16\n\x0estate_key_hash\x18\x01 \x01(\x0c\x12\x0e\n\x06handle\x18\x02 \x01(\t\x12\x0b\n\x03key\x18\x03 \x01(\t\x12\x33\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32%.aptos.transaction.v1.DeleteTableData"0\n\x0f\x44\x65leteTableData\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x10\n\x08key_type\x18\x02 \x01(\t"n\n\x0bWriteModule\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x36\n\x04\x64\x61ta\x18\x03 \x01(\x0b\x32(.aptos.transaction.v1.MoveModuleBytecode"\x8b\x01\n\rWriteResource\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x16\n\x0estate_key_hash\x18\x02 \x01(\x0c\x12\x31\n\x04type\x18\x03 \x01(\x0b\x32#.aptos.transaction.v1.MoveStructTag\x12\x10\n\x08type_str\x18\x04 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x05 \x01(\t"R\n\x0eWriteTableData\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x10\n\x08key_type\x18\x02 \x01(\t\x12\r\n\x05value\x18\x03 \x01(\t\x12\x12\n\nvalue_type\x18\x04 \x01(\t"y\n\x0eWriteTableItem\x12\x16\n\x0estate_key_hash\x18\x01 \x01(\x0c\x12\x0e\n\x06handle\x18\x02 \x01(\t\x12\x0b\n\x03key\x18\x03 \x01(\t\x12\x32\n\x04\x64\x61ta\x18\x04 \x01(\x0b\x32$.aptos.transaction.v1.WriteTableData"\x8c\x04\n\x12TransactionPayload\x12;\n\x04type\x18\x01 \x01(\x0e\x32-.aptos.transaction.v1.TransactionPayload.Type\x12L\n\x16\x65ntry_function_payload\x18\x02 \x01(\x0b\x32*.aptos.transaction.v1.EntryFunctionPayloadH\x00\x12=\n\x0escript_payload\x18\x03 \x01(\x0b\x32#.aptos.transaction.v1.ScriptPayloadH\x00\x12\x42\n\x11write_set_payload\x18\x05 \x01(\x0b\x32%.aptos.transaction.v1.WriteSetPayloadH\x00\x12\x41\n\x10multisig_payload\x18\x06 \x01(\x0b\x32%.aptos.transaction.v1.MultisigPayloadH\x00"\x93\x01\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bTYPE_ENTRY_FUNCTION_PAYLOAD\x10\x01\x12\x17\n\x13TYPE_SCRIPT_PAYLOAD\x10\x02\x12\x1a\n\x16TYPE_WRITE_SET_PAYLOAD\x10\x04\x12\x19\n\x15TYPE_MULTISIG_PAYLOAD\x10\x05"\x04\x08\x03\x10\x03\x42\t\n\x07payloadJ\x04\x08\x04\x10\x05"\xb9\x01\n\x14\x45ntryFunctionPayload\x12\x37\n\x08\x66unction\x18\x01 \x01(\x0b\x32%.aptos.transaction.v1.EntryFunctionId\x12\x36\n\x0etype_arguments\x18\x02 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12\x11\n\targuments\x18\x03 \x03(\t\x12\x1d\n\x15\x65ntry_function_id_str\x18\x04 \x01(\t"W\n\x12MoveScriptBytecode\x12\x10\n\x08\x62ytecode\x18\x01 \x01(\x0c\x12/\n\x03\x61\x62i\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.MoveFunction"\x92\x01\n\rScriptPayload\x12\x36\n\x04\x63ode\x18\x01 \x01(\x0b\x32(.aptos.transaction.v1.MoveScriptBytecode\x12\x36\n\x0etype_arguments\x18\x02 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12\x11\n\targuments\x18\x03 \x03(\t"\x97\x01\n\x0fMultisigPayload\x12\x18\n\x10multisig_address\x18\x01 \x01(\t\x12R\n\x13transaction_payload\x18\x02 \x01(\x0b\x32\x30.aptos.transaction.v1.MultisigTransactionPayloadH\x00\x88\x01\x01\x42\x16\n\x14_transaction_payload"\xf9\x01\n\x1aMultisigTransactionPayload\x12\x43\n\x04type\x18\x01 \x01(\x0e\x32\x35.aptos.transaction.v1.MultisigTransactionPayload.Type\x12L\n\x16\x65ntry_function_payload\x18\x02 \x01(\x0b\x32*.aptos.transaction.v1.EntryFunctionPayloadH\x00"=\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x1f\n\x1bTYPE_ENTRY_FUNCTION_PAYLOAD\x10\x01\x42\t\n\x07payload"U\n\x12MoveModuleBytecode\x12\x10\n\x08\x62ytecode\x18\x01 \x01(\x0c\x12-\n\x03\x61\x62i\x18\x02 \x01(\x0b\x32 .aptos.transaction.v1.MoveModule"\xd2\x01\n\nMoveModule\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x33\n\x07\x66riends\x18\x03 \x03(\x0b\x32".aptos.transaction.v1.MoveModuleId\x12=\n\x11\x65xposed_functions\x18\x04 \x03(\x0b\x32".aptos.transaction.v1.MoveFunction\x12\x31\n\x07structs\x18\x05 \x03(\x0b\x32 .aptos.transaction.v1.MoveStruct"\x92\x03\n\x0cMoveFunction\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x41\n\nvisibility\x18\x02 \x01(\x0e\x32-.aptos.transaction.v1.MoveFunction.Visibility\x12\x10\n\x08is_entry\x18\x03 \x01(\x08\x12O\n\x13generic_type_params\x18\x04 \x03(\x0b\x32\x32.aptos.transaction.v1.MoveFunctionGenericTypeParam\x12.\n\x06params\x18\x05 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType\x12.\n\x06return\x18\x06 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType"n\n\nVisibility\x12\x1a\n\x16VISIBILITY_UNSPECIFIED\x10\x00\x12\x16\n\x12VISIBILITY_PRIVATE\x10\x01\x12\x15\n\x11VISIBILITY_PUBLIC\x10\x02\x12\x15\n\x11VISIBILITY_FRIEND\x10\x03"\xe9\x01\n\nMoveStruct\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\tis_native\x18\x02 \x01(\x08\x12\x34\n\tabilities\x18\x03 \x03(\x0e\x32!.aptos.transaction.v1.MoveAbility\x12M\n\x13generic_type_params\x18\x04 \x03(\x0b\x32\x30.aptos.transaction.v1.MoveStructGenericTypeParam\x12\x35\n\x06\x66ields\x18\x05 \x03(\x0b\x32%.aptos.transaction.v1.MoveStructField"h\n\x1aMoveStructGenericTypeParam\x12\x36\n\x0b\x63onstraints\x18\x01 \x03(\x0e\x32!.aptos.transaction.v1.MoveAbility\x12\x12\n\nis_phantom\x18\x02 \x01(\x08"M\n\x0fMoveStructField\x12\x0c\n\x04name\x18\x01 \x01(\t\x12,\n\x04type\x18\x02 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveType"V\n\x1cMoveFunctionGenericTypeParam\x12\x36\n\x0b\x63onstraints\x18\x01 \x03(\x0e\x32!.aptos.transaction.v1.MoveAbility"\xf8\x02\n\x08MoveType\x12-\n\x04type\x18\x01 \x01(\x0e\x32\x1f.aptos.transaction.v1.MoveTypes\x12\x30\n\x06vector\x18\x03 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveTypeH\x00\x12\x35\n\x06struct\x18\x04 \x01(\x0b\x32#.aptos.transaction.v1.MoveStructTagH\x00\x12"\n\x18generic_type_param_index\x18\x05 \x01(\rH\x00\x12\x41\n\treference\x18\x06 \x01(\x0b\x32,.aptos.transaction.v1.MoveType.ReferenceTypeH\x00\x12\x14\n\nunparsable\x18\x07 \x01(\tH\x00\x1aL\n\rReferenceType\x12\x0f\n\x07mutable\x18\x01 \x01(\x08\x12*\n\x02to\x18\x02 \x01(\x0b\x32\x1e.aptos.transaction.v1.MoveTypeB\t\n\x07\x63ontent"D\n\x0fWriteSetPayload\x12\x31\n\twrite_set\x18\x01 \x01(\x0b\x32\x1e.aptos.transaction.v1.WriteSet"S\n\x0f\x45ntryFunctionId\x12\x32\n\x06module\x18\x01 \x01(\x0b\x32".aptos.transaction.v1.MoveModuleId\x12\x0c\n\x04name\x18\x02 \x01(\t"-\n\x0cMoveModuleId\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t"{\n\rMoveStructTag\x12\x0f\n\x07\x61\x64\x64ress\x18\x01 \x01(\t\x12\x0e\n\x06module\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12;\n\x13generic_type_params\x18\x04 \x03(\x0b\x32\x1e.aptos.transaction.v1.MoveType"\x9b\x04\n\tSignature\x12\x32\n\x04type\x18\x01 \x01(\x0e\x32$.aptos.transaction.v1.Signature.Type\x12\x39\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x02 \x01(\x0b\x32&.aptos.transaction.v1.Ed25519SignatureH\x00\x12\x44\n\rmulti_ed25519\x18\x03 \x01(\x0b\x32+.aptos.transaction.v1.MultiEd25519SignatureH\x00\x12@\n\x0bmulti_agent\x18\x04 \x01(\x0b\x32).aptos.transaction.v1.MultiAgentSignatureH\x00\x12<\n\tfee_payer\x18\x05 \x01(\x0b\x32\'.aptos.transaction.v1.FeePayerSignatureH\x00\x12;\n\rsingle_sender\x18\x07 \x01(\x0b\x32".aptos.transaction.v1.SingleSenderH\x00"\x8e\x01\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x16\n\x12TYPE_MULTI_ED25519\x10\x02\x12\x14\n\x10TYPE_MULTI_AGENT\x10\x03\x12\x12\n\x0eTYPE_FEE_PAYER\x10\x04\x12\x16\n\x12TYPE_SINGLE_SENDER\x10\x06"\x04\x08\x05\x10\x05\x42\x0b\n\tsignature"9\n\x10\x45\x64\x32\x35\x35\x31\x39Signature\x12\x12\n\npublic_key\x18\x01 \x01(\x0c\x12\x11\n\tsignature\x18\x02 \x01(\x0c"o\n\x15MultiEd25519Signature\x12\x13\n\x0bpublic_keys\x18\x01 \x03(\x0c\x12\x12\n\nsignatures\x18\x02 \x03(\x0c\x12\x11\n\tthreshold\x18\x03 \x01(\r\x12\x1a\n\x12public_key_indices\x18\x04 \x03(\r"\xb4\x01\n\x13MultiAgentSignature\x12\x36\n\x06sender\x18\x01 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature\x12"\n\x1asecondary_signer_addresses\x18\x02 \x03(\t\x12\x41\n\x11secondary_signers\x18\x03 \x03(\x0b\x32&.aptos.transaction.v1.AccountSignature"\x8f\x02\n\x11\x46\x65\x65PayerSignature\x12\x36\n\x06sender\x18\x01 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature\x12"\n\x1asecondary_signer_addresses\x18\x02 \x03(\t\x12\x41\n\x11secondary_signers\x18\x03 \x03(\x0b\x32&.aptos.transaction.v1.AccountSignature\x12\x19\n\x11\x66\x65\x65_payer_address\x18\x04 \x01(\t\x12@\n\x10\x66\x65\x65_payer_signer\x18\x05 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature"\xcc\x01\n\x0c\x41nyPublicKey\x12\x35\n\x04type\x18\x01 \x01(\x0e\x32\'.aptos.transaction.v1.AnyPublicKey.Type\x12\x12\n\npublic_key\x18\x02 \x01(\x0c"q\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x18\n\x14TYPE_SECP256K1_ECDSA\x10\x02\x12\x18\n\x14TYPE_SECP256R1_ECDSA\x10\x03\x12\r\n\tTYPE_ZKID\x10\x04"\x91\x03\n\x0c\x41nySignature\x12\x35\n\x04type\x18\x01 \x01(\x0e\x32\'.aptos.transaction.v1.AnySignature.Type\x12\x30\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x02 \x01(\x0b\x32\x1d.aptos.transaction.v1.Ed25519H\x00\x12?\n\x0fsecp256k1_ecdsa\x18\x03 \x01(\x0b\x32$.aptos.transaction.v1.Secp256k1EcdsaH\x00\x12\x32\n\x08webauthn\x18\x04 \x01(\x0b\x32\x1e.aptos.transaction.v1.WebAuthnH\x00\x12*\n\x04zkid\x18\x05 \x01(\x0b\x32\x1a.aptos.transaction.v1.ZkIdH\x00"j\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x18\n\x14TYPE_SECP256K1_ECDSA\x10\x02\x12\x11\n\rTYPE_WEBAUTHN\x10\x03\x12\r\n\tTYPE_ZKID\x10\x04\x42\x0b\n\tsignature"\x1c\n\x07\x45\x64\x32\x35\x35\x31\x39\x12\x11\n\tsignature\x18\x01 \x01(\x0c"#\n\x0eSecp256k1Ecdsa\x12\x11\n\tsignature\x18\x01 \x01(\x0c"\x1d\n\x08WebAuthn\x12\x11\n\tsignature\x18\x01 \x01(\x0c"\x19\n\x04ZkId\x12\x11\n\tsignature\x18\x01 \x01(\x0c"\x83\x01\n\x12SingleKeySignature\x12\x36\n\npublic_key\x18\x01 \x01(\x0b\x32".aptos.transaction.v1.AnyPublicKey\x12\x35\n\tsignature\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.AnySignature"X\n\x10IndexedSignature\x12\r\n\x05index\x18\x01 \x01(\r\x12\x35\n\tsignature\x18\x02 \x01(\x0b\x32".aptos.transaction.v1.AnySignature"\xa5\x01\n\x11MultiKeySignature\x12\x37\n\x0bpublic_keys\x18\x01 \x03(\x0b\x32".aptos.transaction.v1.AnyPublicKey\x12:\n\nsignatures\x18\x02 \x03(\x0b\x32&.aptos.transaction.v1.IndexedSignature\x12\x1b\n\x13signatures_required\x18\x03 \x01(\r"F\n\x0cSingleSender\x12\x36\n\x06sender\x18\x01 \x01(\x0b\x32&.aptos.transaction.v1.AccountSignature"\xe4\x03\n\x10\x41\x63\x63ountSignature\x12\x39\n\x04type\x18\x01 \x01(\x0e\x32+.aptos.transaction.v1.AccountSignature.Type\x12\x39\n\x07\x65\x64\x32\x35\x35\x31\x39\x18\x02 \x01(\x0b\x32&.aptos.transaction.v1.Ed25519SignatureH\x00\x12\x44\n\rmulti_ed25519\x18\x03 \x01(\x0b\x32+.aptos.transaction.v1.MultiEd25519SignatureH\x00\x12H\n\x14single_key_signature\x18\x05 \x01(\x0b\x32(.aptos.transaction.v1.SingleKeySignatureH\x00\x12\x46\n\x13multi_key_signature\x18\x06 \x01(\x0b\x32\'.aptos.transaction.v1.MultiKeySignatureH\x00"u\n\x04Type\x12\x14\n\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n\x0cTYPE_ED25519\x10\x01\x12\x16\n\x12TYPE_MULTI_ED25519\x10\x02\x12\x13\n\x0fTYPE_SINGLE_KEY\x10\x04\x12\x12\n\x0eTYPE_MULTI_KEY\x10\x05"\x04\x08\x03\x10\x03\x42\x0b\n\tsignature*\xea\x02\n\tMoveTypes\x12\x1a\n\x16MOVE_TYPES_UNSPECIFIED\x10\x00\x12\x13\n\x0fMOVE_TYPES_BOOL\x10\x01\x12\x11\n\rMOVE_TYPES_U8\x10\x02\x12\x12\n\x0eMOVE_TYPES_U16\x10\x0c\x12\x12\n\x0eMOVE_TYPES_U32\x10\r\x12\x12\n\x0eMOVE_TYPES_U64\x10\x03\x12\x13\n\x0fMOVE_TYPES_U128\x10\x04\x12\x13\n\x0fMOVE_TYPES_U256\x10\x0e\x12\x16\n\x12MOVE_TYPES_ADDRESS\x10\x05\x12\x15\n\x11MOVE_TYPES_SIGNER\x10\x06\x12\x15\n\x11MOVE_TYPES_VECTOR\x10\x07\x12\x15\n\x11MOVE_TYPES_STRUCT\x10\x08\x12!\n\x1dMOVE_TYPES_GENERIC_TYPE_PARAM\x10\t\x12\x18\n\x14MOVE_TYPES_REFERENCE\x10\n\x12\x19\n\x15MOVE_TYPES_UNPARSABLE\x10\x0b*\x87\x01\n\x0bMoveAbility\x12\x1c\n\x18MOVE_ABILITY_UNSPECIFIED\x10\x00\x12\x15\n\x11MOVE_ABILITY_COPY\x10\x01\x12\x15\n\x11MOVE_ABILITY_DROP\x10\x02\x12\x16\n\x12MOVE_ABILITY_STORE\x10\x03\x12\x14\n\x10MOVE_ABILITY_KEY\x10\x04\x62\x06proto3' ) _globals = globals() @@ -55,10 +55,10 @@ _USERTRANSACTIONREQUEST.fields_by_name[ "gas_unit_price" ]._serialized_options = b"0\001" - _globals["_MOVETYPES"]._serialized_start = 10800 - _globals["_MOVETYPES"]._serialized_end = 11162 - _globals["_MOVEABILITY"]._serialized_start = 11165 - _globals["_MOVEABILITY"]._serialized_end = 11300 + _globals["_MOVETYPES"]._serialized_start = 10622 + _globals["_MOVETYPES"]._serialized_end = 10984 + _globals["_MOVEABILITY"]._serialized_start = 10987 + _globals["_MOVEABILITY"]._serialized_end = 11122 _globals["_BLOCK"]._serialized_start = 103 _globals["_BLOCK"]._serialized_end = 257 _globals["_TRANSACTION"]._serialized_start = 260 @@ -112,89 +112,87 @@ _globals["_WRITETABLEITEM"]._serialized_start = 4361 _globals["_WRITETABLEITEM"]._serialized_end = 4482 _globals["_TRANSACTIONPAYLOAD"]._serialized_start = 4485 - _globals["_TRANSACTIONPAYLOAD"]._serialized_end = 5105 - _globals["_TRANSACTIONPAYLOAD_TYPE"]._serialized_start = 4921 - _globals["_TRANSACTIONPAYLOAD_TYPE"]._serialized_end = 5094 - _globals["_ENTRYFUNCTIONPAYLOAD"]._serialized_start = 5108 - _globals["_ENTRYFUNCTIONPAYLOAD"]._serialized_end = 5293 - _globals["_MOVESCRIPTBYTECODE"]._serialized_start = 5295 - _globals["_MOVESCRIPTBYTECODE"]._serialized_end = 5382 - _globals["_SCRIPTPAYLOAD"]._serialized_start = 5385 - _globals["_SCRIPTPAYLOAD"]._serialized_end = 5531 - _globals["_MULTISIGPAYLOAD"]._serialized_start = 5534 - _globals["_MULTISIGPAYLOAD"]._serialized_end = 5685 - _globals["_MULTISIGTRANSACTIONPAYLOAD"]._serialized_start = 5688 - _globals["_MULTISIGTRANSACTIONPAYLOAD"]._serialized_end = 5937 - _globals["_MULTISIGTRANSACTIONPAYLOAD_TYPE"]._serialized_start = 4921 - _globals["_MULTISIGTRANSACTIONPAYLOAD_TYPE"]._serialized_end = 4982 - _globals["_MODULEBUNDLEPAYLOAD"]._serialized_start = 5939 - _globals["_MODULEBUNDLEPAYLOAD"]._serialized_end = 6019 - _globals["_MOVEMODULEBYTECODE"]._serialized_start = 6021 - _globals["_MOVEMODULEBYTECODE"]._serialized_end = 6106 - _globals["_MOVEMODULE"]._serialized_start = 6109 - _globals["_MOVEMODULE"]._serialized_end = 6319 - _globals["_MOVEFUNCTION"]._serialized_start = 6322 - _globals["_MOVEFUNCTION"]._serialized_end = 6724 - _globals["_MOVEFUNCTION_VISIBILITY"]._serialized_start = 6614 - _globals["_MOVEFUNCTION_VISIBILITY"]._serialized_end = 6724 - _globals["_MOVESTRUCT"]._serialized_start = 6727 - _globals["_MOVESTRUCT"]._serialized_end = 6960 - _globals["_MOVESTRUCTGENERICTYPEPARAM"]._serialized_start = 6962 - _globals["_MOVESTRUCTGENERICTYPEPARAM"]._serialized_end = 7066 - _globals["_MOVESTRUCTFIELD"]._serialized_start = 7068 - _globals["_MOVESTRUCTFIELD"]._serialized_end = 7145 - _globals["_MOVEFUNCTIONGENERICTYPEPARAM"]._serialized_start = 7147 - _globals["_MOVEFUNCTIONGENERICTYPEPARAM"]._serialized_end = 7233 - _globals["_MOVETYPE"]._serialized_start = 7236 - _globals["_MOVETYPE"]._serialized_end = 7612 - _globals["_MOVETYPE_REFERENCETYPE"]._serialized_start = 7525 - _globals["_MOVETYPE_REFERENCETYPE"]._serialized_end = 7601 - _globals["_WRITESETPAYLOAD"]._serialized_start = 7614 - _globals["_WRITESETPAYLOAD"]._serialized_end = 7682 - _globals["_ENTRYFUNCTIONID"]._serialized_start = 7684 - _globals["_ENTRYFUNCTIONID"]._serialized_end = 7767 - _globals["_MOVEMODULEID"]._serialized_start = 7769 - _globals["_MOVEMODULEID"]._serialized_end = 7814 - _globals["_MOVESTRUCTTAG"]._serialized_start = 7816 - _globals["_MOVESTRUCTTAG"]._serialized_end = 7939 - _globals["_SIGNATURE"]._serialized_start = 7942 - _globals["_SIGNATURE"]._serialized_end = 8481 - _globals["_SIGNATURE_TYPE"]._serialized_start = 8326 - _globals["_SIGNATURE_TYPE"]._serialized_end = 8468 - _globals["_ED25519SIGNATURE"]._serialized_start = 8483 - _globals["_ED25519SIGNATURE"]._serialized_end = 8540 - _globals["_MULTIED25519SIGNATURE"]._serialized_start = 8542 - _globals["_MULTIED25519SIGNATURE"]._serialized_end = 8653 - _globals["_MULTIAGENTSIGNATURE"]._serialized_start = 8656 - _globals["_MULTIAGENTSIGNATURE"]._serialized_end = 8836 - _globals["_FEEPAYERSIGNATURE"]._serialized_start = 8839 - _globals["_FEEPAYERSIGNATURE"]._serialized_end = 9110 - _globals["_ANYPUBLICKEY"]._serialized_start = 9113 - _globals["_ANYPUBLICKEY"]._serialized_end = 9317 - _globals["_ANYPUBLICKEY_TYPE"]._serialized_start = 9204 - _globals["_ANYPUBLICKEY_TYPE"]._serialized_end = 9317 - _globals["_ANYSIGNATURE"]._serialized_start = 9320 - _globals["_ANYSIGNATURE"]._serialized_end = 9721 - _globals["_ANYSIGNATURE_TYPE"]._serialized_start = 9602 - _globals["_ANYSIGNATURE_TYPE"]._serialized_end = 9708 - _globals["_ED25519"]._serialized_start = 9723 - _globals["_ED25519"]._serialized_end = 9751 - _globals["_SECP256K1ECDSA"]._serialized_start = 9753 - _globals["_SECP256K1ECDSA"]._serialized_end = 9788 - _globals["_WEBAUTHN"]._serialized_start = 9790 - _globals["_WEBAUTHN"]._serialized_end = 9819 - _globals["_ZKID"]._serialized_start = 9821 - _globals["_ZKID"]._serialized_end = 9846 - _globals["_SINGLEKEYSIGNATURE"]._serialized_start = 9849 - _globals["_SINGLEKEYSIGNATURE"]._serialized_end = 9980 - _globals["_INDEXEDSIGNATURE"]._serialized_start = 9982 - _globals["_INDEXEDSIGNATURE"]._serialized_end = 10070 - _globals["_MULTIKEYSIGNATURE"]._serialized_start = 10073 - _globals["_MULTIKEYSIGNATURE"]._serialized_end = 10238 - _globals["_SINGLESENDER"]._serialized_start = 10240 - _globals["_SINGLESENDER"]._serialized_end = 10310 - _globals["_ACCOUNTSIGNATURE"]._serialized_start = 10313 - _globals["_ACCOUNTSIGNATURE"]._serialized_end = 10797 - _globals["_ACCOUNTSIGNATURE_TYPE"]._serialized_start = 10667 - _globals["_ACCOUNTSIGNATURE_TYPE"]._serialized_end = 10784 + _globals["_TRANSACTIONPAYLOAD"]._serialized_end = 5009 + _globals["_TRANSACTIONPAYLOAD_TYPE"]._serialized_start = 4845 + _globals["_TRANSACTIONPAYLOAD_TYPE"]._serialized_end = 4992 + _globals["_ENTRYFUNCTIONPAYLOAD"]._serialized_start = 5012 + _globals["_ENTRYFUNCTIONPAYLOAD"]._serialized_end = 5197 + _globals["_MOVESCRIPTBYTECODE"]._serialized_start = 5199 + _globals["_MOVESCRIPTBYTECODE"]._serialized_end = 5286 + _globals["_SCRIPTPAYLOAD"]._serialized_start = 5289 + _globals["_SCRIPTPAYLOAD"]._serialized_end = 5435 + _globals["_MULTISIGPAYLOAD"]._serialized_start = 5438 + _globals["_MULTISIGPAYLOAD"]._serialized_end = 5589 + _globals["_MULTISIGTRANSACTIONPAYLOAD"]._serialized_start = 5592 + _globals["_MULTISIGTRANSACTIONPAYLOAD"]._serialized_end = 5841 + _globals["_MULTISIGTRANSACTIONPAYLOAD_TYPE"]._serialized_start = 4845 + _globals["_MULTISIGTRANSACTIONPAYLOAD_TYPE"]._serialized_end = 4906 + _globals["_MOVEMODULEBYTECODE"]._serialized_start = 5843 + _globals["_MOVEMODULEBYTECODE"]._serialized_end = 5928 + _globals["_MOVEMODULE"]._serialized_start = 5931 + _globals["_MOVEMODULE"]._serialized_end = 6141 + _globals["_MOVEFUNCTION"]._serialized_start = 6144 + _globals["_MOVEFUNCTION"]._serialized_end = 6546 + _globals["_MOVEFUNCTION_VISIBILITY"]._serialized_start = 6436 + _globals["_MOVEFUNCTION_VISIBILITY"]._serialized_end = 6546 + _globals["_MOVESTRUCT"]._serialized_start = 6549 + _globals["_MOVESTRUCT"]._serialized_end = 6782 + _globals["_MOVESTRUCTGENERICTYPEPARAM"]._serialized_start = 6784 + _globals["_MOVESTRUCTGENERICTYPEPARAM"]._serialized_end = 6888 + _globals["_MOVESTRUCTFIELD"]._serialized_start = 6890 + _globals["_MOVESTRUCTFIELD"]._serialized_end = 6967 + _globals["_MOVEFUNCTIONGENERICTYPEPARAM"]._serialized_start = 6969 + _globals["_MOVEFUNCTIONGENERICTYPEPARAM"]._serialized_end = 7055 + _globals["_MOVETYPE"]._serialized_start = 7058 + _globals["_MOVETYPE"]._serialized_end = 7434 + _globals["_MOVETYPE_REFERENCETYPE"]._serialized_start = 7347 + _globals["_MOVETYPE_REFERENCETYPE"]._serialized_end = 7423 + _globals["_WRITESETPAYLOAD"]._serialized_start = 7436 + _globals["_WRITESETPAYLOAD"]._serialized_end = 7504 + _globals["_ENTRYFUNCTIONID"]._serialized_start = 7506 + _globals["_ENTRYFUNCTIONID"]._serialized_end = 7589 + _globals["_MOVEMODULEID"]._serialized_start = 7591 + _globals["_MOVEMODULEID"]._serialized_end = 7636 + _globals["_MOVESTRUCTTAG"]._serialized_start = 7638 + _globals["_MOVESTRUCTTAG"]._serialized_end = 7761 + _globals["_SIGNATURE"]._serialized_start = 7764 + _globals["_SIGNATURE"]._serialized_end = 8303 + _globals["_SIGNATURE_TYPE"]._serialized_start = 8148 + _globals["_SIGNATURE_TYPE"]._serialized_end = 8290 + _globals["_ED25519SIGNATURE"]._serialized_start = 8305 + _globals["_ED25519SIGNATURE"]._serialized_end = 8362 + _globals["_MULTIED25519SIGNATURE"]._serialized_start = 8364 + _globals["_MULTIED25519SIGNATURE"]._serialized_end = 8475 + _globals["_MULTIAGENTSIGNATURE"]._serialized_start = 8478 + _globals["_MULTIAGENTSIGNATURE"]._serialized_end = 8658 + _globals["_FEEPAYERSIGNATURE"]._serialized_start = 8661 + _globals["_FEEPAYERSIGNATURE"]._serialized_end = 8932 + _globals["_ANYPUBLICKEY"]._serialized_start = 8935 + _globals["_ANYPUBLICKEY"]._serialized_end = 9139 + _globals["_ANYPUBLICKEY_TYPE"]._serialized_start = 9026 + _globals["_ANYPUBLICKEY_TYPE"]._serialized_end = 9139 + _globals["_ANYSIGNATURE"]._serialized_start = 9142 + _globals["_ANYSIGNATURE"]._serialized_end = 9543 + _globals["_ANYSIGNATURE_TYPE"]._serialized_start = 9424 + _globals["_ANYSIGNATURE_TYPE"]._serialized_end = 9530 + _globals["_ED25519"]._serialized_start = 9545 + _globals["_ED25519"]._serialized_end = 9573 + _globals["_SECP256K1ECDSA"]._serialized_start = 9575 + _globals["_SECP256K1ECDSA"]._serialized_end = 9610 + _globals["_WEBAUTHN"]._serialized_start = 9612 + _globals["_WEBAUTHN"]._serialized_end = 9641 + _globals["_ZKID"]._serialized_start = 9643 + _globals["_ZKID"]._serialized_end = 9668 + _globals["_SINGLEKEYSIGNATURE"]._serialized_start = 9671 + _globals["_SINGLEKEYSIGNATURE"]._serialized_end = 9802 + _globals["_INDEXEDSIGNATURE"]._serialized_start = 9804 + _globals["_INDEXEDSIGNATURE"]._serialized_end = 9892 + _globals["_MULTIKEYSIGNATURE"]._serialized_start = 9895 + _globals["_MULTIKEYSIGNATURE"]._serialized_end = 10060 + _globals["_SINGLESENDER"]._serialized_start = 10062 + _globals["_SINGLESENDER"]._serialized_end = 10132 + _globals["_ACCOUNTSIGNATURE"]._serialized_start = 10135 + _globals["_ACCOUNTSIGNATURE"]._serialized_end = 10619 + _globals["_ACCOUNTSIGNATURE_TYPE"]._serialized_start = 10489 + _globals["_ACCOUNTSIGNATURE_TYPE"]._serialized_end = 10606 # @@protoc_insertion_point(module_scope) diff --git a/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.pyi b/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.pyi index 8dfd96aa32974..caadcb0006078 100644 --- a/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.pyi +++ b/protos/python/aptos_protos/aptos/transaction/v1/transaction_pb2.pyi @@ -557,7 +557,6 @@ class TransactionPayload(_message.Message): "type", "entry_function_payload", "script_payload", - "module_bundle_payload", "write_set_payload", "multisig_payload", ] @@ -567,25 +566,21 @@ class TransactionPayload(_message.Message): TYPE_UNSPECIFIED: _ClassVar[TransactionPayload.Type] TYPE_ENTRY_FUNCTION_PAYLOAD: _ClassVar[TransactionPayload.Type] TYPE_SCRIPT_PAYLOAD: _ClassVar[TransactionPayload.Type] - TYPE_MODULE_BUNDLE_PAYLOAD: _ClassVar[TransactionPayload.Type] TYPE_WRITE_SET_PAYLOAD: _ClassVar[TransactionPayload.Type] TYPE_MULTISIG_PAYLOAD: _ClassVar[TransactionPayload.Type] TYPE_UNSPECIFIED: TransactionPayload.Type TYPE_ENTRY_FUNCTION_PAYLOAD: TransactionPayload.Type TYPE_SCRIPT_PAYLOAD: TransactionPayload.Type - TYPE_MODULE_BUNDLE_PAYLOAD: TransactionPayload.Type TYPE_WRITE_SET_PAYLOAD: TransactionPayload.Type TYPE_MULTISIG_PAYLOAD: TransactionPayload.Type TYPE_FIELD_NUMBER: _ClassVar[int] ENTRY_FUNCTION_PAYLOAD_FIELD_NUMBER: _ClassVar[int] SCRIPT_PAYLOAD_FIELD_NUMBER: _ClassVar[int] - MODULE_BUNDLE_PAYLOAD_FIELD_NUMBER: _ClassVar[int] WRITE_SET_PAYLOAD_FIELD_NUMBER: _ClassVar[int] MULTISIG_PAYLOAD_FIELD_NUMBER: _ClassVar[int] type: TransactionPayload.Type entry_function_payload: EntryFunctionPayload script_payload: ScriptPayload - module_bundle_payload: ModuleBundlePayload write_set_payload: WriteSetPayload multisig_payload: MultisigPayload def __init__( @@ -593,7 +588,6 @@ class TransactionPayload(_message.Message): type: _Optional[_Union[TransactionPayload.Type, str]] = ..., entry_function_payload: _Optional[_Union[EntryFunctionPayload, _Mapping]] = ..., script_payload: _Optional[_Union[ScriptPayload, _Mapping]] = ..., - module_bundle_payload: _Optional[_Union[ModuleBundlePayload, _Mapping]] = ..., write_set_payload: _Optional[_Union[WriteSetPayload, _Mapping]] = ..., multisig_payload: _Optional[_Union[MultisigPayload, _Mapping]] = ..., ) -> None: ... @@ -676,14 +670,6 @@ class MultisigTransactionPayload(_message.Message): entry_function_payload: _Optional[_Union[EntryFunctionPayload, _Mapping]] = ..., ) -> None: ... -class ModuleBundlePayload(_message.Message): - __slots__ = ["modules"] - MODULES_FIELD_NUMBER: _ClassVar[int] - modules: _containers.RepeatedCompositeFieldContainer[MoveModuleBytecode] - def __init__( - self, modules: _Optional[_Iterable[_Union[MoveModuleBytecode, _Mapping]]] = ... - ) -> None: ... - class MoveModuleBytecode(_message.Message): __slots__ = ["bytecode", "abi"] BYTECODE_FIELD_NUMBER: _ClassVar[int] diff --git a/protos/rust/src/pb/aptos.transaction.v1.rs b/protos/rust/src/pb/aptos.transaction.v1.rs index 89e4ee83dd69a..8202c9d2ce857 100644 --- a/protos/rust/src/pb/aptos.transaction.v1.rs +++ b/protos/rust/src/pb/aptos.transaction.v1.rs @@ -435,7 +435,7 @@ pub struct WriteTableItem { pub struct TransactionPayload { #[prost(enumeration="transaction_payload::Type", tag="1")] pub r#type: i32, - #[prost(oneof="transaction_payload::Payload", tags="2, 3, 4, 5, 6")] + #[prost(oneof="transaction_payload::Payload", tags="2, 3, 5, 6")] pub payload: ::core::option::Option, } /// Nested message and enum types in `TransactionPayload`. @@ -446,7 +446,6 @@ pub mod transaction_payload { Unspecified = 0, EntryFunctionPayload = 1, ScriptPayload = 2, - ModuleBundlePayload = 3, WriteSetPayload = 4, MultisigPayload = 5, } @@ -460,7 +459,6 @@ pub mod transaction_payload { Type::Unspecified => "TYPE_UNSPECIFIED", Type::EntryFunctionPayload => "TYPE_ENTRY_FUNCTION_PAYLOAD", Type::ScriptPayload => "TYPE_SCRIPT_PAYLOAD", - Type::ModuleBundlePayload => "TYPE_MODULE_BUNDLE_PAYLOAD", Type::WriteSetPayload => "TYPE_WRITE_SET_PAYLOAD", Type::MultisigPayload => "TYPE_MULTISIG_PAYLOAD", } @@ -471,7 +469,6 @@ pub mod transaction_payload { "TYPE_UNSPECIFIED" => Some(Self::Unspecified), "TYPE_ENTRY_FUNCTION_PAYLOAD" => Some(Self::EntryFunctionPayload), "TYPE_SCRIPT_PAYLOAD" => Some(Self::ScriptPayload), - "TYPE_MODULE_BUNDLE_PAYLOAD" => Some(Self::ModuleBundlePayload), "TYPE_WRITE_SET_PAYLOAD" => Some(Self::WriteSetPayload), "TYPE_MULTISIG_PAYLOAD" => Some(Self::MultisigPayload), _ => None, @@ -485,8 +482,6 @@ pub mod transaction_payload { EntryFunctionPayload(super::EntryFunctionPayload), #[prost(message, tag="3")] ScriptPayload(super::ScriptPayload), - #[prost(message, tag="4")] - ModuleBundlePayload(super::ModuleBundlePayload), #[prost(message, tag="5")] WriteSetPayload(super::WriteSetPayload), #[prost(message, tag="6")] @@ -576,12 +571,6 @@ pub mod multisig_transaction_payload { } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] -pub struct ModuleBundlePayload { - #[prost(message, repeated, tag="1")] - pub modules: ::prost::alloc::vec::Vec, -} -#[allow(clippy::derive_partial_eq_without_eq)] -#[derive(Clone, PartialEq, ::prost::Message)] pub struct MoveModuleBytecode { #[prost(bytes="vec", tag="1")] pub bytecode: ::prost::alloc::vec::Vec, @@ -1190,7 +1179,7 @@ impl MoveAbility { } /// Encoded file descriptor set for the `aptos.transaction.v1` package pub const FILE_DESCRIPTOR_SET: &[u8] = &[ - 0x0a, 0xa9, 0x87, 0x02, 0x0a, 0x26, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, + 0x0a, 0x81, 0x85, 0x02, 0x0a, 0x26, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, @@ -1532,8 +1521,8 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x54, - 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xce, - 0x05, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, + 0x61, 0x62, 0x6c, 0x65, 0x44, 0x61, 0x74, 0x61, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xd9, + 0x04, 0x0a, 0x12, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x41, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, @@ -1549,104 +1538,91 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x0d, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x5f, 0x0a, 0x15, 0x6d, 0x6f, - 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x61, 0x70, 0x74, 0x6f, - 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x13, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x42, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x53, 0x0a, 0x11, 0x77, - 0x72, 0x69, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x72, - 0x69, 0x74, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, - 0x0f, 0x77, 0x72, 0x69, 0x74, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x12, 0x52, 0x0a, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x74, - 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xad, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, - 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x54, 0x52, - 0x59, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, - 0x41, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x52, - 0x49, 0x50, 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x02, 0x12, 0x1e, 0x0a, - 0x1a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x4f, 0x44, 0x55, 0x4c, 0x45, 0x5f, 0x42, 0x55, 0x4e, - 0x44, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x03, 0x12, 0x1a, 0x0a, - 0x16, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, - 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x59, 0x50, - 0x45, 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x49, 0x47, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, - 0x41, 0x44, 0x10, 0x05, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, - 0xf1, 0x01, 0x0a, 0x14, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x41, 0x0a, 0x08, 0x66, 0x75, 0x6e, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x74, - 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x52, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0e, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x0d, 0x74, 0x79, 0x70, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x31, 0x0a, 0x15, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x73, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x12, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x53, 0x74, 0x72, 0x22, 0x66, 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x79, 0x74, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x79, 0x74, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x34, 0x0a, 0x03, 0x61, 0x62, 0x69, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x46, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x61, 0x62, 0x69, 0x22, 0xb2, 0x01, 0x0a, 0x0d, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3c, 0x0a, - 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, - 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x42, 0x79, 0x74, - 0x65, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x74, - 0x79, 0x70, 0x65, 0x5f, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x0d, 0x74, 0x79, 0x70, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, - 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, - 0x22, 0xbc, 0x01, 0x0a, 0x0f, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, - 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x66, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, - 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, - 0x52, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x88, 0x01, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, - 0x95, 0x02, 0x0a, 0x1a, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x49, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x61, - 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x54, - 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x62, 0x0a, 0x16, 0x65, 0x6e, 0x74, - 0x72, 0x79, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, - 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x70, 0x74, 0x6f, + 0x69, 0x70, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x53, 0x0a, 0x11, 0x77, 0x72, + 0x69, 0x74, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x72, 0x69, + 0x74, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x0f, + 0x77, 0x72, 0x69, 0x74, 0x65, 0x53, 0x65, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, + 0x52, 0x0a, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, - 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x14, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, - 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x3d, 0x0a, - 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, - 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x54, - 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, - 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x01, 0x42, 0x09, 0x0a, 0x07, - 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x59, 0x0a, 0x13, 0x4d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x42, - 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x28, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x75, 0x6c, - 0x65, 0x73, 0x22, 0x64, 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, + 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x48, 0x00, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x22, 0x93, 0x01, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x59, + 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, + 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x43, 0x52, 0x49, + 0x50, 0x54, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, + 0x54, 0x59, 0x50, 0x45, 0x5f, 0x57, 0x52, 0x49, 0x54, 0x45, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, + 0x41, 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x59, 0x50, 0x45, + 0x5f, 0x4d, 0x55, 0x4c, 0x54, 0x49, 0x53, 0x49, 0x47, 0x5f, 0x50, 0x41, 0x59, 0x4c, 0x4f, 0x41, + 0x44, 0x10, 0x05, 0x22, 0x04, 0x08, 0x03, 0x10, 0x03, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xf1, 0x01, 0x0a, 0x14, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, + 0x6f, 0x61, 0x64, 0x12, 0x41, 0x0a, 0x08, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x52, 0x08, 0x66, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, + 0x74, 0x79, 0x70, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, + 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x5f, 0x73, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x53, 0x74, 0x72, 0x22, 0x66, + 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x42, 0x79, 0x74, 0x65, + 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, + 0x12, 0x34, 0x0a, 0x03, 0x61, 0x62, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x03, 0x61, 0x62, 0x69, 0x22, 0xb2, 0x01, 0x0a, 0x0d, 0x53, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x3c, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, + 0x76, 0x65, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, + 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x61, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, + 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, + 0x74, 0x79, 0x70, 0x65, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1c, 0x0a, + 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xbc, 0x01, 0x0a, 0x0f, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, + 0x29, 0x0a, 0x10, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, + 0x73, 0x69, 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x66, 0x0a, 0x13, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x00, 0x52, 0x12, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x88, + 0x01, 0x01, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x95, 0x02, 0x0a, 0x1a, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x49, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x35, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, + 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x73, 0x69, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x62, 0x0a, 0x16, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x66, 0x75, + 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x70, 0x74, 0x6f, 0x73, 0x2e, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, + 0x48, 0x00, 0x52, 0x14, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x3d, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1f, 0x0a, 0x1b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, + 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x50, 0x41, + 0x59, 0x4c, 0x4f, 0x41, 0x44, 0x10, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, + 0x61, 0x64, 0x22, 0x64, 0x0a, 0x12, 0x4d, 0x6f, 0x76, 0x65, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x42, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x62, 0x79, 0x74, 0x65, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x32, 0x0a, 0x03, 0x61, 0x62, 0x69, 0x18, 0x02, 0x20, 0x01, 0x28, @@ -2045,7 +2021,7 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x16, 0x41, 0x70, 0x74, 0x6f, 0x73, 0x3a, 0x3a, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3a, 0x56, - 0x31, 0x4a, 0xb0, 0x9c, 0x01, 0x0a, 0x07, 0x12, 0x05, 0x03, 0x00, 0x9a, 0x04, 0x01, 0x0a, 0x4e, + 0x31, 0x4a, 0xd8, 0x9b, 0x01, 0x0a, 0x07, 0x12, 0x05, 0x03, 0x00, 0x96, 0x04, 0x01, 0x0a, 0x4e, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x03, 0x00, 0x12, 0x32, 0x44, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0xc2, 0xa9, 0x20, 0x41, 0x70, 0x74, 0x6f, 0x73, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x20, 0x53, 0x50, 0x44, 0x58, 0x2d, 0x4c, @@ -2634,669 +2610,664 @@ pub const FILE_DESCRIPTOR_SET: &[u8] = &[ 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xe8, 0x01, 0x04, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xe8, 0x01, 0x1a, 0x1b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x17, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0xe9, 0x01, - 0x04, 0x23, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xe9, - 0x01, 0x04, 0x1e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, - 0xe9, 0x01, 0x21, 0x22, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x17, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, - 0xea, 0x01, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, - 0x04, 0xea, 0x01, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x04, 0x02, - 0x12, 0x04, 0xea, 0x01, 0x1d, 0x1e, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x17, 0x04, 0x00, 0x02, 0x05, - 0x12, 0x04, 0xeb, 0x01, 0x04, 0x1e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x05, - 0x01, 0x12, 0x04, 0xeb, 0x01, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, - 0x05, 0x02, 0x12, 0x04, 0xeb, 0x01, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x00, - 0x12, 0x04, 0xee, 0x01, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x06, 0x12, - 0x04, 0xee, 0x01, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x01, 0x12, 0x04, - 0xee, 0x01, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x03, 0x12, 0x04, 0xee, - 0x01, 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x17, 0x08, 0x00, 0x12, 0x06, 0xf0, 0x01, 0x02, - 0xf6, 0x01, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x08, 0x00, 0x01, 0x12, 0x04, 0xf0, 0x01, - 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x04, 0x34, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x06, 0x12, 0x04, 0xf1, 0x01, 0x04, 0x18, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x19, 0x2f, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x03, 0x12, 0x04, 0xf1, 0x01, 0x32, 0x33, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x17, 0x02, 0x02, 0x12, 0x04, 0xf2, 0x01, 0x04, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x17, 0x02, 0x02, 0x06, 0x12, 0x04, 0xf2, 0x01, 0x04, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, - 0x02, 0x02, 0x01, 0x12, 0x04, 0xf2, 0x01, 0x12, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, - 0x02, 0x03, 0x12, 0x04, 0xf2, 0x01, 0x23, 0x24, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x03, - 0x12, 0x04, 0xf3, 0x01, 0x04, 0x32, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x03, 0x06, 0x12, - 0x04, 0xf3, 0x01, 0x04, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x03, 0x01, 0x12, 0x04, - 0xf3, 0x01, 0x18, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x03, 0x03, 0x12, 0x04, 0xf3, - 0x01, 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x04, 0x12, 0x04, 0xf4, 0x01, 0x04, - 0x2a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x04, 0x06, 0x12, 0x04, 0xf4, 0x01, 0x04, 0x13, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x04, 0x01, 0x12, 0x04, 0xf4, 0x01, 0x14, 0x25, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x04, 0x03, 0x12, 0x04, 0xf4, 0x01, 0x28, 0x29, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x17, 0x02, 0x05, 0x12, 0x04, 0xf5, 0x01, 0x04, 0x29, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x17, 0x02, 0x05, 0x06, 0x12, 0x04, 0xf5, 0x01, 0x04, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x17, 0x02, 0x05, 0x01, 0x12, 0x04, 0xf5, 0x01, 0x14, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, - 0x02, 0x05, 0x03, 0x12, 0x04, 0xf5, 0x01, 0x27, 0x28, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x18, 0x12, - 0x06, 0xf9, 0x01, 0x00, 0xfe, 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x18, 0x01, 0x12, 0x04, - 0xf9, 0x01, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x00, 0x12, 0x04, 0xfa, 0x01, - 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x06, 0x12, 0x04, 0xfa, 0x01, 0x02, - 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x01, 0x12, 0x04, 0xfa, 0x01, 0x12, 0x1a, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x03, 0x12, 0x04, 0xfa, 0x01, 0x1d, 0x1e, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x01, 0x12, 0x04, 0xfb, 0x01, 0x02, 0x27, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x18, 0x02, 0x01, 0x04, 0x12, 0x04, 0xfb, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x18, 0x02, 0x01, 0x06, 0x12, 0x04, 0xfb, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x18, 0x02, 0x01, 0x01, 0x12, 0x04, 0xfb, 0x01, 0x14, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, - 0x02, 0x01, 0x03, 0x12, 0x04, 0xfb, 0x01, 0x25, 0x26, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, - 0x02, 0x12, 0x04, 0xfc, 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x04, - 0x12, 0x04, 0xfc, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x05, 0x12, - 0x04, 0xfc, 0x01, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x01, 0x12, 0x04, - 0xfc, 0x01, 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x03, 0x12, 0x04, 0xfc, - 0x01, 0x1e, 0x1f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x03, 0x12, 0x04, 0xfd, 0x01, 0x02, - 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x03, 0x05, 0x12, 0x04, 0xfd, 0x01, 0x02, 0x08, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x03, 0x01, 0x12, 0x04, 0xfd, 0x01, 0x09, 0x1e, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x03, 0x03, 0x12, 0x04, 0xfd, 0x01, 0x21, 0x22, 0x0a, 0x0c, - 0x0a, 0x02, 0x04, 0x19, 0x12, 0x06, 0x80, 0x02, 0x00, 0x83, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, - 0x04, 0x19, 0x01, 0x12, 0x04, 0x80, 0x02, 0x08, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x19, 0x02, - 0x00, 0x12, 0x04, 0x81, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x05, - 0x12, 0x04, 0x81, 0x02, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x01, 0x12, - 0x04, 0x81, 0x02, 0x08, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x03, 0x12, 0x04, - 0x81, 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x19, 0x02, 0x01, 0x12, 0x04, 0x82, 0x02, - 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x01, 0x06, 0x12, 0x04, 0x82, 0x02, 0x02, - 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x01, 0x01, 0x12, 0x04, 0x82, 0x02, 0x0f, 0x12, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x01, 0x03, 0x12, 0x04, 0x82, 0x02, 0x15, 0x16, 0x0a, - 0x0c, 0x0a, 0x02, 0x04, 0x1a, 0x12, 0x06, 0x85, 0x02, 0x00, 0x89, 0x02, 0x01, 0x0a, 0x0b, 0x0a, - 0x03, 0x04, 0x1a, 0x01, 0x12, 0x04, 0x85, 0x02, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, - 0x02, 0x00, 0x12, 0x04, 0x86, 0x02, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, - 0x06, 0x12, 0x04, 0x86, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x01, - 0x12, 0x04, 0x86, 0x02, 0x15, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x03, 0x12, - 0x04, 0x86, 0x02, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x01, 0x12, 0x04, 0x87, - 0x02, 0x02, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x04, 0x12, 0x04, 0x87, 0x02, - 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x06, 0x12, 0x04, 0x87, 0x02, 0x0b, - 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x01, 0x12, 0x04, 0x87, 0x02, 0x14, 0x22, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x03, 0x12, 0x04, 0x87, 0x02, 0x25, 0x26, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x02, 0x12, 0x04, 0x88, 0x02, 0x02, 0x20, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x1a, 0x02, 0x02, 0x04, 0x12, 0x04, 0x88, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x1a, 0x02, 0x02, 0x05, 0x12, 0x04, 0x88, 0x02, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x1a, 0x02, 0x02, 0x01, 0x12, 0x04, 0x88, 0x02, 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, - 0x02, 0x02, 0x03, 0x12, 0x04, 0x88, 0x02, 0x1e, 0x1f, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1b, 0x12, - 0x06, 0x8b, 0x02, 0x00, 0x8e, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1b, 0x01, 0x12, 0x04, - 0x8b, 0x02, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1b, 0x02, 0x00, 0x12, 0x04, 0x8c, 0x02, - 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x00, 0x05, 0x12, 0x04, 0x8c, 0x02, 0x02, - 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8c, 0x02, 0x09, 0x19, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8c, 0x02, 0x1c, 0x1d, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x1b, 0x02, 0x01, 0x12, 0x04, 0x8d, 0x02, 0x02, 0x3e, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x1b, 0x02, 0x01, 0x04, 0x12, 0x04, 0x8d, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x1b, 0x02, 0x01, 0x06, 0x12, 0x04, 0x8d, 0x02, 0x0b, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x1b, 0x02, 0x01, 0x01, 0x12, 0x04, 0x8d, 0x02, 0x26, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, - 0x02, 0x01, 0x03, 0x12, 0x04, 0x8d, 0x02, 0x3c, 0x3d, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1c, 0x12, - 0x06, 0x90, 0x02, 0x00, 0x9b, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1c, 0x01, 0x12, 0x04, - 0x90, 0x02, 0x08, 0x22, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x1c, 0x04, 0x00, 0x12, 0x06, 0x91, 0x02, - 0x02, 0x94, 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x04, 0x00, 0x01, 0x12, 0x04, 0x91, - 0x02, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x92, - 0x02, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, - 0x92, 0x02, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, - 0x04, 0x92, 0x02, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x01, 0x12, - 0x04, 0x93, 0x02, 0x04, 0x24, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x01, 0x01, - 0x12, 0x04, 0x93, 0x02, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x01, - 0x02, 0x12, 0x04, 0x93, 0x02, 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1c, 0x02, 0x00, 0x12, - 0x04, 0x96, 0x02, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x06, 0x12, 0x04, - 0x96, 0x02, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x01, 0x12, 0x04, 0x96, - 0x02, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x03, 0x12, 0x04, 0x96, 0x02, - 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x1c, 0x08, 0x00, 0x12, 0x06, 0x98, 0x02, 0x02, 0x9a, - 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x08, 0x00, 0x01, 0x12, 0x04, 0x98, 0x02, 0x08, - 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1c, 0x02, 0x01, 0x12, 0x04, 0x99, 0x02, 0x04, 0x34, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x01, 0x06, 0x12, 0x04, 0x99, 0x02, 0x04, 0x18, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x01, 0x01, 0x12, 0x04, 0x99, 0x02, 0x19, 0x2f, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x1c, 0x02, 0x01, 0x03, 0x12, 0x04, 0x99, 0x02, 0x32, 0x33, 0x0a, 0x0c, 0x0a, 0x02, - 0x04, 0x1d, 0x12, 0x06, 0x9d, 0x02, 0x00, 0x9f, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1d, - 0x01, 0x12, 0x04, 0x9d, 0x02, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1d, 0x02, 0x00, 0x12, - 0x04, 0x9e, 0x02, 0x02, 0x2a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x04, 0x12, 0x04, - 0x9e, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x06, 0x12, 0x04, 0x9e, - 0x02, 0x0b, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x01, 0x12, 0x04, 0x9e, 0x02, - 0x1e, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9e, 0x02, 0x28, - 0x29, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1e, 0x12, 0x06, 0xa1, 0x02, 0x00, 0xa4, 0x02, 0x01, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x1e, 0x01, 0x12, 0x04, 0xa1, 0x02, 0x08, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x1e, 0x02, 0x00, 0x12, 0x04, 0xa2, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, - 0x02, 0x00, 0x05, 0x12, 0x04, 0xa2, 0x02, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, - 0x00, 0x01, 0x12, 0x04, 0xa2, 0x02, 0x08, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, - 0x03, 0x12, 0x04, 0xa2, 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1e, 0x02, 0x01, 0x12, - 0x04, 0xa3, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x01, 0x06, 0x12, 0x04, - 0xa3, 0x02, 0x02, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa3, - 0x02, 0x0d, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa3, 0x02, - 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1f, 0x12, 0x06, 0xa6, 0x02, 0x00, 0xac, 0x02, 0x01, - 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1f, 0x01, 0x12, 0x04, 0xa6, 0x02, 0x08, 0x12, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x1f, 0x02, 0x00, 0x12, 0x04, 0xa7, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x1f, 0x02, 0x00, 0x05, 0x12, 0x04, 0xa7, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, - 0x02, 0x00, 0x01, 0x12, 0x04, 0xa7, 0x02, 0x09, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, - 0x00, 0x03, 0x12, 0x04, 0xa7, 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x01, - 0x12, 0x04, 0xa8, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x01, 0x05, 0x12, - 0x04, 0xa8, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x01, 0x01, 0x12, 0x04, - 0xa8, 0x02, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa8, - 0x02, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x02, 0x12, 0x04, 0xa9, 0x02, 0x02, - 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x02, 0x04, 0x12, 0x04, 0xa9, 0x02, 0x02, 0x0a, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x02, 0x06, 0x12, 0x04, 0xa9, 0x02, 0x0b, 0x17, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x02, 0x01, 0x12, 0x04, 0xa9, 0x02, 0x18, 0x1f, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x02, 0x03, 0x12, 0x04, 0xa9, 0x02, 0x22, 0x23, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x1f, 0x02, 0x03, 0x12, 0x04, 0xaa, 0x02, 0x02, 0x2e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x1f, 0x02, 0x03, 0x04, 0x12, 0x04, 0xaa, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, - 0x02, 0x03, 0x06, 0x12, 0x04, 0xaa, 0x02, 0x0b, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, - 0x03, 0x01, 0x12, 0x04, 0xaa, 0x02, 0x18, 0x29, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x03, - 0x03, 0x12, 0x04, 0xaa, 0x02, 0x2c, 0x2d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x04, 0x12, - 0x04, 0xab, 0x02, 0x02, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x04, 0x12, 0x04, - 0xab, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x06, 0x12, 0x04, 0xab, - 0x02, 0x0b, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x01, 0x12, 0x04, 0xab, 0x02, - 0x16, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x03, 0x12, 0x04, 0xab, 0x02, 0x20, - 0x21, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x20, 0x12, 0x06, 0xad, 0x02, 0x00, 0xba, 0x02, 0x01, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x20, 0x01, 0x12, 0x04, 0xad, 0x02, 0x08, 0x14, 0x0a, 0x0e, 0x0a, 0x04, - 0x04, 0x20, 0x04, 0x00, 0x12, 0x06, 0xae, 0x02, 0x02, 0xb3, 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x20, 0x04, 0x00, 0x01, 0x12, 0x04, 0xae, 0x02, 0x07, 0x11, 0x0a, 0x0e, 0x0a, 0x06, 0x04, - 0x20, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0xaf, 0x02, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x20, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xaf, 0x02, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x20, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0xaf, 0x02, 0x1d, 0x1e, 0x0a, 0x0e, 0x0a, - 0x06, 0x04, 0x20, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0xb0, 0x02, 0x04, 0x1b, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x20, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb0, 0x02, 0x04, 0x16, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x20, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xb0, 0x02, 0x19, 0x1a, 0x0a, - 0x0e, 0x0a, 0x06, 0x04, 0x20, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0xb1, 0x02, 0x04, 0x1a, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x20, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xb1, 0x02, 0x04, 0x15, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x20, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xb1, 0x02, 0x18, - 0x19, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x20, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0xb2, 0x02, 0x04, - 0x1a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x20, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xb2, 0x02, - 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x20, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xb2, - 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x00, 0x12, 0x04, 0xb4, 0x02, 0x02, - 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x00, 0x05, 0x12, 0x04, 0xb4, 0x02, 0x02, 0x08, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x00, 0x01, 0x12, 0x04, 0xb4, 0x02, 0x09, 0x0d, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb4, 0x02, 0x10, 0x11, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x20, 0x02, 0x01, 0x12, 0x04, 0xb5, 0x02, 0x02, 0x29, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x20, 0x02, 0x01, 0x06, 0x12, 0x04, 0xb5, 0x02, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x20, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb5, 0x02, 0x1a, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, - 0x02, 0x01, 0x03, 0x12, 0x04, 0xb5, 0x02, 0x27, 0x28, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, - 0x02, 0x12, 0x04, 0xb6, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x02, 0x05, - 0x12, 0x04, 0xb6, 0x02, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x02, 0x01, 0x12, - 0x04, 0xb6, 0x02, 0x07, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x02, 0x03, 0x12, 0x04, - 0xb6, 0x02, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x03, 0x12, 0x04, 0xb7, 0x02, - 0x02, 0x40, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x04, 0x12, 0x04, 0xb7, 0x02, 0x02, - 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x06, 0x12, 0x04, 0xb7, 0x02, 0x0b, 0x27, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x01, 0x12, 0x04, 0xb7, 0x02, 0x28, 0x3b, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x03, 0x12, 0x04, 0xb7, 0x02, 0x3e, 0x3f, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x20, 0x02, 0x04, 0x12, 0x04, 0xb8, 0x02, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x20, 0x02, 0x04, 0x04, 0x12, 0x04, 0xb8, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x20, 0x02, 0x04, 0x06, 0x12, 0x04, 0xb8, 0x02, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, - 0x02, 0x04, 0x01, 0x12, 0x04, 0xb8, 0x02, 0x14, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, - 0x04, 0x03, 0x12, 0x04, 0xb8, 0x02, 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x05, - 0x12, 0x04, 0xb9, 0x02, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x05, 0x04, 0x12, - 0x04, 0xb9, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x05, 0x06, 0x12, 0x04, - 0xb9, 0x02, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x05, 0x01, 0x12, 0x04, 0xb9, - 0x02, 0x14, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x05, 0x03, 0x12, 0x04, 0xb9, 0x02, - 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x21, 0x12, 0x06, 0xbc, 0x02, 0x00, 0xc2, 0x02, 0x01, - 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x21, 0x01, 0x12, 0x04, 0xbc, 0x02, 0x08, 0x12, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x21, 0x02, 0x00, 0x12, 0x04, 0xbd, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x21, 0x02, 0x00, 0x05, 0x12, 0x04, 0xbd, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, - 0x02, 0x00, 0x01, 0x12, 0x04, 0xbd, 0x02, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, - 0x00, 0x03, 0x12, 0x04, 0xbd, 0x02, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x21, 0x02, 0x01, - 0x12, 0x04, 0xbe, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x01, 0x05, 0x12, - 0x04, 0xbe, 0x02, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x01, 0x01, 0x12, 0x04, - 0xbe, 0x02, 0x07, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x01, 0x03, 0x12, 0x04, 0xbe, - 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x21, 0x02, 0x02, 0x12, 0x04, 0xbf, 0x02, 0x02, - 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x02, 0x04, 0x12, 0x04, 0xbf, 0x02, 0x02, 0x0a, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x02, 0x06, 0x12, 0x04, 0xbf, 0x02, 0x0b, 0x16, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x02, 0x01, 0x12, 0x04, 0xbf, 0x02, 0x17, 0x20, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x21, 0x02, 0x02, 0x03, 0x12, 0x04, 0xbf, 0x02, 0x23, 0x24, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x21, 0x02, 0x03, 0x12, 0x04, 0xc0, 0x02, 0x02, 0x3e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x21, 0x02, 0x03, 0x04, 0x12, 0x04, 0xc0, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, - 0x02, 0x03, 0x06, 0x12, 0x04, 0xc0, 0x02, 0x0b, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, - 0x03, 0x01, 0x12, 0x04, 0xc0, 0x02, 0x26, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x03, - 0x03, 0x12, 0x04, 0xc0, 0x02, 0x3c, 0x3d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x21, 0x02, 0x04, 0x12, - 0x04, 0xc1, 0x02, 0x02, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x04, 0x04, 0x12, 0x04, - 0xc1, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x04, 0x06, 0x12, 0x04, 0xc1, - 0x02, 0x0b, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x04, 0x01, 0x12, 0x04, 0xc1, 0x02, - 0x1b, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x04, 0x03, 0x12, 0x04, 0xc1, 0x02, 0x24, - 0x25, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x22, 0x12, 0x06, 0xc4, 0x02, 0x00, 0xc7, 0x02, 0x01, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x22, 0x01, 0x12, 0x04, 0xc4, 0x02, 0x08, 0x22, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x22, 0x02, 0x00, 0x12, 0x04, 0xc5, 0x02, 0x02, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, - 0x02, 0x00, 0x04, 0x12, 0x04, 0xc5, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, - 0x00, 0x06, 0x12, 0x04, 0xc5, 0x02, 0x0b, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x00, - 0x01, 0x12, 0x04, 0xc5, 0x02, 0x17, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x00, 0x03, - 0x12, 0x04, 0xc5, 0x02, 0x25, 0x26, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x22, 0x02, 0x01, 0x12, 0x04, - 0xc6, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x01, 0x05, 0x12, 0x04, 0xc6, - 0x02, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x01, 0x01, 0x12, 0x04, 0xc6, 0x02, - 0x07, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x01, 0x03, 0x12, 0x04, 0xc6, 0x02, 0x14, - 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x23, 0x12, 0x06, 0xc9, 0x02, 0x00, 0xcc, 0x02, 0x01, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x23, 0x01, 0x12, 0x04, 0xc9, 0x02, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x23, 0x02, 0x00, 0x12, 0x04, 0xca, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, - 0x02, 0x00, 0x05, 0x12, 0x04, 0xca, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, - 0x00, 0x01, 0x12, 0x04, 0xca, 0x02, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x00, - 0x03, 0x12, 0x04, 0xca, 0x02, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x23, 0x02, 0x01, 0x12, - 0x04, 0xcb, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x01, 0x06, 0x12, 0x04, - 0xcb, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x01, 0x01, 0x12, 0x04, 0xcb, - 0x02, 0x0b, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x01, 0x03, 0x12, 0x04, 0xcb, 0x02, - 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x24, 0x12, 0x06, 0xce, 0x02, 0x00, 0xd0, 0x02, 0x01, - 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x24, 0x01, 0x12, 0x04, 0xce, 0x02, 0x08, 0x24, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x24, 0x02, 0x00, 0x12, 0x04, 0xcf, 0x02, 0x02, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x24, 0x02, 0x00, 0x04, 0x12, 0x04, 0xcf, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, - 0x02, 0x00, 0x06, 0x12, 0x04, 0xcf, 0x02, 0x0b, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, - 0x00, 0x01, 0x12, 0x04, 0xcf, 0x02, 0x17, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x00, - 0x03, 0x12, 0x04, 0xcf, 0x02, 0x25, 0x26, 0x0a, 0x0c, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x06, 0xd2, - 0x02, 0x00, 0xe2, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, 0x04, 0xd2, 0x02, - 0x05, 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x04, 0xd3, 0x02, 0x02, 0x1d, - 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd3, 0x02, 0x02, 0x18, 0x0a, - 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0xd3, 0x02, 0x1b, 0x1c, 0x0a, 0x0c, - 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x04, 0xd4, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xd4, 0x02, 0x02, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x05, - 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xd4, 0x02, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, - 0x02, 0x02, 0x12, 0x04, 0xd5, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, - 0x01, 0x12, 0x04, 0xd5, 0x02, 0x02, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, - 0x12, 0x04, 0xd5, 0x02, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x03, 0x12, 0x04, - 0xd6, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xd6, - 0x02, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xd6, 0x02, - 0x13, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x04, 0x12, 0x04, 0xd7, 0x02, 0x02, 0x16, - 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, 0xd7, 0x02, 0x02, 0x10, 0x0a, - 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, 0x02, 0x12, 0x04, 0xd7, 0x02, 0x13, 0x15, 0x0a, 0x0c, - 0x0a, 0x04, 0x05, 0x00, 0x02, 0x05, 0x12, 0x04, 0xd8, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x05, 0x01, 0x12, 0x04, 0xd8, 0x02, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x05, - 0x00, 0x02, 0x05, 0x02, 0x12, 0x04, 0xd8, 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, - 0x02, 0x06, 0x12, 0x04, 0xd9, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x06, - 0x01, 0x12, 0x04, 0xd9, 0x02, 0x02, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x06, 0x02, - 0x12, 0x04, 0xd9, 0x02, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x07, 0x12, 0x04, - 0xda, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x07, 0x01, 0x12, 0x04, 0xda, - 0x02, 0x02, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x07, 0x02, 0x12, 0x04, 0xda, 0x02, - 0x14, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x08, 0x12, 0x04, 0xdb, 0x02, 0x02, 0x19, - 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x08, 0x01, 0x12, 0x04, 0xdb, 0x02, 0x02, 0x14, 0x0a, - 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x08, 0x02, 0x12, 0x04, 0xdb, 0x02, 0x17, 0x18, 0x0a, 0x0c, - 0x0a, 0x04, 0x05, 0x00, 0x02, 0x09, 0x12, 0x04, 0xdc, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x09, 0x01, 0x12, 0x04, 0xdc, 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x05, - 0x00, 0x02, 0x09, 0x02, 0x12, 0x04, 0xdc, 0x02, 0x16, 0x17, 0x0a, 0x2b, 0x0a, 0x04, 0x05, 0x00, - 0x02, 0x0a, 0x12, 0x04, 0xdd, 0x02, 0x02, 0x18, 0x22, 0x1d, 0x20, 0x60, 0x7b, 0x20, 0x69, 0x74, - 0x65, 0x6d, 0x73, 0x3a, 0x20, 0x42, 0x6f, 0x78, 0x3c, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x3e, 0x20, 0x7d, 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0a, 0x01, - 0x12, 0x04, 0xdd, 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0a, 0x02, 0x12, - 0x04, 0xdd, 0x02, 0x16, 0x17, 0x0a, 0x22, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0b, 0x12, 0x04, 0xde, - 0x02, 0x02, 0x18, 0x22, 0x14, 0x20, 0x60, 0x28, 0x4d, 0x6f, 0x76, 0x65, 0x53, 0x74, 0x72, 0x75, - 0x63, 0x74, 0x54, 0x61, 0x67, 0x29, 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, - 0x0b, 0x01, 0x12, 0x04, 0xde, 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0b, - 0x02, 0x12, 0x04, 0xde, 0x02, 0x16, 0x17, 0x0a, 0x22, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0c, 0x12, - 0x04, 0xdf, 0x02, 0x02, 0x24, 0x22, 0x14, 0x20, 0x60, 0x7b, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, - 0x3a, 0x20, 0x75, 0x31, 0x36, 0x20, 0x7d, 0x60, 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, - 0x00, 0x02, 0x0c, 0x01, 0x12, 0x04, 0xdf, 0x02, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, - 0x02, 0x0c, 0x02, 0x12, 0x04, 0xdf, 0x02, 0x22, 0x23, 0x0a, 0x37, 0x0a, 0x04, 0x05, 0x00, 0x02, - 0x0d, 0x12, 0x04, 0xe0, 0x02, 0x02, 0x1c, 0x22, 0x29, 0x20, 0x60, 0x7b, 0x20, 0x6d, 0x75, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x20, 0x62, 0x6f, 0x6f, 0x6c, 0x2c, 0x20, 0x74, 0x6f, 0x3a, 0x20, - 0x42, 0x6f, 0x78, 0x3c, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x3e, 0x20, 0x7d, 0x60, - 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0d, 0x01, 0x12, 0x04, 0xe0, 0x02, 0x02, - 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0d, 0x02, 0x12, 0x04, 0xe0, 0x02, 0x19, 0x1b, - 0x0a, 0x1b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0e, 0x12, 0x04, 0xe1, 0x02, 0x02, 0x1d, 0x22, 0x0d, - 0x20, 0x60, 0x28, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x29, 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, - 0x05, 0x05, 0x00, 0x02, 0x0e, 0x01, 0x12, 0x04, 0xe1, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, - 0x05, 0x00, 0x02, 0x0e, 0x02, 0x12, 0x04, 0xe1, 0x02, 0x1a, 0x1c, 0x0a, 0x0c, 0x0a, 0x02, 0x04, - 0x25, 0x12, 0x06, 0xe4, 0x02, 0x00, 0xf3, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x25, 0x01, - 0x12, 0x04, 0xe4, 0x02, 0x08, 0x10, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x25, 0x03, 0x00, 0x12, 0x06, - 0xe6, 0x02, 0x02, 0xe9, 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x03, 0x00, 0x01, 0x12, - 0x04, 0xe6, 0x02, 0x0a, 0x17, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x25, 0x03, 0x00, 0x02, 0x00, 0x12, - 0x04, 0xe7, 0x02, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x25, 0x03, 0x00, 0x02, 0x00, 0x05, - 0x12, 0x04, 0xe7, 0x02, 0x04, 0x08, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x25, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x12, 0x04, 0xe7, 0x02, 0x09, 0x10, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x25, 0x03, 0x00, 0x02, - 0x00, 0x03, 0x12, 0x04, 0xe7, 0x02, 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x25, 0x03, 0x00, - 0x02, 0x01, 0x12, 0x04, 0xe8, 0x02, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x25, 0x03, 0x00, - 0x02, 0x01, 0x06, 0x12, 0x04, 0xe8, 0x02, 0x04, 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x25, 0x03, - 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xe8, 0x02, 0x0d, 0x0f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x25, - 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0xe8, 0x02, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x25, 0x02, 0x00, 0x12, 0x04, 0xeb, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, - 0x00, 0x06, 0x12, 0x04, 0xeb, 0x02, 0x02, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x00, - 0x01, 0x12, 0x04, 0xeb, 0x02, 0x0c, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x00, 0x03, - 0x12, 0x04, 0xeb, 0x02, 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x25, 0x08, 0x00, 0x12, 0x06, - 0xec, 0x02, 0x02, 0xf2, 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x08, 0x00, 0x01, 0x12, - 0x04, 0xec, 0x02, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x25, 0x02, 0x01, 0x12, 0x04, 0xed, - 0x02, 0x04, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x01, 0x06, 0x12, 0x04, 0xed, 0x02, - 0x04, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x01, 0x01, 0x12, 0x04, 0xed, 0x02, 0x0d, - 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x01, 0x03, 0x12, 0x04, 0xed, 0x02, 0x16, 0x17, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x25, 0x02, 0x02, 0x12, 0x04, 0xee, 0x02, 0x04, 0x1d, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x25, 0x02, 0x02, 0x06, 0x12, 0x04, 0xee, 0x02, 0x04, 0x11, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x25, 0x02, 0x02, 0x01, 0x12, 0x04, 0xee, 0x02, 0x12, 0x18, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x25, 0x02, 0x02, 0x03, 0x12, 0x04, 0xee, 0x02, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x25, 0x02, 0x03, 0x12, 0x04, 0xef, 0x02, 0x04, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, - 0x03, 0x05, 0x12, 0x04, 0xef, 0x02, 0x04, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x03, - 0x01, 0x12, 0x04, 0xef, 0x02, 0x0b, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x03, 0x03, - 0x12, 0x04, 0xef, 0x02, 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x25, 0x02, 0x04, 0x12, 0x04, - 0xf0, 0x02, 0x04, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x04, 0x06, 0x12, 0x04, 0xf0, - 0x02, 0x04, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x04, 0x01, 0x12, 0x04, 0xf0, 0x02, - 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x04, 0x03, 0x12, 0x04, 0xf0, 0x02, 0x1e, - 0x1f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x25, 0x02, 0x05, 0x12, 0x04, 0xf1, 0x02, 0x04, 0x1a, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x05, 0x05, 0x12, 0x04, 0xf1, 0x02, 0x04, 0x0a, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x25, 0x02, 0x05, 0x01, 0x12, 0x04, 0xf1, 0x02, 0x0b, 0x15, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x25, 0x02, 0x05, 0x03, 0x12, 0x04, 0xf1, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x02, - 0x05, 0x01, 0x12, 0x06, 0xf5, 0x02, 0x00, 0xfb, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x05, 0x01, - 0x01, 0x12, 0x04, 0xf5, 0x02, 0x05, 0x10, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x00, 0x12, - 0x04, 0xf6, 0x02, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x00, 0x01, 0x12, 0x04, - 0xf6, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x00, 0x02, 0x12, 0x04, 0xf6, - 0x02, 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x01, 0x12, 0x04, 0xf7, 0x02, 0x02, - 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x01, 0x01, 0x12, 0x04, 0xf7, 0x02, 0x02, 0x13, - 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x01, 0x02, 0x12, 0x04, 0xf7, 0x02, 0x16, 0x17, 0x0a, - 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x02, 0x12, 0x04, 0xf8, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, - 0x05, 0x05, 0x01, 0x02, 0x02, 0x01, 0x12, 0x04, 0xf8, 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, - 0x05, 0x01, 0x02, 0x02, 0x02, 0x12, 0x04, 0xf8, 0x02, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x05, - 0x01, 0x02, 0x03, 0x12, 0x04, 0xf9, 0x02, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, - 0x03, 0x01, 0x12, 0x04, 0xf9, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, - 0x02, 0x12, 0x04, 0xf9, 0x02, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x04, 0x12, - 0x04, 0xfa, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x04, 0x01, 0x12, 0x04, - 0xfa, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x04, 0x02, 0x12, 0x04, 0xfa, - 0x02, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x26, 0x12, 0x06, 0xfd, 0x02, 0x00, 0xff, 0x02, - 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x26, 0x01, 0x12, 0x04, 0xfd, 0x02, 0x08, 0x17, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x26, 0x02, 0x00, 0x12, 0x04, 0xfe, 0x02, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x26, 0x02, 0x00, 0x06, 0x12, 0x04, 0xfe, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x26, 0x02, 0x00, 0x01, 0x12, 0x04, 0xfe, 0x02, 0x0b, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, - 0x02, 0x00, 0x03, 0x12, 0x04, 0xfe, 0x02, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x27, 0x12, - 0x06, 0x81, 0x03, 0x00, 0x84, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x27, 0x01, 0x12, 0x04, - 0x81, 0x03, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x27, 0x02, 0x00, 0x12, 0x04, 0x82, 0x03, - 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, 0x00, 0x06, 0x12, 0x04, 0x82, 0x03, 0x02, - 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, 0x00, 0x01, 0x12, 0x04, 0x82, 0x03, 0x0f, 0x15, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, 0x00, 0x03, 0x12, 0x04, 0x82, 0x03, 0x18, 0x19, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x27, 0x02, 0x01, 0x12, 0x04, 0x83, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x27, 0x02, 0x01, 0x05, 0x12, 0x04, 0x83, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x27, 0x02, 0x01, 0x01, 0x12, 0x04, 0x83, 0x03, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x27, 0x02, 0x01, 0x03, 0x12, 0x04, 0x83, 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x28, - 0x12, 0x06, 0x86, 0x03, 0x00, 0x89, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x28, 0x01, 0x12, - 0x04, 0x86, 0x03, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x28, 0x02, 0x00, 0x12, 0x04, 0x87, - 0x03, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x00, 0x05, 0x12, 0x04, 0x87, 0x03, - 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x00, 0x01, 0x12, 0x04, 0x87, 0x03, 0x09, - 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x00, 0x03, 0x12, 0x04, 0x87, 0x03, 0x13, 0x14, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x28, 0x02, 0x01, 0x12, 0x04, 0x88, 0x03, 0x02, 0x12, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x28, 0x02, 0x01, 0x05, 0x12, 0x04, 0x88, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x28, 0x02, 0x01, 0x01, 0x12, 0x04, 0x88, 0x03, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x28, 0x02, 0x01, 0x03, 0x12, 0x04, 0x88, 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x02, 0x04, - 0x29, 0x12, 0x06, 0x8b, 0x03, 0x00, 0x90, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x29, 0x01, - 0x12, 0x04, 0x8b, 0x03, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x00, 0x12, 0x04, - 0x8c, 0x03, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x00, 0x05, 0x12, 0x04, 0x8c, - 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8c, 0x03, - 0x09, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8c, 0x03, 0x13, - 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x01, 0x12, 0x04, 0x8d, 0x03, 0x02, 0x14, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x01, 0x05, 0x12, 0x04, 0x8d, 0x03, 0x02, 0x08, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x29, 0x02, 0x01, 0x01, 0x12, 0x04, 0x8d, 0x03, 0x09, 0x0f, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x29, 0x02, 0x01, 0x03, 0x12, 0x04, 0x8d, 0x03, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x29, 0x02, 0x02, 0x12, 0x04, 0x8e, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, - 0x02, 0x02, 0x05, 0x12, 0x04, 0x8e, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, - 0x02, 0x01, 0x12, 0x04, 0x8e, 0x03, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x02, - 0x03, 0x12, 0x04, 0x8e, 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x03, 0x12, - 0x04, 0x8f, 0x03, 0x02, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x03, 0x04, 0x12, 0x04, - 0x8f, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x03, 0x06, 0x12, 0x04, 0x8f, - 0x03, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x03, 0x01, 0x12, 0x04, 0x8f, 0x03, - 0x14, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x03, 0x03, 0x12, 0x04, 0x8f, 0x03, 0x2a, - 0x2b, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2a, 0x12, 0x06, 0x92, 0x03, 0x00, 0xa7, 0x03, 0x01, 0x0a, - 0x0b, 0x0a, 0x03, 0x04, 0x2a, 0x01, 0x12, 0x04, 0x92, 0x03, 0x08, 0x11, 0x0a, 0x0e, 0x0a, 0x04, - 0x04, 0x2a, 0x04, 0x00, 0x12, 0x06, 0x94, 0x03, 0x02, 0x9c, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2a, 0x04, 0x00, 0x01, 0x12, 0x04, 0x94, 0x03, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, - 0x2a, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x95, 0x03, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x2a, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x95, 0x03, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x2a, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0x95, 0x03, 0x17, 0x18, 0x0a, 0x0e, 0x0a, - 0x06, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0x96, 0x03, 0x04, 0x15, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x96, 0x03, 0x04, 0x10, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0x96, 0x03, 0x13, 0x14, 0x0a, - 0x0e, 0x0a, 0x06, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0x97, 0x03, 0x04, 0x1b, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0x97, 0x03, 0x04, 0x16, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0x97, 0x03, 0x19, - 0x1a, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0x98, 0x03, 0x04, - 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0x98, 0x03, - 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0x98, - 0x03, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, 0x99, - 0x03, 0x04, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, - 0x99, 0x03, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, - 0x04, 0x99, 0x03, 0x15, 0x16, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x05, 0x12, - 0x04, 0x9a, 0x03, 0x04, 0x1b, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x05, 0x01, - 0x12, 0x04, 0x9a, 0x03, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x02, 0x05, - 0x02, 0x12, 0x04, 0x9a, 0x03, 0x19, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x04, 0x00, 0x04, - 0x12, 0x04, 0x9b, 0x03, 0x04, 0x0f, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2a, 0x04, 0x00, 0x04, 0x00, - 0x12, 0x04, 0x9b, 0x03, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x04, 0x00, - 0x01, 0x12, 0x04, 0x9b, 0x03, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2a, 0x04, 0x00, 0x04, - 0x00, 0x02, 0x12, 0x04, 0x9b, 0x03, 0x0d, 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2a, 0x02, 0x00, - 0x12, 0x04, 0x9e, 0x03, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x00, 0x06, 0x12, - 0x04, 0x9e, 0x03, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x00, 0x01, 0x12, 0x04, - 0x9e, 0x03, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9e, - 0x03, 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x2a, 0x08, 0x00, 0x12, 0x06, 0x9f, 0x03, 0x02, - 0xa6, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x08, 0x00, 0x01, 0x12, 0x04, 0x9f, 0x03, - 0x08, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2a, 0x02, 0x01, 0x12, 0x04, 0xa0, 0x03, 0x04, 0x21, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x01, 0x06, 0x12, 0x04, 0xa0, 0x03, 0x04, 0x14, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa0, 0x03, 0x15, 0x1c, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa0, 0x03, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x2a, 0x02, 0x02, 0x12, 0x04, 0xa1, 0x03, 0x04, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x2a, 0x02, 0x02, 0x06, 0x12, 0x04, 0xa1, 0x03, 0x04, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, - 0x02, 0x02, 0x01, 0x12, 0x04, 0xa1, 0x03, 0x1a, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, - 0x02, 0x03, 0x12, 0x04, 0xa1, 0x03, 0x2a, 0x2b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2a, 0x02, 0x03, - 0x12, 0x04, 0xa2, 0x03, 0x04, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x03, 0x06, 0x12, - 0x04, 0xa2, 0x03, 0x04, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x03, 0x01, 0x12, 0x04, - 0xa2, 0x03, 0x18, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x03, 0x03, 0x12, 0x04, 0xa2, - 0x03, 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2a, 0x02, 0x04, 0x12, 0x04, 0xa3, 0x03, 0x04, - 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x04, 0x06, 0x12, 0x04, 0xa3, 0x03, 0x04, 0x15, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x04, 0x01, 0x12, 0x04, 0xa3, 0x03, 0x16, 0x1f, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x04, 0x03, 0x12, 0x04, 0xa3, 0x03, 0x22, 0x23, 0x0a, 0x1e, - 0x0a, 0x04, 0x04, 0x2a, 0x02, 0x05, 0x12, 0x04, 0xa5, 0x03, 0x04, 0x23, 0x1a, 0x10, 0x20, 0x36, - 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x05, 0x06, 0x12, 0x04, 0xa5, 0x03, 0x04, 0x10, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x2a, 0x02, 0x05, 0x01, 0x12, 0x04, 0xa5, 0x03, 0x11, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2a, 0x02, 0x05, 0x03, 0x12, 0x04, 0xa5, 0x03, 0x21, 0x22, 0x0a, 0x0c, 0x0a, 0x02, 0x04, - 0x2b, 0x12, 0x06, 0xa9, 0x03, 0x00, 0xac, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2b, 0x01, - 0x12, 0x04, 0xa9, 0x03, 0x08, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2b, 0x02, 0x00, 0x12, 0x04, - 0xaa, 0x03, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x00, 0x05, 0x12, 0x04, 0xaa, - 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x00, 0x01, 0x12, 0x04, 0xaa, 0x03, - 0x08, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x00, 0x03, 0x12, 0x04, 0xaa, 0x03, 0x15, - 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2b, 0x02, 0x01, 0x12, 0x04, 0xab, 0x03, 0x02, 0x16, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x01, 0x05, 0x12, 0x04, 0xab, 0x03, 0x02, 0x07, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x01, 0x01, 0x12, 0x04, 0xab, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x2b, 0x02, 0x01, 0x03, 0x12, 0x04, 0xab, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, - 0x04, 0x2c, 0x12, 0x06, 0xae, 0x03, 0x00, 0xb3, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2c, - 0x01, 0x12, 0x04, 0xae, 0x03, 0x08, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2c, 0x02, 0x00, 0x12, - 0x04, 0xaf, 0x03, 0x02, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x04, 0x12, 0x04, - 0xaf, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x05, 0x12, 0x04, 0xaf, - 0x03, 0x0b, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xaf, 0x03, - 0x11, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xaf, 0x03, 0x1f, - 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2c, 0x02, 0x01, 0x12, 0x04, 0xb0, 0x03, 0x02, 0x20, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x01, 0x04, 0x12, 0x04, 0xb0, 0x03, 0x02, 0x0a, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x01, 0x05, 0x12, 0x04, 0xb0, 0x03, 0x0b, 0x10, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x2c, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb0, 0x03, 0x11, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2c, 0x02, 0x01, 0x03, 0x12, 0x04, 0xb0, 0x03, 0x1e, 0x1f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x2c, 0x02, 0x02, 0x12, 0x04, 0xb1, 0x03, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, - 0x02, 0x05, 0x12, 0x04, 0xb1, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x02, - 0x01, 0x12, 0x04, 0xb1, 0x03, 0x09, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x02, 0x03, - 0x12, 0x04, 0xb1, 0x03, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2c, 0x02, 0x03, 0x12, 0x04, - 0xb2, 0x03, 0x02, 0x29, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x03, 0x04, 0x12, 0x04, 0xb2, - 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x03, 0x05, 0x12, 0x04, 0xb2, 0x03, - 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x03, 0x01, 0x12, 0x04, 0xb2, 0x03, 0x12, - 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x03, 0x03, 0x12, 0x04, 0xb2, 0x03, 0x27, 0x28, - 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2d, 0x12, 0x06, 0xb5, 0x03, 0x00, 0xb9, 0x03, 0x01, 0x0a, 0x0b, - 0x0a, 0x03, 0x04, 0x2d, 0x01, 0x12, 0x04, 0xb5, 0x03, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x2d, 0x02, 0x00, 0x12, 0x04, 0xb6, 0x03, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, - 0x00, 0x06, 0x12, 0x04, 0xb6, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x00, - 0x01, 0x12, 0x04, 0xb6, 0x03, 0x13, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x00, 0x03, - 0x12, 0x04, 0xb6, 0x03, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2d, 0x02, 0x01, 0x12, 0x04, - 0xb7, 0x03, 0x02, 0x31, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x04, 0x12, 0x04, 0xb7, - 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x05, 0x12, 0x04, 0xb7, 0x03, - 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb7, 0x03, 0x12, - 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x03, 0x12, 0x04, 0xb7, 0x03, 0x2f, 0x30, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2d, 0x02, 0x02, 0x12, 0x04, 0xb8, 0x03, 0x02, 0x32, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x02, 0x04, 0x12, 0x04, 0xb8, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x2d, 0x02, 0x02, 0x06, 0x12, 0x04, 0xb8, 0x03, 0x0b, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2d, 0x02, 0x02, 0x01, 0x12, 0x04, 0xb8, 0x03, 0x1c, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x2d, 0x02, 0x02, 0x03, 0x12, 0x04, 0xb8, 0x03, 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2e, - 0x12, 0x06, 0xbb, 0x03, 0x00, 0xc1, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2e, 0x01, 0x12, - 0x04, 0xbb, 0x03, 0x08, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2e, 0x02, 0x00, 0x12, 0x04, 0xbc, - 0x03, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x00, 0x06, 0x12, 0x04, 0xbc, 0x03, - 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x00, 0x01, 0x12, 0x04, 0xbc, 0x03, 0x13, - 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xbc, 0x03, 0x1c, 0x1d, - 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2e, 0x02, 0x01, 0x12, 0x04, 0xbd, 0x03, 0x02, 0x31, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x01, 0x04, 0x12, 0x04, 0xbd, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x2e, 0x02, 0x01, 0x05, 0x12, 0x04, 0xbd, 0x03, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2e, 0x02, 0x01, 0x01, 0x12, 0x04, 0xbd, 0x03, 0x12, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x2e, 0x02, 0x01, 0x03, 0x12, 0x04, 0xbd, 0x03, 0x2f, 0x30, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2e, - 0x02, 0x02, 0x12, 0x04, 0xbe, 0x03, 0x02, 0x32, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x02, - 0x04, 0x12, 0x04, 0xbe, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x02, 0x06, - 0x12, 0x04, 0xbe, 0x03, 0x0b, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x02, 0x01, 0x12, - 0x04, 0xbe, 0x03, 0x1c, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x02, 0x03, 0x12, 0x04, - 0xbe, 0x03, 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2e, 0x02, 0x03, 0x12, 0x04, 0xbf, 0x03, - 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x03, 0x05, 0x12, 0x04, 0xbf, 0x03, 0x02, - 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x03, 0x01, 0x12, 0x04, 0xbf, 0x03, 0x09, 0x1a, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x03, 0x03, 0x12, 0x04, 0xbf, 0x03, 0x1d, 0x1e, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x2e, 0x02, 0x04, 0x12, 0x04, 0xc0, 0x03, 0x02, 0x28, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x2e, 0x02, 0x04, 0x06, 0x12, 0x04, 0xc0, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2e, 0x02, 0x04, 0x01, 0x12, 0x04, 0xc0, 0x03, 0x13, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x2e, 0x02, 0x04, 0x03, 0x12, 0x04, 0xc0, 0x03, 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2f, - 0x12, 0x06, 0xc3, 0x03, 0x00, 0xce, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2f, 0x01, 0x12, - 0x04, 0xc3, 0x03, 0x08, 0x14, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x2f, 0x04, 0x00, 0x12, 0x06, 0xc4, - 0x03, 0x02, 0xca, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x04, 0x00, 0x01, 0x12, 0x04, - 0xc4, 0x03, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, - 0xc5, 0x03, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, - 0x04, 0xc5, 0x03, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x00, 0x02, - 0x12, 0x04, 0xc5, 0x03, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x01, - 0x12, 0x04, 0xc6, 0x03, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x01, - 0x01, 0x12, 0x04, 0xc6, 0x03, 0x04, 0x10, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, - 0x01, 0x02, 0x12, 0x04, 0xc6, 0x03, 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, 0x04, 0x00, - 0x02, 0x02, 0x12, 0x04, 0xc7, 0x03, 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, - 0x02, 0x02, 0x01, 0x12, 0x04, 0xc7, 0x03, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, - 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xc7, 0x03, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, - 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0xc8, 0x03, 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, - 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xc8, 0x03, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x2f, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xc8, 0x03, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, - 0x04, 0x2f, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, 0xc9, 0x03, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x2f, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, 0xc9, 0x03, 0x04, 0x0d, 0x0a, 0x0f, 0x0a, - 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x04, 0xc9, 0x03, 0x10, 0x11, 0x0a, 0x0c, - 0x0a, 0x04, 0x04, 0x2f, 0x02, 0x00, 0x12, 0x04, 0xcc, 0x03, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x2f, 0x02, 0x00, 0x06, 0x12, 0x04, 0xcc, 0x03, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x2f, 0x02, 0x00, 0x01, 0x12, 0x04, 0xcc, 0x03, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, - 0x02, 0x00, 0x03, 0x12, 0x04, 0xcc, 0x03, 0x0e, 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2f, 0x02, - 0x01, 0x12, 0x04, 0xcd, 0x03, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x01, 0x05, - 0x12, 0x04, 0xcd, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x01, 0x01, 0x12, - 0x04, 0xcd, 0x03, 0x08, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x01, 0x03, 0x12, 0x04, - 0xcd, 0x03, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x30, 0x12, 0x06, 0xd0, 0x03, 0x00, 0xe1, - 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x30, 0x01, 0x12, 0x04, 0xd0, 0x03, 0x08, 0x14, 0x0a, - 0x0e, 0x0a, 0x04, 0x04, 0x30, 0x04, 0x00, 0x12, 0x06, 0xd1, 0x03, 0x02, 0xd7, 0x03, 0x03, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x04, 0x00, 0x01, 0x12, 0x04, 0xd1, 0x03, 0x07, 0x0b, 0x0a, 0x0e, - 0x0a, 0x06, 0x04, 0x30, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0xd2, 0x03, 0x04, 0x19, 0x0a, 0x0f, - 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd2, 0x03, 0x04, 0x14, 0x0a, - 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0xd2, 0x03, 0x17, 0x18, - 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x30, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0xd3, 0x03, 0x04, 0x15, - 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xd3, 0x03, 0x04, - 0x10, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xd3, 0x03, - 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x30, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0xd4, 0x03, - 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xd4, - 0x03, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, - 0xd4, 0x03, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x30, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, - 0xd5, 0x03, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, - 0x04, 0xd5, 0x03, 0x04, 0x11, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x03, 0x02, - 0x12, 0x04, 0xd5, 0x03, 0x14, 0x15, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x30, 0x04, 0x00, 0x02, 0x04, - 0x12, 0x04, 0xd6, 0x03, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, 0x04, - 0x01, 0x12, 0x04, 0xd6, 0x03, 0x04, 0x0d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x30, 0x04, 0x00, 0x02, - 0x04, 0x02, 0x12, 0x04, 0xd6, 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x30, 0x02, 0x00, - 0x12, 0x04, 0xd9, 0x03, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x00, 0x06, 0x12, - 0x04, 0xd9, 0x03, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x00, 0x01, 0x12, 0x04, - 0xd9, 0x03, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x00, 0x03, 0x12, 0x04, 0xd9, - 0x03, 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x30, 0x08, 0x00, 0x12, 0x06, 0xdb, 0x03, 0x02, - 0xe0, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x08, 0x00, 0x01, 0x12, 0x04, 0xdb, 0x03, - 0x08, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x30, 0x02, 0x01, 0x12, 0x04, 0xdc, 0x03, 0x04, 0x18, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x01, 0x06, 0x12, 0x04, 0xdc, 0x03, 0x04, 0x0b, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x01, 0x01, 0x12, 0x04, 0xdc, 0x03, 0x0c, 0x13, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x30, 0x02, 0x01, 0x03, 0x12, 0x04, 0xdc, 0x03, 0x16, 0x17, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x30, 0x02, 0x02, 0x12, 0x04, 0xdd, 0x03, 0x04, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x30, 0x02, 0x02, 0x06, 0x12, 0x04, 0xdd, 0x03, 0x04, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, - 0x02, 0x02, 0x01, 0x12, 0x04, 0xdd, 0x03, 0x13, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, - 0x02, 0x03, 0x12, 0x04, 0xdd, 0x03, 0x25, 0x26, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x30, 0x02, 0x03, - 0x12, 0x04, 0xde, 0x03, 0x04, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x03, 0x06, 0x12, - 0x04, 0xde, 0x03, 0x04, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x03, 0x01, 0x12, 0x04, - 0xde, 0x03, 0x0d, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x03, 0x03, 0x12, 0x04, 0xde, - 0x03, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x30, 0x02, 0x04, 0x12, 0x04, 0xdf, 0x03, 0x04, - 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x04, 0x06, 0x12, 0x04, 0xdf, 0x03, 0x04, 0x08, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x04, 0x01, 0x12, 0x04, 0xdf, 0x03, 0x09, 0x0d, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x04, 0x03, 0x12, 0x04, 0xdf, 0x03, 0x10, 0x11, 0x0a, 0x0c, - 0x0a, 0x02, 0x04, 0x31, 0x12, 0x06, 0xe3, 0x03, 0x00, 0xe5, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, - 0x04, 0x31, 0x01, 0x12, 0x04, 0xe3, 0x03, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x31, 0x02, - 0x00, 0x12, 0x04, 0xe4, 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x31, 0x02, 0x00, 0x05, - 0x12, 0x04, 0xe4, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x31, 0x02, 0x00, 0x01, 0x12, - 0x04, 0xe4, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x31, 0x02, 0x00, 0x03, 0x12, 0x04, - 0xe4, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x32, 0x12, 0x06, 0xe7, 0x03, 0x00, 0xe9, - 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x32, 0x01, 0x12, 0x04, 0xe7, 0x03, 0x08, 0x16, 0x0a, - 0x0c, 0x0a, 0x04, 0x04, 0x32, 0x02, 0x00, 0x12, 0x04, 0xe8, 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x32, 0x02, 0x00, 0x05, 0x12, 0x04, 0xe8, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x32, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe8, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x32, 0x02, 0x00, 0x03, 0x12, 0x04, 0xe8, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x33, - 0x12, 0x06, 0xeb, 0x03, 0x00, 0xed, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x33, 0x01, 0x12, - 0x04, 0xeb, 0x03, 0x08, 0x10, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x33, 0x02, 0x00, 0x12, 0x04, 0xec, - 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x33, 0x02, 0x00, 0x05, 0x12, 0x04, 0xec, 0x03, - 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x33, 0x02, 0x00, 0x01, 0x12, 0x04, 0xec, 0x03, 0x08, - 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x33, 0x02, 0x00, 0x03, 0x12, 0x04, 0xec, 0x03, 0x14, 0x15, - 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x34, 0x12, 0x06, 0xef, 0x03, 0x00, 0xf1, 0x03, 0x01, 0x0a, 0x0b, - 0x0a, 0x03, 0x04, 0x34, 0x01, 0x12, 0x04, 0xef, 0x03, 0x08, 0x0c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, - 0x34, 0x02, 0x00, 0x12, 0x04, 0xf0, 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, - 0x00, 0x05, 0x12, 0x04, 0xf0, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x00, - 0x01, 0x12, 0x04, 0xf0, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x00, 0x03, - 0x12, 0x04, 0xf0, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x35, 0x12, 0x06, 0xf3, 0x03, - 0x00, 0xf6, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x35, 0x01, 0x12, 0x04, 0xf3, 0x03, 0x08, - 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x35, 0x02, 0x00, 0x12, 0x04, 0xf4, 0x03, 0x02, 0x1e, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x00, 0x06, 0x12, 0x04, 0xf4, 0x03, 0x02, 0x0e, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x35, 0x02, 0x00, 0x01, 0x12, 0x04, 0xf4, 0x03, 0x0f, 0x19, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x35, 0x02, 0x00, 0x03, 0x12, 0x04, 0xf4, 0x03, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, - 0x04, 0x35, 0x02, 0x01, 0x12, 0x04, 0xf5, 0x03, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, - 0x02, 0x01, 0x06, 0x12, 0x04, 0xf5, 0x03, 0x02, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, - 0x01, 0x01, 0x12, 0x04, 0xf5, 0x03, 0x0f, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x01, - 0x03, 0x12, 0x04, 0xf5, 0x03, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x36, 0x12, 0x06, 0xf8, - 0x03, 0x00, 0xfb, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x36, 0x01, 0x12, 0x04, 0xf8, 0x03, - 0x08, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x36, 0x02, 0x00, 0x12, 0x04, 0xf9, 0x03, 0x02, 0x13, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x00, 0x05, 0x12, 0x04, 0xf9, 0x03, 0x02, 0x08, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x00, 0x01, 0x12, 0x04, 0xf9, 0x03, 0x09, 0x0e, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x36, 0x02, 0x00, 0x03, 0x12, 0x04, 0xf9, 0x03, 0x11, 0x12, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x36, 0x02, 0x01, 0x12, 0x04, 0xfa, 0x03, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x36, 0x02, 0x01, 0x06, 0x12, 0x04, 0xfa, 0x03, 0x02, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, - 0x02, 0x01, 0x01, 0x12, 0x04, 0xfa, 0x03, 0x0f, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, - 0x01, 0x03, 0x12, 0x04, 0xfa, 0x03, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x37, 0x12, 0x06, - 0xfd, 0x03, 0x00, 0x81, 0x04, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x37, 0x01, 0x12, 0x04, 0xfd, - 0x03, 0x08, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x37, 0x02, 0x00, 0x12, 0x04, 0xfe, 0x03, 0x02, - 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x04, 0x12, 0x04, 0xfe, 0x03, 0x02, 0x0a, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x06, 0x12, 0x04, 0xfe, 0x03, 0x0b, 0x17, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x01, 0x12, 0x04, 0xfe, 0x03, 0x18, 0x23, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x03, 0x12, 0x04, 0xfe, 0x03, 0x26, 0x27, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x37, 0x02, 0x01, 0x12, 0x04, 0xff, 0x03, 0x02, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x37, 0x02, 0x01, 0x04, 0x12, 0x04, 0xff, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, - 0x02, 0x01, 0x06, 0x12, 0x04, 0xff, 0x03, 0x0b, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, - 0x01, 0x01, 0x12, 0x04, 0xff, 0x03, 0x1c, 0x26, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x01, - 0x03, 0x12, 0x04, 0xff, 0x03, 0x29, 0x2a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x37, 0x02, 0x02, 0x12, - 0x04, 0x80, 0x04, 0x02, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x02, 0x05, 0x12, 0x04, - 0x80, 0x04, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x02, 0x01, 0x12, 0x04, 0x80, - 0x04, 0x09, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x02, 0x03, 0x12, 0x04, 0x80, 0x04, - 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x38, 0x12, 0x06, 0x83, 0x04, 0x00, 0x85, 0x04, 0x01, - 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x38, 0x01, 0x12, 0x04, 0x83, 0x04, 0x08, 0x14, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x38, 0x02, 0x00, 0x12, 0x04, 0x84, 0x04, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x38, 0x02, 0x00, 0x06, 0x12, 0x04, 0x84, 0x04, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, - 0x02, 0x00, 0x01, 0x12, 0x04, 0x84, 0x04, 0x13, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, - 0x00, 0x03, 0x12, 0x04, 0x84, 0x04, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x39, 0x12, 0x06, - 0x87, 0x04, 0x00, 0x9a, 0x04, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x39, 0x01, 0x12, 0x04, 0x87, - 0x04, 0x08, 0x18, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x39, 0x04, 0x00, 0x12, 0x06, 0x88, 0x04, 0x02, - 0x90, 0x04, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x04, 0x00, 0x01, 0x12, 0x04, 0x88, 0x04, - 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x39, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x89, 0x04, - 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x89, - 0x04, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, - 0x89, 0x04, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x39, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, - 0x8a, 0x04, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, - 0x04, 0x8a, 0x04, 0x04, 0x10, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, 0x02, 0x01, 0x02, - 0x12, 0x04, 0x8a, 0x04, 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x39, 0x04, 0x00, 0x02, 0x02, - 0x12, 0x04, 0x8b, 0x04, 0x04, 0x1b, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, 0x02, 0x02, - 0x01, 0x12, 0x04, 0x8b, 0x04, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, 0x02, - 0x02, 0x02, 0x12, 0x04, 0x8b, 0x04, 0x19, 0x1a, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x39, 0x04, 0x00, - 0x02, 0x03, 0x12, 0x04, 0x8c, 0x04, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, 0x00, - 0x02, 0x03, 0x01, 0x12, 0x04, 0x8c, 0x04, 0x04, 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, 0x04, - 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0x8c, 0x04, 0x16, 0x17, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x39, - 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, 0x8d, 0x04, 0x04, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x39, - 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, 0x8d, 0x04, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x39, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x04, 0x8d, 0x04, 0x15, 0x16, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x39, 0x04, 0x00, 0x04, 0x12, 0x04, 0x8f, 0x04, 0x04, 0x0f, 0x0a, 0x0e, 0x0a, 0x06, 0x04, - 0x39, 0x04, 0x00, 0x04, 0x00, 0x12, 0x04, 0x8f, 0x04, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, - 0x39, 0x04, 0x00, 0x04, 0x00, 0x01, 0x12, 0x04, 0x8f, 0x04, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, - 0x04, 0x39, 0x04, 0x00, 0x04, 0x00, 0x02, 0x12, 0x04, 0x8f, 0x04, 0x0d, 0x0e, 0x0a, 0x0c, 0x0a, - 0x04, 0x04, 0x39, 0x02, 0x00, 0x12, 0x04, 0x92, 0x04, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x39, 0x02, 0x00, 0x06, 0x12, 0x04, 0x92, 0x04, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, - 0x02, 0x00, 0x01, 0x12, 0x04, 0x92, 0x04, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, - 0x00, 0x03, 0x12, 0x04, 0x92, 0x04, 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x39, 0x08, 0x00, - 0x12, 0x06, 0x93, 0x04, 0x02, 0x99, 0x04, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x08, 0x00, - 0x01, 0x12, 0x04, 0x93, 0x04, 0x08, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x39, 0x02, 0x01, 0x12, - 0x04, 0x94, 0x04, 0x04, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x01, 0x06, 0x12, 0x04, - 0x94, 0x04, 0x04, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x01, 0x01, 0x12, 0x04, 0x94, - 0x04, 0x15, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x01, 0x03, 0x12, 0x04, 0x94, 0x04, - 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x39, 0x02, 0x02, 0x12, 0x04, 0x95, 0x04, 0x04, 0x2c, - 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x02, 0x06, 0x12, 0x04, 0x95, 0x04, 0x04, 0x19, 0x0a, - 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x02, 0x01, 0x12, 0x04, 0x95, 0x04, 0x1a, 0x27, 0x0a, 0x0d, - 0x0a, 0x05, 0x04, 0x39, 0x02, 0x02, 0x03, 0x12, 0x04, 0x95, 0x04, 0x2a, 0x2b, 0x0a, 0x1e, 0x0a, - 0x04, 0x04, 0x39, 0x02, 0x03, 0x12, 0x04, 0x97, 0x04, 0x04, 0x30, 0x1a, 0x10, 0x20, 0x34, 0x20, - 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, - 0x05, 0x04, 0x39, 0x02, 0x03, 0x06, 0x12, 0x04, 0x97, 0x04, 0x04, 0x16, 0x0a, 0x0d, 0x0a, 0x05, - 0x04, 0x39, 0x02, 0x03, 0x01, 0x12, 0x04, 0x97, 0x04, 0x17, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, - 0x39, 0x02, 0x03, 0x03, 0x12, 0x04, 0x97, 0x04, 0x2e, 0x2f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x39, - 0x02, 0x04, 0x12, 0x04, 0x98, 0x04, 0x04, 0x2e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x04, - 0x06, 0x12, 0x04, 0x98, 0x04, 0x04, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x04, 0x01, - 0x12, 0x04, 0x98, 0x04, 0x16, 0x29, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x39, 0x02, 0x04, 0x03, 0x12, - 0x04, 0x98, 0x04, 0x2c, 0x2d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xe9, + 0x01, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, + 0xe9, 0x01, 0x1d, 0x1e, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x17, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, + 0xea, 0x01, 0x04, 0x1e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, + 0x04, 0xea, 0x01, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x02, 0x04, 0x02, + 0x12, 0x04, 0xea, 0x01, 0x1c, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x04, 0x00, 0x04, 0x12, + 0x04, 0xeb, 0x01, 0x04, 0x0f, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x17, 0x04, 0x00, 0x04, 0x00, 0x12, + 0x04, 0xeb, 0x01, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x04, 0x00, 0x01, + 0x12, 0x04, 0xeb, 0x01, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x17, 0x04, 0x00, 0x04, 0x00, + 0x02, 0x12, 0x04, 0xeb, 0x01, 0x0d, 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x00, 0x12, + 0x04, 0xee, 0x01, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x06, 0x12, 0x04, + 0xee, 0x01, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x01, 0x12, 0x04, 0xee, + 0x01, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x00, 0x03, 0x12, 0x04, 0xee, 0x01, + 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x17, 0x08, 0x00, 0x12, 0x06, 0xf0, 0x01, 0x02, 0xf5, + 0x01, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x08, 0x00, 0x01, 0x12, 0x04, 0xf0, 0x01, 0x08, + 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x04, 0x34, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x06, 0x12, 0x04, 0xf1, 0x01, 0x04, 0x18, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x17, 0x02, 0x01, 0x01, 0x12, 0x04, 0xf1, 0x01, 0x19, 0x2f, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x17, 0x02, 0x01, 0x03, 0x12, 0x04, 0xf1, 0x01, 0x32, 0x33, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x17, 0x02, 0x02, 0x12, 0x04, 0xf2, 0x01, 0x04, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, + 0x02, 0x02, 0x06, 0x12, 0x04, 0xf2, 0x01, 0x04, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, + 0x02, 0x01, 0x12, 0x04, 0xf2, 0x01, 0x12, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x02, + 0x03, 0x12, 0x04, 0xf2, 0x01, 0x23, 0x24, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x03, 0x12, + 0x04, 0xf3, 0x01, 0x04, 0x2a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x03, 0x06, 0x12, 0x04, + 0xf3, 0x01, 0x04, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x03, 0x01, 0x12, 0x04, 0xf3, + 0x01, 0x14, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x03, 0x03, 0x12, 0x04, 0xf3, 0x01, + 0x28, 0x29, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, 0x02, 0x04, 0x12, 0x04, 0xf4, 0x01, 0x04, 0x29, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x04, 0x06, 0x12, 0x04, 0xf4, 0x01, 0x04, 0x13, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x02, 0x04, 0x01, 0x12, 0x04, 0xf4, 0x01, 0x14, 0x24, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x17, 0x02, 0x04, 0x03, 0x12, 0x04, 0xf4, 0x01, 0x27, 0x28, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x17, 0x09, 0x12, 0x04, 0xf6, 0x01, 0x02, 0x0d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x17, + 0x09, 0x00, 0x12, 0x04, 0xf6, 0x01, 0x0b, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x09, 0x00, + 0x01, 0x12, 0x04, 0xf6, 0x01, 0x0b, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x17, 0x09, 0x00, 0x02, + 0x12, 0x04, 0xf6, 0x01, 0x0b, 0x0c, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x18, 0x12, 0x06, 0xf9, 0x01, + 0x00, 0xfe, 0x01, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x18, 0x01, 0x12, 0x04, 0xf9, 0x01, 0x08, + 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x00, 0x12, 0x04, 0xfa, 0x01, 0x02, 0x1f, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x06, 0x12, 0x04, 0xfa, 0x01, 0x02, 0x11, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x18, 0x02, 0x00, 0x01, 0x12, 0x04, 0xfa, 0x01, 0x12, 0x1a, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x18, 0x02, 0x00, 0x03, 0x12, 0x04, 0xfa, 0x01, 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x18, 0x02, 0x01, 0x12, 0x04, 0xfb, 0x01, 0x02, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, + 0x02, 0x01, 0x04, 0x12, 0x04, 0xfb, 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, + 0x01, 0x06, 0x12, 0x04, 0xfb, 0x01, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x01, + 0x01, 0x12, 0x04, 0xfb, 0x01, 0x14, 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x01, 0x03, + 0x12, 0x04, 0xfb, 0x01, 0x25, 0x26, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x02, 0x12, 0x04, + 0xfc, 0x01, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x04, 0x12, 0x04, 0xfc, + 0x01, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x05, 0x12, 0x04, 0xfc, 0x01, + 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x01, 0x12, 0x04, 0xfc, 0x01, 0x12, + 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x18, 0x02, 0x02, 0x03, 0x12, 0x04, 0xfc, 0x01, 0x1e, 0x1f, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x18, 0x02, 0x03, 0x12, 0x04, 0xfd, 0x01, 0x02, 0x23, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x18, 0x02, 0x03, 0x05, 0x12, 0x04, 0xfd, 0x01, 0x02, 0x08, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x18, 0x02, 0x03, 0x01, 0x12, 0x04, 0xfd, 0x01, 0x09, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x18, 0x02, 0x03, 0x03, 0x12, 0x04, 0xfd, 0x01, 0x21, 0x22, 0x0a, 0x0c, 0x0a, 0x02, 0x04, + 0x19, 0x12, 0x06, 0x80, 0x02, 0x00, 0x83, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x19, 0x01, + 0x12, 0x04, 0x80, 0x02, 0x08, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x19, 0x02, 0x00, 0x12, 0x04, + 0x81, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x05, 0x12, 0x04, 0x81, + 0x02, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x01, 0x12, 0x04, 0x81, 0x02, + 0x08, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x00, 0x03, 0x12, 0x04, 0x81, 0x02, 0x13, + 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x19, 0x02, 0x01, 0x12, 0x04, 0x82, 0x02, 0x02, 0x17, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x19, 0x02, 0x01, 0x06, 0x12, 0x04, 0x82, 0x02, 0x02, 0x0e, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x19, 0x02, 0x01, 0x01, 0x12, 0x04, 0x82, 0x02, 0x0f, 0x12, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x19, 0x02, 0x01, 0x03, 0x12, 0x04, 0x82, 0x02, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x02, + 0x04, 0x1a, 0x12, 0x06, 0x85, 0x02, 0x00, 0x89, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1a, + 0x01, 0x12, 0x04, 0x85, 0x02, 0x08, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x00, 0x12, + 0x04, 0x86, 0x02, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x06, 0x12, 0x04, + 0x86, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x01, 0x12, 0x04, 0x86, + 0x02, 0x15, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x00, 0x03, 0x12, 0x04, 0x86, 0x02, + 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1a, 0x02, 0x01, 0x12, 0x04, 0x87, 0x02, 0x02, 0x27, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x04, 0x12, 0x04, 0x87, 0x02, 0x02, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x06, 0x12, 0x04, 0x87, 0x02, 0x0b, 0x13, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x01, 0x01, 0x12, 0x04, 0x87, 0x02, 0x14, 0x22, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1a, 0x02, 0x01, 0x03, 0x12, 0x04, 0x87, 0x02, 0x25, 0x26, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x1a, 0x02, 0x02, 0x12, 0x04, 0x88, 0x02, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, + 0x02, 0x02, 0x04, 0x12, 0x04, 0x88, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, + 0x02, 0x05, 0x12, 0x04, 0x88, 0x02, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x02, + 0x01, 0x12, 0x04, 0x88, 0x02, 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1a, 0x02, 0x02, 0x03, + 0x12, 0x04, 0x88, 0x02, 0x1e, 0x1f, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1b, 0x12, 0x06, 0x8b, 0x02, + 0x00, 0x8e, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1b, 0x01, 0x12, 0x04, 0x8b, 0x02, 0x08, + 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1b, 0x02, 0x00, 0x12, 0x04, 0x8c, 0x02, 0x02, 0x1e, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x00, 0x05, 0x12, 0x04, 0x8c, 0x02, 0x02, 0x08, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8c, 0x02, 0x09, 0x19, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1b, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8c, 0x02, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x1b, 0x02, 0x01, 0x12, 0x04, 0x8d, 0x02, 0x02, 0x3e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, + 0x02, 0x01, 0x04, 0x12, 0x04, 0x8d, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, + 0x01, 0x06, 0x12, 0x04, 0x8d, 0x02, 0x0b, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x01, + 0x01, 0x12, 0x04, 0x8d, 0x02, 0x26, 0x39, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1b, 0x02, 0x01, 0x03, + 0x12, 0x04, 0x8d, 0x02, 0x3c, 0x3d, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1c, 0x12, 0x06, 0x90, 0x02, + 0x00, 0x9b, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1c, 0x01, 0x12, 0x04, 0x90, 0x02, 0x08, + 0x22, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x1c, 0x04, 0x00, 0x12, 0x06, 0x91, 0x02, 0x02, 0x94, 0x02, + 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x04, 0x00, 0x01, 0x12, 0x04, 0x91, 0x02, 0x07, 0x0b, + 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x92, 0x02, 0x04, 0x19, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x92, 0x02, 0x04, + 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0x92, 0x02, + 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0x93, 0x02, + 0x04, 0x24, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x93, + 0x02, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1c, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, + 0x93, 0x02, 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1c, 0x02, 0x00, 0x12, 0x04, 0x96, 0x02, + 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x06, 0x12, 0x04, 0x96, 0x02, 0x02, + 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x01, 0x12, 0x04, 0x96, 0x02, 0x07, 0x0b, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x02, 0x00, 0x03, 0x12, 0x04, 0x96, 0x02, 0x0e, 0x0f, 0x0a, + 0x0e, 0x0a, 0x04, 0x04, 0x1c, 0x08, 0x00, 0x12, 0x06, 0x98, 0x02, 0x02, 0x9a, 0x02, 0x03, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x1c, 0x08, 0x00, 0x01, 0x12, 0x04, 0x98, 0x02, 0x08, 0x0f, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x1c, 0x02, 0x01, 0x12, 0x04, 0x99, 0x02, 0x04, 0x34, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1c, 0x02, 0x01, 0x06, 0x12, 0x04, 0x99, 0x02, 0x04, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x1c, 0x02, 0x01, 0x01, 0x12, 0x04, 0x99, 0x02, 0x19, 0x2f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1c, + 0x02, 0x01, 0x03, 0x12, 0x04, 0x99, 0x02, 0x32, 0x33, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1d, 0x12, + 0x06, 0x9d, 0x02, 0x00, 0xa0, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1d, 0x01, 0x12, 0x04, + 0x9d, 0x02, 0x08, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1d, 0x02, 0x00, 0x12, 0x04, 0x9e, 0x02, + 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x05, 0x12, 0x04, 0x9e, 0x02, 0x02, + 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x01, 0x12, 0x04, 0x9e, 0x02, 0x08, 0x10, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1d, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9e, 0x02, 0x13, 0x14, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x1d, 0x02, 0x01, 0x12, 0x04, 0x9f, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1d, 0x02, 0x01, 0x06, 0x12, 0x04, 0x9f, 0x02, 0x02, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1d, 0x02, 0x01, 0x01, 0x12, 0x04, 0x9f, 0x02, 0x0d, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x1d, 0x02, 0x01, 0x03, 0x12, 0x04, 0x9f, 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1e, + 0x12, 0x06, 0xa2, 0x02, 0x00, 0xa8, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1e, 0x01, 0x12, + 0x04, 0xa2, 0x02, 0x08, 0x12, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1e, 0x02, 0x00, 0x12, 0x04, 0xa3, + 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x05, 0x12, 0x04, 0xa3, 0x02, + 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa3, 0x02, 0x09, + 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xa3, 0x02, 0x13, 0x14, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1e, 0x02, 0x01, 0x12, 0x04, 0xa4, 0x02, 0x02, 0x12, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x01, 0x05, 0x12, 0x04, 0xa4, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1e, 0x02, 0x01, 0x01, 0x12, 0x04, 0xa4, 0x02, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1e, 0x02, 0x01, 0x03, 0x12, 0x04, 0xa4, 0x02, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x1e, 0x02, 0x02, 0x12, 0x04, 0xa5, 0x02, 0x02, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, + 0x02, 0x04, 0x12, 0x04, 0xa5, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x02, + 0x06, 0x12, 0x04, 0xa5, 0x02, 0x0b, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x02, 0x01, + 0x12, 0x04, 0xa5, 0x02, 0x18, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x02, 0x03, 0x12, + 0x04, 0xa5, 0x02, 0x22, 0x23, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1e, 0x02, 0x03, 0x12, 0x04, 0xa6, + 0x02, 0x02, 0x2e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x03, 0x04, 0x12, 0x04, 0xa6, 0x02, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x03, 0x06, 0x12, 0x04, 0xa6, 0x02, 0x0b, + 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x03, 0x01, 0x12, 0x04, 0xa6, 0x02, 0x18, 0x29, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, 0x02, 0x03, 0x03, 0x12, 0x04, 0xa6, 0x02, 0x2c, 0x2d, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x1e, 0x02, 0x04, 0x12, 0x04, 0xa7, 0x02, 0x02, 0x22, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1e, 0x02, 0x04, 0x04, 0x12, 0x04, 0xa7, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1e, 0x02, 0x04, 0x06, 0x12, 0x04, 0xa7, 0x02, 0x0b, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x1e, 0x02, 0x04, 0x01, 0x12, 0x04, 0xa7, 0x02, 0x16, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1e, + 0x02, 0x04, 0x03, 0x12, 0x04, 0xa7, 0x02, 0x20, 0x21, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x1f, 0x12, + 0x06, 0xa9, 0x02, 0x00, 0xb6, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x1f, 0x01, 0x12, 0x04, + 0xa9, 0x02, 0x08, 0x14, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x1f, 0x04, 0x00, 0x12, 0x06, 0xaa, 0x02, + 0x02, 0xaf, 0x02, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x04, 0x00, 0x01, 0x12, 0x04, 0xaa, + 0x02, 0x07, 0x11, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1f, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0xab, + 0x02, 0x04, 0x1f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, + 0xab, 0x02, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, + 0x04, 0xab, 0x02, 0x1d, 0x1e, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1f, 0x04, 0x00, 0x02, 0x01, 0x12, + 0x04, 0xac, 0x02, 0x04, 0x1b, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, 0x00, 0x02, 0x01, 0x01, + 0x12, 0x04, 0xac, 0x02, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, 0x00, 0x02, 0x01, + 0x02, 0x12, 0x04, 0xac, 0x02, 0x19, 0x1a, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1f, 0x04, 0x00, 0x02, + 0x02, 0x12, 0x04, 0xad, 0x02, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, 0x00, 0x02, + 0x02, 0x01, 0x12, 0x04, 0xad, 0x02, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, 0x00, + 0x02, 0x02, 0x02, 0x12, 0x04, 0xad, 0x02, 0x18, 0x19, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x1f, 0x04, + 0x00, 0x02, 0x03, 0x12, 0x04, 0xae, 0x02, 0x04, 0x1a, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, 0x04, + 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xae, 0x02, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x1f, + 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xae, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x1f, 0x02, 0x00, 0x12, 0x04, 0xb0, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, + 0x00, 0x05, 0x12, 0x04, 0xb0, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x00, + 0x01, 0x12, 0x04, 0xb0, 0x02, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x00, 0x03, + 0x12, 0x04, 0xb0, 0x02, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x01, 0x12, 0x04, + 0xb1, 0x02, 0x02, 0x29, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x01, 0x06, 0x12, 0x04, 0xb1, + 0x02, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb1, 0x02, + 0x1a, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x01, 0x03, 0x12, 0x04, 0xb1, 0x02, 0x27, + 0x28, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x02, 0x12, 0x04, 0xb2, 0x02, 0x02, 0x14, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x02, 0x05, 0x12, 0x04, 0xb2, 0x02, 0x02, 0x06, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x02, 0x01, 0x12, 0x04, 0xb2, 0x02, 0x07, 0x0f, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1f, 0x02, 0x02, 0x03, 0x12, 0x04, 0xb2, 0x02, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x1f, 0x02, 0x03, 0x12, 0x04, 0xb3, 0x02, 0x02, 0x40, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, + 0x02, 0x03, 0x04, 0x12, 0x04, 0xb3, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, + 0x03, 0x06, 0x12, 0x04, 0xb3, 0x02, 0x0b, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x03, + 0x01, 0x12, 0x04, 0xb3, 0x02, 0x28, 0x3b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x03, 0x03, + 0x12, 0x04, 0xb3, 0x02, 0x3e, 0x3f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x04, 0x12, 0x04, + 0xb4, 0x02, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x04, 0x12, 0x04, 0xb4, + 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x06, 0x12, 0x04, 0xb4, 0x02, + 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x01, 0x12, 0x04, 0xb4, 0x02, 0x14, + 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x04, 0x03, 0x12, 0x04, 0xb4, 0x02, 0x1d, 0x1e, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x1f, 0x02, 0x05, 0x12, 0x04, 0xb5, 0x02, 0x02, 0x1f, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x1f, 0x02, 0x05, 0x04, 0x12, 0x04, 0xb5, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x1f, 0x02, 0x05, 0x06, 0x12, 0x04, 0xb5, 0x02, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x1f, 0x02, 0x05, 0x01, 0x12, 0x04, 0xb5, 0x02, 0x14, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x1f, 0x02, 0x05, 0x03, 0x12, 0x04, 0xb5, 0x02, 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x20, + 0x12, 0x06, 0xb8, 0x02, 0x00, 0xbe, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x20, 0x01, 0x12, + 0x04, 0xb8, 0x02, 0x08, 0x12, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x00, 0x12, 0x04, 0xb9, + 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x00, 0x05, 0x12, 0x04, 0xb9, 0x02, + 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x00, 0x01, 0x12, 0x04, 0xb9, 0x02, 0x09, + 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb9, 0x02, 0x10, 0x11, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x01, 0x12, 0x04, 0xba, 0x02, 0x02, 0x15, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x20, 0x02, 0x01, 0x05, 0x12, 0x04, 0xba, 0x02, 0x02, 0x06, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x20, 0x02, 0x01, 0x01, 0x12, 0x04, 0xba, 0x02, 0x07, 0x10, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x20, 0x02, 0x01, 0x03, 0x12, 0x04, 0xba, 0x02, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x20, 0x02, 0x02, 0x12, 0x04, 0xbb, 0x02, 0x02, 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, + 0x02, 0x04, 0x12, 0x04, 0xbb, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x02, + 0x06, 0x12, 0x04, 0xbb, 0x02, 0x0b, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x02, 0x01, + 0x12, 0x04, 0xbb, 0x02, 0x17, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x02, 0x03, 0x12, + 0x04, 0xbb, 0x02, 0x23, 0x24, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x03, 0x12, 0x04, 0xbc, + 0x02, 0x02, 0x3e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x04, 0x12, 0x04, 0xbc, 0x02, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x06, 0x12, 0x04, 0xbc, 0x02, 0x0b, + 0x25, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x01, 0x12, 0x04, 0xbc, 0x02, 0x26, 0x39, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, 0x02, 0x03, 0x03, 0x12, 0x04, 0xbc, 0x02, 0x3c, 0x3d, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x20, 0x02, 0x04, 0x12, 0x04, 0xbd, 0x02, 0x02, 0x26, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x20, 0x02, 0x04, 0x04, 0x12, 0x04, 0xbd, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x20, 0x02, 0x04, 0x06, 0x12, 0x04, 0xbd, 0x02, 0x0b, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x20, 0x02, 0x04, 0x01, 0x12, 0x04, 0xbd, 0x02, 0x1b, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x20, + 0x02, 0x04, 0x03, 0x12, 0x04, 0xbd, 0x02, 0x24, 0x25, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x21, 0x12, + 0x06, 0xc0, 0x02, 0x00, 0xc3, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x21, 0x01, 0x12, 0x04, + 0xc0, 0x02, 0x08, 0x22, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x21, 0x02, 0x00, 0x12, 0x04, 0xc1, 0x02, + 0x02, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x00, 0x04, 0x12, 0x04, 0xc1, 0x02, 0x02, + 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x00, 0x06, 0x12, 0x04, 0xc1, 0x02, 0x0b, 0x16, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc1, 0x02, 0x17, 0x22, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x21, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc1, 0x02, 0x25, 0x26, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x21, 0x02, 0x01, 0x12, 0x04, 0xc2, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x21, 0x02, 0x01, 0x05, 0x12, 0x04, 0xc2, 0x02, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x21, 0x02, 0x01, 0x01, 0x12, 0x04, 0xc2, 0x02, 0x07, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x21, + 0x02, 0x01, 0x03, 0x12, 0x04, 0xc2, 0x02, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x22, 0x12, + 0x06, 0xc5, 0x02, 0x00, 0xc8, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x22, 0x01, 0x12, 0x04, + 0xc5, 0x02, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x22, 0x02, 0x00, 0x12, 0x04, 0xc6, 0x02, + 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x00, 0x05, 0x12, 0x04, 0xc6, 0x02, 0x02, + 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc6, 0x02, 0x09, 0x0d, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x22, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc6, 0x02, 0x10, 0x11, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x22, 0x02, 0x01, 0x12, 0x04, 0xc7, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x22, 0x02, 0x01, 0x06, 0x12, 0x04, 0xc7, 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x22, 0x02, 0x01, 0x01, 0x12, 0x04, 0xc7, 0x02, 0x0b, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x22, 0x02, 0x01, 0x03, 0x12, 0x04, 0xc7, 0x02, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x23, + 0x12, 0x06, 0xca, 0x02, 0x00, 0xcc, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x23, 0x01, 0x12, + 0x04, 0xca, 0x02, 0x08, 0x24, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x23, 0x02, 0x00, 0x12, 0x04, 0xcb, + 0x02, 0x02, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x00, 0x04, 0x12, 0x04, 0xcb, 0x02, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x00, 0x06, 0x12, 0x04, 0xcb, 0x02, 0x0b, + 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x00, 0x01, 0x12, 0x04, 0xcb, 0x02, 0x17, 0x22, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x23, 0x02, 0x00, 0x03, 0x12, 0x04, 0xcb, 0x02, 0x25, 0x26, 0x0a, + 0x0c, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x06, 0xce, 0x02, 0x00, 0xde, 0x02, 0x01, 0x0a, 0x0b, 0x0a, + 0x03, 0x05, 0x00, 0x01, 0x12, 0x04, 0xce, 0x02, 0x05, 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, + 0x02, 0x00, 0x12, 0x04, 0xcf, 0x02, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, + 0x01, 0x12, 0x04, 0xcf, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00, 0x02, + 0x12, 0x04, 0xcf, 0x02, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x01, 0x12, 0x04, + 0xd0, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xd0, + 0x02, 0x02, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xd0, 0x02, + 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x02, 0x12, 0x04, 0xd1, 0x02, 0x02, 0x14, + 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xd1, 0x02, 0x02, 0x0f, 0x0a, + 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xd1, 0x02, 0x12, 0x13, 0x0a, 0x0c, + 0x0a, 0x04, 0x05, 0x00, 0x02, 0x03, 0x12, 0x04, 0xd2, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, + 0x05, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xd2, 0x02, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xd2, 0x02, 0x13, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, + 0x02, 0x04, 0x12, 0x04, 0xd3, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, + 0x01, 0x12, 0x04, 0xd3, 0x02, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x04, 0x02, + 0x12, 0x04, 0xd3, 0x02, 0x13, 0x15, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x05, 0x12, 0x04, + 0xd4, 0x02, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x05, 0x01, 0x12, 0x04, 0xd4, + 0x02, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x05, 0x02, 0x12, 0x04, 0xd4, 0x02, + 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x06, 0x12, 0x04, 0xd5, 0x02, 0x02, 0x16, + 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x06, 0x01, 0x12, 0x04, 0xd5, 0x02, 0x02, 0x11, 0x0a, + 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x06, 0x02, 0x12, 0x04, 0xd5, 0x02, 0x14, 0x15, 0x0a, 0x0c, + 0x0a, 0x04, 0x05, 0x00, 0x02, 0x07, 0x12, 0x04, 0xd6, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, + 0x05, 0x00, 0x02, 0x07, 0x01, 0x12, 0x04, 0xd6, 0x02, 0x02, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x05, + 0x00, 0x02, 0x07, 0x02, 0x12, 0x04, 0xd6, 0x02, 0x14, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, + 0x02, 0x08, 0x12, 0x04, 0xd7, 0x02, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x08, + 0x01, 0x12, 0x04, 0xd7, 0x02, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x08, 0x02, + 0x12, 0x04, 0xd7, 0x02, 0x17, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x09, 0x12, 0x04, + 0xd8, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x09, 0x01, 0x12, 0x04, 0xd8, + 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x09, 0x02, 0x12, 0x04, 0xd8, 0x02, + 0x16, 0x17, 0x0a, 0x2b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0a, 0x12, 0x04, 0xd9, 0x02, 0x02, 0x18, + 0x22, 0x1d, 0x20, 0x60, 0x7b, 0x20, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x3a, 0x20, 0x42, 0x6f, 0x78, + 0x3c, 0x4d, 0x6f, 0x76, 0x65, 0x54, 0x79, 0x70, 0x65, 0x3e, 0x20, 0x7d, 0x60, 0x2c, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0a, 0x01, 0x12, 0x04, 0xd9, 0x02, 0x02, 0x13, 0x0a, 0x0d, + 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0a, 0x02, 0x12, 0x04, 0xd9, 0x02, 0x16, 0x17, 0x0a, 0x22, 0x0a, + 0x04, 0x05, 0x00, 0x02, 0x0b, 0x12, 0x04, 0xda, 0x02, 0x02, 0x18, 0x22, 0x14, 0x20, 0x60, 0x28, + 0x4d, 0x6f, 0x76, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x54, 0x61, 0x67, 0x29, 0x60, 0x2c, + 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0b, 0x01, 0x12, 0x04, 0xda, 0x02, 0x02, 0x13, + 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0b, 0x02, 0x12, 0x04, 0xda, 0x02, 0x16, 0x17, 0x0a, + 0x22, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0c, 0x12, 0x04, 0xdb, 0x02, 0x02, 0x24, 0x22, 0x14, 0x20, + 0x60, 0x7b, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x3a, 0x20, 0x75, 0x31, 0x36, 0x20, 0x7d, 0x60, + 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0c, 0x01, 0x12, 0x04, 0xdb, 0x02, + 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0c, 0x02, 0x12, 0x04, 0xdb, 0x02, 0x22, + 0x23, 0x0a, 0x37, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0d, 0x12, 0x04, 0xdc, 0x02, 0x02, 0x1c, 0x22, + 0x29, 0x20, 0x60, 0x7b, 0x20, 0x6d, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3a, 0x20, 0x62, 0x6f, + 0x6f, 0x6c, 0x2c, 0x20, 0x74, 0x6f, 0x3a, 0x20, 0x42, 0x6f, 0x78, 0x3c, 0x4d, 0x6f, 0x76, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x3e, 0x20, 0x7d, 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, + 0x02, 0x0d, 0x01, 0x12, 0x04, 0xdc, 0x02, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, + 0x0d, 0x02, 0x12, 0x04, 0xdc, 0x02, 0x19, 0x1b, 0x0a, 0x1b, 0x0a, 0x04, 0x05, 0x00, 0x02, 0x0e, + 0x12, 0x04, 0xdd, 0x02, 0x02, 0x1d, 0x22, 0x0d, 0x20, 0x60, 0x28, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x29, 0x60, 0x2c, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0e, 0x01, 0x12, 0x04, + 0xdd, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x0e, 0x02, 0x12, 0x04, 0xdd, + 0x02, 0x1a, 0x1c, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x24, 0x12, 0x06, 0xe0, 0x02, 0x00, 0xef, 0x02, + 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x24, 0x01, 0x12, 0x04, 0xe0, 0x02, 0x08, 0x10, 0x0a, 0x0e, + 0x0a, 0x04, 0x04, 0x24, 0x03, 0x00, 0x12, 0x06, 0xe2, 0x02, 0x02, 0xe5, 0x02, 0x03, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x24, 0x03, 0x00, 0x01, 0x12, 0x04, 0xe2, 0x02, 0x0a, 0x17, 0x0a, 0x0e, 0x0a, + 0x06, 0x04, 0x24, 0x03, 0x00, 0x02, 0x00, 0x12, 0x04, 0xe3, 0x02, 0x04, 0x15, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x24, 0x03, 0x00, 0x02, 0x00, 0x05, 0x12, 0x04, 0xe3, 0x02, 0x04, 0x08, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x24, 0x03, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe3, 0x02, 0x09, 0x10, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x24, 0x03, 0x00, 0x02, 0x00, 0x03, 0x12, 0x04, 0xe3, 0x02, 0x13, 0x14, + 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x24, 0x03, 0x00, 0x02, 0x01, 0x12, 0x04, 0xe4, 0x02, 0x04, 0x14, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x24, 0x03, 0x00, 0x02, 0x01, 0x06, 0x12, 0x04, 0xe4, 0x02, 0x04, + 0x0c, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x24, 0x03, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xe4, 0x02, + 0x0d, 0x0f, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x24, 0x03, 0x00, 0x02, 0x01, 0x03, 0x12, 0x04, 0xe4, + 0x02, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x24, 0x02, 0x00, 0x12, 0x04, 0xe7, 0x02, 0x02, + 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x00, 0x06, 0x12, 0x04, 0xe7, 0x02, 0x02, 0x0b, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe7, 0x02, 0x0c, 0x10, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x00, 0x03, 0x12, 0x04, 0xe7, 0x02, 0x13, 0x14, 0x0a, 0x0e, + 0x0a, 0x04, 0x04, 0x24, 0x08, 0x00, 0x12, 0x06, 0xe8, 0x02, 0x02, 0xee, 0x02, 0x03, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x24, 0x08, 0x00, 0x01, 0x12, 0x04, 0xe8, 0x02, 0x08, 0x0f, 0x0a, 0x0c, 0x0a, + 0x04, 0x04, 0x24, 0x02, 0x01, 0x12, 0x04, 0xe9, 0x02, 0x04, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x24, 0x02, 0x01, 0x06, 0x12, 0x04, 0xe9, 0x02, 0x04, 0x0c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, + 0x02, 0x01, 0x01, 0x12, 0x04, 0xe9, 0x02, 0x0d, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, + 0x01, 0x03, 0x12, 0x04, 0xe9, 0x02, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x24, 0x02, 0x02, + 0x12, 0x04, 0xea, 0x02, 0x04, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x02, 0x06, 0x12, + 0x04, 0xea, 0x02, 0x04, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x02, 0x01, 0x12, 0x04, + 0xea, 0x02, 0x12, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x02, 0x03, 0x12, 0x04, 0xea, + 0x02, 0x1b, 0x1c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x24, 0x02, 0x03, 0x12, 0x04, 0xeb, 0x02, 0x04, + 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x03, 0x05, 0x12, 0x04, 0xeb, 0x02, 0x04, 0x0a, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x03, 0x01, 0x12, 0x04, 0xeb, 0x02, 0x0b, 0x23, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x03, 0x03, 0x12, 0x04, 0xeb, 0x02, 0x26, 0x27, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x24, 0x02, 0x04, 0x12, 0x04, 0xec, 0x02, 0x04, 0x20, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x24, 0x02, 0x04, 0x06, 0x12, 0x04, 0xec, 0x02, 0x04, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x24, 0x02, 0x04, 0x01, 0x12, 0x04, 0xec, 0x02, 0x12, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, + 0x02, 0x04, 0x03, 0x12, 0x04, 0xec, 0x02, 0x1e, 0x1f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x24, 0x02, + 0x05, 0x12, 0x04, 0xed, 0x02, 0x04, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x05, 0x05, + 0x12, 0x04, 0xed, 0x02, 0x04, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x05, 0x01, 0x12, + 0x04, 0xed, 0x02, 0x0b, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x24, 0x02, 0x05, 0x03, 0x12, 0x04, + 0xed, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x02, 0x05, 0x01, 0x12, 0x06, 0xf1, 0x02, 0x00, 0xf7, + 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x05, 0x01, 0x01, 0x12, 0x04, 0xf1, 0x02, 0x05, 0x10, 0x0a, + 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x00, 0x12, 0x04, 0xf2, 0x02, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, + 0x05, 0x05, 0x01, 0x02, 0x00, 0x01, 0x12, 0x04, 0xf2, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, + 0x05, 0x01, 0x02, 0x00, 0x02, 0x12, 0x04, 0xf2, 0x02, 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x05, + 0x01, 0x02, 0x01, 0x12, 0x04, 0xf3, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, + 0x01, 0x01, 0x12, 0x04, 0xf3, 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x01, + 0x02, 0x12, 0x04, 0xf3, 0x02, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x02, 0x12, + 0x04, 0xf4, 0x02, 0x02, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x02, 0x01, 0x12, 0x04, + 0xf4, 0x02, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x02, 0x02, 0x12, 0x04, 0xf4, + 0x02, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x03, 0x12, 0x04, 0xf5, 0x02, 0x02, + 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, 0x01, 0x12, 0x04, 0xf5, 0x02, 0x02, 0x14, + 0x0a, 0x0d, 0x0a, 0x05, 0x05, 0x01, 0x02, 0x03, 0x02, 0x12, 0x04, 0xf5, 0x02, 0x17, 0x18, 0x0a, + 0x0c, 0x0a, 0x04, 0x05, 0x01, 0x02, 0x04, 0x12, 0x04, 0xf6, 0x02, 0x02, 0x17, 0x0a, 0x0d, 0x0a, + 0x05, 0x05, 0x01, 0x02, 0x04, 0x01, 0x12, 0x04, 0xf6, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, + 0x05, 0x01, 0x02, 0x04, 0x02, 0x12, 0x04, 0xf6, 0x02, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x02, 0x04, + 0x25, 0x12, 0x06, 0xf9, 0x02, 0x00, 0xfb, 0x02, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x25, 0x01, + 0x12, 0x04, 0xf9, 0x02, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x25, 0x02, 0x00, 0x12, 0x04, + 0xfa, 0x02, 0x02, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x00, 0x06, 0x12, 0x04, 0xfa, + 0x02, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x00, 0x01, 0x12, 0x04, 0xfa, 0x02, + 0x0b, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x25, 0x02, 0x00, 0x03, 0x12, 0x04, 0xfa, 0x02, 0x17, + 0x18, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x26, 0x12, 0x06, 0xfd, 0x02, 0x00, 0x80, 0x03, 0x01, 0x0a, + 0x0b, 0x0a, 0x03, 0x04, 0x26, 0x01, 0x12, 0x04, 0xfd, 0x02, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x26, 0x02, 0x00, 0x12, 0x04, 0xfe, 0x02, 0x02, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, + 0x02, 0x00, 0x06, 0x12, 0x04, 0xfe, 0x02, 0x02, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, 0x02, + 0x00, 0x01, 0x12, 0x04, 0xfe, 0x02, 0x0f, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, 0x02, 0x00, + 0x03, 0x12, 0x04, 0xfe, 0x02, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x26, 0x02, 0x01, 0x12, + 0x04, 0xff, 0x02, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, 0x02, 0x01, 0x05, 0x12, 0x04, + 0xff, 0x02, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, 0x02, 0x01, 0x01, 0x12, 0x04, 0xff, + 0x02, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x26, 0x02, 0x01, 0x03, 0x12, 0x04, 0xff, 0x02, + 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x27, 0x12, 0x06, 0x82, 0x03, 0x00, 0x85, 0x03, 0x01, + 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x27, 0x01, 0x12, 0x04, 0x82, 0x03, 0x08, 0x14, 0x0a, 0x0c, 0x0a, + 0x04, 0x04, 0x27, 0x02, 0x00, 0x12, 0x04, 0x83, 0x03, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x27, 0x02, 0x00, 0x05, 0x12, 0x04, 0x83, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, + 0x02, 0x00, 0x01, 0x12, 0x04, 0x83, 0x03, 0x09, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, + 0x00, 0x03, 0x12, 0x04, 0x83, 0x03, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x27, 0x02, 0x01, + 0x12, 0x04, 0x84, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, 0x01, 0x05, 0x12, + 0x04, 0x84, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, 0x01, 0x01, 0x12, 0x04, + 0x84, 0x03, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x27, 0x02, 0x01, 0x03, 0x12, 0x04, 0x84, + 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x28, 0x12, 0x06, 0x87, 0x03, 0x00, 0x8c, 0x03, + 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x28, 0x01, 0x12, 0x04, 0x87, 0x03, 0x08, 0x15, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x28, 0x02, 0x00, 0x12, 0x04, 0x88, 0x03, 0x02, 0x15, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x28, 0x02, 0x00, 0x05, 0x12, 0x04, 0x88, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x28, 0x02, 0x00, 0x01, 0x12, 0x04, 0x88, 0x03, 0x09, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, + 0x02, 0x00, 0x03, 0x12, 0x04, 0x88, 0x03, 0x13, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x28, 0x02, + 0x01, 0x12, 0x04, 0x89, 0x03, 0x02, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x01, 0x05, + 0x12, 0x04, 0x89, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x01, 0x01, 0x12, + 0x04, 0x89, 0x03, 0x09, 0x0f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x01, 0x03, 0x12, 0x04, + 0x89, 0x03, 0x12, 0x13, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x28, 0x02, 0x02, 0x12, 0x04, 0x8a, 0x03, + 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x02, 0x05, 0x12, 0x04, 0x8a, 0x03, 0x02, + 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x02, 0x01, 0x12, 0x04, 0x8a, 0x03, 0x09, 0x0d, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, 0x02, 0x02, 0x03, 0x12, 0x04, 0x8a, 0x03, 0x10, 0x11, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x28, 0x02, 0x03, 0x12, 0x04, 0x8b, 0x03, 0x02, 0x2c, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x28, 0x02, 0x03, 0x04, 0x12, 0x04, 0x8b, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x28, 0x02, 0x03, 0x06, 0x12, 0x04, 0x8b, 0x03, 0x0b, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x28, 0x02, 0x03, 0x01, 0x12, 0x04, 0x8b, 0x03, 0x14, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x28, + 0x02, 0x03, 0x03, 0x12, 0x04, 0x8b, 0x03, 0x2a, 0x2b, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x29, 0x12, + 0x06, 0x8e, 0x03, 0x00, 0xa3, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x29, 0x01, 0x12, 0x04, + 0x8e, 0x03, 0x08, 0x11, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x29, 0x04, 0x00, 0x12, 0x06, 0x90, 0x03, + 0x02, 0x98, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x04, 0x00, 0x01, 0x12, 0x04, 0x90, + 0x03, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x29, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x91, + 0x03, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, + 0x91, 0x03, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, + 0x04, 0x91, 0x03, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x29, 0x04, 0x00, 0x02, 0x01, 0x12, + 0x04, 0x92, 0x03, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, 0x01, 0x01, + 0x12, 0x04, 0x92, 0x03, 0x04, 0x10, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, 0x01, + 0x02, 0x12, 0x04, 0x92, 0x03, 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x29, 0x04, 0x00, 0x02, + 0x02, 0x12, 0x04, 0x93, 0x03, 0x04, 0x1b, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, + 0x02, 0x01, 0x12, 0x04, 0x93, 0x03, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, + 0x02, 0x02, 0x02, 0x12, 0x04, 0x93, 0x03, 0x19, 0x1a, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x29, 0x04, + 0x00, 0x02, 0x03, 0x12, 0x04, 0x94, 0x03, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, + 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0x94, 0x03, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x29, + 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0x94, 0x03, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, + 0x29, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, 0x95, 0x03, 0x04, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x29, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, 0x95, 0x03, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x29, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x04, 0x95, 0x03, 0x15, 0x16, 0x0a, 0x0e, 0x0a, + 0x06, 0x04, 0x29, 0x04, 0x00, 0x02, 0x05, 0x12, 0x04, 0x96, 0x03, 0x04, 0x1b, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, 0x05, 0x01, 0x12, 0x04, 0x96, 0x03, 0x04, 0x16, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x02, 0x05, 0x02, 0x12, 0x04, 0x96, 0x03, 0x19, 0x1a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x04, 0x00, 0x04, 0x12, 0x04, 0x97, 0x03, 0x04, 0x0f, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x29, 0x04, 0x00, 0x04, 0x00, 0x12, 0x04, 0x97, 0x03, 0x0d, 0x0e, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x04, 0x00, 0x01, 0x12, 0x04, 0x97, 0x03, 0x0d, 0x0e, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x29, 0x04, 0x00, 0x04, 0x00, 0x02, 0x12, 0x04, 0x97, 0x03, 0x0d, 0x0e, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x00, 0x12, 0x04, 0x9a, 0x03, 0x02, 0x10, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x29, 0x02, 0x00, 0x06, 0x12, 0x04, 0x9a, 0x03, 0x02, 0x06, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x29, 0x02, 0x00, 0x01, 0x12, 0x04, 0x9a, 0x03, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x29, 0x02, 0x00, 0x03, 0x12, 0x04, 0x9a, 0x03, 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, + 0x29, 0x08, 0x00, 0x12, 0x06, 0x9b, 0x03, 0x02, 0xa2, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x29, 0x08, 0x00, 0x01, 0x12, 0x04, 0x9b, 0x03, 0x08, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, + 0x02, 0x01, 0x12, 0x04, 0x9c, 0x03, 0x04, 0x21, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x01, + 0x06, 0x12, 0x04, 0x9c, 0x03, 0x04, 0x14, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x01, 0x01, + 0x12, 0x04, 0x9c, 0x03, 0x15, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x01, 0x03, 0x12, + 0x04, 0x9c, 0x03, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x02, 0x12, 0x04, 0x9d, + 0x03, 0x04, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x02, 0x06, 0x12, 0x04, 0x9d, 0x03, + 0x04, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x02, 0x01, 0x12, 0x04, 0x9d, 0x03, 0x1a, + 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x02, 0x03, 0x12, 0x04, 0x9d, 0x03, 0x2a, 0x2b, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x03, 0x12, 0x04, 0x9e, 0x03, 0x04, 0x28, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x29, 0x02, 0x03, 0x06, 0x12, 0x04, 0x9e, 0x03, 0x04, 0x17, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x29, 0x02, 0x03, 0x01, 0x12, 0x04, 0x9e, 0x03, 0x18, 0x23, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x29, 0x02, 0x03, 0x03, 0x12, 0x04, 0x9e, 0x03, 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x29, 0x02, 0x04, 0x12, 0x04, 0x9f, 0x03, 0x04, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, + 0x04, 0x06, 0x12, 0x04, 0x9f, 0x03, 0x04, 0x15, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x04, + 0x01, 0x12, 0x04, 0x9f, 0x03, 0x16, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x04, 0x03, + 0x12, 0x04, 0x9f, 0x03, 0x22, 0x23, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x29, 0x02, 0x05, 0x12, 0x04, + 0xa1, 0x03, 0x04, 0x23, 0x1a, 0x10, 0x20, 0x36, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x05, 0x06, 0x12, + 0x04, 0xa1, 0x03, 0x04, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x05, 0x01, 0x12, 0x04, + 0xa1, 0x03, 0x11, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x29, 0x02, 0x05, 0x03, 0x12, 0x04, 0xa1, + 0x03, 0x21, 0x22, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2a, 0x12, 0x06, 0xa5, 0x03, 0x00, 0xa8, 0x03, + 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2a, 0x01, 0x12, 0x04, 0xa5, 0x03, 0x08, 0x18, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x2a, 0x02, 0x00, 0x12, 0x04, 0xa6, 0x03, 0x02, 0x17, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x2a, 0x02, 0x00, 0x05, 0x12, 0x04, 0xa6, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x2a, 0x02, 0x00, 0x01, 0x12, 0x04, 0xa6, 0x03, 0x08, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, + 0x02, 0x00, 0x03, 0x12, 0x04, 0xa6, 0x03, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2a, 0x02, + 0x01, 0x12, 0x04, 0xa7, 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x01, 0x05, + 0x12, 0x04, 0xa7, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x01, 0x01, 0x12, + 0x04, 0xa7, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2a, 0x02, 0x01, 0x03, 0x12, 0x04, + 0xa7, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2b, 0x12, 0x06, 0xaa, 0x03, 0x00, 0xaf, + 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2b, 0x01, 0x12, 0x04, 0xaa, 0x03, 0x08, 0x1d, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x2b, 0x02, 0x00, 0x12, 0x04, 0xab, 0x03, 0x02, 0x21, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x2b, 0x02, 0x00, 0x04, 0x12, 0x04, 0xab, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x2b, 0x02, 0x00, 0x05, 0x12, 0x04, 0xab, 0x03, 0x0b, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x2b, 0x02, 0x00, 0x01, 0x12, 0x04, 0xab, 0x03, 0x11, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, + 0x02, 0x00, 0x03, 0x12, 0x04, 0xab, 0x03, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2b, 0x02, + 0x01, 0x12, 0x04, 0xac, 0x03, 0x02, 0x20, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x01, 0x04, + 0x12, 0x04, 0xac, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x01, 0x05, 0x12, + 0x04, 0xac, 0x03, 0x0b, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x01, 0x01, 0x12, 0x04, + 0xac, 0x03, 0x11, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x01, 0x03, 0x12, 0x04, 0xac, + 0x03, 0x1e, 0x1f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2b, 0x02, 0x02, 0x12, 0x04, 0xad, 0x03, 0x02, + 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x02, 0x05, 0x12, 0x04, 0xad, 0x03, 0x02, 0x08, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x02, 0x01, 0x12, 0x04, 0xad, 0x03, 0x09, 0x12, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, 0x02, 0x03, 0x12, 0x04, 0xad, 0x03, 0x15, 0x16, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x2b, 0x02, 0x03, 0x12, 0x04, 0xae, 0x03, 0x02, 0x29, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x2b, 0x02, 0x03, 0x04, 0x12, 0x04, 0xae, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x2b, 0x02, 0x03, 0x05, 0x12, 0x04, 0xae, 0x03, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, + 0x02, 0x03, 0x01, 0x12, 0x04, 0xae, 0x03, 0x12, 0x24, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2b, 0x02, + 0x03, 0x03, 0x12, 0x04, 0xae, 0x03, 0x27, 0x28, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2c, 0x12, 0x06, + 0xb1, 0x03, 0x00, 0xb5, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2c, 0x01, 0x12, 0x04, 0xb1, + 0x03, 0x08, 0x1b, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2c, 0x02, 0x00, 0x12, 0x04, 0xb2, 0x03, 0x02, + 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x06, 0x12, 0x04, 0xb2, 0x03, 0x02, 0x12, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x01, 0x12, 0x04, 0xb2, 0x03, 0x13, 0x19, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x00, 0x03, 0x12, 0x04, 0xb2, 0x03, 0x1c, 0x1d, 0x0a, 0x0c, + 0x0a, 0x04, 0x04, 0x2c, 0x02, 0x01, 0x12, 0x04, 0xb3, 0x03, 0x02, 0x31, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x2c, 0x02, 0x01, 0x04, 0x12, 0x04, 0xb3, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x2c, 0x02, 0x01, 0x05, 0x12, 0x04, 0xb3, 0x03, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, + 0x02, 0x01, 0x01, 0x12, 0x04, 0xb3, 0x03, 0x12, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, + 0x01, 0x03, 0x12, 0x04, 0xb3, 0x03, 0x2f, 0x30, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2c, 0x02, 0x02, + 0x12, 0x04, 0xb4, 0x03, 0x02, 0x32, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x02, 0x04, 0x12, + 0x04, 0xb4, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x02, 0x06, 0x12, 0x04, + 0xb4, 0x03, 0x0b, 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x02, 0x01, 0x12, 0x04, 0xb4, + 0x03, 0x1c, 0x2d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2c, 0x02, 0x02, 0x03, 0x12, 0x04, 0xb4, 0x03, + 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2d, 0x12, 0x06, 0xb7, 0x03, 0x00, 0xbd, 0x03, 0x01, + 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2d, 0x01, 0x12, 0x04, 0xb7, 0x03, 0x08, 0x19, 0x0a, 0x0c, 0x0a, + 0x04, 0x04, 0x2d, 0x02, 0x00, 0x12, 0x04, 0xb8, 0x03, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x2d, 0x02, 0x00, 0x06, 0x12, 0x04, 0xb8, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, + 0x02, 0x00, 0x01, 0x12, 0x04, 0xb8, 0x03, 0x13, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, + 0x00, 0x03, 0x12, 0x04, 0xb8, 0x03, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2d, 0x02, 0x01, + 0x12, 0x04, 0xb9, 0x03, 0x02, 0x31, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x04, 0x12, + 0x04, 0xb9, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x05, 0x12, 0x04, + 0xb9, 0x03, 0x0b, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x01, 0x12, 0x04, 0xb9, + 0x03, 0x12, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x01, 0x03, 0x12, 0x04, 0xb9, 0x03, + 0x2f, 0x30, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2d, 0x02, 0x02, 0x12, 0x04, 0xba, 0x03, 0x02, 0x32, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x02, 0x04, 0x12, 0x04, 0xba, 0x03, 0x02, 0x0a, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x02, 0x06, 0x12, 0x04, 0xba, 0x03, 0x0b, 0x1b, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x02, 0x01, 0x12, 0x04, 0xba, 0x03, 0x1c, 0x2d, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x2d, 0x02, 0x02, 0x03, 0x12, 0x04, 0xba, 0x03, 0x30, 0x31, 0x0a, 0x0c, 0x0a, 0x04, + 0x04, 0x2d, 0x02, 0x03, 0x12, 0x04, 0xbb, 0x03, 0x02, 0x1f, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, + 0x02, 0x03, 0x05, 0x12, 0x04, 0xbb, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, + 0x03, 0x01, 0x12, 0x04, 0xbb, 0x03, 0x09, 0x1a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x03, + 0x03, 0x12, 0x04, 0xbb, 0x03, 0x1d, 0x1e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2d, 0x02, 0x04, 0x12, + 0x04, 0xbc, 0x03, 0x02, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x04, 0x06, 0x12, 0x04, + 0xbc, 0x03, 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x04, 0x01, 0x12, 0x04, 0xbc, + 0x03, 0x13, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2d, 0x02, 0x04, 0x03, 0x12, 0x04, 0xbc, 0x03, + 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x2e, 0x12, 0x06, 0xbf, 0x03, 0x00, 0xca, 0x03, 0x01, + 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2e, 0x01, 0x12, 0x04, 0xbf, 0x03, 0x08, 0x14, 0x0a, 0x0e, 0x0a, + 0x04, 0x04, 0x2e, 0x04, 0x00, 0x12, 0x06, 0xc0, 0x03, 0x02, 0xc6, 0x03, 0x03, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x2e, 0x04, 0x00, 0x01, 0x12, 0x04, 0xc0, 0x03, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, + 0x04, 0x2e, 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0xc1, 0x03, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x2e, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc1, 0x03, 0x04, 0x14, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0xc1, 0x03, 0x17, 0x18, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0xc2, 0x03, 0x04, 0x15, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0xc2, 0x03, 0x04, 0x10, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xc2, 0x03, 0x13, 0x14, + 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0xc3, 0x03, 0x04, 0x1d, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xc3, 0x03, 0x04, + 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xc3, 0x03, + 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0xc4, 0x03, + 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xc4, + 0x03, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, + 0xc4, 0x03, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, + 0xc5, 0x03, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, + 0x04, 0xc5, 0x03, 0x04, 0x0d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2e, 0x04, 0x00, 0x02, 0x04, 0x02, + 0x12, 0x04, 0xc5, 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2e, 0x02, 0x00, 0x12, 0x04, + 0xc8, 0x03, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x00, 0x06, 0x12, 0x04, 0xc8, + 0x03, 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x00, 0x01, 0x12, 0x04, 0xc8, 0x03, + 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x00, 0x03, 0x12, 0x04, 0xc8, 0x03, 0x0e, + 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2e, 0x02, 0x01, 0x12, 0x04, 0xc9, 0x03, 0x02, 0x17, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x01, 0x05, 0x12, 0x04, 0xc9, 0x03, 0x02, 0x07, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x2e, 0x02, 0x01, 0x01, 0x12, 0x04, 0xc9, 0x03, 0x08, 0x12, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x2e, 0x02, 0x01, 0x03, 0x12, 0x04, 0xc9, 0x03, 0x15, 0x16, 0x0a, 0x0c, 0x0a, 0x02, + 0x04, 0x2f, 0x12, 0x06, 0xcc, 0x03, 0x00, 0xdd, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x2f, + 0x01, 0x12, 0x04, 0xcc, 0x03, 0x08, 0x14, 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x2f, 0x04, 0x00, 0x12, + 0x06, 0xcd, 0x03, 0x02, 0xd3, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x04, 0x00, 0x01, + 0x12, 0x04, 0xcd, 0x03, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x00, + 0x12, 0x04, 0xce, 0x03, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x00, + 0x01, 0x12, 0x04, 0xce, 0x03, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, + 0x00, 0x02, 0x12, 0x04, 0xce, 0x03, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, 0x04, 0x00, + 0x02, 0x01, 0x12, 0x04, 0xcf, 0x03, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, + 0x02, 0x01, 0x01, 0x12, 0x04, 0xcf, 0x03, 0x04, 0x10, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, + 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0xcf, 0x03, 0x13, 0x14, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x2f, + 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0xd0, 0x03, 0x04, 0x1d, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x2f, + 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0xd0, 0x03, 0x04, 0x18, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x2f, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0xd0, 0x03, 0x1b, 0x1c, 0x0a, 0x0e, 0x0a, 0x06, + 0x04, 0x2f, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0xd1, 0x03, 0x04, 0x16, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x2f, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0xd1, 0x03, 0x04, 0x11, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0xd1, 0x03, 0x14, 0x15, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, 0xd2, 0x03, 0x04, 0x12, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, 0xd2, 0x03, 0x04, 0x0d, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x2f, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x04, 0xd2, 0x03, 0x10, 0x11, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2f, 0x02, 0x00, 0x12, 0x04, 0xd5, 0x03, 0x02, 0x10, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x00, 0x06, 0x12, 0x04, 0xd5, 0x03, 0x02, 0x06, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x2f, 0x02, 0x00, 0x01, 0x12, 0x04, 0xd5, 0x03, 0x07, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x2f, 0x02, 0x00, 0x03, 0x12, 0x04, 0xd5, 0x03, 0x0e, 0x0f, 0x0a, 0x0e, 0x0a, 0x04, 0x04, + 0x2f, 0x08, 0x00, 0x12, 0x06, 0xd7, 0x03, 0x02, 0xdc, 0x03, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x2f, 0x08, 0x00, 0x01, 0x12, 0x04, 0xd7, 0x03, 0x08, 0x11, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2f, + 0x02, 0x01, 0x12, 0x04, 0xd8, 0x03, 0x04, 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x01, + 0x06, 0x12, 0x04, 0xd8, 0x03, 0x04, 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x01, 0x01, + 0x12, 0x04, 0xd8, 0x03, 0x0c, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x01, 0x03, 0x12, + 0x04, 0xd8, 0x03, 0x16, 0x17, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2f, 0x02, 0x02, 0x12, 0x04, 0xd9, + 0x03, 0x04, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x02, 0x06, 0x12, 0x04, 0xd9, 0x03, + 0x04, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x02, 0x01, 0x12, 0x04, 0xd9, 0x03, 0x13, + 0x22, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x02, 0x03, 0x12, 0x04, 0xd9, 0x03, 0x25, 0x26, + 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x2f, 0x02, 0x03, 0x12, 0x04, 0xda, 0x03, 0x04, 0x1a, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x03, 0x06, 0x12, 0x04, 0xda, 0x03, 0x04, 0x0c, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x2f, 0x02, 0x03, 0x01, 0x12, 0x04, 0xda, 0x03, 0x0d, 0x15, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x2f, 0x02, 0x03, 0x03, 0x12, 0x04, 0xda, 0x03, 0x18, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x2f, 0x02, 0x04, 0x12, 0x04, 0xdb, 0x03, 0x04, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, + 0x04, 0x06, 0x12, 0x04, 0xdb, 0x03, 0x04, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x04, + 0x01, 0x12, 0x04, 0xdb, 0x03, 0x09, 0x0d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x2f, 0x02, 0x04, 0x03, + 0x12, 0x04, 0xdb, 0x03, 0x10, 0x11, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x30, 0x12, 0x06, 0xdf, 0x03, + 0x00, 0xe1, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x30, 0x01, 0x12, 0x04, 0xdf, 0x03, 0x08, + 0x0f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x30, 0x02, 0x00, 0x12, 0x04, 0xe0, 0x03, 0x02, 0x16, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x30, 0x02, 0x00, 0x05, 0x12, 0x04, 0xe0, 0x03, 0x02, 0x07, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x30, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe0, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x30, 0x02, 0x00, 0x03, 0x12, 0x04, 0xe0, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, + 0x04, 0x31, 0x12, 0x06, 0xe3, 0x03, 0x00, 0xe5, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x31, + 0x01, 0x12, 0x04, 0xe3, 0x03, 0x08, 0x16, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x31, 0x02, 0x00, 0x12, + 0x04, 0xe4, 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x31, 0x02, 0x00, 0x05, 0x12, 0x04, + 0xe4, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x31, 0x02, 0x00, 0x01, 0x12, 0x04, 0xe4, + 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x31, 0x02, 0x00, 0x03, 0x12, 0x04, 0xe4, 0x03, + 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x32, 0x12, 0x06, 0xe7, 0x03, 0x00, 0xe9, 0x03, 0x01, + 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x32, 0x01, 0x12, 0x04, 0xe7, 0x03, 0x08, 0x10, 0x0a, 0x0c, 0x0a, + 0x04, 0x04, 0x32, 0x02, 0x00, 0x12, 0x04, 0xe8, 0x03, 0x02, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x32, 0x02, 0x00, 0x05, 0x12, 0x04, 0xe8, 0x03, 0x02, 0x07, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x32, + 0x02, 0x00, 0x01, 0x12, 0x04, 0xe8, 0x03, 0x08, 0x11, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x32, 0x02, + 0x00, 0x03, 0x12, 0x04, 0xe8, 0x03, 0x14, 0x15, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x33, 0x12, 0x06, + 0xeb, 0x03, 0x00, 0xed, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x33, 0x01, 0x12, 0x04, 0xeb, + 0x03, 0x08, 0x0c, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x33, 0x02, 0x00, 0x12, 0x04, 0xec, 0x03, 0x02, + 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x33, 0x02, 0x00, 0x05, 0x12, 0x04, 0xec, 0x03, 0x02, 0x07, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x33, 0x02, 0x00, 0x01, 0x12, 0x04, 0xec, 0x03, 0x08, 0x11, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x33, 0x02, 0x00, 0x03, 0x12, 0x04, 0xec, 0x03, 0x14, 0x15, 0x0a, 0x0c, + 0x0a, 0x02, 0x04, 0x34, 0x12, 0x06, 0xef, 0x03, 0x00, 0xf2, 0x03, 0x01, 0x0a, 0x0b, 0x0a, 0x03, + 0x04, 0x34, 0x01, 0x12, 0x04, 0xef, 0x03, 0x08, 0x1a, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x34, 0x02, + 0x00, 0x12, 0x04, 0xf0, 0x03, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x00, 0x06, + 0x12, 0x04, 0xf0, 0x03, 0x02, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x00, 0x01, 0x12, + 0x04, 0xf0, 0x03, 0x0f, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x00, 0x03, 0x12, 0x04, + 0xf0, 0x03, 0x1c, 0x1d, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x34, 0x02, 0x01, 0x12, 0x04, 0xf1, 0x03, + 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x01, 0x06, 0x12, 0x04, 0xf1, 0x03, 0x02, + 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x01, 0x01, 0x12, 0x04, 0xf1, 0x03, 0x0f, 0x18, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x34, 0x02, 0x01, 0x03, 0x12, 0x04, 0xf1, 0x03, 0x1b, 0x1c, 0x0a, + 0x0c, 0x0a, 0x02, 0x04, 0x35, 0x12, 0x06, 0xf4, 0x03, 0x00, 0xf7, 0x03, 0x01, 0x0a, 0x0b, 0x0a, + 0x03, 0x04, 0x35, 0x01, 0x12, 0x04, 0xf4, 0x03, 0x08, 0x18, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x35, + 0x02, 0x00, 0x12, 0x04, 0xf5, 0x03, 0x02, 0x13, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x00, + 0x05, 0x12, 0x04, 0xf5, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x00, 0x01, + 0x12, 0x04, 0xf5, 0x03, 0x09, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xf5, 0x03, 0x11, 0x12, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x35, 0x02, 0x01, 0x12, 0x04, 0xf6, + 0x03, 0x02, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x01, 0x06, 0x12, 0x04, 0xf6, 0x03, + 0x02, 0x0e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x01, 0x01, 0x12, 0x04, 0xf6, 0x03, 0x0f, + 0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x35, 0x02, 0x01, 0x03, 0x12, 0x04, 0xf6, 0x03, 0x1b, 0x1c, + 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x36, 0x12, 0x06, 0xf9, 0x03, 0x00, 0xfd, 0x03, 0x01, 0x0a, 0x0b, + 0x0a, 0x03, 0x04, 0x36, 0x01, 0x12, 0x04, 0xf9, 0x03, 0x08, 0x19, 0x0a, 0x0c, 0x0a, 0x04, 0x04, + 0x36, 0x02, 0x00, 0x12, 0x04, 0xfa, 0x03, 0x02, 0x28, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, + 0x00, 0x04, 0x12, 0x04, 0xfa, 0x03, 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x00, + 0x06, 0x12, 0x04, 0xfa, 0x03, 0x0b, 0x17, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x00, 0x01, + 0x12, 0x04, 0xfa, 0x03, 0x18, 0x23, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x00, 0x03, 0x12, + 0x04, 0xfa, 0x03, 0x26, 0x27, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x36, 0x02, 0x01, 0x12, 0x04, 0xfb, + 0x03, 0x02, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x01, 0x04, 0x12, 0x04, 0xfb, 0x03, + 0x02, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x01, 0x06, 0x12, 0x04, 0xfb, 0x03, 0x0b, + 0x1b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x01, 0x01, 0x12, 0x04, 0xfb, 0x03, 0x1c, 0x26, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x36, 0x02, 0x01, 0x03, 0x12, 0x04, 0xfb, 0x03, 0x29, 0x2a, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x36, 0x02, 0x02, 0x12, 0x04, 0xfc, 0x03, 0x02, 0x21, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x36, 0x02, 0x02, 0x05, 0x12, 0x04, 0xfc, 0x03, 0x02, 0x08, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x36, 0x02, 0x02, 0x01, 0x12, 0x04, 0xfc, 0x03, 0x09, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x36, 0x02, 0x02, 0x03, 0x12, 0x04, 0xfc, 0x03, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x37, + 0x12, 0x06, 0xff, 0x03, 0x00, 0x81, 0x04, 0x01, 0x0a, 0x0b, 0x0a, 0x03, 0x04, 0x37, 0x01, 0x12, + 0x04, 0xff, 0x03, 0x08, 0x14, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x37, 0x02, 0x00, 0x12, 0x04, 0x80, + 0x04, 0x02, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x06, 0x12, 0x04, 0x80, 0x04, + 0x02, 0x12, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x01, 0x12, 0x04, 0x80, 0x04, 0x13, + 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x37, 0x02, 0x00, 0x03, 0x12, 0x04, 0x80, 0x04, 0x1c, 0x1d, + 0x0a, 0x0c, 0x0a, 0x02, 0x04, 0x38, 0x12, 0x06, 0x83, 0x04, 0x00, 0x96, 0x04, 0x01, 0x0a, 0x0b, + 0x0a, 0x03, 0x04, 0x38, 0x01, 0x12, 0x04, 0x83, 0x04, 0x08, 0x18, 0x0a, 0x0e, 0x0a, 0x04, 0x04, + 0x38, 0x04, 0x00, 0x12, 0x06, 0x84, 0x04, 0x02, 0x8c, 0x04, 0x03, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x38, 0x04, 0x00, 0x01, 0x12, 0x04, 0x84, 0x04, 0x07, 0x0b, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x38, + 0x04, 0x00, 0x02, 0x00, 0x12, 0x04, 0x85, 0x04, 0x04, 0x19, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x04, 0x85, 0x04, 0x04, 0x14, 0x0a, 0x0f, 0x0a, 0x07, 0x04, + 0x38, 0x04, 0x00, 0x02, 0x00, 0x02, 0x12, 0x04, 0x85, 0x04, 0x17, 0x18, 0x0a, 0x0e, 0x0a, 0x06, + 0x04, 0x38, 0x04, 0x00, 0x02, 0x01, 0x12, 0x04, 0x86, 0x04, 0x04, 0x15, 0x0a, 0x0f, 0x0a, 0x07, + 0x04, 0x38, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x04, 0x86, 0x04, 0x04, 0x10, 0x0a, 0x0f, 0x0a, + 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x01, 0x02, 0x12, 0x04, 0x86, 0x04, 0x13, 0x14, 0x0a, 0x0e, + 0x0a, 0x06, 0x04, 0x38, 0x04, 0x00, 0x02, 0x02, 0x12, 0x04, 0x87, 0x04, 0x04, 0x1b, 0x0a, 0x0f, + 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x04, 0x87, 0x04, 0x04, 0x16, 0x0a, + 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x02, 0x02, 0x12, 0x04, 0x87, 0x04, 0x19, 0x1a, + 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x38, 0x04, 0x00, 0x02, 0x03, 0x12, 0x04, 0x88, 0x04, 0x04, 0x18, + 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x04, 0x88, 0x04, 0x04, + 0x13, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x03, 0x02, 0x12, 0x04, 0x88, 0x04, + 0x16, 0x17, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x38, 0x04, 0x00, 0x02, 0x04, 0x12, 0x04, 0x89, 0x04, + 0x04, 0x17, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x04, 0x01, 0x12, 0x04, 0x89, + 0x04, 0x04, 0x12, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x02, 0x04, 0x02, 0x12, 0x04, + 0x89, 0x04, 0x15, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x04, 0x00, 0x04, 0x12, 0x04, 0x8b, + 0x04, 0x04, 0x0f, 0x0a, 0x0e, 0x0a, 0x06, 0x04, 0x38, 0x04, 0x00, 0x04, 0x00, 0x12, 0x04, 0x8b, + 0x04, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x04, 0x00, 0x01, 0x12, 0x04, + 0x8b, 0x04, 0x0d, 0x0e, 0x0a, 0x0f, 0x0a, 0x07, 0x04, 0x38, 0x04, 0x00, 0x04, 0x00, 0x02, 0x12, + 0x04, 0x8b, 0x04, 0x0d, 0x0e, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x38, 0x02, 0x00, 0x12, 0x04, 0x8e, + 0x04, 0x02, 0x10, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x00, 0x06, 0x12, 0x04, 0x8e, 0x04, + 0x02, 0x06, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x00, 0x01, 0x12, 0x04, 0x8e, 0x04, 0x07, + 0x0b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x00, 0x03, 0x12, 0x04, 0x8e, 0x04, 0x0e, 0x0f, + 0x0a, 0x0e, 0x0a, 0x04, 0x04, 0x38, 0x08, 0x00, 0x12, 0x06, 0x8f, 0x04, 0x02, 0x95, 0x04, 0x03, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x08, 0x00, 0x01, 0x12, 0x04, 0x8f, 0x04, 0x08, 0x11, 0x0a, + 0x0c, 0x0a, 0x04, 0x04, 0x38, 0x02, 0x01, 0x12, 0x04, 0x90, 0x04, 0x04, 0x21, 0x0a, 0x0d, 0x0a, + 0x05, 0x04, 0x38, 0x02, 0x01, 0x06, 0x12, 0x04, 0x90, 0x04, 0x04, 0x14, 0x0a, 0x0d, 0x0a, 0x05, + 0x04, 0x38, 0x02, 0x01, 0x01, 0x12, 0x04, 0x90, 0x04, 0x15, 0x1c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, + 0x38, 0x02, 0x01, 0x03, 0x12, 0x04, 0x90, 0x04, 0x1f, 0x20, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x38, + 0x02, 0x02, 0x12, 0x04, 0x91, 0x04, 0x04, 0x2c, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x02, + 0x06, 0x12, 0x04, 0x91, 0x04, 0x04, 0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x02, 0x01, + 0x12, 0x04, 0x91, 0x04, 0x1a, 0x27, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x02, 0x03, 0x12, + 0x04, 0x91, 0x04, 0x2a, 0x2b, 0x0a, 0x1e, 0x0a, 0x04, 0x04, 0x38, 0x02, 0x03, 0x12, 0x04, 0x93, + 0x04, 0x04, 0x30, 0x1a, 0x10, 0x20, 0x34, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x03, 0x06, 0x12, 0x04, + 0x93, 0x04, 0x04, 0x16, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x03, 0x01, 0x12, 0x04, 0x93, + 0x04, 0x17, 0x2b, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x03, 0x03, 0x12, 0x04, 0x93, 0x04, + 0x2e, 0x2f, 0x0a, 0x0c, 0x0a, 0x04, 0x04, 0x38, 0x02, 0x04, 0x12, 0x04, 0x94, 0x04, 0x04, 0x2e, + 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x04, 0x06, 0x12, 0x04, 0x94, 0x04, 0x04, 0x15, 0x0a, + 0x0d, 0x0a, 0x05, 0x04, 0x38, 0x02, 0x04, 0x01, 0x12, 0x04, 0x94, 0x04, 0x16, 0x29, 0x0a, 0x0d, + 0x0a, 0x05, 0x04, 0x38, 0x02, 0x04, 0x03, 0x12, 0x04, 0x94, 0x04, 0x2c, 0x2d, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, ]; include!("aptos.transaction.v1.serde.rs"); // @@protoc_insertion_point(module) diff --git a/protos/rust/src/pb/aptos.transaction.v1.serde.rs b/protos/rust/src/pb/aptos.transaction.v1.serde.rs index 3bd20ad9ec1ae..b61a574a04e86 100644 --- a/protos/rust/src/pb/aptos.transaction.v1.serde.rs +++ b/protos/rust/src/pb/aptos.transaction.v1.serde.rs @@ -2755,97 +2755,6 @@ impl<'de> serde::Deserialize<'de> for IndexedSignature { deserializer.deserialize_struct("aptos.transaction.v1.IndexedSignature", FIELDS, GeneratedVisitor) } } -impl serde::Serialize for ModuleBundlePayload { - #[allow(deprecated)] - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - use serde::ser::SerializeStruct; - let mut len = 0; - if !self.modules.is_empty() { - len += 1; - } - let mut struct_ser = serializer.serialize_struct("aptos.transaction.v1.ModuleBundlePayload", len)?; - if !self.modules.is_empty() { - struct_ser.serialize_field("modules", &self.modules)?; - } - struct_ser.end() - } -} -impl<'de> serde::Deserialize<'de> for ModuleBundlePayload { - #[allow(deprecated)] - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - const FIELDS: &[&str] = &[ - "modules", - ]; - - #[allow(clippy::enum_variant_names)] - enum GeneratedField { - Modules, - } - impl<'de> serde::Deserialize<'de> for GeneratedField { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - struct GeneratedVisitor; - - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = GeneratedField; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(formatter, "expected one of: {:?}", &FIELDS) - } - - #[allow(unused_variables)] - fn visit_str(self, value: &str) -> std::result::Result - where - E: serde::de::Error, - { - match value { - "modules" => Ok(GeneratedField::Modules), - _ => Err(serde::de::Error::unknown_field(value, FIELDS)), - } - } - } - deserializer.deserialize_identifier(GeneratedVisitor) - } - } - struct GeneratedVisitor; - impl<'de> serde::de::Visitor<'de> for GeneratedVisitor { - type Value = ModuleBundlePayload; - - fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - formatter.write_str("struct aptos.transaction.v1.ModuleBundlePayload") - } - - fn visit_map(self, mut map: V) -> std::result::Result - where - V: serde::de::MapAccess<'de>, - { - let mut modules__ = None; - while let Some(k) = map.next_key()? { - match k { - GeneratedField::Modules => { - if modules__.is_some() { - return Err(serde::de::Error::duplicate_field("modules")); - } - modules__ = Some(map.next_value()?); - } - } - } - Ok(ModuleBundlePayload { - modules: modules__.unwrap_or_default(), - }) - } - } - deserializer.deserialize_struct("aptos.transaction.v1.ModuleBundlePayload", FIELDS, GeneratedVisitor) - } -} impl serde::Serialize for MoveAbility { #[allow(deprecated)] fn serialize(&self, serializer: S) -> std::result::Result @@ -6869,9 +6778,6 @@ impl serde::Serialize for TransactionPayload { transaction_payload::Payload::ScriptPayload(v) => { struct_ser.serialize_field("scriptPayload", v)?; } - transaction_payload::Payload::ModuleBundlePayload(v) => { - struct_ser.serialize_field("moduleBundlePayload", v)?; - } transaction_payload::Payload::WriteSetPayload(v) => { struct_ser.serialize_field("writeSetPayload", v)?; } @@ -6895,8 +6801,6 @@ impl<'de> serde::Deserialize<'de> for TransactionPayload { "entryFunctionPayload", "script_payload", "scriptPayload", - "module_bundle_payload", - "moduleBundlePayload", "write_set_payload", "writeSetPayload", "multisig_payload", @@ -6908,7 +6812,6 @@ impl<'de> serde::Deserialize<'de> for TransactionPayload { Type, EntryFunctionPayload, ScriptPayload, - ModuleBundlePayload, WriteSetPayload, MultisigPayload, } @@ -6935,7 +6838,6 @@ impl<'de> serde::Deserialize<'de> for TransactionPayload { "type" => Ok(GeneratedField::Type), "entryFunctionPayload" | "entry_function_payload" => Ok(GeneratedField::EntryFunctionPayload), "scriptPayload" | "script_payload" => Ok(GeneratedField::ScriptPayload), - "moduleBundlePayload" | "module_bundle_payload" => Ok(GeneratedField::ModuleBundlePayload), "writeSetPayload" | "write_set_payload" => Ok(GeneratedField::WriteSetPayload), "multisigPayload" | "multisig_payload" => Ok(GeneratedField::MultisigPayload), _ => Err(serde::de::Error::unknown_field(value, FIELDS)), @@ -6979,13 +6881,6 @@ impl<'de> serde::Deserialize<'de> for TransactionPayload { return Err(serde::de::Error::duplicate_field("scriptPayload")); } payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::ScriptPayload) -; - } - GeneratedField::ModuleBundlePayload => { - if payload__.is_some() { - return Err(serde::de::Error::duplicate_field("moduleBundlePayload")); - } - payload__ = map.next_value::<::std::option::Option<_>>()?.map(transaction_payload::Payload::ModuleBundlePayload) ; } GeneratedField::WriteSetPayload => { @@ -7023,7 +6918,6 @@ impl serde::Serialize for transaction_payload::Type { Self::Unspecified => "TYPE_UNSPECIFIED", Self::EntryFunctionPayload => "TYPE_ENTRY_FUNCTION_PAYLOAD", Self::ScriptPayload => "TYPE_SCRIPT_PAYLOAD", - Self::ModuleBundlePayload => "TYPE_MODULE_BUNDLE_PAYLOAD", Self::WriteSetPayload => "TYPE_WRITE_SET_PAYLOAD", Self::MultisigPayload => "TYPE_MULTISIG_PAYLOAD", }; @@ -7040,7 +6934,6 @@ impl<'de> serde::Deserialize<'de> for transaction_payload::Type { "TYPE_UNSPECIFIED", "TYPE_ENTRY_FUNCTION_PAYLOAD", "TYPE_SCRIPT_PAYLOAD", - "TYPE_MODULE_BUNDLE_PAYLOAD", "TYPE_WRITE_SET_PAYLOAD", "TYPE_MULTISIG_PAYLOAD", ]; @@ -7088,7 +6981,6 @@ impl<'de> serde::Deserialize<'de> for transaction_payload::Type { "TYPE_UNSPECIFIED" => Ok(transaction_payload::Type::Unspecified), "TYPE_ENTRY_FUNCTION_PAYLOAD" => Ok(transaction_payload::Type::EntryFunctionPayload), "TYPE_SCRIPT_PAYLOAD" => Ok(transaction_payload::Type::ScriptPayload), - "TYPE_MODULE_BUNDLE_PAYLOAD" => Ok(transaction_payload::Type::ModuleBundlePayload), "TYPE_WRITE_SET_PAYLOAD" => Ok(transaction_payload::Type::WriteSetPayload), "TYPE_MULTISIG_PAYLOAD" => Ok(transaction_payload::Type::MultisigPayload), _ => Err(serde::de::Error::unknown_variant(value, FIELDS)), diff --git a/protos/typescript/src/aptos/transaction/v1/transaction.ts b/protos/typescript/src/aptos/transaction/v1/transaction.ts index 061b8e21cd284..75d1af8466382 100644 --- a/protos/typescript/src/aptos/transaction/v1/transaction.ts +++ b/protos/typescript/src/aptos/transaction/v1/transaction.ts @@ -527,7 +527,6 @@ export interface TransactionPayload { type?: TransactionPayload_Type | undefined; entryFunctionPayload?: EntryFunctionPayload | undefined; scriptPayload?: ScriptPayload | undefined; - moduleBundlePayload?: ModuleBundlePayload | undefined; writeSetPayload?: WriteSetPayload | undefined; multisigPayload?: MultisigPayload | undefined; } @@ -536,7 +535,6 @@ export enum TransactionPayload_Type { TYPE_UNSPECIFIED = 0, TYPE_ENTRY_FUNCTION_PAYLOAD = 1, TYPE_SCRIPT_PAYLOAD = 2, - TYPE_MODULE_BUNDLE_PAYLOAD = 3, TYPE_WRITE_SET_PAYLOAD = 4, TYPE_MULTISIG_PAYLOAD = 5, UNRECOGNIZED = -1, @@ -553,9 +551,6 @@ export function transactionPayload_TypeFromJSON(object: any): TransactionPayload case 2: case "TYPE_SCRIPT_PAYLOAD": return TransactionPayload_Type.TYPE_SCRIPT_PAYLOAD; - case 3: - case "TYPE_MODULE_BUNDLE_PAYLOAD": - return TransactionPayload_Type.TYPE_MODULE_BUNDLE_PAYLOAD; case 4: case "TYPE_WRITE_SET_PAYLOAD": return TransactionPayload_Type.TYPE_WRITE_SET_PAYLOAD; @@ -577,8 +572,6 @@ export function transactionPayload_TypeToJSON(object: TransactionPayload_Type): return "TYPE_ENTRY_FUNCTION_PAYLOAD"; case TransactionPayload_Type.TYPE_SCRIPT_PAYLOAD: return "TYPE_SCRIPT_PAYLOAD"; - case TransactionPayload_Type.TYPE_MODULE_BUNDLE_PAYLOAD: - return "TYPE_MODULE_BUNDLE_PAYLOAD"; case TransactionPayload_Type.TYPE_WRITE_SET_PAYLOAD: return "TYPE_WRITE_SET_PAYLOAD"; case TransactionPayload_Type.TYPE_MULTISIG_PAYLOAD: @@ -650,10 +643,6 @@ export function multisigTransactionPayload_TypeToJSON(object: MultisigTransactio } } -export interface ModuleBundlePayload { - modules?: MoveModuleBytecode[] | undefined; -} - export interface MoveModuleBytecode { bytecode?: Uint8Array | undefined; abi?: MoveModule | undefined; @@ -4391,7 +4380,6 @@ function createBaseTransactionPayload(): TransactionPayload { type: 0, entryFunctionPayload: undefined, scriptPayload: undefined, - moduleBundlePayload: undefined, writeSetPayload: undefined, multisigPayload: undefined, }; @@ -4408,9 +4396,6 @@ export const TransactionPayload = { if (message.scriptPayload !== undefined) { ScriptPayload.encode(message.scriptPayload, writer.uint32(26).fork()).ldelim(); } - if (message.moduleBundlePayload !== undefined) { - ModuleBundlePayload.encode(message.moduleBundlePayload, writer.uint32(34).fork()).ldelim(); - } if (message.writeSetPayload !== undefined) { WriteSetPayload.encode(message.writeSetPayload, writer.uint32(42).fork()).ldelim(); } @@ -4448,13 +4433,6 @@ export const TransactionPayload = { message.scriptPayload = ScriptPayload.decode(reader, reader.uint32()); continue; - case 4: - if (tag !== 34) { - break; - } - - message.moduleBundlePayload = ModuleBundlePayload.decode(reader, reader.uint32()); - continue; case 5: if (tag !== 42) { break; @@ -4519,9 +4497,6 @@ export const TransactionPayload = { ? EntryFunctionPayload.fromJSON(object.entryFunctionPayload) : undefined, scriptPayload: isSet(object.scriptPayload) ? ScriptPayload.fromJSON(object.scriptPayload) : undefined, - moduleBundlePayload: isSet(object.moduleBundlePayload) - ? ModuleBundlePayload.fromJSON(object.moduleBundlePayload) - : undefined, writeSetPayload: isSet(object.writeSetPayload) ? WriteSetPayload.fromJSON(object.writeSetPayload) : undefined, multisigPayload: isSet(object.multisigPayload) ? MultisigPayload.fromJSON(object.multisigPayload) : undefined, }; @@ -4538,9 +4513,6 @@ export const TransactionPayload = { if (message.scriptPayload !== undefined) { obj.scriptPayload = ScriptPayload.toJSON(message.scriptPayload); } - if (message.moduleBundlePayload !== undefined) { - obj.moduleBundlePayload = ModuleBundlePayload.toJSON(message.moduleBundlePayload); - } if (message.writeSetPayload !== undefined) { obj.writeSetPayload = WriteSetPayload.toJSON(message.writeSetPayload); } @@ -4562,9 +4534,6 @@ export const TransactionPayload = { message.scriptPayload = (object.scriptPayload !== undefined && object.scriptPayload !== null) ? ScriptPayload.fromPartial(object.scriptPayload) : undefined; - message.moduleBundlePayload = (object.moduleBundlePayload !== undefined && object.moduleBundlePayload !== null) - ? ModuleBundlePayload.fromPartial(object.moduleBundlePayload) - : undefined; message.writeSetPayload = (object.writeSetPayload !== undefined && object.writeSetPayload !== null) ? WriteSetPayload.fromPartial(object.writeSetPayload) : undefined; @@ -5184,103 +5153,6 @@ export const MultisigTransactionPayload = { }, }; -function createBaseModuleBundlePayload(): ModuleBundlePayload { - return { modules: [] }; -} - -export const ModuleBundlePayload = { - encode(message: ModuleBundlePayload, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.modules !== undefined && message.modules.length !== 0) { - for (const v of message.modules) { - MoveModuleBytecode.encode(v!, writer.uint32(10).fork()).ldelim(); - } - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ModuleBundlePayload { - const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); - let end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseModuleBundlePayload(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - if (tag !== 10) { - break; - } - - message.modules!.push(MoveModuleBytecode.decode(reader, reader.uint32())); - continue; - } - if ((tag & 7) === 4 || tag === 0) { - break; - } - reader.skipType(tag & 7); - } - return message; - }, - - // encodeTransform encodes a source of message objects. - // Transform - async *encodeTransform( - source: - | AsyncIterable - | Iterable, - ): AsyncIterable { - for await (const pkt of source) { - if (globalThis.Array.isArray(pkt)) { - for (const p of (pkt as any)) { - yield* [ModuleBundlePayload.encode(p).finish()]; - } - } else { - yield* [ModuleBundlePayload.encode(pkt as any).finish()]; - } - } - }, - - // decodeTransform decodes a source of encoded messages. - // Transform - async *decodeTransform( - source: AsyncIterable | Iterable, - ): AsyncIterable { - for await (const pkt of source) { - if (globalThis.Array.isArray(pkt)) { - for (const p of (pkt as any)) { - yield* [ModuleBundlePayload.decode(p)]; - } - } else { - yield* [ModuleBundlePayload.decode(pkt as any)]; - } - } - }, - - fromJSON(object: any): ModuleBundlePayload { - return { - modules: globalThis.Array.isArray(object?.modules) - ? object.modules.map((e: any) => MoveModuleBytecode.fromJSON(e)) - : [], - }; - }, - - toJSON(message: ModuleBundlePayload): unknown { - const obj: any = {}; - if (message.modules?.length) { - obj.modules = message.modules.map((e) => MoveModuleBytecode.toJSON(e)); - } - return obj; - }, - - create(base?: DeepPartial): ModuleBundlePayload { - return ModuleBundlePayload.fromPartial(base ?? {}); - }, - fromPartial(object: DeepPartial): ModuleBundlePayload { - const message = createBaseModuleBundlePayload(); - message.modules = object.modules?.map((e) => MoveModuleBytecode.fromPartial(e)) || []; - return message; - }, -}; - function createBaseMoveModuleBytecode(): MoveModuleBytecode { return { bytecode: new Uint8Array(0), abi: undefined }; } diff --git a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs index 8e81845df7d34..b9d329cbbf7ae 100644 --- a/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs +++ b/testsuite/fuzzer/fuzz/fuzz_targets/move/aptosvm_publish_and_run.rs @@ -8,8 +8,8 @@ use aptos_language_e2e_tests::{ use aptos_types::{ chain_id::ChainId, transaction::{ - EntryFunction, ExecutionStatus, ModuleBundle, Script, TransactionArgument, - TransactionPayload, TransactionStatus, + EntryFunction, ExecutionStatus, Script, TransactionArgument, TransactionPayload, + TransactionStatus, }, write_set::WriteSet, }; @@ -233,53 +233,13 @@ fn run_case(mut input: RunnableState) -> Result<(), Corpus> { // publish all packages for group in packages { - let sender = *group[0].address(); - let serialized_modules: Vec> = group - .iter() - .map(|m| { - let mut b = vec![]; - m.serialize(&mut b).map(|_| b) - }) - .collect::>, _>>() - .map_err(|_| Corpus::Keep)?; - - // deprecated but easiest way to publish modules - let mb = ModuleBundle::new(serialized_modules); - let acc = vm.new_account_at(sender); - let tx = acc - .transaction() - .gas_unit_price(100) - .sequence_number(0) - .payload(TransactionPayload::ModuleBundle(mb)) - .sign(); + // TODO: Publish modules through native context instead. tdbg!("publishing"); - let res = vm - .execute_block(vec![tx]) - .map_err(|e| { - check_for_invariant_violation(e); - Corpus::Keep - })? - .pop() - .expect("expected 1 output"); - tdbg!(&res); - // if error exit gracefully - let status = match tdbg!(res.status()) { - TransactionStatus::Keep(status) => status, - _ => return Err(Corpus::Keep), - }; - vm.apply_write_set(res.write_set()); - match tdbg!(status) { - ExecutionStatus::Success => (), - ExecutionStatus::MiscellaneousError(e) => { - if let Some(e) = e { - if e.status_type() == StatusType::InvariantViolation { - panic!("invariant violation {:?}", e); - } - } - return Err(Corpus::Keep); - }, - _ => return Err(Corpus::Keep), - }; + for module in group.iter() { + let mut b = vec![]; + module.serialize(&mut b).map_err(|_| Corpus::Keep)?; + vm.add_module(&module.self_id(), b); + } tdbg!("published"); } diff --git a/testsuite/generate-format/tests/staged/api.yaml b/testsuite/generate-format/tests/staged/api.yaml index 82f357fbe24a2..3d9845c2dc130 100644 --- a/testsuite/generate-format/tests/staged/api.yaml +++ b/testsuite/generate-format/tests/staged/api.yaml @@ -202,6 +202,9 @@ DKGTranscriptMetadata: DepositEvent: STRUCT: - amount: U64 +DeprecatedPayload: + STRUCT: + - dummy_value: U64 Ed25519PublicKey: NEWTYPESTRUCT: BYTES Ed25519Signature: @@ -299,14 +302,6 @@ JWKMoveStruct: STRUCT: - variant: TYPENAME: Any -Module: - STRUCT: - - code: BYTES -ModuleBundle: - STRUCT: - - codes: - SEQ: - TYPENAME: Module ModuleId: STRUCT: - address: @@ -677,7 +672,7 @@ TransactionPayload: 1: ModuleBundle: NEWTYPE: - TYPENAME: ModuleBundle + TYPENAME: DeprecatedPayload 2: EntryFunction: NEWTYPE: diff --git a/testsuite/generate-format/tests/staged/aptos.yaml b/testsuite/generate-format/tests/staged/aptos.yaml index 3b4d586ee507e..b578f684fef83 100644 --- a/testsuite/generate-format/tests/staged/aptos.yaml +++ b/testsuite/generate-format/tests/staged/aptos.yaml @@ -179,6 +179,9 @@ DKGTranscriptMetadata: - epoch: U64 - author: TYPENAME: AccountAddress +DeprecatedPayload: + STRUCT: + - dummy_value: U64 Ed25519PublicKey: NEWTYPESTRUCT: BYTES Ed25519Signature: @@ -245,14 +248,6 @@ JWKMoveStruct: STRUCT: - variant: TYPENAME: Any -Module: - STRUCT: - - code: BYTES -ModuleBundle: - STRUCT: - - codes: - SEQ: - TYPENAME: Module ModuleId: STRUCT: - address: @@ -562,7 +557,7 @@ TransactionPayload: 1: ModuleBundle: NEWTYPE: - TYPENAME: ModuleBundle + TYPENAME: DeprecatedPayload 2: EntryFunction: NEWTYPE: diff --git a/testsuite/generate-format/tests/staged/consensus.yaml b/testsuite/generate-format/tests/staged/consensus.yaml index 28978965358e3..81fbf1c5776db 100644 --- a/testsuite/generate-format/tests/staged/consensus.yaml +++ b/testsuite/generate-format/tests/staged/consensus.yaml @@ -424,6 +424,9 @@ DKGTranscriptMetadata: - epoch: U64 - author: TYPENAME: AccountAddress +DeprecatedPayload: + STRUCT: + - dummy_value: U64 Ed25519PublicKey: NEWTYPESTRUCT: BYTES Ed25519Signature: @@ -523,14 +526,6 @@ LedgerInfoWithV0: TYPENAME: LedgerInfo - signatures: TYPENAME: AggregateSignature -Module: - STRUCT: - - code: BYTES -ModuleBundle: - STRUCT: - - codes: - SEQ: - TYPENAME: Module ModuleId: STRUCT: - address: @@ -933,7 +928,7 @@ TransactionPayload: 1: ModuleBundle: NEWTYPE: - TYPENAME: ModuleBundle + TYPENAME: DeprecatedPayload 2: EntryFunction: NEWTYPE: diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index 2ebde083bfb66..ddc0ae23a9446 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -23,10 +23,10 @@ use crate::{ proof::TransactionInfoListWithProof, state_store::{state_key::StateKey, state_value::StateValue}, transaction::{ - ChangeSet, ExecutionStatus, Module, ModuleBundle, RawTransaction, Script, - SignatureCheckedTransaction, SignedTransaction, Transaction, TransactionArgument, - TransactionInfo, TransactionListWithProof, TransactionPayload, TransactionStatus, - TransactionToCommit, Version, WriteSetPayload, + ChangeSet, ExecutionStatus, Module, RawTransaction, Script, SignatureCheckedTransaction, + SignedTransaction, Transaction, TransactionArgument, TransactionInfo, + TransactionListWithProof, TransactionPayload, TransactionStatus, TransactionToCommit, + Version, WriteSetPayload, }, validator_info::ValidatorInfo, validator_signer::ValidatorSigner, @@ -367,15 +367,9 @@ fn new_raw_transaction( ) -> RawTransaction { let chain_id = ChainId::test(); match payload { - TransactionPayload::ModuleBundle(module) => RawTransaction::new_module_bundle( - sender, - sequence_number, - module, - max_gas_amount, - gas_unit_price, - expiration_time_secs, - chain_id, - ), + TransactionPayload::ModuleBundle(_) => { + unreachable!("Module bundle payload has been removed") + }, TransactionPayload::Script(script) => RawTransaction::new_script( sender, sequence_number, @@ -424,12 +418,6 @@ impl SignatureCheckedTransaction { Self::strategy_impl(keypair_strategy, TransactionPayload::script_strategy()) } - pub fn module_strategy( - keypair_strategy: impl Strategy>, - ) -> impl Strategy { - Self::strategy_impl(keypair_strategy, TransactionPayload::module_strategy()) - } - fn strategy_impl( keypair_strategy: impl Strategy>, payload_strategy: impl Strategy, @@ -484,6 +472,7 @@ impl Arbitrary for SignatureCheckedTransaction { type Strategy = BoxedStrategy; fn arbitrary_with(_args: ()) -> Self::Strategy { + // Right now only script transaction payloads are generated! Self::strategy_impl(ed25519::keypair_strategy(), any::()).boxed() } } @@ -504,11 +493,6 @@ impl TransactionPayload { pub fn script_strategy() -> impl Strategy { any::