diff --git a/aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_asset.move b/aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_asset.move index 32c07f8c04f..49ee659f265 100644 --- a/aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_asset.move +++ b/aptos-move/framework/aptos-experimental/sources/confidential_asset/confidential_asset.move @@ -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 diff --git a/config/src/config/admin_service_config.rs b/config/src/config/admin_service_config.rs index e4096b108c0..d42571756d4 100644 --- a/config/src/config/admin_service_config.rs +++ b/config/src/config/admin_service_config.rs @@ -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"); + } } diff --git a/config/src/config/config_optimizer.rs b/config/src/config/config_optimizer.rs index 0165cbadb97..e5a3f9b335c 100644 --- a/config/src/config/config_optimizer.rs +++ b/config/src/config/config_optimizer.rs @@ -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] = [( - "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. diff --git a/config/src/config/execution_config.rs b/config/src/config/execution_config.rs index 0959ba8aa9d..cd93e23ce6b 100644 --- a/config/src/config/execution_config.rs +++ b/config/src/config/execution_config.rs @@ -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 (/genesis_waypoint.txt). const MAINNET_GENESIS_WAYPOINT: &str = - "0:6072b68a942aace147e0655c5704beaa255c84a7829baa4e72a500f1516584c4"; + "0:fb098815125443b6337c61b81aade770e7dcf69d93e8a636365a664939f100a3"; const TESTNET_GENESIS_WAYPOINT: &str = - "0:4b56f15c1dcef7f9f3eb4b4798c0cba0f1caacc0d35f1c80ad9b7a21f1f8b454"; + "0:1b6eeb5566c6267b610340e17d47849742ff488a21eeb3fc1971fb8c2b128133"; #[derive(Clone, Deserialize, PartialEq, Eq, Serialize)] #[serde(default, deny_unknown_fields)] diff --git a/config/src/config/inspection_service_config.rs b/config/src/config/inspection_service_config.rs index ea510d5b4ca..f25ce61f7ee 100644 --- a/config/src/config/inspection_service_config.rs +++ b/config/src/config/inspection_service_config.rs @@ -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"); + } } diff --git a/crates/aptos-faucet/core/src/funder/common.rs b/crates/aptos-faucet/core/src/funder/common.rs index d88cf44e5f4..1c2ac3126a4 100644 --- a/crates/aptos-faucet/core/src/funder/common.rs +++ b/crates/aptos-faucet/core/src/funder/common.rs @@ -76,9 +76,10 @@ pub struct ApiConnectionConfig { #[clap(long, value_parser = ConfigKey::::from_encoded_string)] key: Option>, - /// 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, } diff --git a/crates/aptos/src/node/mod.rs b/crates/aptos/src/node/mod.rs index e062e721cc9..e20a850bee7 100644 --- a/crates/aptos/src/node/mod.rs +++ b/crates/aptos/src/node/mod.rs @@ -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, @@ -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"); @@ -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"); } diff --git a/types/src/chain_id.rs b/types/src/chain_id.rs index aa2c1707e14..54b58db93bf 100644 --- a/types/src/chain_id.rs +++ b/types/src/chain_id.rs @@ -8,17 +8,11 @@ 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, @@ -26,8 +20,6 @@ pub enum NamedChain { MOVETESTNET = 250, } -const MAINNET: &str = "mainnet"; -const TESTNET: &str = "testnet"; const DEVNET: &str = "devnet"; const TESTING: &str = "testing"; const PREMAINNET: &str = "premainnet"; @@ -47,8 +39,6 @@ impl NamedChain { pub fn from_chain_id(chain_id: &ChainId) -> Result { 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), @@ -64,8 +54,8 @@ impl FromStr for NamedChain { fn from_str(string: &str) -> Result { 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, @@ -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) { @@ -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, @@ -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()) } } @@ -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()); } } diff --git a/types/src/on_chain_config/timed_features.rs b/types/src/on_chain_config/timed_features.rs index fe5e895a1a0..8d06d7fb31e 100644 --- a/types/src/on_chain_config/timed_features.rs +++ b/types/src/on_chain_config/timed_features.rs @@ -89,61 +89,9 @@ impl TimedFeatureFlag { .with_ymd_and_hms(2025, 8, 11, 17, 0, 0) .unwrap() .with_timezone(&Utc), - // Enabled from the beginning of time. - (DisableInvariantViolationCheckInSwapLoc, TESTNET) => BEGINNING_OF_TIME, - (DisableInvariantViolationCheckInSwapLoc, MAINNET) => BEGINNING_OF_TIME, - - // Note: These have been enabled since the start due to a bug. - (_LimitTypeTagSize, TESTNET) => BEGINNING_OF_TIME, - (_LimitTypeTagSize, MAINNET) => BEGINNING_OF_TIME, - - (_ModuleComplexityCheck, TESTNET) => Los_Angeles - .with_ymd_and_hms(2024, 6, 25, 16, 0, 0) - .unwrap() - .with_timezone(&Utc), - (_ModuleComplexityCheck, MAINNET) => Los_Angeles - .with_ymd_and_hms(2024, 7, 3, 12, 0, 0) - .unwrap() - .with_timezone(&Utc), - - (EntryCompatibility, TESTNET) => Los_Angeles - .with_ymd_and_hms(2024, 11, 6, 12, 0, 0) - .unwrap() - .with_timezone(&Utc), - (EntryCompatibility, MAINNET) => Los_Angeles - .with_ymd_and_hms(2024, 11, 12, 12, 0, 0) - .unwrap() - .with_timezone(&Utc), - // Note: Activation time set to 1 hour after the beginning of time // so we can test the old and new behaviors in tests. (FixMemoryUsageTracking, TESTING) => Utc.with_ymd_and_hms(1970, 1, 1, 1, 0, 0).unwrap(), - (FixMemoryUsageTracking, TESTNET) => Los_Angeles - .with_ymd_and_hms(2025, 3, 7, 12, 0, 0) - .unwrap() - .with_timezone(&Utc), - (FixMemoryUsageTracking, MAINNET) => Los_Angeles - .with_ymd_and_hms(2025, 3, 11, 17, 0, 0) - .unwrap() - .with_timezone(&Utc), - - (ChargeBytesForPrints, TESTNET) => Los_Angeles - .with_ymd_and_hms(2025, 3, 7, 12, 0, 0) - .unwrap() - .with_timezone(&Utc), - (ChargeBytesForPrints, MAINNET) => Los_Angeles - .with_ymd_and_hms(2025, 3, 11, 17, 0, 0) - .unwrap() - .with_timezone(&Utc), - - (FixTableNativesMemoryDoubleCounting, TESTNET) => Los_Angeles - .with_ymd_and_hms(2025, 10, 16, 17, 0, 0) - .unwrap() - .with_timezone(&Utc), - (FixTableNativesMemoryDoubleCounting, MAINNET) => Los_Angeles - .with_ymd_and_hms(2025, 10, 21, 10, 0, 0) - .unwrap() - .with_timezone(&Utc), // 1 hour after the beginning of time (FixCryptoAlgebraNativesTypeTagConversion, _) => { @@ -153,8 +101,8 @@ impl TimedFeatureFlag { // Irrelevant for us except for testing (UseFullTransactionSizeForTransactionMetadata, _) => BEGINNING_OF_TIME, - // For chains other than testnet and mainnet, a timed feature is considered enabled from - // the very beginning, if left unspecified. + // For chains other than Movement mainnet and testnet, a timed feature is considered + // enabled from the very beginning, if left unspecified. (_, TESTING | DEVNET | PREMAINNET) => BEGINNING_OF_TIME, } } @@ -250,8 +198,6 @@ mod test { #[test] fn test_micros_conversion() { - use NamedChain::*; - assert_eq!( Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0) .unwrap() @@ -265,117 +211,49 @@ mod test { .timestamp_micros(), 1_731_628_800_000_000 ); - - assert_eq!( - TimedFeatureFlag::_ModuleComplexityCheck - .activation_time_on(&TESTNET) - .timestamp_micros(), - 1_719_356_400_000_000 - ); - assert_eq!( - TimedFeatureFlag::_ModuleComplexityCheck - .activation_time_on(&MAINNET) - .timestamp_micros(), - 1_720_033_200_000_000 - ); - - assert_eq!( - TimedFeatureFlag::EntryCompatibility - .activation_time_on(&TESTNET) - .timestamp_micros(), - 1_730_923_200_000_000 - ); - assert_eq!( - TimedFeatureFlag::EntryCompatibility - .activation_time_on(&MAINNET) - .timestamp_micros(), - 1_731_441_600_000_000 - ); } #[test] fn test_timed_features_activation() { use TimedFeatureFlag::*; - let jan_1_2024_micros = Utc - .with_ymd_and_hms(2024, 1, 1, 0, 0, 0) + + // On Movement's chains (mainnet 126 / testnet 250) every timed feature + // activates on 2025-08-11 (America/Los_Angeles), except + // UseFullTransactionSizeForTransactionMetadata, which activates 2026-05-04. + let before_micros = Utc + .with_ymd_and_hms(2025, 8, 1, 0, 0, 0) .unwrap() .timestamp_micros() as u64; - let nov_15_2024_micros = Utc - .with_ymd_and_hms(2024, 11, 15, 0, 0, 0) + let after_micros = Utc + .with_ymd_and_hms(2025, 9, 1, 0, 0, 0) + .unwrap() + .timestamp_micros() as u64; + let after_full_txn_size_micros = Utc + .with_ymd_and_hms(2026, 6, 1, 0, 0, 0) .unwrap() .timestamp_micros() as u64; - // Check testnet on Jan 1, 2024. - let testnet_jan_1_2024 = TimedFeaturesBuilder::new(ChainId::testnet(), jan_1_2024_micros); - assert!( - testnet_jan_1_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), - "DisableInvariantViolationCheckInSwapLoc should always be enabled" - ); - assert!( - testnet_jan_1_2024.is_enabled(_LimitTypeTagSize), - "LimitTypeTagSize should always be enabled" - ); - assert!( - !testnet_jan_1_2024.is_enabled(_ModuleComplexityCheck), - "ModuleComplexityCheck should be disabled on Jan 1, 2024 on testnet" - ); - assert!( - !testnet_jan_1_2024.is_enabled(EntryCompatibility), - "EntryCompatibility should be disabled on Jan 1, 2024 on testnet" - ); - // Check testnet on Nov 15, 2024. - let testnet_nov_15_2024 = TimedFeaturesBuilder::new(ChainId::testnet(), nov_15_2024_micros); - assert!( - testnet_nov_15_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), - "DisableInvariantViolationCheckInSwapLoc should always be enabled" - ); - assert!( - testnet_nov_15_2024.is_enabled(_LimitTypeTagSize), - "LimitTypeTagSize should always be enabled" - ); - assert!( - testnet_nov_15_2024.is_enabled(_ModuleComplexityCheck), - "ModuleComplexityCheck should be enabled on Nov 15, 2024 on testnet" - ); - assert!( - testnet_nov_15_2024.is_enabled(EntryCompatibility), - "EntryCompatibility should be enabled on Nov 15, 2024 on testnet" - ); - // Check mainnet on Jan 1, 2024. - let mainnet_jan_1_2024 = TimedFeaturesBuilder::new(ChainId::mainnet(), jan_1_2024_micros); - assert!( - mainnet_jan_1_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), - "DisableInvariantViolationCheckInSwapLoc should always be enabled" - ); - assert!( - mainnet_jan_1_2024.is_enabled(_LimitTypeTagSize), - "LimitTypeTagSize should always be enabled" - ); - assert!( - !mainnet_jan_1_2024.is_enabled(_ModuleComplexityCheck), - "ModuleComplexityCheck should be disabled on Jan 1, 2024 on mainnet" - ); - assert!( - !mainnet_jan_1_2024.is_enabled(EntryCompatibility), - "EntryCompatibility should be disabled on Jan 1, 2024 on mainnet" - ); - // Check mainnet on Nov 15, 2024. - let mainnet_nov_15_2024 = TimedFeaturesBuilder::new(ChainId::mainnet(), nov_15_2024_micros); - assert!( - mainnet_nov_15_2024.is_enabled(DisableInvariantViolationCheckInSwapLoc), - "DisableInvariantViolationCheckInSwapLoc should always be enabled" - ); - assert!( - mainnet_nov_15_2024.is_enabled(_LimitTypeTagSize), - "LimitTypeTagSize should always be enabled" - ); - assert!( - mainnet_nov_15_2024.is_enabled(_ModuleComplexityCheck), - "ModuleComplexityCheck should be enabled on Nov 15, 2024 on mainnet" - ); - assert!( - mainnet_nov_15_2024.is_enabled(EntryCompatibility), - "EntryCompatibility should be enabled on Nov 15, 2024 on mainnet" - ); + // Both our mainnet and testnet follow the same Movement schedule. + for chain_id in [ChainId::mainnet(), ChainId::testnet()] { + // Before the activation date, timed features are not yet enabled. + let before = TimedFeaturesBuilder::new(chain_id, before_micros); + assert!(!before.is_enabled(DisableInvariantViolationCheckInSwapLoc)); + assert!(!before.is_enabled(_LimitTypeTagSize)); + assert!(!before.is_enabled(_ModuleComplexityCheck)); + assert!(!before.is_enabled(EntryCompatibility)); + + // After the activation date, they are enabled, except the later + // UseFullTransactionSizeForTransactionMetadata. + let after = TimedFeaturesBuilder::new(chain_id, after_micros); + assert!(after.is_enabled(DisableInvariantViolationCheckInSwapLoc)); + assert!(after.is_enabled(_LimitTypeTagSize)); + assert!(after.is_enabled(_ModuleComplexityCheck)); + assert!(after.is_enabled(EntryCompatibility)); + assert!(!after.is_enabled(UseFullTransactionSizeForTransactionMetadata)); + + // After its own later activation date, it is enabled too. + let after_full = TimedFeaturesBuilder::new(chain_id, after_full_txn_size_micros); + assert!(after_full.is_enabled(UseFullTransactionSizeForTransactionMetadata)); + } } }