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
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ module aptos_experimental::confidential_asset {
/// The maximum number of transactions can be aggregated on the pending balance before rollover is required.
const MAX_TRANSFERS_BEFORE_ROLLOVER: u64 = 65534;

/// The mainnet chain ID. If the chain ID is 1, the allow list is enabled.
const MAINNET_CHAIN_ID: u8 = 1;
/// The Movement mainnet chain ID. On mainnet the allow list is enabled.
const MAINNET_CHAIN_ID: u8 = 126;

//
// Structs
Expand Down
46 changes: 46 additions & 0 deletions config/src/config/admin_service_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,50 @@ mod tests {
assert_eq!(node_config.admin_service.enabled, Some(false));
assert!(modified_config);
}

// Mainnet must reject an admin service with empty auth. Passes for Aptos
// mainnet (1); fails for Movement mainnet (126) until is_mainnet() matches 126.
fn admin_service_enabled_without_auth() -> NodeConfig {
NodeConfig {
admin_service: AdminServiceConfig {
enabled: Some(true),
..Default::default()
},
..Default::default()
}
}

// Chain 1 (Aptos mainnet) is not this network's mainnet, so the mainnet
// hardening gate does not fire and the empty auth list is accepted.
#[test]
fn admin_service_treats_aptos_mainnet_as_non_production() {
AdminServiceConfig::sanitize(
&admin_service_enabled_without_auth(),
NodeType::Validator,
Some(ChainId::new(1)), // Aptos mainnet — not this network's mainnet
)
.expect("chain 1 is not this network's mainnet; gate does not fire");
}

#[test]
fn admin_service_requires_auth_on_movement_mainnet() {
AdminServiceConfig::sanitize(
&admin_service_enabled_without_auth(),
NodeType::Validator,
Some(ChainId::new(126)),
)
.expect_err("mainnet must reject admin service with empty auth");
}

// Same as the new(1) case but via the ChainId::mainnet() helper — cross-checks
// that the number behind the `mainnet` name still resolves to a production chain.
#[test]
fn admin_service_requires_auth_on_aptos_mainnet_via_helper() {
AdminServiceConfig::sanitize(
&admin_service_enabled_without_auth(),
NodeType::Validator,
Some(ChainId::mainnet()),
)
.expect_err("mainnet must reject admin service with empty auth");
}
}
43 changes: 14 additions & 29 deletions config/src/config/config_optimizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,23 @@ const VALIDATOR_NETWORK_OPTIMIZER_NAME: &str = "ValidatorNetworkConfigOptimizer"

const IDENTITY_KEY_FILE: &str = "ephemeral_identity_key";

// Mainnet seed peers. Each seed peer entry is a tuple
// of (account address, public key, network address).
// Movement mainnet seed peers, published at
// https://github.com/movementlabsxyz/movement-networks (mainnet/configs/fullnode.yaml).
// Each seed peer entry is a tuple of (account address, public key, network address).
const MAINNET_SEED_PEERS: [(&str, &str, &str); 1] = [(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace with the movement seed peers?

@apenzk apenzk Jul 13, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — swapped in the Movement mainnet/testnet seed peers (consensus.{mainnet,testnet}.movementnetwork.xyz).

"568fdb6acf26aae2a84419108ff13baa3ebf133844ef18e23a9f47b5af16b698",
"0x003cc2ed36e7d486539ac2c411b48d962f1ef17d884c3a7109cad43f16bd5008",
"/dns/node1.cloud-b.mainnet.aptoslabs.com/tcp/6182/noise-ik/0x003cc2ed36e7d486539ac2c411b48d962f1ef17d884c3a7109cad43f16bd5008/handshake/0",
"9967EBF40AC8C2CCB38709488952DA1826176584EA3067B63B1695362ECB3D1F",
"0x9967EBF40AC8C2CCB38709488952DA1826176584EA3067B63B1695362ECB3D1F",
"/dns/consensus.mainnet.movementnetwork.xyz/tcp/6182/noise-ik/9967EBF40AC8C2CCB38709488952DA1826176584EA3067B63B1695362ECB3D1F/handshake/0",
)];

// Testnet seed peers. Each seed peer entry is a tuple
// of (account address, public key, network address).
const TESTNET_SEED_PEERS: [(&str, &str, &str); 4] = [
(
"31e55012a7d439dcd16fee0509cd5855c1fbdc62057ba7fac3f7c88f5453dd8e",
"0x87bb19b02580b7e2a91a8e9342ec77ffd8f3ad967f54e77b22aaf558c5c11755",
"/dns/seed0.testnet.aptoslabs.com/tcp/6182/noise-ik/0x87bb19b02580b7e2a91a8e9342ec77ffd8f3ad967f54e77b22aaf558c5c11755/handshake/0",
),
(
"116176e2af223a8b7f8db80dc52f7a423b4d7f8c0553a1747e92ef58849aff4f",
"0xc2f24389f31c9c18d2ceb69d153ad9299e0ea7bbd66f457e0a28ef41c77c2b64",
"/dns/seed1.testnet.aptoslabs.com/tcp/6182/noise-ik/0xc2f24389f31c9c18d2ceb69d153ad9299e0ea7bbd66f457e0a28ef41c77c2b64/handshake/0",
),
(
"12000330d7cd8a748f46c25e6ce5d236a27e13d0b510d4516ac84ecc5fddd002",
"0x171c661e5b785283978a74eafc52a906e68c73ae78119737b92f93507c753933",
"/dns/seed2.testnet.aptoslabs.com/tcp/6182/noise-ik/0x171c661e5b785283978a74eafc52a906e68c73ae78119737b92f93507c753933/handshake/0",
),
(
"03c04549114877c55f45649aba48ac0a4ff086ab7bdce3b8cc8d3d9947bc0d99",
"0xafc38bf177bd825326a1c314748612137d2b35dae6472932806806a32c23174a",
"/dns/seed3.testnet.aptoslabs.com/tcp/6182/noise-ik/0xafc38bf177bd825326a1c314748612137d2b35dae6472932806806a32c23174a/handshake/0",
),
];
// Movement testnet seed peers, published at
// https://github.com/movementlabsxyz/movement-networks (testnet/configs/fullnode.yaml).
// Each seed peer entry is a tuple of (account address, public key, network address).
const TESTNET_SEED_PEERS: [(&str, &str, &str); 1] = [(
"9967EBF40AC8C2CCB38709488952DA1826176584EA3067B63B1695362ECB3D1F",
"0x9967EBF40AC8C2CCB38709488952DA1826176584EA3067B63B1695362ECB3D1F",
"/dns/consensus.testnet.movementnetwork.xyz/tcp/6182/noise-ik/9967EBF40AC8C2CCB38709488952DA1826176584EA3067B63B1695362ECB3D1F/handshake/0",
)];

/// A trait for optimizing node configs (and their sub-configs) by tweaking
/// config values based on node types, chain IDs and compiler features.
Expand Down
6 changes: 4 additions & 2 deletions config/src/config/execution_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ pub const DEFAULT_EXECUTION_CONCURRENCY_LEVEL: u16 = 32;
// Genesis constants
const GENESIS_BLOB_FILENAME: &str = "genesis.blob";
const GENESIS_VERSION: u64 = 0;
// Movement genesis waypoints, published at
// https://github.com/movementlabsxyz/movement-networks (<network>/genesis_waypoint.txt).
const MAINNET_GENESIS_WAYPOINT: &str =
"0:6072b68a942aace147e0655c5704beaa255c84a7829baa4e72a500f1516584c4";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replace with movement values

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"0:fb098815125443b6337c61b81aade770e7dcf69d93e8a636365a664939f100a3";
const TESTNET_GENESIS_WAYPOINT: &str =
"0:4b56f15c1dcef7f9f3eb4b4798c0cba0f1caacc0d35f1c80ad9b7a21f1f8b454";
"0:1b6eeb5566c6267b610340e17d47849742ff488a21eeb3fc1971fb8c2b128133";

#[derive(Clone, Deserialize, PartialEq, Eq, Serialize)]
#[serde(default, deny_unknown_fields)]
Expand Down
46 changes: 46 additions & 0 deletions config/src/config/inspection_service_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,50 @@ mod tests {
.unwrap_err();
assert!(matches!(error, Error::ConfigSanitizerFailed(_, _)));
}

// Mainnet validators must not expose configuration. Passes for Aptos mainnet
// (1); fails for Movement mainnet (126) until is_mainnet() matches 126.
fn validator_exposing_configuration() -> NodeConfig {
NodeConfig {
inspection_service: InspectionServiceConfig {
expose_configuration: true,
..Default::default()
},
..Default::default()
}
}

// Chain 1 (Aptos mainnet) is not this network's mainnet, so the mainnet
// hardening gate does not fire and the exposed configuration is accepted.
#[test]
fn inspection_treats_aptos_mainnet_as_non_production() {
InspectionServiceConfig::sanitize(
&validator_exposing_configuration(),
NodeType::Validator,
Some(ChainId::new(1)), // Aptos mainnet — not this network's mainnet
)
.expect("chain 1 is not this network's mainnet; gate does not fire");
}

#[test]
fn inspection_rejects_config_exposure_on_movement_mainnet() {
InspectionServiceConfig::sanitize(
&validator_exposing_configuration(),
NodeType::Validator,
Some(ChainId::new(126)),
)
.expect_err("mainnet validator must not expose configuration");
}

// Same as the new(1) case but via the ChainId::mainnet() helper — cross-checks
// that the number behind the `mainnet` name still resolves to a production chain.
#[test]
fn inspection_rejects_config_exposure_on_aptos_mainnet_via_helper() {
InspectionServiceConfig::sanitize(
&validator_exposing_configuration(),
NodeType::Validator,
Some(ChainId::mainnet()),
)
.expect_err("mainnet validator must not expose configuration");
}
}
7 changes: 4 additions & 3 deletions crates/aptos-faucet/core/src/funder/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,10 @@ pub struct ApiConnectionConfig {
#[clap(long, value_parser = ConfigKey::<Ed25519PrivateKey>::from_encoded_string)]
key: Option<ConfigKey<Ed25519PrivateKey>>,

/// Chain ID of the network this client is connecting to. For example, for mainnet:
/// "MAINNET" or 1, testnet: "TESTNET" or 2. If there is no predefined string
/// alias (e.g. "MAINNET"), just use the number. Note: Chain ID of 0 is not allowed.
/// Chain ID of the network this client is connecting to, as a number
/// (e.g. 126 for Movement mainnet, 250 for testnet). The aliases
/// "movement_mainnet" / "movement_testnet" are also accepted.
/// Note: Chain ID of 0 is not allowed.
#[clap(long, default_value_t = ChainId::testnet())]
pub chain_id: ChainId,
}
Expand Down
8 changes: 4 additions & 4 deletions crates/aptos/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1371,8 +1371,8 @@ pub struct CheckNetworkConnectivity {

/// `ChainId` of remote server.
/// Examples include:
/// - Chain numbers, e.g., `2`, `3` and `25`.
/// - Chain names, e.g., `devnet`, `testnet`, `mainnet` and `testing` (for local test networks).
/// - Chain numbers, e.g., `126`, `250` and `25`.
/// - Chain names, e.g., `movement_mainnet`, `movement_testnet`, `devnet` and `testing` (for local test networks).
#[clap(long)]
pub chain_id: ChainId,

Expand Down Expand Up @@ -1508,7 +1508,7 @@ mod tests {
"--address",
"invalid-address",
"--chain-id",
"mainnet",
"movement_mainnet",
];
let error_message = run_tool_with_args(args).await.unwrap_err();
assert_contains(error_message, "Invalid address");
Expand All @@ -1519,7 +1519,7 @@ mod tests {
assert_contains(error_message, "invalid value");

// Verify that a failure to connect will return a timeout
let args = &["aptos", "node", "check-network-connectivity", "--address", "/ip4/31.71.116.169/tcp/0001/noise-ik/0x249f3301db104705652e0a0c471b46d13172b2baf14e31f007413f3baee46b0c/handshake/0", "--chain-id", "testnet"];
let args = &["aptos", "node", "check-network-connectivity", "--address", "/ip4/31.71.116.169/tcp/0001/noise-ik/0x249f3301db104705652e0a0c471b46d13172b2baf14e31f007413f3baee46b0c/handshake/0", "--chain-id", "movement_testnet"];
let error_message = run_tool_with_args(args).await.unwrap_err();
assert_contains(error_message, "Timed out while checking endpoint");
}
Expand Down
51 changes: 22 additions & 29 deletions types/src/chain_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,18 @@ use std::{convert::TryFrom, fmt, str::FromStr};
/// A registry of named chain IDs
/// Its main purpose is to improve human readability of reserved chain IDs in config files and CLI
/// When signing transactions for such chains, the numerical chain ID should still be used
/// (e.g. MAINNET has numeric chain ID 1, TESTNET has chain ID 2, etc)
/// (e.g. MOVEMAINNET has numeric chain ID 126, MOVETESTNET has chain ID 250)
/// Note: ChainId 0 is reserved to guard against accidental zero-initialization.
#[repr(u8)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum NamedChain {
/// Users might accidentally initialize the ChainId field to 0, hence reserving ChainId 0 for accidental
/// initialization.
/// MAINNET is the Aptos mainnet production chain and is reserved for 1
MAINNET = 1,
// Even though these CHAIN IDs do not correspond to MAINNET, changing them should be avoided since they
// can break test environments for various organisations.
TESTNET = 2,
DEVNET = 3,
TESTING = 4,
PREMAINNET = 5,
MOVEMAINNET = 126,
MOVETESTNET = 250,
}

const MAINNET: &str = "mainnet";
const TESTNET: &str = "testnet";
const DEVNET: &str = "devnet";
const TESTING: &str = "testing";
const PREMAINNET: &str = "premainnet";
Expand All @@ -47,8 +39,6 @@ impl NamedChain {
pub fn from_chain_id(chain_id: &ChainId) -> Result<NamedChain, String> {
let chain_id = chain_id.id();
match chain_id {
1 => Ok(NamedChain::MAINNET),
2 => Ok(NamedChain::TESTNET),
3 => Ok(NamedChain::DEVNET), // TODO: this is not correct and should removed. The devnet chain ID changes.
4 => Ok(NamedChain::TESTING),
5 => Ok(NamedChain::PREMAINNET),
Expand All @@ -64,8 +54,8 @@ impl FromStr for NamedChain {

fn from_str(string: &str) -> Result<Self> {
let named_chain = match string.to_lowercase().as_str() {
MAINNET => NamedChain::MAINNET,
TESTNET => NamedChain::TESTNET,
MOVEMENT_MAINNET => NamedChain::MOVEMAINNET,
MOVEMENT_TESTNET => NamedChain::MOVETESTNET,
DEVNET => NamedChain::DEVNET,
TESTING => NamedChain::TESTING,
PREMAINNET => NamedChain::PREMAINNET,
Expand All @@ -83,24 +73,16 @@ impl FromStr for NamedChain {
pub struct ChainId(u8);

impl ChainId {
/// Returns true iff the chain ID matches testnet
/// Returns true iff the chain ID matches Movement testnet.
pub fn is_testnet(&self) -> bool {
self.matches_named_chain(NamedChain::TESTNET)
self.matches_named_chain(NamedChain::MOVETESTNET)
}

/// Returns true iff the chain ID matches mainnet
/// Returns true iff the chain ID matches Movement mainnet.
pub fn is_mainnet(&self) -> bool {
self.matches_named_chain(NamedChain::MAINNET)
}

pub fn is_movement_mainnet(&self) -> bool {
self.matches_named_chain(NamedChain::MOVEMAINNET)
}

pub fn is_movement_testnet(&self) -> bool {
self.matches_named_chain(NamedChain::MOVETESTNET)
}

/// Returns true iff the chain ID matches the given named chain
fn matches_named_chain(&self, expected_chain: NamedChain) -> bool {
if let Ok(named_chain) = NamedChain::from_chain_id(self) {
Expand Down Expand Up @@ -167,8 +149,6 @@ impl fmt::Display for NamedChain {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match self {
NamedChain::DEVNET => DEVNET,
NamedChain::TESTNET => TESTNET,
NamedChain::MAINNET => MAINNET,
NamedChain::TESTING => TESTING,
NamedChain::PREMAINNET => PREMAINNET,
NamedChain::MOVEMAINNET => MOVEMENT_MAINNET,
Expand Down Expand Up @@ -211,11 +191,11 @@ impl ChainId {
}

pub fn testnet() -> Self {
ChainId::new(NamedChain::TESTNET.id())
ChainId::new(NamedChain::MOVETESTNET.id())
}

pub fn mainnet() -> Self {
ChainId::new(NamedChain::MAINNET.id())
ChainId::new(NamedChain::MOVEMAINNET.id())
}
}

Expand All @@ -231,5 +211,18 @@ mod test {
assert!(ChainId::from_str("255255").is_err());
assert_eq!(ChainId::from_str("TESTING").unwrap(), ChainId::test());
assert_eq!(ChainId::from_str("255").unwrap(), ChainId::new(255));

// The Movement chains parse from their canonical names, matching Display output.
assert_eq!(
ChainId::from_str("movement_mainnet").unwrap(),
ChainId::mainnet()
);
assert_eq!(
ChainId::from_str("movement_testnet").unwrap(),
ChainId::testnet()
);
// The Aptos "mainnet"/"testnet" names are no longer reserved.
assert!(ChainId::from_str("mainnet").is_err());
assert!(ChainId::from_str("testnet").is_err());
}
}
Loading
Loading