Skip to content

Commit

Permalink
Implementation of the gas schedule upgrade (#2290)
Browse files Browse the repository at this point in the history
* Implementation of the gas schedule upgrade

* cargo clippy

* use wrapped move function calling method

* remove unused codes
  • Loading branch information
steelgeek091 authored Jul 26, 2024
1 parent 3063872 commit 15d75d9
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 2 deletions.
56 changes: 55 additions & 1 deletion crates/rooch-genesis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use anyhow::{ensure, Result};
use framework_builder::stdlib_version::StdlibVersion;
use framework_builder::Stdlib;
use include_dir::{include_dir, Dir};
use move_core_types::gas_algebra::{InternalGas, InternalGasPerArg};
use move_core_types::value::MoveTypeLayout;
use move_core_types::{account_address::AccountAddress, identifier::Identifier};
use move_vm_runtime::native_functions::NativeFunction;
Expand Down Expand Up @@ -54,6 +55,9 @@ pub static ROOCH_LOCAL_GENESIS: Lazy<RoochGenesis> = Lazy::new(|| {
network.set_sequencer_account(sequencer_account);
RoochGenesis::build(network).expect("build rooch genesis failed")
});
pub const LATEST_GAS_SCHEDULE_VERSION: u64 = GAS_SCHEDULE_RELEASE_V1;
// update the gas config for function calling
pub const GAS_SCHEDULE_RELEASE_V1: u64 = 1;

pub(crate) const STATIC_GENESIS_DIR: Dir = include_dir!("released");

Expand Down Expand Up @@ -92,6 +96,48 @@ impl FrameworksGasParameters {
}
}

pub fn latest() -> Self {
let mut gas_parameter = Self {
max_gas_amount: GasScheduleConfig::INITIAL_MAX_GAS_AMOUNT,
vm_gas_params: VMGasParameters::initial(),
rooch_framework_gas_params: rooch_framework::natives::NativeGasParameters::initial(),
bitcoin_move_gas_params: bitcoin_move::natives::GasParameters::initial(),
};

if LATEST_GAS_SCHEDULE_VERSION >= GAS_SCHEDULE_RELEASE_V1 {
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_base = InternalGas::new(167);
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_per_arg = InternalGasPerArg::new(15);
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_per_local = InternalGasPerArg::new(15);
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_generic_base = InternalGas::new(167);
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_generic_per_arg = InternalGasPerArg::new(15);
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_generic_per_local = InternalGasPerArg::new(15);
gas_parameter
.vm_gas_params
.instruction_gas_parameter
.call_generic_per_ty_arg = InternalGasPerArg::new(15);
}

gas_parameter
}

pub fn to_gas_schedule_config(&self) -> GasScheduleConfig {
let mut entries = self.vm_gas_params.to_on_chain_gas_schedule();
entries.extend(self.rooch_framework_gas_params.to_on_chain_gas_schedule());
Expand Down Expand Up @@ -201,7 +247,15 @@ impl RoochGenesis {
.clone()
.into_moveos_transaction(ObjectMeta::genesis_root());

let gas_parameter = FrameworksGasParameters::initial();
let gas_parameter = {
if network.chain_id == BuiltinChainID::Dev.chain_id()
|| network.chain_id == BuiltinChainID::Local.chain_id()
{
FrameworksGasParameters::latest()
} else {
FrameworksGasParameters::initial()
}
};
let gas_config = gas_parameter.to_gas_schedule_config();
genesis_moveos_tx.ctx.add(genesis_ctx.clone())?;
genesis_moveos_tx.ctx.add(moveos_genesis_ctx.clone())?;
Expand Down
12 changes: 12 additions & 0 deletions crates/rooch-types/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,18 @@ pub enum RoochError {
#[error("Invalid sequencer or proposer or relayer key pair")]
InvalidSequencerOrProposerOrRelayerKeyPair,

#[error("The local gas_config version {0} is lower than the onchain version {1}")]
InvalidLocalGasVersion(u64, u64),

#[error("The content length of local gas schedule is less")]
LessLocalGasScheduleLength,

#[error("The content of local gas schedule must be subset of onchain gas schedule")]
LocalIncorrectGasSchedule,

#[error("The onchain gas schedule is empty.")]
OnchainGasScheduleIsEmpty,

#[error("VM error: {0}")]
VMError(VMError),
}
Expand Down
1 change: 1 addition & 0 deletions crates/rooch/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ pub mod session_key;
pub mod state;
pub mod statedb;
pub mod transaction;
pub mod upgrade;
4 changes: 4 additions & 0 deletions crates/rooch/src/commands/upgrade/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

pub mod upgrade_gas_config;
176 changes: 176 additions & 0 deletions crates/rooch/src/commands/upgrade/commands/upgrade_gas_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use std::collections::BTreeMap;

use async_trait::async_trait;
use move_core_types::identifier::Identifier;
use move_core_types::language_storage::ModuleId;

use framework_types::addresses::ROOCH_FRAMEWORK_ADDRESS;
use moveos_types::module_binding::MoveFunctionCaller;
use moveos_types::move_types::FunctionId;
use moveos_types::state::MoveState;
use moveos_types::transaction::MoveAction;
use rooch_framework::natives::gas_parameter::gas_member::ToOnChainGasSchedule;
use rooch_genesis::{FrameworksGasParameters, LATEST_GAS_SCHEDULE_VERSION};
use rooch_rpc_api::jsonrpc_types::ExecuteTransactionResponseView;
use rooch_types::error::{RoochError, RoochResult};
use rooch_types::transaction::RoochTransaction;

use crate::cli_types::{CommandAction, TransactionOptions, WalletContextOptions};

/// Upgrade the onchain gas config
#[derive(Debug, clap::Parser)]
pub struct UpgradeGasConfigCommand {
#[clap(flatten)]
pub(crate) context_options: WalletContextOptions,

#[clap(flatten)]
tx_options: TransactionOptions,
}

#[async_trait]
impl CommandAction<ExecuteTransactionResponseView> for UpgradeGasConfigCommand {
async fn execute(self) -> RoochResult<ExecuteTransactionResponseView> {
let context = self.context_options.build_require_password()?;

let client = context.get_client().await?;
let gas_schedule_module =
client.as_module_binding::<moveos_types::moveos_std::gas_schedule::GasScheduleModule>();
let gas_schedule_opt = gas_schedule_module.gas_schedule();

let onchain_gas_schedule = match gas_schedule_opt {
Ok(gas_schedule) => {
let mut entries_map = BTreeMap::new();
let _: Vec<_> = gas_schedule
.entries
.iter()
.map(|gas_entry| entries_map.insert(gas_entry.key.to_string(), gas_entry.val))
.collect();
Some((gas_schedule.schedule_version, entries_map))
}
_ => None,
};

let local_latest_gas_parameters = FrameworksGasParameters::latest();

match onchain_gas_schedule {
None => {
return Err(RoochError::OnchainGasScheduleIsEmpty);
}
Some((onchain_gas_schedule_version, onchain_gas_schedule_map)) => {
let mut local_gas_entries = local_latest_gas_parameters
.vm_gas_params
.to_on_chain_gas_schedule();
local_gas_entries.extend(
local_latest_gas_parameters
.rooch_framework_gas_params
.to_on_chain_gas_schedule(),
);
local_gas_entries.extend(
local_latest_gas_parameters
.bitcoin_move_gas_params
.to_on_chain_gas_schedule(),
);

if LATEST_GAS_SCHEDULE_VERSION < onchain_gas_schedule_version {
return Err(RoochError::InvalidLocalGasVersion(
LATEST_GAS_SCHEDULE_VERSION,
onchain_gas_schedule_version,
));
}

let local_gas_schedule_map: BTreeMap<String, u64> =
local_gas_entries.into_iter().collect();

if local_gas_schedule_map.len() < onchain_gas_schedule_map.len() {
return Err(RoochError::LessLocalGasScheduleLength);
}

for (gas_key, _) in onchain_gas_schedule_map.iter() {
match local_gas_schedule_map.get(gas_key) {
None => {
return Err(RoochError::LocalIncorrectGasSchedule);
}
Some(_) => {}
}
}

let mut modified_gas_entries = Vec::new();
let mut added_gas_entries = Vec::new();

for (gas_key, gas_value) in local_gas_schedule_map.iter() {
match onchain_gas_schedule_map.get(gas_key) {
None => added_gas_entries.push((gas_key.clone(), *gas_value)),
Some(onchain_gas_value) => {
if *onchain_gas_value != *gas_value {
modified_gas_entries.push((gas_key.clone(), *gas_value))
}
}
}
}

if !added_gas_entries.is_empty() {
println!(
"Found {:} new gas entries that need to be upgraded:",
added_gas_entries.len()
);
for (gas_key, gas_value) in added_gas_entries.iter() {
println!("new gas: {:}, value: {:}", gas_key, gas_value);
}
}

if !modified_gas_entries.is_empty() {
println!(
"Found {:} modified gas entries that need to be upgraded:",
modified_gas_entries.len()
);
for (gas_key, gas_value) in modified_gas_entries.iter() {
println!("modified gas: {:}, value: {:}", gas_key, gas_value);
}
}

(onchain_gas_schedule_version, onchain_gas_schedule_map)
}
};

let latest_gas_schedule = local_latest_gas_parameters.to_gas_schedule_config();
let gas_schedule_bytes = latest_gas_schedule
.to_move_value()
.simple_serialize()
.unwrap();

let args = vec![bcs::to_bytes(&gas_schedule_bytes).unwrap()];

let action = MoveAction::new_function_call(
FunctionId::new(
ModuleId::new(
ROOCH_FRAMEWORK_ADDRESS,
Identifier::new("upgrade".to_owned()).unwrap(),
),
Identifier::new("upgrade_gas_schedule".to_owned()).unwrap(),
),
vec![],
args,
);

let sender = context.resolve_address(self.tx_options.sender)?.into();
let max_gas_amount: Option<u64> = self.tx_options.max_gas_amount;

match self.tx_options.authenticator {
Some(authenticator) => {
let tx_data = context
.build_tx_data(sender, action, max_gas_amount)
.await?;
let tx = RoochTransaction::new(tx_data, authenticator.into());
context.execute(tx).await
}
None => {
context
.sign_and_execute(sender, action, context.get_password(), max_gas_amount)
.await
}
}
}
}
32 changes: 32 additions & 0 deletions crates/rooch/src/commands/upgrade/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use crate::cli_types::CommandAction;
use crate::commands::upgrade::commands::upgrade_gas_config::UpgradeGasConfigCommand;

use async_trait::async_trait;
use clap::{Parser, Subcommand};
use rooch_types::error::RoochResult;

pub mod commands;

/// Tool for interacting with system upgrade
#[derive(Parser)]
pub struct Upgrade {
#[clap(subcommand)]
cmd: UpgradeCommand,
}

#[async_trait]
impl CommandAction<String> for Upgrade {
async fn execute(self) -> RoochResult<String> {
match self.cmd {
UpgradeCommand::UpgradeGasConfig(cmd) => cmd.execute_serialized().await,
}
}
}

#[derive(Subcommand)]
pub enum UpgradeCommand {
UpgradeGasConfig(UpgradeGasConfigCommand),
}
4 changes: 3 additions & 1 deletion crates/rooch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use cli_types::CommandAction;
use commands::{
abi::ABI, account::Account, env::Env, genesis::Genesis, init::Init, move_cli::MoveCli,
object::ObjectCommand, resource::ResourceCommand, rpc::Rpc, server::Server,
session_key::SessionKey, state::StateCommand, transaction::Transaction,
session_key::SessionKey, state::StateCommand, transaction::Transaction, upgrade::Upgrade,
};
use once_cell::sync::Lazy;
use rooch_types::error::RoochResult;
Expand Down Expand Up @@ -55,6 +55,7 @@ pub enum Command {
Statedb(Statedb),
Indexer(Indexer),
Genesis(Genesis),
Upgrade(Upgrade),
}

pub async fn run_cli(opt: RoochCli) -> RoochResult<String> {
Expand All @@ -75,5 +76,6 @@ pub async fn run_cli(opt: RoochCli) -> RoochResult<String> {
Command::Statedb(statedb) => statedb.execute().await,
Command::Indexer(indexer) => indexer.execute().await,
Command::Genesis(genesis) => genesis.execute().await,
Command::Upgrade(upgrade) => upgrade.execute().await,
}
}
13 changes: 13 additions & 0 deletions frameworks/rooch-framework/doc/upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
- [Struct `FrameworkUpgradeEvent`](#0x3_upgrade_FrameworkUpgradeEvent)
- [Constants](#@Constants_0)
- [Function `upgrade_entry`](#0x3_upgrade_upgrade_entry)
- [Function `upgrade_gas_schedule`](#0x3_upgrade_upgrade_gas_schedule)


<pre><code><b>use</b> <a href="">0x2::account</a>;
<b>use</b> <a href="">0x2::event</a>;
<b>use</b> <a href="">0x2::gas_schedule</a>;
<b>use</b> <a href="">0x2::module_store</a>;
<b>use</b> <a href="">0x2::signer</a>;
<b>use</b> <a href="onchain_config.md#0x3_onchain_config">0x3::onchain_config</a>;
Expand Down Expand Up @@ -89,3 +91,14 @@ Event for framework upgrades

<pre><code>entry <b>fun</b> <a href="upgrade.md#0x3_upgrade_upgrade_entry">upgrade_entry</a>(<a href="">account</a>: &<a href="">signer</a>, move_std_bundles: <a href="">vector</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;, moveos_std_bundles: <a href="">vector</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;, rooch_framework_bundles: <a href="">vector</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;, bitcoin_move_bundles: <a href="">vector</a>&lt;<a href="">vector</a>&lt;u8&gt;&gt;)
</code></pre>



<a name="0x3_upgrade_upgrade_gas_schedule"></a>

## Function `upgrade_gas_schedule`



<pre><code>entry <b>fun</b> <a href="upgrade.md#0x3_upgrade_upgrade_gas_schedule">upgrade_gas_schedule</a>(<a href="">account</a>: &<a href="">signer</a>, gas_schedule_config: <a href="">vector</a>&lt;u8&gt;)
</code></pre>
10 changes: 10 additions & 0 deletions frameworks/rooch-framework/sources/upgrade.move
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

module rooch_framework::upgrade {

use moveos_std::gas_schedule::update_gas_schedule;
use moveos_std::signer::module_signer;
use moveos_std::signer;
use moveos_std::event;
Expand Down Expand Up @@ -48,4 +49,13 @@ module rooch_framework::upgrade {
onchain_config::update_framework_version();
event::emit<FrameworkUpgradeEvent>(FrameworkUpgradeEvent { version: onchain_config::framework_version() });
}

entry fun upgrade_gas_schedule(account: &signer, gas_schedule_config: vector<u8>) {
let sender_address = signer::address_of(account);
assert!(sender_address == onchain_config::sequencer(), ErrorNotSequencer);

let system = module_signer<FrameworkUpgradeEvent>();
let moveos_std_signer = create_signer_for_system(&system, MoveosStdAccount);
update_gas_schedule(&moveos_std_signer, gas_schedule_config);
}
}
Loading

0 comments on commit 15d75d9

Please sign in to comment.