use ahash::HashMap;
use cid::Cid;
use libp2p::Multiaddr;
use std::str::FromStr;
use std::sync::LazyLock;
use url::Url;
use crate::{
db::SettingsStore, eth::EthChainId, make_height, shim::version::NetworkVersion,
utils::net::http_get,
};
use super::{
DrandPoint, Height, HeightInfo, NetworkChain, actors_bundle::ACTOR_BUNDLES_METADATA,
drand::DRAND_QUICKNET, parse_bootstrap_peers,
};
pub const NETWORK_COMMON_NAME: &str = "butterflynet";
pub const GENESIS_NETWORK_VERSION: NetworkVersion = NetworkVersion::V27;
pub async fn fetch_genesis<DB: SettingsStore>(db: &DB) -> anyhow::Result<Vec<u8>> {
let genesis_key = format!("BUTTERFLY_GENESIS-{}", &*GENESIS_CID);
if let Some(genesis) = db.read_bin(&genesis_key)? {
Ok(genesis)
} else {
let response = if let Ok(genesis) = http_get(&GENESIS_URL).await {
genesis
} else {
http_get(&GENESIS_URL_ALT).await?
};
let genesis = response.bytes().await?;
db.write_bin(&genesis_key, &genesis)?;
Ok(genesis.to_vec())
}
}
pub static GENESIS_CID: LazyLock<Cid> = LazyLock::new(|| {
Cid::from_str("bafy2bzaceakkgnqbuam2qoyds57f4h6ennt3o5or5ek3i3a4qpetirt7et5jw").unwrap()
});
static GENESIS_URL: LazyLock<Url> = LazyLock::new(|| {
"https://forest-snapshots.fra1.cdn.digitaloceanspaces.com/genesis/butterflynet-bafy2bzaceakkgnqbuam2qoyds57f4h6ennt3o5or5ek3i3a4qpetirt7et5jw.car.zst"
.parse()
.expect("hard-coded URL must parse")
});
static GENESIS_URL_ALT: LazyLock<Url> = LazyLock::new(|| {
"https://github.com/filecoin-project/lotus/raw/76d4ca672262105bf406ef2f0b54ed69ea39636f/build/genesis/butterflynet.car.zst".parse().expect("hard-coded URL must parse")
});
pub(crate) const MINIMUM_CONSENSUS_POWER: i64 = 2 << 30;
pub(crate) const MINIMUM_VERIED_ALLOCATION: i64 = 1 << 20;
pub(crate) const PRE_COMMIT_CHALLENGE_DELAY: i64 = 150;
pub static DEFAULT_BOOTSTRAP: LazyLock<Vec<Multiaddr>> =
LazyLock::new(|| parse_bootstrap_peers(include_str!("../../../build/bootstrap/butterflynet")));
pub const ETH_CHAIN_ID: EthChainId = 3141592;
pub const BREEZE_GAS_TAMPING_DURATION: i64 = 120;
pub static HEIGHT_INFOS: LazyLock<HashMap<Height, HeightInfo>> = LazyLock::new(|| {
HashMap::from_iter([
make_height!(Breeze, -50),
make_height!(Smoke, -2),
make_height!(Ignition, -3),
make_height!(Refuel, -4),
make_height!(Assembly, -5),
make_height!(Tape, -6),
make_height!(Liftoff, -7),
make_height!(Kumquat, -8),
make_height!(Calico, -9),
make_height!(Persian, -10),
make_height!(Claus, -11),
make_height!(Orange, -12),
make_height!(Trust, -13),
make_height!(Norwegian, -14),
make_height!(Turbo, -15),
make_height!(Hyperdrive, -16),
make_height!(Chocolate, -17),
make_height!(OhSnap, -18),
make_height!(Skyr, -19),
make_height!(Shark, -20),
make_height!(Hygge, -21),
make_height!(Lightning, -22),
make_height!(Thunder, -23),
make_height!(Watermelon, -24),
make_height!(Dragon, -25),
make_height!(Phoenix, i64::MIN),
make_height!(Waffle, -26),
make_height!(TukTuk, -27),
make_height!(Teep, -28),
make_height!(Tock, -29),
make_height!(GoldenWeek, -30),
make_height!(FireHorse, 960, get_bundle_cid("v18.0.0-rc1")),
])
});
fn get_bundle_cid(version: &str) -> Cid {
ACTOR_BUNDLES_METADATA
.get(&(NetworkChain::Butterflynet, version.into()))
.expect("bundle must be defined")
.bundle_cid
}
pub(super) static DRAND_SCHEDULE: LazyLock<[DrandPoint<'static>; 1]> = LazyLock::new(|| {
[DrandPoint {
height: 0,
config: &DRAND_QUICKNET,
}]
});
#[macro_export]
macro_rules! make_butterfly_policy {
(v10) => {{
use $crate::networks::butterflynet::*;
use $crate::shim::sector::{RegisteredPoStProofV3, RegisteredSealProofV3};
let mut policy = fil_actors_shared::v10::runtime::Policy::default();
policy.minimum_consensus_power = MINIMUM_CONSENSUS_POWER.into();
policy.minimum_verified_allocation_size = MINIMUM_VERIED_ALLOCATION.into();
policy.pre_commit_challenge_delay = PRE_COMMIT_CHALLENGE_DELAY;
#[allow(clippy::disallowed_types)]
let allowed_proof_types = std::collections::HashSet::from_iter(vec![
RegisteredSealProofV3::StackedDRG512MiBV1,
RegisteredSealProofV3::StackedDRG32GiBV1,
RegisteredSealProofV3::StackedDRG64GiBV1,
]);
policy.valid_pre_commit_proof_type = allowed_proof_types;
#[allow(clippy::disallowed_types)]
let allowed_proof_types = std::collections::HashSet::from_iter(vec![
RegisteredPoStProofV3::StackedDRGWindow512MiBV1,
RegisteredPoStProofV3::StackedDRGWindow32GiBV1,
RegisteredPoStProofV3::StackedDRGWindow64GiBV1,
]);
policy.valid_post_proof_type = allowed_proof_types;
policy
}};
($version:tt) => {{
use $crate::networks::butterflynet::*;
use $crate::shim::sector::{RegisteredPoStProofV3, RegisteredSealProofV3};
let mut policy = fil_actors_shared::$version::runtime::Policy::default();
policy.minimum_consensus_power = MINIMUM_CONSENSUS_POWER.into();
policy.minimum_verified_allocation_size = MINIMUM_VERIED_ALLOCATION.into();
policy.pre_commit_challenge_delay = PRE_COMMIT_CHALLENGE_DELAY;
let mut proofs = fil_actors_shared::$version::runtime::ProofSet::default();
proofs.insert(RegisteredSealProofV3::StackedDRG512MiBV1P1);
proofs.insert(RegisteredSealProofV3::StackedDRG32GiBV1P1);
proofs.insert(RegisteredSealProofV3::StackedDRG64GiBV1P1);
proofs.insert(RegisteredSealProofV3::StackedDRG512MiBV1P1_Feat_SyntheticPoRep);
proofs.insert(RegisteredSealProofV3::StackedDRG32GiBV1P1_Feat_SyntheticPoRep);
proofs.insert(RegisteredSealProofV3::StackedDRG64GiBV1P1_Feat_SyntheticPoRep);
policy.valid_pre_commit_proof_type = proofs;
let mut proofs = fil_actors_shared::$version::runtime::ProofSet::default();
proofs.insert(RegisteredPoStProofV3::StackedDRGWindow512MiBV1);
proofs.insert(RegisteredPoStProofV3::StackedDRGWindow32GiBV1);
proofs.insert(RegisteredPoStProofV3::StackedDRGWindow64GiBV1);
policy.valid_post_proof_type = proofs;
policy
}};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_boostrap_list_not_empty() {
assert!(!DEFAULT_BOOTSTRAP.is_empty());
}
#[test]
fn can_create_butterfly_policy() {
let v10 = make_butterfly_policy!(v10);
let v11 = make_butterfly_policy!(v11);
let v12 = make_butterfly_policy!(v12);
let v13 = make_butterfly_policy!(v13);
let v14 = make_butterfly_policy!(v14);
assert_eq!(v10.minimum_consensus_power, MINIMUM_CONSENSUS_POWER.into());
assert_eq!(v11.minimum_consensus_power, MINIMUM_CONSENSUS_POWER.into());
assert_eq!(v12.minimum_consensus_power, MINIMUM_CONSENSUS_POWER.into());
assert_eq!(v13.minimum_consensus_power, MINIMUM_CONSENSUS_POWER.into());
assert_eq!(v14.minimum_consensus_power, MINIMUM_CONSENSUS_POWER.into());
}
}