diff --git a/Cargo.lock b/Cargo.lock index 04e8f76c7264c..a674973871a55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,8 +206,8 @@ dependencies = [ "aptos-debugger", "aptos-faucet-core", "aptos-framework", - "aptos-gas", "aptos-gas-profiling", + "aptos-gas-schedule", "aptos-genesis", "aptos-github-client", "aptos-global-constants", @@ -289,13 +289,13 @@ dependencies = [ "aptos-crypto", "aptos-language-e2e-tests", "aptos-state-view", + "aptos-table-natives", "aptos-types", "bcs 0.1.4", "better_any", "claims", "move-binary-format", "move-core-types", - "move-table-extension", "once_cell", "smallvec", ] @@ -312,7 +312,8 @@ dependencies = [ "aptos-config", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-meter", + "aptos-gas-schedule", "aptos-logger", "aptos-mempool", "aptos-metrics-core", @@ -1006,13 +1007,15 @@ version = "0.1.0" dependencies = [ "anyhow", "aptos-crypto", - "aptos-gas", + "aptos-gas-meter", "aptos-gas-profiling", + "aptos-gas-schedule", "aptos-logger", "aptos-memory-usage-tracker", "aptos-resource-viewer", "aptos-rest-client", "aptos-state-view", + "aptos-table-natives", "aptos-types", "aptos-validator-interface", "aptos-vm", @@ -1024,7 +1027,6 @@ dependencies = [ "move-compiler", "move-core-types", "move-resource-viewer", - "move-table-extension", "move-vm-runtime", "move-vm-test-utils", "tokio", @@ -1412,12 +1414,15 @@ dependencies = [ "anyhow", "aptos-aggregator", "aptos-crypto", - "aptos-gas", - "aptos-gas-algebra-ext", + "aptos-gas-algebra", + "aptos-gas-meter", + "aptos-gas-schedule", "aptos-language-e2e-tests", "aptos-move-stdlib", + "aptos-native-interface", "aptos-sdk-builder", "aptos-state-view", + "aptos-table-natives", "aptos-types", "aptos-vm", "ark-bls12-381", @@ -1434,6 +1439,7 @@ dependencies = [ "clap 4.3.5", "codespan-reporting", "curve25519-dalek", + "either", "flate2", "hex", "include_dir 0.7.2", @@ -1451,7 +1457,6 @@ dependencies = [ "move-prover", "move-prover-boogie-backend", "move-stackless-bytecode", - "move-table-extension", "move-unit-test", "move-vm-runtime", "move-vm-types", @@ -1526,12 +1531,21 @@ dependencies = [ ] [[package]] -name = "aptos-gas" +name = "aptos-gas-algebra" +version = "0.0.1" +dependencies = [ + "either", + "move-core-types", +] + +[[package]] +name = "aptos-gas-meter" version = "0.1.0" dependencies = [ "anyhow", "aptos-framework", - "aptos-gas-algebra-ext", + "aptos-gas-algebra", + "aptos-gas-schedule", "aptos-global-constants", "aptos-logger", "aptos-move-stdlib", @@ -1540,28 +1554,23 @@ dependencies = [ "aptos-vm-types", "bcs 0.1.4", "clap 4.3.5", + "either", "move-binary-format", "move-core-types", "move-model", - "move-table-extension", "move-vm-types", + "paste", "tempfile", ] -[[package]] -name = "aptos-gas-algebra-ext" -version = "0.0.1" -dependencies = [ - "move-core-types", -] - [[package]] name = "aptos-gas-profiling" version = "0.1.0" dependencies = [ "anyhow", "aptos-framework", - "aptos-gas", + "aptos-gas-algebra", + "aptos-gas-meter", "aptos-package-builder", "aptos-types", "inferno", @@ -1572,6 +1581,35 @@ dependencies = [ "smallvec", ] +[[package]] +name = "aptos-gas-schedule" +version = "0.1.0" +dependencies = [ + "aptos-gas-algebra", + "aptos-global-constants", + "aptos-types", + "either", + "move-core-types", + "move-vm-types", + "paste", +] + +[[package]] +name = "aptos-gas-schedule-updator" +version = "0.1.0" +dependencies = [ + "anyhow", + "aptos-framework", + "aptos-gas-schedule", + "aptos-package-builder", + "aptos-types", + "bcs 0.1.4", + "clap 4.3.5", + "move-core-types", + "move-model", + "tempfile", +] + [[package]] name = "aptos-genesis" version = "0.1.0" @@ -2025,16 +2063,20 @@ dependencies = [ "aptos-cached-packages", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-algebra", + "aptos-gas-meter", "aptos-gas-profiling", + "aptos-gas-schedule", "aptos-keygen", "aptos-memory-usage-tracker", "aptos-proptest-helpers", "aptos-state-view", + "aptos-table-natives", "aptos-types", "aptos-vm", "aptos-vm-genesis", "aptos-vm-logging", + "aptos-vm-types", "bcs 0.1.4", "goldenfile", "hex", @@ -2042,7 +2084,6 @@ dependencies = [ "move-command-line-common", "move-core-types", "move-ir-compiler", - "move-table-extension", "move-vm-types", "num_cpus", "once_cell", @@ -2104,7 +2145,8 @@ dependencies = [ name = "aptos-memory-usage-tracker" version = "0.1.0" dependencies = [ - "aptos-gas", + "aptos-gas-algebra", + "aptos-gas-meter", "aptos-types", "move-binary-format", "move-core-types", @@ -2193,7 +2235,7 @@ dependencies = [ name = "aptos-move-examples" version = "0.1.0" dependencies = [ - "aptos-gas", + "aptos-gas-schedule", "aptos-types", "aptos-vm", "clap 4.3.5", @@ -2210,7 +2252,10 @@ name = "aptos-move-stdlib" version = "0.1.1" dependencies = [ "anyhow", + "aptos-gas-schedule", + "aptos-native-interface", "dir-diff", + "either", "file_diff", "hex", "log", @@ -2258,6 +2303,20 @@ dependencies = [ "rayon", ] +[[package]] +name = "aptos-native-interface" +version = "0.1.0" +dependencies = [ + "aptos-gas-algebra", + "aptos-gas-schedule", + "aptos-types", + "move-binary-format", + "move-core-types", + "move-vm-runtime", + "move-vm-types", + "smallvec", +] + [[package]] name = "aptos-netcore" version = "0.1.0" @@ -2694,7 +2753,7 @@ dependencies = [ "aptos-build-info", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-schedule-updator", "aptos-genesis", "aptos-rest-client", "aptos-temppath", @@ -3162,6 +3221,24 @@ dependencies = [ "thiserror", ] +[[package]] +name = "aptos-table-natives" +version = "0.1.0" +dependencies = [ + "anyhow", + "aptos-gas-schedule", + "aptos-native-interface", + "aptos-types", + "better_any", + "move-binary-format", + "move-core-types", + "move-vm-runtime", + "move-vm-test-utils", + "move-vm-types", + "sha3 0.9.1", + "smallvec", +] + [[package]] name = "aptos-telemetry" version = "0.1.0" @@ -3305,7 +3382,7 @@ dependencies = [ "aptos-block-partitioner", "aptos-crypto", "aptos-executor-service", - "aptos-gas", + "aptos-gas-meter", "aptos-language-e2e-tests", "aptos-logger", "aptos-metrics-core", @@ -3406,7 +3483,7 @@ dependencies = [ "aptos-cached-packages", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-schedule", "aptos-language-e2e-tests", "aptos-state-view", "aptos-storage-interface", @@ -3445,7 +3522,6 @@ dependencies = [ "hex", "itertools", "move-core-types", - "move-table-extension", "num-derive", "num-traits 0.2.15", "once_cell", @@ -3515,7 +3591,9 @@ dependencies = [ "aptos-crypto", "aptos-crypto-derive", "aptos-framework", - "aptos-gas", + "aptos-gas-algebra", + "aptos-gas-meter", + "aptos-gas-schedule", "aptos-infallible", "aptos-language-e2e-tests", "aptos-logger", @@ -3523,7 +3601,9 @@ dependencies = [ "aptos-metrics-core", "aptos-move-stdlib", "aptos-mvhashmap", + "aptos-native-interface", "aptos-state-view", + "aptos-table-natives", "aptos-types", "aptos-utils", "aptos-vm-logging", @@ -3536,7 +3616,6 @@ dependencies = [ "move-bytecode-utils", "move-bytecode-verifier", "move-core-types", - "move-table-extension", "move-unit-test", "move-vm-runtime", "move-vm-test-utils", @@ -3577,11 +3656,12 @@ dependencies = [ "aptos-cached-packages", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-schedule", "aptos-proptest-helpers", "aptos-state-view", "aptos-types", "aptos-vm", + "aptos-vm-types", "bcs 0.1.4", "move-core-types", "move-vm-types", @@ -3613,8 +3693,11 @@ version = "0.1.0" dependencies = [ "anyhow", "aptos-cached-packages", + "aptos-gas-schedule", "aptos-language-e2e-tests", "aptos-move-stdlib", + "aptos-native-interface", + "aptos-table-natives", "aptos-types", "aptos-vm", "aptos-vm-genesis", @@ -3624,7 +3707,6 @@ dependencies = [ "move-binary-format", "move-core-types", "move-ir-compiler", - "move-table-extension", "move-vm-runtime", "move-vm-test-utils", "move-vm-types", @@ -3638,10 +3720,13 @@ version = "0.0.1" dependencies = [ "anyhow", "aptos-aggregator", + "aptos-gas-algebra", + "aptos-gas-schedule", "aptos-language-e2e-tests", "aptos-state-view", "aptos-types", "claims", + "either", "move-binary-format", "move-core-types", ] @@ -3655,7 +3740,8 @@ dependencies = [ "aptos-crypto", "aptos-db", "aptos-executor-test-helpers", - "aptos-gas", + "aptos-gas-meter", + "aptos-gas-schedule", "aptos-scratchpad", "aptos-state-view", "aptos-storage-interface", @@ -3692,10 +3778,11 @@ dependencies = [ "aptos-crypto", "aptos-crypto-derive", "aptos-framework", - "aptos-gas", + "aptos-gas-schedule", "aptos-state-view", "aptos-types", "aptos-vm", + "aptos-vm-types", "bcs 0.1.4", "handlebars", "move-command-line-common", @@ -5744,8 +5831,9 @@ dependencies = [ "aptos-cached-packages", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-algebra", "aptos-gas-profiling", + "aptos-gas-schedule", "aptos-keygen", "aptos-language-e2e-tests", "aptos-logger", @@ -7546,7 +7634,8 @@ dependencies = [ "aptos-cached-packages", "aptos-crypto", "aptos-framework", - "aptos-gas", + "aptos-gas-meter", + "aptos-gas-schedule", "aptos-keygen", "aptos-language-e2e-tests", "aptos-logger", @@ -7556,6 +7645,7 @@ dependencies = [ "aptos-vm", "aptos-vm-genesis", "aptos-vm-logging", + "aptos-vm-types", "aptos-writeset-generator", "bcs 0.1.4", "fail 0.5.0", @@ -11629,7 +11719,8 @@ dependencies = [ "aptos-faucet-core", "aptos-forge", "aptos-framework", - "aptos-gas", + "aptos-gas-algebra", + "aptos-gas-schedule", "aptos-genesis", "aptos-global-constants", "aptos-indexer", diff --git a/Cargo.toml b/Cargo.toml index 39ec40a446bda..092f1f75be5c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,9 +8,13 @@ members = [ "api/types", "aptos-move/aptos-aggregator", "aptos-move/aptos-debugger", - "aptos-move/aptos-gas", + "aptos-move/aptos-gas-algebra", + "aptos-move/aptos-gas-meter", "aptos-move/aptos-gas-profiling", + "aptos-move/aptos-gas-schedule", + "aptos-move/aptos-gas-schedule-updator", "aptos-move/aptos-memory-usage-tracker", + "aptos-move/aptos-native-interface", "aptos-move/aptos-release-builder", "aptos-move/aptos-resource-viewer", "aptos-move/aptos-sdk-builder", @@ -28,7 +32,7 @@ members = [ "aptos-move/e2e-testsuite", "aptos-move/framework", "aptos-move/framework/cached-packages", - "aptos-move/gas-algebra-ext", + "aptos-move/framework/table-natives", "aptos-move/move-examples", "aptos-move/mvhashmap", "aptos-move/package-builder", @@ -296,9 +300,11 @@ aptos-forge = { path = "testsuite/forge" } aptos-framework = { path = "aptos-move/framework" } aptos-fuzzer = { path = "testsuite/aptos-fuzzer" } fuzzer = { path = "testsuite/fuzzer" } -aptos-gas = { path = "aptos-move/aptos-gas" } -aptos-gas-algebra-ext = { path = "aptos-move/gas-algebra-ext" } +aptos-gas-meter = { path = "aptos-move/aptos-gas-meter" } +aptos-gas-algebra = { path = "aptos-move/aptos-gas-algebra" } aptos-gas-profiling = { path = "aptos-move/aptos-gas-profiling" } +aptos-gas-schedule = { path = "aptos-move/aptos-gas-schedule" } +aptos-gas-schedule-updator = { path = "aptos-move/aptos-gas-schedule-updator" } aptos-genesis = { path = "crates/aptos-genesis" } aptos-github-client = { path = "crates/aptos-github-client" } aptos-global-constants = { path = "config/global-constants" } @@ -328,6 +334,7 @@ aptos-metrics-core = { path = "crates/aptos-metrics-core" } aptos-move-examples = { path = "aptos-move/move-examples" } aptos-moving-average = { path = "crates/moving-average" } aptos-mvhashmap = { path = "aptos-move/mvhashmap" } +aptos-native-interface = { path = "aptos-move/aptos-native-interface" } aptos-netcore = { path = "network/netcore" } aptos-network = { path = "network" } aptos-network-builder = { path = "network/builder" } @@ -631,6 +638,7 @@ move-prover = { path = "third_party/move/move-prover" } move-prover-boogie-backend = { path = "third_party/move/move-prover/boogie-backend" } move-stackless-bytecode = { path = "third_party/move/move-prover/bytecode" } aptos-move-stdlib = { path = "aptos-move/framework/move-stdlib" } +aptos-table-natives = { path = "aptos-move/framework/table-natives" } move-prover-test-utils = { path = "third_party/move/move-prover/test-utils" } move-resource-viewer = { path = "third_party/move/tools/move-resource-viewer" } move-symbol-pool = { path = "third_party/move/move-symbol-pool" } diff --git a/api/Cargo.toml b/api/Cargo.toml index b0ad8e9bfb8b0..7d8e03995c6c4 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -18,7 +18,7 @@ aptos-api-types = { workspace = true } aptos-build-info = { workspace = true } aptos-config = { workspace = true } aptos-crypto = { workspace = true } -aptos-gas = { workspace = true } +aptos-gas-schedule = { workspace = true } aptos-logger = { workspace = true } aptos-mempool = { workspace = true } aptos-metrics-core = { workspace = true } @@ -52,7 +52,7 @@ url = { workspace = true } aptos-api-test-context = { workspace = true } aptos-cached-packages = { workspace = true } aptos-framework = { workspace = true } -aptos-gas = { workspace = true, features = ["testing"] } +aptos-gas-meter = { workspace = true, features = ["testing"] } aptos-proptest-helpers = { workspace = true } aptos-sdk = { workspace = true } move-package = { workspace = true } diff --git a/api/src/context.rs b/api/src/context.rs index d4347a19345b4..ad0954bb2577c 100644 --- a/api/src/context.rs +++ b/api/src/context.rs @@ -17,7 +17,7 @@ use aptos_api_types::{ }; use aptos_config::config::{NodeConfig, RoleType}; use aptos_crypto::HashValue; -use aptos_gas::{AptosGasParameters, FromOnChainGasSchedule}; +use aptos_gas_schedule::{AptosGasParameters, FromOnChainGasSchedule}; use aptos_logger::error; use aptos_mempool::{MempoolClientRequest, MempoolClientSender, SubmissionStatus}; use aptos_state_view::TStateView; @@ -1092,7 +1092,7 @@ impl Context { fn min_gas_unit_price(&self, ledger_info: &LedgerInfo) -> Result { let (_, gas_schedule) = self.get_gas_schedule(ledger_info)?; - Ok(gas_schedule.txn.min_price_per_gas_unit.into()) + Ok(gas_schedule.vm.txn.min_price_per_gas_unit.into()) } pub fn get_gas_schedule( diff --git a/api/src/transactions.rs b/api/src/transactions.rs index ac94edbcb66f9..8d2f6bde1cd2d 100644 --- a/api/src/transactions.rs +++ b/api/src/transactions.rs @@ -452,9 +452,9 @@ impl TransactionsApi { let estimated_max_gas_amount = if estimate_max_gas_amount.0.unwrap_or_default() { // Retrieve max possible gas units let (_, gas_params) = self.context.get_gas_schedule(&ledger_info)?; - let min_number_of_gas_units = u64::from(gas_params.txn.min_transaction_gas_units) - / u64::from(gas_params.txn.gas_unit_scaling_factor); - let max_number_of_gas_units = u64::from(gas_params.txn.maximum_number_of_gas_units); + let min_number_of_gas_units = u64::from(gas_params.vm.txn.min_transaction_gas_units) + / u64::from(gas_params.vm.txn.gas_unit_scaling_factor); + let max_number_of_gas_units = u64::from(gas_params.vm.txn.maximum_number_of_gas_units); // Retrieve account balance to determine max gas available let account_state = self diff --git a/aptos-move/aptos-aggregator/Cargo.toml b/aptos-move/aptos-aggregator/Cargo.toml index 08c67c7be1b8a..3ecb185cea6f7 100644 --- a/aptos-move/aptos-aggregator/Cargo.toml +++ b/aptos-move/aptos-aggregator/Cargo.toml @@ -16,12 +16,12 @@ rust-version = { workspace = true } anyhow = { workspace = true } aptos-crypto = { workspace = true } aptos-state-view = { workspace = true } +aptos-table-natives = { workspace = true } aptos-types = { workspace = true } bcs = { workspace = true } better_any = { workspace = true } move-binary-format = { workspace = true } move-core-types = { workspace = true } -move-table-extension = { workspace = true } once_cell = { workspace = true } smallvec = { workspace = true } diff --git a/aptos-move/aptos-aggregator/src/aggregator_extension.rs b/aptos-move/aptos-aggregator/src/aggregator_extension.rs index 5f9ec715b2309..8a654085b6005 100644 --- a/aptos-move/aptos-aggregator/src/aggregator_extension.rs +++ b/aptos-move/aptos-aggregator/src/aggregator_extension.rs @@ -2,10 +2,10 @@ // SPDX-License-Identifier: Apache-2.0 use crate::delta_change_set::{addition, deserialize, subtraction}; +use aptos_table_natives::{TableHandle, TableResolver}; use aptos_types::vm_status::StatusCode; use move_binary_format::errors::{PartialVMError, PartialVMResult}; use move_core_types::account_address::AccountAddress; -use move_table_extension::{TableHandle, TableResolver}; use std::collections::{BTreeMap, BTreeSet}; /// Describes the state of each aggregator instance. diff --git a/aptos-move/aptos-debugger/Cargo.toml b/aptos-move/aptos-debugger/Cargo.toml index de1dd8c28aa26..6af4d089526a2 100644 --- a/aptos-move/aptos-debugger/Cargo.toml +++ b/aptos-move/aptos-debugger/Cargo.toml @@ -12,13 +12,15 @@ edition = "2021" [dependencies] anyhow = { workspace = true } aptos-crypto = { workspace = true } -aptos-gas = { workspace = true } +aptos-gas-meter = { workspace = true } aptos-gas-profiling = { workspace = true } +aptos-gas-schedule = { workspace = true } aptos-logger = { workspace = true } aptos-memory-usage-tracker = { workspace = true } aptos-resource-viewer = { workspace = true } aptos-rest-client = { workspace = true } aptos-state-view = { workspace = true } +aptos-table-natives = { workspace = true } aptos-types = { workspace = true } aptos-validator-interface = { workspace = true } aptos-vm = { workspace = true } @@ -30,7 +32,6 @@ move-cli = { workspace = true } move-compiler = { workspace = true } move-core-types = { workspace = true } move-resource-viewer = { workspace = true } -move-table-extension = { workspace = true } move-vm-runtime = { workspace = true } move-vm-test-utils = { workspace = true } tokio = { workspace = true } diff --git a/aptos-move/aptos-debugger/src/lib.rs b/aptos-move/aptos-debugger/src/lib.rs index 7fbd9a6517922..462f334499356 100644 --- a/aptos-move/aptos-debugger/src/lib.rs +++ b/aptos-move/aptos-debugger/src/lib.rs @@ -2,11 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use anyhow::{format_err, Result}; -use aptos_gas::{ - AbstractValueSizeGasParameters, ChangeSetConfigs, NativeGasParameters, StandardGasMeter, - LATEST_GAS_FEATURE_VERSION, -}; +use aptos_gas_meter::{StandardGasAlgebra, StandardGasMeter}; use aptos_gas_profiling::{GasProfiler, TransactionGasLog}; +use aptos_gas_schedule::{MiscGasParameters, NativeGasParameters, LATEST_GAS_FEATURE_VERSION}; use aptos_memory_usage_tracker::MemoryTrackedGasMeter; use aptos_resource_viewer::{AnnotatedAccountStateBlob, AptosValueAnnotator}; use aptos_rest_client::Client; @@ -30,7 +28,7 @@ use aptos_vm::{ AptosVM, VMExecutor, }; use aptos_vm_logging::log_schema::AdapterLogSchema; -use aptos_vm_types::{change_set::VMChangeSet, output::VMOutput}; +use aptos_vm_types::{change_set::VMChangeSet, output::VMOutput, storage::ChangeSetConfigs}; use move_binary_format::errors::VMResult; use std::{path::Path, sync::Arc}; @@ -80,12 +78,13 @@ impl AptosDebugger { &txn, &log_context, |gas_feature_version, gas_params, storage_gas_params, balance| { - let gas_meter = MemoryTrackedGasMeter::new(StandardGasMeter::new( - gas_feature_version, - gas_params, - storage_gas_params, - balance, - )); + let gas_meter = + MemoryTrackedGasMeter::new(StandardGasMeter::new(StandardGasAlgebra::new( + gas_feature_version, + gas_params, + storage_gas_params, + balance, + ))); let gas_profiler = match txn.payload() { TransactionPayload::Script(_) => GasProfiler::new_script(gas_meter), TransactionPayload::EntryFunction(entry_func) => GasProfiler::new_function( @@ -229,7 +228,7 @@ impl AptosDebugger { let features = Features::fetch_config(&state_view_storage).unwrap_or_default(); let move_vm = MoveVmExt::new( NativeGasParameters::zeros(), - AbstractValueSizeGasParameters::zeros(), + MiscGasParameters::zeros(), LATEST_GAS_FEATURE_VERSION, ChainId::test().id(), features, diff --git a/aptos-move/gas-algebra-ext/Cargo.toml b/aptos-move/aptos-gas-algebra/Cargo.toml similarity index 78% rename from aptos-move/gas-algebra-ext/Cargo.toml rename to aptos-move/aptos-gas-algebra/Cargo.toml index 122e5f3854805..c7d2077281514 100644 --- a/aptos-move/gas-algebra-ext/Cargo.toml +++ b/aptos-move/aptos-gas-algebra/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "aptos-gas-algebra-ext" -description = "Gas Algebra Ext" +name = "aptos-gas-algebra" +description = "Aptos Gas Algebra" version = "0.0.1" # Workspace inherited keys @@ -13,4 +13,5 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] +either = { workspace = true } move-core-types = { workspace = true } diff --git a/aptos-move/aptos-gas-algebra/src/abstract_algebra.rs b/aptos-move/aptos-gas-algebra/src/abstract_algebra.rs new file mode 100644 index 0000000000000..046ff55699315 --- /dev/null +++ b/aptos-move/aptos-gas-algebra/src/abstract_algebra.rs @@ -0,0 +1,273 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +use either::Either; +use move_core_types::gas_algebra::{GasQuantity, UnitDiv}; +use std::{ + marker::PhantomData, + ops::{Add, Mul}, +}; + +/*************************************************************************************************** + * Gas Expression & Visitor + * + **************************************************************************************************/ +/// Trait representing an abstract expression that can be used to calculate some gas amount. +/// +/// It carries a type parameter `E`, indicating an environment in which the expression can be +/// evaluated/materialized. +pub trait GasExpression { + type Unit; + + /// Evaluates the expression within the given environment to a concrete number. + fn evaluate(&self, feature_version: u64, env: &E) -> GasQuantity; + + /// Traverse the expression in post-order using the given visitor. + /// See [`GasExpressionVisitor`] for details. + fn visit(&self, visitor: &mut impl GasExpressionVisitor); + + /// Performs a division on the unit of the expression. + /// + /// This is sometimes required if you want to multiply an amount by a certain count. + fn per(self) -> GasPerUnit + where + Self: Sized, + { + GasPerUnit { + inner: self, + phantom: PhantomData, + } + } +} + +/// An interface for performing post-order traversal of the tree structure of a gas expression. +/// +/// Alternatively, one could think that the callbacks are invoked following the Reverse Polish +/// notation of the expression. +/// +/// Here are a few examples: +/// - `1 + 2` +/// - `quantity(1)` +/// - `quantity(2)` +/// - `add()` +/// - `A + B * 50` +/// - `gas_param()` +/// - `gas_param()` +/// - `quantity(50)` +/// - `mul()` +/// - `add()` +pub trait GasExpressionVisitor { + fn add(&mut self); + + fn mul(&mut self); + + fn gas_param

(&mut self); + + fn quantity(&mut self, quantity: GasQuantity); + + fn per(&mut self); +} + +/*************************************************************************************************** + * Built-in Gas Expressions + * + **************************************************************************************************/ +/// Representing the addition of two gas expressions. +#[derive(Debug, Clone)] +pub struct GasAdd { + pub left: L, + pub right: R, +} + +/// Representing the multiplication of two gas expressions. +#[derive(Debug, Clone)] +pub struct GasMul { + pub left: L, + pub right: R, +} + +/// Representing a gas expression divided by a particular unit. +/// This is sometimes required for further multiplications. +#[derive(Debug, Clone)] +pub struct GasPerUnit { + pub inner: T, + phantom: PhantomData, +} + +/*************************************************************************************************** + * Gas Expression Impl + * + **************************************************************************************************/ +// Notation: +// E | T: U means T is a valid gas expression with unit U under environment E. + +// E | T: U +// --------- +// E | &T: U +impl GasExpression for &T +where + T: GasExpression, +{ + type Unit = T::Unit; + + #[inline] + fn evaluate(&self, feature_version: u64, env: &E) -> GasQuantity { + (*self).evaluate(feature_version, env) + } + + #[inline] + fn visit(&self, visitor: &mut impl GasExpressionVisitor) { + (*self).visit(visitor) + } +} + +// --------------------- +// E | GasQuantity: U +impl GasExpression for GasQuantity { + type Unit = U; + + #[inline] + fn evaluate(&self, _feature_version: u64, _env: &E) -> GasQuantity { + *self + } + + #[inline] + fn visit(&self, visitor: &mut impl GasExpressionVisitor) { + visitor.quantity(*self) + } +} + +// E | L: U, E | R: U +// ------------------- +// E | L + R: U +impl GasExpression for GasAdd +where + L: GasExpression, + R: GasExpression, +{ + type Unit = U; + + #[inline] + fn evaluate(&self, feature_version: u64, env: &E) -> GasQuantity { + self.left.evaluate(feature_version, env) + self.right.evaluate(feature_version, env) + } + + #[inline] + fn visit(&self, visitor: &mut impl GasExpressionVisitor) { + self.left.visit(visitor); + self.right.visit(visitor); + visitor.add(); + } +} + +// E | L: UL, E | R: UR, O = UL * UR +// ----------------------------------- +// E | L * R: O +impl GasExpression for GasMul +where + L: GasExpression, + R: GasExpression, + GasQuantity