extern crate alloc;
use alloc::vec::Vec;
use core::ffi::c_uint;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::p2p::ServiceFlags;
use bitcoin::params::Params;
use bitcoin::Block;
use bitcoin::BlockHash;
use rustreexo::accumulator::node_hash::NodeHash;
use crate::prelude::*;
use crate::AssumeValidArg;
use crate::Network;
#[derive(Clone, Debug)]
pub struct ChainParams {
pub params: Params,
pub genesis: Block,
pub subsidy_halving_interval: u64,
pub pow_target_timespan: u64,
pub coinbase_maturity: u32,
pub segwit_activation_height: u32,
pub csv_activation_height: u32,
pub exceptions: HashMap<BlockHash, c_uint>,
pub network: bitcoin::Network,
}
pub struct DnsSeed {
pub network: Network,
pub seed: &'static str,
pub filters: ServiceFlags,
}
impl DnsSeed {
pub fn new(network: Network, seed: &'static str, filters: ServiceFlags) -> Self {
DnsSeed {
network,
seed,
filters,
}
}
}
#[derive(Debug, Clone)]
pub struct AssumeUtreexoValue {
pub block_hash: BlockHash,
pub height: u32,
pub roots: Vec<NodeHash>,
pub leaves: u64,
}
impl ChainParams {
pub fn get_assume_utreexo(network: Network) -> AssumeUtreexoValue {
let genesis = genesis_block(Params::new(network.into()));
match network {
Network::Bitcoin => AssumeUtreexoValue {
block_hash: BlockHash::from_str(
"00000000000000000000569f4d863c27e667cbee8acc8da195e7e5551658e6e9",
)
.unwrap(),
height: 855571,
roots: [
"4dcc014cc23611dda2dcf0f34a3e62e7d302146df4b0b01ac701d440358c19d6",
"988e0a883e4ad0c5559432f4747395115112755ec1138dcdd62e2f5741c31c2c",
"49ecba683e12823d44f2ad190120d3028386d8bb7860a3eea62a250a1f293c60",
"7c02e55ae35f12501134f0b81a351abb6c5e7a2529641d0c537a7534a560c770",
"59cb07c73d71164ce1a4f953cfd01ef0e3269080e29d34022d4251523cb1e8ac",
"ff96c9983b6765092403f8089fe5d0cdd6a94c58e4dcd14e77570c8b10c17628",
"47ed934529b2ea03a7382febcf0c05e0bfc5884cc1235c2ad42624a56234b9a6",
"d5c9373ed35de281d426888bd656f04a36623197a33706932ab82014d67f26ae",
"05de50991df991f0b78d9166d06ce3c61cb29e07dc7c53ba75d75df6455e6967",
"ebfdaf53b7240e9cd25d7c63b35d462763253f9282cc97d8d0c92ea9ade6aa02",
"c349b6850f75346224cf7cf1e0a69e194306c59489017cd4f4a045c001f1fefc",
"7edfd925905e88fd14c47edaaf09606cf0ae19f3b898239a2feb607d175d9a90",
"442dadd38fd16949d2ef03d799aa6b61ad8c0b7c611aaa5e218bc6360c4f41ce",
"2a57b73e540c7a72cb44fdc4ab7fcc3f0f148be7885667f07fce345430f08a15",
"66dc66000a8baaacacef280783a0245b4d33bd7eba5f1f14b939bd3a54e135cb",
"67ba89afe6bce9bafbf0b88013e4446c861e6c746e291c3921e0b65c93671ba3",
"972ea2c7472c22e4eab49e9c2db5757a048b271b6251883ce89ccfeaa38b47ab",
]
.into_iter()
.map(|x| NodeHash::from_str(x).unwrap())
.collect(),
leaves: 2587882501,
},
Network::Testnet => AssumeUtreexoValue {
block_hash: genesis.block_hash(),
height: 0,
leaves: 0,
roots: Vec::new(),
},
Network::Signet => AssumeUtreexoValue {
block_hash: genesis.block_hash(),
height: 0,
leaves: 0,
roots: Vec::new(),
},
Network::Regtest => AssumeUtreexoValue {
block_hash: genesis.block_hash(),
height: 0,
leaves: 0,
roots: Vec::new(),
},
}
}
pub fn get_assume_valid(network: Network, arg: AssumeValidArg) -> Option<BlockHash> {
fn get_hash(hash: &str) -> BlockHash {
BlockHash::from_str(hash).expect("hardcoded hash should not fail")
}
match arg {
AssumeValidArg::Disabled => None,
AssumeValidArg::UserInput(hash) => Some(hash),
AssumeValidArg::Hardcoded => match network {
Network::Bitcoin => {
get_hash("00000000000000000000569f4d863c27e667cbee8acc8da195e7e5551658e6e9")
.into()
}
Network::Testnet => {
get_hash("000000000000001142ad197bff16a1393290fca09e4ca904dd89e7ae98a90fcd")
.into()
}
Network::Signet => {
get_hash("0000003ed17b9c93954daab00d73ccbd0092074c4ebfc751c7458d58b827dfea")
.into()
}
Network::Regtest => {
get_hash("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206")
.into()
}
},
}
}
}
#[cfg(feature = "bitcoinconsensus")]
fn get_exceptions() -> HashMap<BlockHash, c_uint> {
use bitcoinconsensus::VERIFY_NONE;
use bitcoinconsensus::VERIFY_P2SH;
use bitcoinconsensus::VERIFY_WITNESS;
let mut exceptions = HashMap::new();
exceptions.insert(
BlockHash::from_str("00000000000002dc756eebf4f49723ed8d30cc28a5f108eb94b1ba88ac4f9c22")
.unwrap(),
VERIFY_NONE,
); exceptions.insert(
BlockHash::from_str("0000000000000000000f14c35b2d841e986ab5441de8c585d5ffe55ea1e395ad")
.unwrap(),
VERIFY_P2SH | VERIFY_WITNESS,
); exceptions.insert(
BlockHash::from_str("00000000dd30457c001f4095d208cc1296b0eed002427aa599874af7a432b105")
.unwrap(),
VERIFY_NONE,
); exceptions
}
#[cfg(not(feature = "bitcoinconsensus"))]
fn get_exceptions() -> HashMap<BlockHash, c_uint> {
HashMap::new()
}
impl AsRef<Params> for ChainParams {
fn as_ref(&self) -> &Params {
&self.params
}
}
impl From<Network> for ChainParams {
fn from(net: Network) -> Self {
let genesis = genesis_block(Params::new(net.into()));
let exceptions = get_exceptions();
match net {
Network::Bitcoin => ChainParams {
params: Params::new(net.into()),
network: net.into(),
genesis,
pow_target_timespan: 14 * 24 * 60 * 60, subsidy_halving_interval: 210_000,
coinbase_maturity: 100,
segwit_activation_height: 481824,
csv_activation_height: 419328,
exceptions,
},
Network::Testnet => ChainParams {
params: Params::new(net.into()),
network: net.into(),
genesis,
pow_target_timespan: 14 * 24 * 60 * 60, subsidy_halving_interval: 210_000,
coinbase_maturity: 100,
segwit_activation_height: 834_624,
csv_activation_height: 770_112,
exceptions,
},
Network::Signet => ChainParams {
params: Params::new(net.into()),
network: net.into(),
genesis,
pow_target_timespan: 14 * 24 * 60 * 60, subsidy_halving_interval: 210_000,
coinbase_maturity: 100,
csv_activation_height: 1,
segwit_activation_height: 1,
exceptions,
},
Network::Regtest => ChainParams {
params: Params::new(net.into()),
network: net.into(),
genesis,
pow_target_timespan: 14 * 24 * 60 * 60, subsidy_halving_interval: 150,
coinbase_maturity: 100,
csv_activation_height: 0,
segwit_activation_height: 0,
exceptions,
},
}
}
}
pub fn get_chain_dns_seeds(network: Network) -> Vec<DnsSeed> {
let mut seeds = Vec::new();
let x9: ServiceFlags = ServiceFlags::from(0x9);
let x49 = ServiceFlags::from(0x49);
let x1000049 = ServiceFlags::from(0x1000049);
let none = ServiceFlags::NONE;
match network {
Network::Bitcoin => {
seeds.push(DnsSeed::new(
Network::Bitcoin,
"seed.bitcoin.sipa.be",
x9, ));
seeds.push(DnsSeed::new(Network::Bitcoin, "dnsseed.bluematt.me", x49));
seeds.push(DnsSeed::new(
Network::Bitcoin,
"dnsseed.bitcoin.dashjr.org",
none, ));
seeds.push(DnsSeed::new(Network::Bitcoin, "seed.bitcoinstats.com", x49));
seeds.push(DnsSeed::new(
Network::Bitcoin,
"seed.bitcoin.jonasschnelli.ch",
x49,
));
seeds.push(DnsSeed::new(
Network::Bitcoin,
"seed.btc.petertodd.org",
x49,
));
seeds.push(DnsSeed::new(
Network::Bitcoin,
"seed.bitcoin.sprovoost.nl",
x49,
));
seeds.push(DnsSeed::new(Network::Bitcoin, "dnsseed.emzy.de", x49));
seeds.push(DnsSeed::new(Network::Bitcoin, "seed.bitcoin.wiz.biz", x49));
}
Network::Testnet => {
seeds.push(DnsSeed::new(
Network::Testnet,
"testnet-seed.bitcoin.jonasschnelli.ch",
x49,
));
seeds.push(DnsSeed::new(
Network::Testnet,
"seed.tbtc.petertodd.org",
x49,
));
seeds.push(DnsSeed::new(
Network::Testnet,
"seed.testnet.bitcoin.sprovoost.nl",
x49,
));
seeds.push(DnsSeed::new(
Network::Testnet,
"testnet-seed.bluematt.me",
none,
));
}
Network::Signet => {
seeds.push(DnsSeed::new(
Network::Signet,
"seed.signet.bitcoin.sprovoost.nl",
x49,
));
seeds.push(DnsSeed::new(Network::Signet, "seed.dlsouza.lol", x1000049));
}
Network::Regtest => {
}
};
seeds
}