diff --git a/Cargo.lock b/Cargo.lock index e9e5b1f2285f8..c1df85b78ca76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -593,15 +593,21 @@ dependencies = [ name = "aptos-gas" version = "0.1.0" dependencies = [ + "anyhow", "aptos-global-constants", "aptos-types", + "bcs", + "clap 3.2.17", "framework", "gas-algebra-ext", "move-binary-format", "move-core-types", + "move-model", "move-stdlib", "move-table-extension", "move-vm-types", + "package-builder", + "tempfile", ] [[package]] @@ -3338,6 +3344,7 @@ dependencies = [ "itertools", "language-e2e-tests", "move-deps", + "package-builder", "project-root", "proptest", "rand 0.7.3", @@ -6718,6 +6725,18 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "package-builder" +version = "0.1.0" +dependencies = [ + "anyhow", + "framework", + "itertools", + "move-command-line-common", + "move-package", + "tempfile", +] + [[package]] name = "parking" version = "2.0.0" diff --git a/Cargo.toml b/Cargo.toml index 6d2e5f7c2ab11..8e07535aa7289 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ members = [ "aptos-move/move-deps", "aptos-move/move-examples", "aptos-move/mvhashmap", + "aptos-move/package-builder", "aptos-move/parallel-executor", "aptos-move/vm-genesis", "aptos-move/writeset-transaction-generator", diff --git a/aptos-move/aptos-gas/Cargo.toml b/aptos-move/aptos-gas/Cargo.toml index 0b976e3bfd688..215cf8370a364 100644 --- a/aptos-move/aptos-gas/Cargo.toml +++ b/aptos-move/aptos-gas/Cargo.toml @@ -10,8 +10,13 @@ publish = false edition = "2021" [dependencies] +anyhow = "1.0.57" +bcs = "0.1.3" +clap = { version = "3.1.17", features = ["derive"] } + move-binary-format = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } move-core-types = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } +move-model = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } move-stdlib = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } move-table-extension = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } move-vm-types = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } @@ -20,6 +25,14 @@ aptos-global-constants = { path = "../../config/global-constants" } aptos-types = { path = "../../types" } framework = { path = "../framework" } gas-algebra-ext = { path = "../gas-algebra-ext" } +package-builder = { path = "../package-builder" } + +[dev-dependencies] +tempfile = "3.3.0" [features] testing = ["move-stdlib/testing", "aptos-global-constants/testing"] + +[[bin]] +name = "aptos-gas-gen-update-proposal" +path = "src/bin/gen_proposal.rs" diff --git a/aptos-move/aptos-gas/src/bin/gen_proposal.rs b/aptos-move/aptos-gas/src/bin/gen_proposal.rs new file mode 100644 index 0000000000000..ee42b1788d6be --- /dev/null +++ b/aptos-move/aptos-gas/src/bin/gen_proposal.rs @@ -0,0 +1,12 @@ +// Copyright (c) Aptos +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::Result; +use aptos_gas::gen::{generate_update_proposal, GenArgs}; +use clap::Parser; + +fn main() -> Result<()> { + let args = GenArgs::parse(); + + generate_update_proposal(&args) +} diff --git a/aptos-move/aptos-gas/src/gas_meter.rs b/aptos-move/aptos-gas/src/gas_meter.rs index 4230c077e4cc4..dd2dfbd09968f 100644 --- a/aptos-move/aptos-gas/src/gas_meter.rs +++ b/aptos-move/aptos-gas/src/gas_meter.rs @@ -21,6 +21,8 @@ use move_vm_types::{ }; use std::collections::BTreeMap; +pub const LATEST_GAS_FEATURE_VERSION: u64 = 1; + /// A trait for converting from a map representation of the on-chain gas schedule. pub trait FromOnChainGasSchedule: Sized { /// Constructs a value of this type from a map representation of the on-chain gas schedule. diff --git a/aptos-move/aptos-gas/src/gen.rs b/aptos-move/aptos-gas/src/gen.rs new file mode 100644 index 0000000000000..667c5ea045281 --- /dev/null +++ b/aptos-move/aptos-gas/src/gen.rs @@ -0,0 +1,125 @@ +// Copyright (c) Aptos +// SPDX-License-Identifier: Apache-2.0 + +use crate::gas_meter::{ + AptosGasParameters, InitialGasSchedule, ToOnChainGasSchedule, LATEST_GAS_FEATURE_VERSION, +}; +use anyhow::Result; +use aptos_types::on_chain_config::GasScheduleV2; +use clap::Parser; +use move_core_types::account_address::AccountAddress; +use move_model::{code_writer::CodeWriter, emit, emitln, model::Loc}; +use package_builder::PackageBuilder; +use std::path::{Path, PathBuf}; + +fn current_gas_schedule() -> GasScheduleV2 { + GasScheduleV2 { + feature_version: LATEST_GAS_FEATURE_VERSION, + entries: AptosGasParameters::initial().to_on_chain_gas_schedule(), + } +} + +fn generate_blob(writer: &CodeWriter, data: &[u8]) { + emitln!(writer, "vector["); + writer.indent(); + for (i, b) in data.iter().enumerate() { + if i % 20 == 0 { + if i > 0 { + emitln!(writer); + } + } else { + emit!(writer, " "); + } + emit!(writer, "{},", b); + } + emitln!(writer); + writer.unindent(); + emit!(writer, "]") +} + +fn generate_script(gas_schedule: &GasScheduleV2) -> Result { + let gas_schedule_blob = bcs::to_bytes(gas_schedule).unwrap(); + + assert!(gas_schedule_blob.len() < 65536); + + let writer = CodeWriter::new(Loc::default()); + emitln!(writer, "// Gas schedule upgrade proposal\n"); + + emitln!( + writer, + "// Feature version: {}", + gas_schedule.feature_version + ); + emitln!(writer, "//"); + emitln!(writer, "// Entries:"); + let max_len = gas_schedule + .entries + .iter() + .fold(0, |acc, (name, _)| usize::max(acc, name.len())); + for (name, val) in &gas_schedule.entries { + let name_with_spaces = format!("{}{}", name, " ".repeat(max_len - name.len())); + emitln!(writer, "// {} : {}", name_with_spaces, val); + } + emitln!(writer); + + emitln!(writer, "script {"); + writer.indent(); + + emitln!(writer, "use aptos_framework::aptos_governance;"); + emitln!(writer, "use aptos_framework::gas_schedule;"); + emitln!(writer); + + emitln!(writer, "fun main(proposal_id: u64) {"); + writer.indent(); + + emitln!( + writer, + "let framework_signer = aptos_governance::resolve(proposal_id, @{});\n", + AccountAddress::ONE, + ); + + emit!(writer, "let gas_schedule_blob: vector = "); + generate_blob(&writer, &gas_schedule_blob); + emitln!(writer, ";\n"); + + emitln!( + writer, + "gas_schedule::set_gas_schedule(&framework_signer, gas_schedule_blob);" + ); + + writer.unindent(); + emitln!(writer, "}"); + + writer.unindent(); + emitln!(writer, "}"); + + Ok(writer.process_result(|s| s.to_string())) +} + +fn aptos_framework_path() -> PathBuf { + Path::join( + Path::new(env!("CARGO_MANIFEST_DIR")), + "../framework/aptos-framework", + ) +} + +#[derive(Debug, Parser)] +pub struct GenArgs { + #[clap(short, long)] + pub output: Option, +} + +pub fn generate_update_proposal(args: &GenArgs) -> Result<()> { + let mut pack = PackageBuilder::new("GasScheduleUpdate"); + + pack.add_source( + "update_gas_schedule.move", + &generate_script(¤t_gas_schedule())?, + ); + // TODO: use relative path here + pack.add_local_dep("AptosFramework", &aptos_framework_path().to_string_lossy()); + + pack.write_to_disk(args.output.as_deref().unwrap_or("./proposal"))?; + + Ok(()) +} diff --git a/aptos-move/aptos-gas/src/lib.rs b/aptos-move/aptos-gas/src/lib.rs index 1a1f33a0c3ce1..8e26aaeab9d8a 100644 --- a/aptos-move/aptos-gas/src/lib.rs +++ b/aptos-move/aptos-gas/src/lib.rs @@ -27,6 +27,7 @@ mod params; mod algebra; mod aptos_framework; mod gas_meter; +pub mod gen; mod instr; mod misc; mod move_stdlib; @@ -36,7 +37,7 @@ mod transaction; pub use algebra::*; pub use gas_meter::{ AptosGasMeter, AptosGasParameters, FromOnChainGasSchedule, InitialGasSchedule, - NativeGasParameters, ToOnChainGasSchedule, + NativeGasParameters, ToOnChainGasSchedule, LATEST_GAS_FEATURE_VERSION, }; pub use instr::InstructionGasParameters; pub use misc::{AbstractValueSizeGasParameters, MiscGasParameters}; diff --git a/aptos-move/aptos-gas/tests/gen_tests.rs b/aptos-move/aptos-gas/tests/gen_tests.rs new file mode 100644 index 0000000000000..72f089e798c30 --- /dev/null +++ b/aptos-move/aptos-gas/tests/gen_tests.rs @@ -0,0 +1,17 @@ +// Copyright (c) Aptos +// SPDX-License-Identifier: Apache-2.0 + +use aptos_gas::gen::{generate_update_proposal, GenArgs}; +use framework::{BuildOptions, BuiltPackage}; + +#[test] +fn can_generate_and_build_update_proposal() { + let output_dir = tempfile::tempdir().unwrap(); + + generate_update_proposal(&GenArgs { + output: Some(output_dir.path().to_string_lossy().to_string()), + }) + .unwrap(); + + BuiltPackage::build(output_dir.path().to_path_buf(), BuildOptions::default()).unwrap(); +} diff --git a/aptos-move/e2e-move-tests/Cargo.toml b/aptos-move/e2e-move-tests/Cargo.toml index b71b557a9b9fd..64afe7190800c 100644 --- a/aptos-move/e2e-move-tests/Cargo.toml +++ b/aptos-move/e2e-move-tests/Cargo.toml @@ -31,6 +31,7 @@ aptos-types = { path = "../../types", features = ["fuzzing"] } aptos-vm = { path = "../aptos-vm", features = ["fuzzing"] } cached-packages = { path = "../framework/cached-packages" } framework = { path = "../framework" } +package-builder = { path = "../package-builder" } vm-genesis = { path = "../vm-genesis" } aptos-writeset-generator = { path = "../writeset-transaction-generator" } diff --git a/aptos-move/e2e-move-tests/src/lib.rs b/aptos-move/e2e-move-tests/src/lib.rs index 1ca919588f477..58436da85a992 100644 --- a/aptos-move/e2e-move-tests/src/lib.rs +++ b/aptos-move/e2e-move-tests/src/lib.rs @@ -3,7 +3,6 @@ pub mod aggregator; pub mod harness; -pub mod package_builder; pub mod stake; use anyhow::bail; diff --git a/aptos-move/e2e-move-tests/tests/code_publishing.rs b/aptos-move/e2e-move-tests/tests/code_publishing.rs index 11f485d64c211..ded869048f337 100644 --- a/aptos-move/e2e-move-tests/tests/code_publishing.rs +++ b/aptos-move/e2e-move-tests/tests/code_publishing.rs @@ -3,11 +3,11 @@ use aptos_types::account_address::AccountAddress; use aptos_types::on_chain_config::FeatureFlag; -use e2e_move_tests::package_builder::PackageBuilder; use e2e_move_tests::{assert_abort, assert_success, assert_vm_status, MoveHarness}; use framework::natives::code::{PackageRegistry, UpgradePolicy}; use move_deps::move_core_types::parser::parse_struct_tag; use move_deps::move_core_types::vm_status::StatusCode; +use package_builder::PackageBuilder; use rstest::rstest; use serde::{Deserialize, Serialize}; @@ -251,10 +251,7 @@ fn code_publishing_weak_dep_fail(#[case] features: Vec) { assert_success!(h.publish_package(&acc, weak_dir.path())); let mut normal = PackageBuilder::new("Package").with_policy(UpgradePolicy::compat()); - normal.add_dep(&format!( - "WeakPackage = {{ local = \"{}\" }}", - weak_dir.path().display() - )); + normal.add_local_dep("WeakPackage", &weak_dir.path().to_string_lossy()); normal.add_source( "normal", "module 0xcafe::normal { use 0xcafe::weak; public fun f() { weak::f() } }", @@ -278,10 +275,7 @@ fn code_publishing_arbitray_dep_different_address(#[case] features: Vec) { // pack2 has a higher policy and should not be able to depend on pack1 let mut pack2 = PackageBuilder::new("Package2").with_policy(UpgradePolicy::immutable()); - pack2.add_dep(&format!( - "Package1 = {{ local = \"{}\" }}", - pack1_dir.path().display() - )); + pack2.add_local_dep("Package1", &pack1_dir.path().to_string_lossy()); pack2.add_source( "m", "module 0xdeaf::m { use 0xcafe::m; public fun f() { m::f() } }", diff --git a/aptos-move/e2e-move-tests/tests/generate_upgrade_script.rs b/aptos-move/e2e-move-tests/tests/generate_upgrade_script.rs index 2b547d864677b..96ae45a7cde13 100644 --- a/aptos-move/e2e-move-tests/tests/generate_upgrade_script.rs +++ b/aptos-move/e2e-move-tests/tests/generate_upgrade_script.rs @@ -3,10 +3,10 @@ use crate::common::test_dir_path; use aptos_types::account_address::AccountAddress; -use e2e_move_tests::package_builder::PackageBuilder; use e2e_move_tests::MoveHarness; use framework::{BuildOptions, BuiltPackage, ReleasePackage}; use move_deps::move_package::compilation::package_layout::CompiledPackageLayout; +use package_builder::PackageBuilder; mod common; @@ -33,10 +33,10 @@ module 0x{}::test {{ let upgrade_dir = upgrade.write_to_temp().unwrap(); let mut proposal = PackageBuilder::new("Proposal"); - proposal.add_dep(&format!( - "AptosFramework = {{ local = \"{}\" }}", - test_dir_path("../../framework/aptos-framework").display() - )); + proposal.add_local_dep( + "AptosFramework", + &test_dir_path("../../framework/aptos-framework").to_string_lossy(), + ); let proposal_dir = proposal.write_to_temp().unwrap(); let upgrade_release = ReleasePackage::new( diff --git a/aptos-move/e2e-move-tests/tests/lazy_natives.rs b/aptos-move/e2e-move-tests/tests/lazy_natives.rs index 117848ca2c54e..db78a3b376570 100644 --- a/aptos-move/e2e-move-tests/tests/lazy_natives.rs +++ b/aptos-move/e2e-move-tests/tests/lazy_natives.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_types::account_address::AccountAddress; -use e2e_move_tests::package_builder::PackageBuilder; use e2e_move_tests::{assert_success, assert_vm_status, MoveHarness}; use move_deps::move_core_types::vm_status::StatusCode; +use package_builder::PackageBuilder; #[test] fn lazy_natives() { diff --git a/aptos-move/e2e-testsuite/src/tests/failed_transaction_tests.rs b/aptos-move/e2e-testsuite/src/tests/failed_transaction_tests.rs index d90df131bb890..cff018d675189 100644 --- a/aptos-move/e2e-testsuite/src/tests/failed_transaction_tests.rs +++ b/aptos-move/e2e-testsuite/src/tests/failed_transaction_tests.rs @@ -1,7 +1,9 @@ // Copyright (c) Aptos // SPDX-License-Identifier: Apache-2.0 -use aptos_gas::{AptosGasMeter, AptosGasParameters, StorageGasParameters}; +use aptos_gas::{ + AptosGasMeter, AptosGasParameters, StorageGasParameters, LATEST_GAS_FEATURE_VERSION, +}; use aptos_state_view::StateView; use aptos_types::{ transaction::ExecutionStatus, @@ -41,7 +43,7 @@ fn failed_transaction_cleanup_test() { let gas_params = AptosGasParameters::zeros(); let storage_gas_params = StorageGasParameters::zeros(); - let mut gas_meter = AptosGasMeter::new(vm_genesis::LATEST_GAS_FEATURE_VERSION, gas_params, Some(storage_gas_params), 10_000); + let mut gas_meter = AptosGasMeter::new(LATEST_GAS_FEATURE_VERSION, gas_params, Some(storage_gas_params), 10_000); // TYPE_MISMATCH should be kept and charged. let out1 = aptos_vm.failed_transaction_cleanup( diff --git a/aptos-move/package-builder/Cargo.toml b/aptos-move/package-builder/Cargo.toml new file mode 100644 index 0000000000000..f066caf0786af --- /dev/null +++ b/aptos-move/package-builder/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "package-builder" +version = "0.1.0" +authors = ["Aptos Labs "] +description = "Helper for building Move packages for tests" +repository = "https://github.com/aptos-labs/aptos-core" +homepage = "https://aptoslabs.com" +license = "Apache-2.0" +publish = false +edition = "2021" + +[dependencies] +anyhow = "1.0.57" +itertools = "0.10.0" +tempfile = "3.3.0" + +move-command-line-common = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } +move-package = { git = "https://github.com/move-language/move", rev = "0fe2e6ce5af811d68b8a995b7da3f4c4ecc485fa" } + +framework = { path = "../framework" } diff --git a/aptos-move/e2e-move-tests/src/package_builder.rs b/aptos-move/package-builder/src/lib.rs similarity index 74% rename from aptos-move/e2e-move-tests/src/package_builder.rs rename to aptos-move/package-builder/src/lib.rs index f29088ed30ffc..05b0aceb4997b 100644 --- a/aptos-move/e2e-move-tests/src/package_builder.rs +++ b/aptos-move/package-builder/src/lib.rs @@ -3,9 +3,9 @@ use framework::natives::code::UpgradePolicy; use itertools::Itertools; -use move_deps::move_command_line_common::files::MOVE_EXTENSION; -use move_deps::move_package::compilation::package_layout::CompiledPackageLayout; -use std::path::PathBuf; +use move_command_line_common::files::MOVE_EXTENSION; +use move_package::compilation::package_layout::CompiledPackageLayout; +use std::path::Path; use tempfile::{tempdir, TempDir}; /// A helper for building Move packages on-the-fly for testing. @@ -13,7 +13,7 @@ use tempfile::{tempdir, TempDir}; pub struct PackageBuilder { name: String, policy: UpgradePolicy, - deps: Vec, + deps: Vec<(String, String)>, aliases: Vec<(String, String)>, sources: Vec<(String, String)>, } @@ -33,8 +33,8 @@ impl PackageBuilder { Self { policy, ..self } } - pub fn add_dep(&mut self, dep: &str) { - self.deps.push(dep.to_string()) + pub fn add_local_dep(&mut self, name: &str, path: &str) { + self.deps.push((name.to_string(), path.to_string())) } pub fn add_alias(&mut self, name: &str, addr: &str) { @@ -45,7 +45,9 @@ impl PackageBuilder { self.sources.push((name.to_string(), src.to_string())) } - pub fn write_to_disk(self, path: PathBuf) -> anyhow::Result<()> { + pub fn write_to_disk(self, path: impl AsRef) -> anyhow::Result<()> { + let path = path.as_ref(); + let sources_path = path.join(CompiledPackageLayout::Sources.path()); std::fs::create_dir_all(&sources_path)?; std::fs::write( @@ -66,7 +68,10 @@ upgrade_policy = \"{}\" .into_iter() .map(|(k, v)| format!("{} = \"{}\"", k, v)) .join("\n"), - self.deps.into_iter().join("\n") + self.deps + .into_iter() + .map(|(name, dep_path)| format!("{} = {{ local = \"{}\" }}", name, dep_path)) + .join("\n") ), )?; for (name, src) in self.sources { @@ -77,7 +82,7 @@ upgrade_policy = \"{}\" pub fn write_to_temp(self) -> anyhow::Result { let dir = tempdir()?; - self.write_to_disk(dir.path().to_path_buf())?; + self.write_to_disk(dir.path())?; Ok(dir) } } diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 9caf27ba206b7..b6fc3597ffc96 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -325,8 +325,6 @@ fn exec_function( }); } -pub const LATEST_GAS_FEATURE_VERSION: u64 = 1; - fn initialize( session: &mut SessionExt, consensus_config: OnChainConsensusConfig, @@ -340,7 +338,7 @@ fn initialize( // We should get rid of it after we make another testnet release. let gas_schedule_blob = if use_gas_schedule_v2 { let gas_schedule = GasScheduleV2 { - feature_version: LATEST_GAS_FEATURE_VERSION, + feature_version: aptos_gas::LATEST_GAS_FEATURE_VERSION, entries: genesis_gas_params.to_on_chain_gas_schedule(), }; bcs::to_bytes(&gas_schedule).expect("Failure serializing genesis gas schedule")