Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ aptos-framework-upgrade-gas-release = { path = "protocol-units/execution/maptos/
aptos-framework-known-release = { path = "protocol-units/execution/maptos/framework/releases/known-release" }
aptos-framework-set-feature-flags-release = { path = "protocol-units/execution/maptos/framework/releases/feature-flags" }
aptos-framework-release-script-release = { path = "protocol-units/execution/maptos/framework/releases/release-script" }
mvt-aptos-l1-migration = { path = "protocol-units/execution/maptos/framework/releases/l1-migration" }


# framework migrations
aptos-framework-elsa-to-biarritz-rc1-migration = { path = "protocol-units/execution/maptos/framework/migrations/elsa-to-biarritz-rc1" }
Expand Down
9 changes: 9 additions & 0 deletions docker/scripts/l1-migration-update-epoch-duration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash -e

export DOT_MOVEMENT_PATH=/.movement
export CONTAINER_REV=63d8719-amd64
export HOME="$(pwd)"
export MVT_NODE_REST_URL="http://movement-full-node:30731"

/usr/bin/docker run -e MVT_NODE_REST_URL=$MVT_NODE_REST_URL -e DOT_MOVEMENT_PATH=$DOT_MOVEMENT_PATH -v $HOME/.movement:/.movement --rm ghcr.io/movementlabsxyz/movement-full-node:${CONTAINER_REV} admin l1-migration change-epoch

3 changes: 3 additions & 0 deletions networks/movement/movement-full-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ movement-da-sequencer-config = { workspace = true }
ed25519-dalek = { workspace = true }
mcr-settlement-setup = { workspace = true }

mvt-aptos-l1-migration = { workspace = true }


url = { workspace = true }


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use crate::common_args::MovementArgs;
use clap::Parser;
use mvt_aptos_l1_migration::set_epoch_duration;

const TWO_HOURS_EPOCH_DURATION: u64 = 7_200_000_000; // default 2hours, 7_200_000_000 micro second.

#[derive(Debug, Parser, Clone)]
#[clap(rename_all = "kebab-case", about = "Rotates the key for a core resource account.")]
pub struct ChangeEpochDuration {
#[clap(flatten)]
pub movement_args: MovementArgs,
pub new_epoch_duration: Option<u64>,
}

impl ChangeEpochDuration {
pub async fn execute(&self) -> Result<(), anyhow::Error> {
// get the movement config from dot movement
let _dot_movement = self.movement_args.dot_movement()?;
let epoch_duration = self.new_epoch_duration.unwrap_or(TWO_HOURS_EPOCH_DURATION);
set_epoch_duration(epoch_duration).await?;
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::admin::l1_migration::change_epoch_duration::ChangeEpochDuration;
use clap::Subcommand;

mod change_epoch_duration;

#[derive(Subcommand, Debug)]
#[clap(rename_all = "kebab-case", about = "Commands for rotating keys")]
pub enum L1Migration {
ChangeEpoch(ChangeEpochDuration),
}

impl L1Migration {
pub async fn execute(&self) -> Result<(), anyhow::Error> {
match self {
L1Migration::ChangeEpoch(change_epoch_duration) => {
change_epoch_duration.execute().await
}
}
}
}
4 changes: 4 additions & 0 deletions networks/movement/movement-full-node/src/admin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod bring_up;
pub mod config;
pub mod framework;
pub mod governed_gas_pool;
pub mod l1_migration;
pub mod mcr;
pub mod ops;
pub mod rotate_key;
Expand All @@ -28,6 +29,8 @@ pub enum Admin {
Config(config::Config),
#[clap(subcommand)]
TestKey(testkey::TestKey),
#[clap(subcommand)]
L1Migration(l1_migration::L1Migration),
}

impl Admin {
Expand All @@ -41,6 +44,7 @@ impl Admin {
Admin::Framework(framework) => framework.execute().await,
Admin::Config(config) => config.execute().await,
Admin::TestKey(key) => key.execute().await,
Admin::L1Migration(l1_migration) => l1_migration.execute().await,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ processes:
setup:
environment:
- "MAYBE_RUN_LOCAL=true"
- APTOS_ACCOUNT_WHITELIST=$DOT_MOVEMENT_PATH/default_signer_address_whitelist
- MAPTOS_PRIVATE_KEY=random
command: |
RUST_BACKTRACE=1 movement-full-node setup all
depends_on:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[package]
name = "mvt-aptos-l1-migration"
description = "Mvt Aptos L1 migration functions."
authors = { workspace = true }
edition = { workspace = true }
homepage = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
version = { workspace = true }

[lib]
path = "src/lib.rs"

[dependencies]
aptos-crypto = { workspace = true }
serde = { workspace = true }
maptos-framework-release-util = { workspace = true }
movement-config = { workspace = true }
movement-client = { workspace = true }
once_cell = { workspace = true }
aptos-framework = { workspace = true }
tokio = { workspace = true }
anyhow = { workspace = true }
url = { workspace = true }
dot-movement = { workspace = true }
tempfile = { workspace = true }
bcs = { workspace = true }
aptos-framework-upgrade-gas-release = { workspace = true }
aptos-framework-set-feature-flags-release = { workspace = true }
aptos-framework-release-script-release = { workspace = true }
aptos-types = { workspace = true }
aptos-gas-schedule = { workspace = true }
aptos-sdk = { workspace = true }
aptos-release-builder = { workspace = true }
hex = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
rand = { workspace = true }
ed25519-dalek = { workspace = true }

[build-dependencies]
maptos-framework-release-util = { workspace = true }
movement-config = { workspace = true }
movement-client = { workspace = true }
once_cell = { workspace = true }
aptos-framework = { workspace = true }
tokio = { workspace = true }
anyhow = { workspace = true }
url = { workspace = true }
dot-movement = { workspace = true }
tempfile = { workspace = true }
bcs = { workspace = true }
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
script {
use aptos_framework::aptos_governance;
// use aptos_framework::signer;
use aptos_framework::block;

fun main(core_resources: &signer, new_interval_us: u64) {
let core_signer = aptos_governance::get_signer_testnet_only(core_resources, @0000000000000000000000000000000000000000000000000000000000000001);

block::update_epoch_interval_microsecs(&core_signer, new_interval_us);

aptos_governance::reconfigure(&core_signer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use aptos_sdk::rest_client::Resource;
use aptos_sdk::types::transaction::TransactionArgument;
use aptos_sdk::{
rest_client::Client,
transaction_builder::TransactionFactory,
types::{account_address::AccountAddress, transaction::TransactionPayload},
};
use aptos_types::{chain_id::ChainId, transaction::Script};
use movement_client::types::{account_config::aptos_test_root_address, LocalAccount};
use once_cell::sync::Lazy;
use std::str::FromStr;
use url::Url;

static MOVEMENT_CONFIG: Lazy<movement_config::Config> = Lazy::new(|| {
let dot_movement = dot_movement::DotMovement::try_from_env().unwrap();
dot_movement.try_get_config_from_json::<movement_config::Config>().unwrap()
});

static NODE_URL: Lazy<Url> = Lazy::new(|| {
let addr = MOVEMENT_CONFIG
.execution_config
.maptos_config
.client
.maptos_rest_connection_hostname
.clone();
let port = MOVEMENT_CONFIG
.execution_config
.maptos_config
.client
.maptos_rest_connection_port
.clone();
Url::from_str(&format!("http://{}:{}", addr, port)).unwrap()
});

const GAS_UNIT_LIMIT: u64 = 100_000;

const CHANGE_EPOCH_MV: &[u8] = include_bytes!("../move/build/change_epoch.mv");

pub async fn set_epoch_duration(epoch_duration: u64) -> Result<(), anyhow::Error> {
let node_url = std::env::var("MVT_NODE_REST_URL")
.as_ref()
.map(|url| Url::from_str(url))
.unwrap_or(Ok(NODE_URL.clone()))?;
let rest_client = Client::new(node_url);

// Core resources (aptos_test_root) address
let gov_root_address = aptos_test_root_address();
tracing::info!("aptos_test_root_address() (constant): {}", gov_root_address);
// Load *core_resources* private key (from your config/genesis)
let raw_private_key = MOVEMENT_CONFIG
.execution_config
.maptos_config
.chain
.maptos_private_key_signer_identifier
.try_raw_private_key()?;
let gov_priv =
movement_client::crypto::ed25519::Ed25519PrivateKey::try_from(raw_private_key.as_slice())?;

// Build signer by *forcing* core_resources address + current on-chain seq
let gov_root_account = {
let onchain = rest_client.get_account(gov_root_address).await?.into_inner();
LocalAccount::new(gov_root_address, gov_priv.clone(), onchain.sequence_number)
};
tracing::info!("Signer (gov_root_account) address: {}", gov_root_account.address());

let ledger_info = rest_client.get_ledger_information().await?.into_inner();
let factory = TransactionFactory::new(ChainId::new(ledger_info.chain_id))
.with_gas_unit_price(100)
.with_max_gas_amount(GAS_UNIT_LIMIT);

let payload = TransactionPayload::Script(Script::new(
CHANGE_EPOCH_MV.to_vec(),
vec![], // no type args
vec![TransactionArgument::U64(epoch_duration)], // New epoch duration.
));

// Sign & submit
let signed_txn = gov_root_account.sign_with_transaction_builder(factory.payload(payload));

let tx_hash = rest_client.submit(&signed_txn).await?.into_inner();
let res = rest_client.wait_for_transaction(&tx_hash).await?.into_inner();

// Verify the epoch has been changed
let block_res: Resource = rest_client
.get_account_resource(AccountAddress::from_hex_literal("0x1")?, "0x1::block::BlockResource")
.await?
.into_inner()
.unwrap();

let interval_str = block_res.data["epoch_interval"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("epoch_interval missing or not a string"))?;

let onchain_duration: u64 = interval_str.parse()?;

assert!(
onchain_duration == epoch_duration,
"Epoch duration not updated, epoch after update is:{onchain_duration}"
);

tracing::info!(
"✅ Executed change epoch script, new epoch duration:{onchain_duration}, with Tx hash: {}",
res.transaction_info().unwrap().hash
);
Ok(())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod change_epoch;

pub use change_epoch::set_epoch_duration;
Loading