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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,6 @@ genesis_antithesis_*/

# Ignore generated credentials from google-github-actions/auth
gha-creds-*.json

# Ignore Claude Code local config
.claude/
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
script {
use aptos_framework::aptos_governance;
use aptos_framework::staking_config;

/// Restore staking params after the post-move2-upgrade migration overwrites
/// them with placeholder values. Uses mainnet values as of 2026-03-05:
///
/// min_stake: 10_000_000_000_000 (100,000 MOVE)
/// max_stake: 100_000_000_000_000_000 (1,000,000,000 MOVE)
/// rewards_rate: 2176 / 100_000_000 (0.002176% per epoch)
fun main(core_resources: &signer) {
let core_signer = aptos_governance::get_signer_testnet_only(core_resources, @0000000000000000000000000000000000000000000000000000000000000001);

// Match mainnet: min 100K MOVE, max 1B MOVE
staking_config::update_required_stake(&core_signer, 10_000_000_000_000, 100_000_000_000_000_000);

// Match mainnet: 2176 / 100_000_000 per epoch
staking_config::update_rewards_rate(&core_signer, 2176, 100_000_000);

aptos_governance::force_end_epoch(&core_signer);
}
}
2 changes: 1 addition & 1 deletion terraform/helm/aptos-node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Aptos blockchain node deployment
| fullnode.storage.class | string | `nil` | Kubernetes storage class to use for fullnode persistent storage |
| fullnode.storage.size | string | `"2048Gi"` | Size of fullnode persistent storage |
| fullnode.tolerations | list | `[]` | |
| genesis_blob_upload_url | string | `"https://us-west1-aptos-forge-gcp-0.cloudfunctions.net/signed-url?cluster_name=unknown&era=1"` | |
| genesis_blob_upload_url | string | `""` | |
| haproxy.affinity | object | `{}` | |
| haproxy.config.send_proxy_protocol | bool | `false` | Whether to send Proxy Protocol v2 |
| haproxy.config.user | string | `"nobody"` | System user to run HA |
Expand Down
11 changes: 4 additions & 7 deletions terraform/helm/aptos-node/templates/fullnode.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,16 @@ spec:
type: RuntimeDefault
initContainers:
- name: run-script
image: curlimages/curl:latest
args:
image: amazon/aws-cli:latest
command:
- sh
- -c
- |
set -x
cp /opt/aptos/genesis_readonly/* /opt/aptos/genesis
if [ ! -f /opt/aptos/genesis/genesis.blob ]; then
genesis_blob_upload_url="{{ $.Values.genesis_blob_upload_url }}"
genesis_blob_upload_url="$genesis_blob_upload_url&namespace={{ $.Release.Namespace }}&method=GET"
echo "genesis.blob not found locally, downloading..."
signed_url=$(curl -s -X GET "$genesis_blob_upload_url")
curl -o /opt/aptos/genesis/genesis.blob "$signed_url"
echo "genesis.blob not found locally, downloading from S3..."
aws s3 cp "s3://{{ $.Values.genesis_blob_s3_bucket }}/{{ $.Release.Namespace }}/genesis.blob" /opt/aptos/genesis/genesis.blob
else
echo "genesis.blob found locally"
fi
Expand Down
11 changes: 4 additions & 7 deletions terraform/helm/aptos-node/templates/validator.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,19 +103,16 @@ spec:
type: RuntimeDefault
initContainers:
- name: run-script
image: curlimages/curl:latest
args:
image: amazon/aws-cli:latest
command:
- sh
- -c
- |
set -x
cp /opt/aptos/genesis_readonly/* /opt/aptos/genesis
if [ ! -f /opt/aptos/genesis/genesis.blob ]; then
genesis_blob_upload_url="{{ $.Values.genesis_blob_upload_url }}"
genesis_blob_upload_url="$genesis_blob_upload_url&namespace={{ $.Release.Namespace }}&method=GET"
echo "genesis.blob not found locally, downloading..."
signed_url=$(curl -s -X GET "$genesis_blob_upload_url")
curl -o /opt/aptos/genesis/genesis.blob "$signed_url"
echo "genesis.blob not found locally, downloading from S3..."
aws s3 cp "s3://{{ $.Values.genesis_blob_s3_bucket }}/{{ $.Release.Namespace }}/genesis.blob" /opt/aptos/genesis/genesis.blob
else
echo "genesis.blob found locally"
fi
Expand Down
6 changes: 4 additions & 2 deletions terraform/helm/aptos-node/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ validator:
name:
image:
# -- Image repo to use for validator images
repo: aptoslabs/validator
repo: ghcr.io/movementlabsxyz/validator
# -- Image tag to use for validator images. If set, overrides `imageTag`
tag:
# -- Image pull policy to use for validator images
Expand Down Expand Up @@ -193,7 +193,9 @@ loadTestGenesis: false
# -- TEST ONLY: Enable running as root for profiling
enablePrivilegedMode: false

genesis_blob_upload_url: https://us-west1-aptos-forge-gcp-0.cloudfunctions.net/signed-url?cluster_name=unknown&era=1
genesis_blob_upload_url: ""
# -- S3 bucket to download the genesis blob from (s3://<bucket>/<namespace>/genesis.blob), using the node instance role. Set when genesis is distributed via S3 rather than a k8s Secret.
genesis_blob_s3_bucket: ""
cluster_name: unknown

# Additional labels
Expand Down
2 changes: 1 addition & 1 deletion terraform/helm/genesis/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Aptos blockchain automated genesis ceremony for testnets
| genesis.domain | string | `nil` | If set, the base domain name of the fullnode and validator endpoints |
| genesis.fullnode.enable_onchain_discovery | bool | `true` | Use External DNS as created by aptos-node helm chart for fullnode host in genesis |
| genesis.fullnode.internal_host_suffix | string | `"fullnode-lb"` | If `enable_onchain_discovery` is false, use this host suffix for internal kubernetes service name |
| genesis.genesis_blob_upload_url | string | `"https://us-west1-aptos-forge-gcp-0.cloudfunctions.net/signed-url"` | |
| genesis.genesis_blob_upload_url | string | `""` | |
| genesis.image.pullPolicy | string | `"IfNotPresent"` | Image pull policy to use for tools image |
| genesis.image.repo | string | `"aptoslabs/tools"` | Image repo to use for tools image for running genesis |
| genesis.image.tag | string | `nil` | Image tag to use for tools image. If set, overrides `imageTag` |
Expand Down
18 changes: 16 additions & 2 deletions terraform/helm/genesis/files/genesis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,22 @@ create_secrets() {
done
}

# Include the genesis blob in the secrets if we can't upload it
if upload_genesis_blob; then
# Upload the genesis blob to S3 using the node instance role. Preferred: the
# blob is too large (~1 MB+) for a k8s Secret, so it is stored under the run's
# namespace key and validators download it at startup.
upload_genesis_blob_s3() {
if [ -z "${GENESIS_BLOB_S3_BUCKET}" ]; then
echo "Skipping S3 genesis blob upload, GENESIS_BLOB_S3_BUCKET is not set"
return 1
fi
aws s3 cp "${WORKSPACE}/genesis.blob" "s3://${GENESIS_BLOB_S3_BUCKET}/${NAMESPACE}/genesis.blob"
}

# Prefer S3, then the signed-url service, then embedding in the secret.
if upload_genesis_blob_s3; then
echo "Genesis blob uploaded to S3"
create_secrets false
elif upload_genesis_blob; then
echo "Genesis blob uploaded successfully"
create_secrets false
else
Expand Down
2 changes: 2 additions & 0 deletions terraform/helm/genesis/templates/genesis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ spec:
value: {{ .Values.genesis.multicluster.domain_suffixes | quote }}
- name: GENESIS_BLOB_UPLOAD_URL
value: {{ .Values.genesis.genesis_blob_upload_url | quote }}
- name: GENESIS_BLOB_S3_BUCKET
value: {{ .Values.genesis.genesis_blob_s3_bucket | quote }}
- name: CLUSTER_NAME
value: {{ .Values.genesis.cluster_name | quote }}
volumeMounts:
Expand Down
6 changes: 4 additions & 2 deletions terraform/helm/genesis/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ imageTag: testnet
genesis:
image:
# -- Image repo to use for tools image for running genesis
repo: aptoslabs/tools
repo: ghcr.io/movementlabsxyz/tools
# -- Image tag to use for tools image. If set, overrides `imageTag`
tag:
# -- Image pull policy to use for tools image
Expand Down Expand Up @@ -80,7 +80,9 @@ genesis:
enabled: false
# comma separated list of cluster names
domain_suffixes: ""
genesis_blob_upload_url: "https://us-west1-aptos-forge-gcp-0.cloudfunctions.net/signed-url"
genesis_blob_upload_url: ""
# -- S3 bucket to upload the genesis blob to (preferred over a k8s Secret, which caps at 1 MB). Uploaded under s3://<bucket>/<namespace>/genesis.blob using the node instance role.
genesis_blob_s3_bucket: ""
cluster_name: "unknown"

serviceAccount:
Expand Down
2 changes: 2 additions & 0 deletions testsuite/forge-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::{self, env, num::NonZeroUsize, process, time::Duration};
use sugars::{boxed, hmap};
use suites::{
dag::get_dag_test,
eph_devnet::get_eph_devnet_test,
indexer::get_indexer_test,
land_blocking::get_land_blocking_test,
multi_region::get_multi_region_test,
Expand Down Expand Up @@ -519,6 +520,7 @@ fn get_test_suite(
let named_test_suites = [
boxed!(|| get_land_blocking_test(test_name, duration, test_cmd))
as Box<dyn Fn() -> Option<ForgeConfig>>,
boxed!(|| get_eph_devnet_test(test_name)),
boxed!(|| get_multi_region_test(test_name)),
boxed!(|| get_netbench_test(test_name)),
boxed!(|| get_pfn_test(test_name, duration)),
Expand Down
59 changes: 59 additions & 0 deletions testsuite/forge-cli/src/suites/eph_devnet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright © Aptos Foundation
// Parts of the project are originally copyright © Meta Platforms, Inc.
// SPDX-License-Identifier: Apache-2.0

use crate::suites::ungrouped::GetMetadata;
use aptos_forge::{ForgeConfig, NodeResourceOverride};
use std::{num::NonZeroUsize, sync::Arc};

/// Matches the test name to the ephemeral devnet suite.
pub(crate) fn get_eph_devnet_test(test_name: &str) -> Option<ForgeConfig> {
let test = match test_name {
"eph_devnet" => eph_devnet(),
_ => return None,
};
Some(test)
}

/// A mainnet-aligned ephemeral devnet: four validators with Movement mainnet
/// chain parameters, deployed and kept alive (`--keep`) for a developer to
/// test a branch build against, then torn down.
///
/// Chain parameters mirror the ephemeral-devnet prototype
/// (movement-infra/cdktf-mvmt-networks#156): compressed timings and mainnet
/// staking bounds queried from Movement mainnet. Chain id is 126
/// (`NamedChain::MOVEMAINNET`), so `ChainId::is_movement_mainnet` is true and a
/// branch exercises under the same chain identity and staking config as
/// Movement mainnet. The residual post-genesis migration (governed gas pool
/// extension, treasury reward feature) runs separately. Genesis already
/// initializes the base governed gas pool.
pub(crate) fn eph_devnet() -> ForgeConfig {
ForgeConfig::default()
.with_initial_validator_count(NonZeroUsize::new(4).unwrap())
.add_admin_test(GetMetadata)
// Fit one validator per m6a.2xlarge (8 vCPU / 32 GiB), leaving headroom
// for system pods. Without this the chart default (30 vCPU) is unschedulable.
.with_validator_resource_override(NodeResourceOverride {
cpu_cores: Some(6),
memory_gib: Some(24),
storage_gib: Some(100),
})
.with_genesis_helm_config_fn(Arc::new(|helm_values| {
let chain = &mut helm_values["chain"];
chain["chain_id"] = 126.into();
chain["allow_new_validators"] = true.into();
chain["epoch_duration_secs"] = 600.into();
chain["is_test"] = true.into();
chain["min_stake"] = 10_000_000_000_000i64.into();
chain["max_stake"] = 100_000_000_000_000_000i64.into();
chain["recurring_lockup_duration_secs"] = 3600.into();
chain["rewards_apy_percentage"] = 10.into();
chain["voting_duration_secs"] = 1800.into();
chain["voting_power_increase_limit"] = 20.into();

// Single cluster: validators/fullnodes discover each other by
// in-cluster service name, so on-chain (DNS domain) discovery is off.
helm_values["genesis"]["validator"]["enable_onchain_discovery"] = false.into();
helm_values["genesis"]["fullnode"]["enable_onchain_discovery"] = false.into();
}))
}
1 change: 1 addition & 0 deletions testsuite/forge-cli/src/suites/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

pub mod dag;
pub mod db;
pub mod eph_devnet;
pub mod indexer;
pub mod land_blocking;
pub mod multi_region;
Expand Down
Loading
Loading