Skip to content

Commit

Permalink
chore: benchmark updates, extrinsc type change
Browse files Browse the repository at this point in the history
- replaced `u32` with `u64` for the `gas_limit` parameter in all
  extrinsics
- updated benchmark tests trying to achieve similar gas cost for
  publishing modules and publishing bundles
- tiny fixes in assets/move-projects
  • Loading branch information
Rqnsom committed May 20, 2024
1 parent 553c0df commit 949af15
Show file tree
Hide file tree
Showing 18 changed files with 168 additions and 90 deletions.
2 changes: 1 addition & 1 deletion doc/gas-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ All internal MoveVM gas handling costs are defined in the same [gas schedule mod

Three main extrinsics interact with MoveVM, which stores its state within the Substrate storage:
- `publish_module`
- `publish_bundle`
- `publish_module_bundle`
- `execute`

All above extrinsics have a `gas_limit` argument which is used as an input to the `MoveVM`.
Expand Down
10 changes: 10 additions & 0 deletions pallet/src/assets/move-projects/basic_coin/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "basic_coin"
version = "0.0.0"

[dependencies]
MoveStdlib = { git = "https://github.com/eigerco/move-stdlib", rev = "main" }

[addresses]
std = "0x1"
CafeAccount = "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
68 changes: 68 additions & 0 deletions pallet/src/assets/move-projects/basic_coin/sources/BasicCoin.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/// This module defines a minimal Coin and Balance.
module CafeAccount::BasicCoin {
use std::signer;

/// Address of the owner of this module
const MODULE_OWNER: address = @CafeAccount;

/// Error codes
const ENOT_MODULE_OWNER: u64 = 0;
const EINSUFFICIENT_BALANCE: u64 = 1;
const EALREADY_HAS_BALANCE: u64 = 2;

struct Coin has store {
value: u64
}

/// Struct representing the balance of each address.
struct Balance has key {
coin: Coin
}

/// Publish an empty balance resource under `account`'s address. This function must be called before
/// minting or transferring to the account.
/// Making this function entry allows to call it directly in the transactions
entry public fun publish_balance(account: &signer) {
let empty_coin = Coin { value: 0 };
assert!(!exists<Balance>(signer::address_of(account)), EALREADY_HAS_BALANCE);
move_to(account, Balance { coin: empty_coin });
}

/// Mint `amount` tokens to `mint_addr`. Mint must be approved by the module owner.
public fun mint(module_owner: &signer, mint_addr: address, amount: u64) acquires Balance {
// Only the owner of the module can initialize this module
assert!(signer::address_of(module_owner) == MODULE_OWNER, ENOT_MODULE_OWNER);

// Deposit `amount` of tokens to `mint_addr`'s balance
deposit(mint_addr, Coin { value: amount });
}

/// Returns the balance of `owner`.
public fun balance_of(owner: address): u64 acquires Balance {
borrow_global<Balance>(owner).coin.value
}

/// Transfers `amount` of tokens from `from` to `to`.
public fun transfer(from: &signer, to: address, amount: u64) acquires Balance {
let check = withdraw(signer::address_of(from), amount);
deposit(to, check);
}

/// Withdraw `amount` number of tokens from the balance under `addr`.
fun withdraw(addr: address, amount: u64) : Coin acquires Balance {
let balance = balance_of(addr);
// balance must be greater than the withdraw amount
assert!(balance >= amount, EINSUFFICIENT_BALANCE);
let balance_ref = &mut borrow_global_mut<Balance>(addr).coin.value;
*balance_ref = balance - amount;
Coin { value: amount }
}

/// Deposit `amount` number of tokens to the balance under `addr`.
fun deposit(addr: address, check: Coin) acquires Balance {
let balance = balance_of(addr);
let balance_ref = &mut borrow_global_mut<Balance>(addr).coin.value;
let Coin { value } = check;
*balance_ref = balance + value;
}
}
15 changes: 15 additions & 0 deletions pallet/src/assets/move-projects/basic_coin/sources/GetCoin.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
script {
use CafeAccount::BasicCoin;

fun publish_balance(s: signer) {
BasicCoin::publish_balance(&s);
}
}

script {
use CafeAccount::BasicCoin;

fun mint_some(module_owner: signer, rx_addr: address, amount: u64) {
BasicCoin::mint(&module_owner, rx_addr, amount);
}
}
2 changes: 1 addition & 1 deletion pallet/src/assets/move-projects/car-wash-example/build.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh
cd $(dirname $0)
# Build the project
smove build
smove bundle
# Create all Script-Transactions
smove create-transaction --compiled-script-path build/car-wash-example/bytecode_scripts/initial_coin_minting.mv --args signer:5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty
smove create-transaction --compiled-script-path build/car-wash-example/bytecode_scripts/register_new_user.mv --args signer:5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
Expand Down
2 changes: 1 addition & 1 deletion pallet/src/assets/move-projects/multiple-signers/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ALICE=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
DAVE=5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy
EVE=5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw
# Build the Move sources.
smove build
smove bundle
# Generate script-transactions.
# 1. init_module(Bob)
smove create-transaction --compiled-script-path build/multiple-signers/bytecode_scripts/init_module.mv --args signer:$BOB
Expand Down
18 changes: 16 additions & 2 deletions pallet/src/assets/move-projects/smove-build-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,21 @@ build_dir=(
"signer-scripts"
)
bundle_dir=(
"developer-bundle",
"prohibited-bundle"
"testing-move-stdlib"
"testing-substrate-stdlib"
"using_stdlib_natives"

"car-wash-example"
"multiple-signers"
"base58_smove_build"
"basic_coin"
)


# Info for the below actions:
# If the script needs to be bundled, it should be done in build.sh script if one exists.

# Build simple packages
for dir in "${build_dir[@]}"; do
echo $dir
Expand All @@ -36,5 +44,11 @@ done
# Build bundles
for dir in "${bundle_dir[@]}"; do
echo $dir
smove bundle -p $dir
build_script=$dir"/build.sh"
if [ -f "$build_script" ];
then
sh $build_script
else
smove bundle -p $dir
fi
done
52 changes: 38 additions & 14 deletions pallet/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
use frame_benchmarking::v2::*;
use frame_system::{Config as SysConfig, RawOrigin};
use move_vm_backend::types::MAX_GAS_AMOUNT;
use pallet_balances::{Config as BalancesConfig, Pallet as Balances};
use sp_core::crypto::Ss58Codec;

use crate::{mock_utils as utils, *};

const LIMIT: u128 = 60_000_000_000_000;

const MAX_GAS_AMOUNT: u32 = u32::MAX;

type SourceOf<T> = <<T as SysConfig>::Lookup as sp_runtime::traits::StaticLookup>::Source;

#[benchmarks(
Expand Down Expand Up @@ -151,12 +152,12 @@ mod benchmarks {
let bob_32 = utils::account::<T>(utils::BOB_ADDR);

let module_bcs = [
move_basics_module().to_vec(),
using_stdlib_natives_module().to_vec(),
multiple_signers_module().to_vec(),
car_wash_example_module().to_vec(),
base58_smove_build_module().to_vec(),
basic_coin_module().to_vec(),
];
let gas = [101, 325, 661, 732];
let gas = [661, 732, 100, 576];

#[extrinsic_call]
publish_module(
Expand All @@ -171,11 +172,12 @@ mod benchmarks {
let bob_32 = utils::account::<T>(utils::BOB_ADDR);

let bundles = [
core::include_bytes!("assets/move-projects/using_stdlib_natives/build/using_stdlib_natives/bundles/using_stdlib_natives.mvb").to_vec(),
core::include_bytes!("assets/move-projects/developer-bundle/build/developer-bundle/bundles/developer-bundle.mvb").to_vec(),
multiple_signers_module_as_bundle().to_vec(),
car_wash_example_module_as_bundle().to_vec(),
base58_smove_build_module_as_bundle().to_vec(),
basic_coin_module_as_bundle().to_vec(),
];

let gas = [528, 1500];
let gas = [664, 735, 102, 579];

#[extrinsic_call]
publish_module_bundle(
Expand Down Expand Up @@ -223,16 +225,28 @@ mod benchmarks {
use benchmark_only::*;

mod benchmark_only {
// Move Basics Example
pub fn move_basics_module() -> &'static [u8] {
// Base58 build example
pub fn base58_smove_build_module() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/base58_smove_build/build/base58_smove_build/bytecode_modules/BobBase58.mv"
)
}
pub fn base58_smove_build_module_as_bundle() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/move-basics/build/move-basics/bytecode_modules/EmptyBob.mv"
"assets/move-projects/base58_smove_build/build/base58_smove_build/bundles/base58_smove_build.mvb"
)
}

// Using Stdlib Natives Example
pub fn using_stdlib_natives_module() -> &'static [u8] {
core::include_bytes!("assets/move-projects/using_stdlib_natives/build/using_stdlib_natives/bytecode_modules/Vector.mv")
// basic_coin example
pub fn basic_coin_module() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/basic_coin/build/basic_coin/bytecode_modules/BasicCoin.mv"
)
}
pub fn basic_coin_module_as_bundle() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/basic_coin/build/basic_coin/bundles/basic_coin.mvb"
)
}

// Car Wash Example
Expand All @@ -241,6 +255,11 @@ mod benchmark_only {
"assets/move-projects/car-wash-example/build/car-wash-example/bytecode_modules/CarWash.mv"
)
}
pub fn car_wash_example_module_as_bundle() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/car-wash-example/build/car-wash-example/bundles/car-wash-example.mvb"
)
}

pub fn car_wash_initial_coin_miniting() -> &'static [u8] {
core::include_bytes!("assets/move-projects/car-wash-example/build/car-wash-example/script_transactions/initial_coin_minting.mvt")
Expand Down Expand Up @@ -268,6 +287,11 @@ mod benchmark_only {
"assets/move-projects/multiple-signers/build/multiple-signers/bytecode_modules/Dorm.mv"
)
}
pub fn multiple_signers_module_as_bundle() -> &'static [u8] {
core::include_bytes!(
"assets/move-projects/multiple-signers/build/multiple-signers/bundles/multiple-signers.mvb"
)
}

pub fn multiple_signers_init_module() -> &'static [u8] {
core::include_bytes!("assets/move-projects/multiple-signers/build/multiple-signers/script_transactions/init_module.mvt")
Expand Down
30 changes: 12 additions & 18 deletions pallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,20 @@ pub mod pallet {
#[pallet::call]
impl<T: Config> Pallet<T> {
/// Execute Move script transaction sent by the user.
// TODO(eiger) in M3: ensure the weight depends on basic extrinsic cost + gas_limit + size of the
// transaction_bc.
#[pallet::call_index(0)]
#[pallet::weight(T::WeightInfo::execute(*gas_limit as u32))]
#[pallet::weight(T::WeightInfo::execute(*gas_limit))]
pub fn execute(
origin: OriginFor<T>,
transaction_bc: Vec<u8>,
gas_limit: u64,
gas_limit: u32,
cheque_limit: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
// A signer for the extrinsic and a signer for the Move script.
let who = ensure_signed(origin)?;

// We use gas in order to prevent infinite scripts from breaking the MoveVM.
let gas_amount = GasAmount::new(gas_limit).map_err(|_| Error::<T>::GasLimitExceeded)?;
let gas_amount =
GasAmount::new(gas_limit.into()).map_err(|_| Error::<T>::GasLimitExceeded)?;
let gas = GasStrategy::Metered(gas_amount);

// Main input for the VM are these script parameters.
Expand Down Expand Up @@ -320,8 +319,6 @@ pub mod pallet {

// If we have multiple signers and they all have signed, we have to remove the multi-signer request from the MultisigStorage.
if let Some(script_hash) = contains_multisig {
// TODO: Consider remove the entry from the ChoreOnIdleStorage in the future. Not
// cleaning it shall cause no harm.
MultisigStorage::<T>::remove(script_hash);
}

Expand Down Expand Up @@ -352,19 +349,19 @@ pub mod pallet {

/// Publish a Move module sent by the user.
/// Module is published under its sender's address.
// TODO(eiger) in M3: ensure the weight depends on basic extrinsic cost + gas_limit
#[pallet::call_index(1)]
#[pallet::weight(T::WeightInfo::publish_module(*gas_limit as u32))]
#[pallet::weight(T::WeightInfo::publish_module(*gas_limit))]
pub fn publish_module(
origin: OriginFor<T>,
bytecode: Vec<u8>,
gas_limit: u64,
gas_limit: u32,
) -> DispatchResultWithPostInfo {
// Allow only signed calls.
let who = ensure_signed(origin)?;
let address = Self::to_move_address(&who)?;

let gas_amount = GasAmount::new(gas_limit).map_err(|_| Error::<T>::GasLimitExceeded)?;
let gas_amount =
GasAmount::new(gas_limit.into()).map_err(|_| Error::<T>::GasLimitExceeded)?;
let gas = GasStrategy::Metered(gas_amount);

let vm_result = Self::raw_publish_module(&address, bytecode, gas)?;
Expand All @@ -381,18 +378,18 @@ pub mod pallet {
/// Publish a Move bundle sent by the user.
///
/// Bundle is just a set of multiple modules.
// TODO(eiger) in M3: ensure the weight depends on basic extrinsic cost + gas_limit
#[pallet::call_index(2)]
#[pallet::weight(T::WeightInfo::publish_module_bundle(*gas_limit as u32))]
#[pallet::weight(T::WeightInfo::publish_module_bundle(*gas_limit))]
pub fn publish_module_bundle(
origin: OriginFor<T>,
bundle: Vec<u8>,
gas_limit: u64,
gas_limit: u32,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let address = Self::to_move_address(&who)?;

let gas_amount = GasAmount::new(gas_limit).map_err(|_| Error::<T>::GasLimitExceeded)?;
let gas_amount =
GasAmount::new(gas_limit.into()).map_err(|_| Error::<T>::GasLimitExceeded)?;
let gas = GasStrategy::Metered(gas_amount);

let vm_result = Self::raw_publish_bundle(&address, bundle, gas)?;
Expand Down Expand Up @@ -522,7 +519,6 @@ pub mod pallet {
) -> Result<Option<ModuleAbi>, Vec<u8>> {
let vm = Self::move_vm()?;

// TODO: Return a normal message to the RPC caller
let address = Self::to_move_address(address).map_err(|_| vec![])?;

vm.get_module_abi(address, name)
Expand All @@ -532,7 +528,6 @@ pub mod pallet {
pub fn get_module(address: &T::AccountId, name: &str) -> Result<Option<Vec<u8>>, Vec<u8>> {
let vm = Self::move_vm()?;

// TODO: Return a normal message to the RPC caller
let address = Self::to_move_address(address).map_err(|_| vec![])?;

vm.get_module(address, name)
Expand All @@ -544,7 +539,6 @@ pub mod pallet {
tag: &[u8],
) -> Result<Option<Vec<u8>>, Vec<u8>> {
let vm = Self::move_vm()?;
// TODO: Return a normal message to the RPC caller
let address = Self::to_move_address(account).map_err(|_| vec![])?;

vm.get_resource(&address, tag)
Expand Down
3 changes: 3 additions & 0 deletions pallet/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ pub use move_core_types::account_address::AccountAddress;
pub use move_vm_backend_common::types::ScriptTransaction;
pub use sp_runtime::AccountId32;

// Internally, within move-vm-backend, the gas is of type u64 and the maximum value is even greater.
pub const MAX_GAS_AMOUNT: u32 = u32::MAX;

// Primitive type definitions for this mockup.
pub type Balance = u128;
pub type Block = frame_system::mocking::MockBlock<Test>;
Expand Down
2 changes: 1 addition & 1 deletion pallet/src/tests/balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
};

use frame_support::assert_ok;
use move_vm_backend::{balance::BalanceHandler, types::MAX_GAS_AMOUNT};
use move_vm_backend::balance::BalanceHandler;

#[test]
fn verify_get_balance() {
Expand Down
Loading

0 comments on commit 949af15

Please sign in to comment.