use std::sync::LazyLock;
use dusk_vm::FeatureActivation;
use crate::node::{FEATURE_DISABLE_3RD_PARTY, FEATURE_DISABLE_WASM32};
use super::feature::{
FEATURE_ABI_PUBLIC_SENDER, FEATURE_BLOB, FEATURE_DISABLE_WASM64,
FEATURE_HARDFORK_AEGIS, FEATURE_PLONK_V2, HQ_KECCAK256,
HQ_SECP256K1_RECOVER, HQ_SHA256, HQ_VERIFY_KZG_PROOF,
};
use super::{
DEFAULT_BLOCK_GAS_LIMIT, DEFAULT_GAS_PER_BLOB, DEFAULT_GAS_PER_DEPLOY_BYTE,
DEFAULT_MIN_DEPLOY_POINTS, DEFAULT_MIN_DEPLOYMENT_GAS_PRICE,
};
pub const MAINNET_ID: u8 = 1;
pub const TESTNET_ID: u8 = 2;
pub const DEVNET_ID: u8 = 3;
const GENESIS: FeatureActivation = FeatureActivation::Height(1);
const NEVER: FeatureActivation = FeatureActivation::Height(u64::MAX);
#[derive(Debug, Clone)]
pub struct WellKnownConfig {
pub gas_per_blob: u64,
pub gas_per_deploy_byte: u64,
pub min_deploy_points: u64,
pub min_deployment_gas_price: u64,
pub block_gas_limit: u64,
pub features: [(&'static str, FeatureActivation); 12],
}
impl WellKnownConfig {
pub fn from_chain_id(chain_id: u8) -> Self {
match chain_id {
MAINNET_ID => MAINNET_CONFIG.clone(),
TESTNET_ID => TESTNET_CONFIG,
DEVNET_ID => DEVNET_CONFIG,
_ => LOCALNET_CONFIG,
}
}
}
pub const FILLER: &str = "FILLER_FEATURE";
const FILLER_FEATURE: (&str, FeatureActivation) = (FILLER, NEVER);
const MAINNET_AT_10_12_2025_AT_09_00_UTC: u64 = 2_873_420;
const MAINNET_AT_17_12_2025_AT_09_00_UTC: u64 = 2_933_850;
const MAINNET_SENDER_ACTIVATION_HEIGHT: FeatureActivation =
FeatureActivation::Height(355_000);
const MAINNET_DISABLED_3D_PARTY_START: u64 = 2_710_376;
const MAINNET_DISABLED_3D_PARTY_END: u64 = MAINNET_AT_10_12_2025_AT_09_00_UTC;
static MAINNET_3RD_PARTY_OFF: LazyLock<FeatureActivation> =
LazyLock::new(|| {
FeatureActivation::Ranges(vec![(
MAINNET_DISABLED_3D_PARTY_START,
MAINNET_DISABLED_3D_PARTY_END,
)])
});
static MAINNET_DISABLE_WASM_64: LazyLock<FeatureActivation> =
LazyLock::new(|| {
FeatureActivation::Ranges(vec![(
MAINNET_DISABLED_3D_PARTY_START,
u64::MAX,
)])
});
const MAINNET_BLOB_ACTIVATION: FeatureActivation =
FeatureActivation::Height(MAINNET_AT_10_12_2025_AT_09_00_UTC);
const MAINNET_PLONK_V2_ACTIVATION: FeatureActivation =
FeatureActivation::Height(3_470_360);
const MAINNET_HARDFORK_AEGIS_ACTIVATION: FeatureActivation =
FeatureActivation::Height(3_590_904);
static MAINNET_CONFIG: LazyLock<WellKnownConfig> = LazyLock::new(|| {
WellKnownConfig {
gas_per_blob: DEFAULT_GAS_PER_BLOB,
gas_per_deploy_byte: DEFAULT_GAS_PER_DEPLOY_BYTE,
min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS,
min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE,
block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT,
features: [
(FEATURE_ABI_PUBLIC_SENDER, MAINNET_SENDER_ACTIVATION_HEIGHT),
(HQ_KECCAK256, NEVER),
(HQ_SHA256, NEVER),
(HQ_VERIFY_KZG_PROOF, NEVER),
(HQ_SECP256K1_RECOVER, NEVER),
(FEATURE_BLOB, MAINNET_BLOB_ACTIVATION),
(FEATURE_PLONK_V2, MAINNET_PLONK_V2_ACTIVATION),
(FEATURE_HARDFORK_AEGIS, MAINNET_HARDFORK_AEGIS_ACTIVATION),
(FEATURE_DISABLE_WASM64, MAINNET_DISABLE_WASM_64.clone()),
(FEATURE_DISABLE_WASM32, MAINNET_3RD_PARTY_OFF.clone()),
(FEATURE_DISABLE_3RD_PARTY, MAINNET_3RD_PARTY_OFF.clone()),
(
"shade_6fdfdc713a18fc6ca2ad20eb2b4a3305a935ef47d6a872d9a4df8bc9fd9d169e",
FeatureActivation::Ranges(vec![(
MAINNET_DISABLED_3D_PARTY_END,
MAINNET_AT_17_12_2025_AT_09_00_UTC,
)]),
),
],
}
});
const TESTNET_AT_12_11_2025_AT_09_00_UTC: FeatureActivation =
FeatureActivation::Height(1_814_090);
const TESTNET_AT_04_02_2026_AT_09_00_UTC: FeatureActivation =
FeatureActivation::Height(2_539_820);
const TESTNET_PLONK_V2_ACTIVATION: FeatureActivation =
FeatureActivation::Height(2_653_175);
const TESTNET_HARDFORK_AEGIS_ACTIVATION: FeatureActivation =
FeatureActivation::Height(2_773_727);
const TESTNET_CONFIG: WellKnownConfig = WellKnownConfig {
gas_per_blob: DEFAULT_GAS_PER_BLOB,
gas_per_deploy_byte: DEFAULT_GAS_PER_DEPLOY_BYTE,
min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS,
min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE,
block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT,
features: [
(FEATURE_ABI_PUBLIC_SENDER, GENESIS),
(HQ_KECCAK256, TESTNET_AT_04_02_2026_AT_09_00_UTC),
(HQ_SHA256, NEVER),
(HQ_VERIFY_KZG_PROOF, NEVER),
(HQ_SECP256K1_RECOVER, NEVER),
(FEATURE_BLOB, TESTNET_AT_12_11_2025_AT_09_00_UTC),
(FEATURE_PLONK_V2, TESTNET_PLONK_V2_ACTIVATION),
(FEATURE_HARDFORK_AEGIS, TESTNET_HARDFORK_AEGIS_ACTIVATION),
(FEATURE_DISABLE_WASM64, TESTNET_AT_12_11_2025_AT_09_00_UTC),
(FEATURE_DISABLE_WASM32, NEVER),
(FEATURE_DISABLE_3RD_PARTY, NEVER),
FILLER_FEATURE,
],
};
const DEVNET_CONFIG: WellKnownConfig = WellKnownConfig {
gas_per_blob: DEFAULT_GAS_PER_BLOB,
gas_per_deploy_byte: DEFAULT_GAS_PER_DEPLOY_BYTE,
min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS,
min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE,
block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT,
features: [
(FEATURE_ABI_PUBLIC_SENDER, GENESIS),
(HQ_KECCAK256, GENESIS),
(HQ_SHA256, GENESIS),
(HQ_VERIFY_KZG_PROOF, GENESIS),
(HQ_SECP256K1_RECOVER, GENESIS),
(FEATURE_BLOB, GENESIS),
(FEATURE_PLONK_V2, NEVER),
(FEATURE_HARDFORK_AEGIS, GENESIS),
(FEATURE_DISABLE_WASM64, GENESIS),
FILLER_FEATURE,
FILLER_FEATURE,
FILLER_FEATURE,
],
};
const LOCALNET_CONFIG: WellKnownConfig = WellKnownConfig {
gas_per_blob: DEFAULT_GAS_PER_BLOB,
gas_per_deploy_byte: DEFAULT_GAS_PER_DEPLOY_BYTE,
min_deploy_points: DEFAULT_MIN_DEPLOY_POINTS,
min_deployment_gas_price: DEFAULT_MIN_DEPLOYMENT_GAS_PRICE,
block_gas_limit: DEFAULT_BLOCK_GAS_LIMIT,
features: [
(FEATURE_ABI_PUBLIC_SENDER, GENESIS),
(HQ_KECCAK256, GENESIS),
(HQ_SHA256, GENESIS),
(HQ_VERIFY_KZG_PROOF, GENESIS),
(HQ_SECP256K1_RECOVER, GENESIS),
(FEATURE_BLOB, GENESIS),
(FEATURE_PLONK_V2, GENESIS),
(FEATURE_HARDFORK_AEGIS, GENESIS),
(FEATURE_DISABLE_WASM64, GENESIS),
FILLER_FEATURE,
FILLER_FEATURE,
FILLER_FEATURE,
],
};