diff --git a/src/blockdata/constants.rs b/src/blockdata/constants.rs index 8cbb5bd4..a7108d53 100644 --- a/src/blockdata/constants.rs +++ b/src/blockdata/constants.rs @@ -128,6 +128,19 @@ pub fn genesis_block(network: Network) -> Block { txdata: txdata } } + Network::Signet => { + Block { + header: BlockHeader { + version: 1, + prev_blockhash: Default::default(), + merkle_root, + time: 1598918400, + bits: 0x1e0377ae, + nonce: 52613770 + }, + txdata: txdata + } + } Network::Regtest => { Block { header: BlockHeader { @@ -204,5 +217,19 @@ mod test { assert_eq!(format!("{:x}", gen.header.block_hash()), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943".to_string()); } + + #[test] + fn signet_genesis_full_block() { + let gen = genesis_block(Network::Signet); + assert_eq!(gen.header.version, 1); + assert_eq!(gen.header.prev_blockhash, Default::default()); + assert_eq!(format!("{:x}", gen.header.merkle_root), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b".to_string()); + assert_eq!(gen.header.time, 1598918400); + assert_eq!(gen.header.bits, 0x1e0377ae); + assert_eq!(gen.header.nonce, 52613770); + assert_eq!(format!("{:x}", gen.header.block_hash()), + "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6".to_string()); + } } diff --git a/src/consensus/params.rs b/src/consensus/params.rs index c31bd16e..b3f62f45 100644 --- a/src/consensus/params.rs +++ b/src/consensus/params.rs @@ -34,6 +34,13 @@ const MAX_BITS_TESTNET: Uint256 = Uint256([ 0x0000000000000000u64, 0x00000000ffff0000u64, ]); +/// Lowest possible difficulty for Signet. See comment on Params::pow_limit for more info. +const MAX_BITS_SIGNET: Uint256 = Uint256([ + 0x0000000000000000u64, + 0x0000000000000000u64, + 0x0000000000000000u64, + 0x00000377ae000000u64, +]); /// Lowest possible difficulty for Regtest. See comment on Params::pow_limit for more info. const MAX_BITS_REGTEST: Uint256 = Uint256([ 0x0000000000000000u64, @@ -112,6 +119,20 @@ impl Params { allow_min_difficulty_blocks: true, no_pow_retargeting: false, }, + Network::Signet => Params { + network: Network::Signet, + bip16_time: 1333238400, // Apr 1 2012 + bip34_height: 1, + bip65_height: 1, + bip66_height: 1, + rule_change_activation_threshold: 1916, // 95% + miner_confirmation_window: 2016, + pow_limit: MAX_BITS_SIGNET, + pow_target_spacing: 10 * 60, // 10 minutes. + pow_target_timespan: 14 * 24 * 60 * 60, // 2 weeks. + allow_min_difficulty_blocks: false, + no_pow_retargeting: false, + }, Network::Regtest => Params { network: Network::Regtest, bip16_time: 1333238400, // Apr 1 2012 diff --git a/src/network/constants.rs b/src/network/constants.rs index 0540981a..ebdafee8 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -52,6 +52,8 @@ user_enum! { Bitcoin <-> "bitcoin", /// Bitcoin's testnet Testnet <-> "testnet", + /// Bitcoin's signet + Signet <-> "signet", /// Bitcoin's regtest Regtest <-> "regtest" } @@ -73,6 +75,7 @@ impl Network { match magic { 0xD9B4BEF9 => Some(Network::Bitcoin), 0x0709110B => Some(Network::Testnet), + 0x40CF030A => Some(Network::Signet), 0xDAB5BFFA => Some(Network::Regtest), _ => None } @@ -94,6 +97,7 @@ impl Network { match self { Network::Bitcoin => 0xD9B4BEF9, Network::Testnet => 0x0709110B, + Network::Signet => 0x40CF030A, Network::Regtest => 0xDAB5BFFA, } } @@ -285,6 +289,10 @@ mod tests { serialize(&Network::Testnet.magic()), &[0x0b, 0x11, 0x09, 0x07] ); + assert_eq!( + serialize(&Network::Signet.magic()), + &[0x0a, 0x03, 0xcf, 0x40] + ); assert_eq!( serialize(&Network::Regtest.magic()), &[0xfa, 0xbf, 0xb5, 0xda] @@ -298,6 +306,10 @@ mod tests { deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet.magic()) ); + assert_eq!( + deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), + Some(Network::Signet.magic()) + ); assert_eq!( deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest.magic()) @@ -309,10 +321,12 @@ mod tests { assert_eq!(Network::Bitcoin.to_string(), "bitcoin"); assert_eq!(Network::Testnet.to_string(), "testnet"); assert_eq!(Network::Regtest.to_string(), "regtest"); + assert_eq!(Network::Signet.to_string(), "signet"); assert_eq!("bitcoin".parse::().unwrap(), Network::Bitcoin); assert_eq!("testnet".parse::().unwrap(), Network::Testnet); assert_eq!("regtest".parse::().unwrap(), Network::Regtest); + assert_eq!("signet".parse::().unwrap(), Network::Signet); assert!("fakenet".parse::().is_err()); } diff --git a/src/util/address.rs b/src/util/address.rs index 771926ce..a8095346 100644 --- a/src/util/address.rs +++ b/src/util/address.rs @@ -365,7 +365,7 @@ impl Display for Address { let mut prefixed = [0; 21]; prefixed[0] = match self.network { Network::Bitcoin => 0, - Network::Testnet | Network::Regtest => 111, + Network::Testnet | Network::Signet | Network::Regtest => 111, }; prefixed[1..].copy_from_slice(&hash[..]); base58::check_encode_slice_to_fmt(fmt, &prefixed[..]) @@ -374,7 +374,7 @@ impl Display for Address { let mut prefixed = [0; 21]; prefixed[0] = match self.network { Network::Bitcoin => 5, - Network::Testnet | Network::Regtest => 196, + Network::Testnet | Network::Signet | Network::Regtest => 196, }; prefixed[1..].copy_from_slice(&hash[..]); base58::check_encode_slice_to_fmt(fmt, &prefixed[..]) @@ -385,7 +385,7 @@ impl Display for Address { } => { let hrp = match self.network { Network::Bitcoin => "bc", - Network::Testnet => "tb", + Network::Testnet | Network::Signet => "tb", Network::Regtest => "bcrt", }; let mut bech32_writer = bech32::Bech32Writer::new(hrp, fmt)?; @@ -414,7 +414,7 @@ impl FromStr for Address { let bech32_network = match find_bech32_prefix(s) { // note that upper or lowercase is allowed but NOT mixed case "bc" | "BC" => Some(Network::Bitcoin), - "tb" | "TB" => Some(Network::Testnet), + "tb" | "TB" => Some(Network::Testnet), // this may also be signet "bcrt" | "BCRT" => Some(Network::Regtest), _ => None, }; diff --git a/src/util/bip32.rs b/src/util/bip32.rs index 3fd8fc2b..282ffbd4 100644 --- a/src/util/bip32.rs +++ b/src/util/bip32.rs @@ -566,7 +566,7 @@ impl fmt::Display for ExtendedPrivKey { let mut ret = [0; 78]; ret[0..4].copy_from_slice(&match self.network { Network::Bitcoin => [0x04, 0x88, 0xAD, 0xE4], - Network::Testnet | Network::Regtest => [0x04, 0x35, 0x83, 0x94], + Network::Testnet | Network::Signet | Network::Regtest => [0x04, 0x35, 0x83, 0x94], }[..]); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); @@ -623,7 +623,7 @@ impl fmt::Display for ExtendedPubKey { let mut ret = [0; 78]; ret[0..4].copy_from_slice(&match self.network { Network::Bitcoin => [0x04u8, 0x88, 0xB2, 0x1E], - Network::Testnet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF], + Network::Testnet | Network::Signet | Network::Regtest => [0x04u8, 0x35, 0x87, 0xCF], }[..]); ret[4] = self.depth as u8; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); diff --git a/src/util/key.rs b/src/util/key.rs index 89946be7..7c7fd47d 100644 --- a/src/util/key.rs +++ b/src/util/key.rs @@ -173,7 +173,7 @@ impl PrivateKey { let mut ret = [0; 34]; ret[0] = match self.network { Network::Bitcoin => 128, - Network::Testnet | Network::Regtest => 239, + Network::Testnet | Network::Signet | Network::Regtest => 239, }; ret[1..33].copy_from_slice(&self.key[..]); let privkey = if self.compressed {