From 4b36d64c69e3fcabc9e75049ce423e81f019add8 Mon Sep 17 00:00:00 2001 From: Hajime Yamaguchi Date: Tue, 24 Dec 2019 13:29:27 +0900 Subject: [PATCH] Support new network mode (Prod and Dev) --- .../tapyrus/deserialize_script.rs | 2 +- tapyrus/embedded/src/main.rs | 2 +- tapyrus/examples/bip32.rs | 2 +- tapyrus/examples/ecdsa-psbt.rs | 4 +- tapyrus/examples/handshake.rs | 8 +- tapyrus/examples/taproot-psbt.rs | 4 +- tapyrus/src/address/mod.rs | 236 ++++++------- tapyrus/src/bip32.rs | 72 ++-- tapyrus/src/blockdata/block.rs | 6 +- tapyrus/src/blockdata/constants.rs | 325 ++++++++---------- tapyrus/src/blockdata/transaction.rs | 13 - tapyrus/src/consensus/params.rs | 34 +- tapyrus/src/crypto/key.rs | 14 +- tapyrus/src/network.rs | 219 ++++-------- tapyrus/src/p2p/message.rs | 31 +- tapyrus/src/p2p/mod.rs | 57 +-- tapyrus/src/psbt/mod.rs | 6 +- tapyrus/src/sign_message.rs | 8 +- tapyrus/src/taproot.rs | 2 +- tapyrus/tests/psbt.rs | 2 +- tapyrus/tests/serde.rs | 2 +- 21 files changed, 426 insertions(+), 623 deletions(-) diff --git a/fuzz/fuzz_targets/tapyrus/deserialize_script.rs b/fuzz/fuzz_targets/tapyrus/deserialize_script.rs index 86b9b57d..973f1542 100644 --- a/fuzz/fuzz_targets/tapyrus/deserialize_script.rs +++ b/fuzz/fuzz_targets/tapyrus/deserialize_script.rs @@ -38,7 +38,7 @@ fn do_test(data: &[u8]) { assert_eq!(data, &encode::serialize(&script)[..]); // Check if valid address and if that address roundtrips. - if let Ok(addr) = Address::from_script(&script, Network::Bitcoin) { + if let Ok(addr) = Address::from_script(&script, Network::Prod) { assert_eq!(addr.script_pubkey(), script); } } diff --git a/tapyrus/embedded/src/main.rs b/tapyrus/embedded/src/main.rs index 33b7b64a..02672d48 100644 --- a/tapyrus/embedded/src/main.rs +++ b/tapyrus/embedded/src/main.rs @@ -44,7 +44,7 @@ fn main() -> ! { // Derive address let pubkey = pk.public_key(&secp); - let address = Address::p2wpkh(&pubkey, Network::Bitcoin).unwrap(); + let address = Address::p2wpkh(&pubkey, Network::Prod).unwrap(); hprintln!("Address: {}", address).unwrap(); assert_eq!(address.to_string(), "bc1qpx9t9pzzl4qsydmhyt6ctrxxjd4ep549np9993".to_string()); diff --git a/tapyrus/examples/bip32.rs b/tapyrus/examples/bip32.rs index 61b95289..c8b6fb48 100644 --- a/tapyrus/examples/bip32.rs +++ b/tapyrus/examples/bip32.rs @@ -28,7 +28,7 @@ fn main() { println!("Seed: {}", seed_hex); // default network as mainnet - let network = tapyrus::Network::Bitcoin; + let network = tapyrus::Network::Prod; println!("Network: {:?}", network); let seed = Vec::from_hex(seed_hex).unwrap(); diff --git a/tapyrus/examples/ecdsa-psbt.rs b/tapyrus/examples/ecdsa-psbt.rs index c5c0c7f3..835482d2 100644 --- a/tapyrus/examples/ecdsa-psbt.rs +++ b/tapyrus/examples/ecdsa-psbt.rs @@ -64,7 +64,7 @@ const RECEIVE_ADDRESS: &str = "bcrt1qcmnpjjjw78yhyjrxtql6lk7pzpujs3h244p7ae"; // const OUTPUT_AMOUNT_BTC: &str = "1 BTC"; const CHANGE_AMOUNT_BTC: &str = "48.99999 BTC"; // 1000 sat transaction fee. -const NETWORK: Network = Network::Regtest; +const NETWORK: Network = Network::Dev; fn main() -> Result<()> { let secp = Secp256k1::new(); @@ -170,7 +170,7 @@ impl WatchOnly { /// Creates the PSBT, in BIP174 parlance this is the 'Creater'. fn create_psbt(&self, secp: &Secp256k1) -> Result { - let to_address = Address::from_str(RECEIVE_ADDRESS)?.require_network(Network::Regtest)?; + let to_address = Address::from_str(RECEIVE_ADDRESS)?.require_network(Network::Dev)?; let to_amount = Amount::from_str(OUTPUT_AMOUNT_BTC)?; let (_, change_address, _) = self.change_address(secp)?; diff --git a/tapyrus/examples/handshake.rs b/tapyrus/examples/handshake.rs index 9a35fb9e..86def45b 100644 --- a/tapyrus/examples/handshake.rs +++ b/tapyrus/examples/handshake.rs @@ -6,9 +6,10 @@ use std::time::{SystemTime, UNIX_EPOCH}; use std::{env, process}; use tapyrus::consensus::{encode, Decodable}; -use tapyrus::p2p::{self, address, message, message_network}; +use tapyrus::p2p::{self, address, message, message_network, Magic}; use tapyrus::secp256k1; use tapyrus::secp256k1::rand::Rng; +use tapyrus::network::NetworkId; fn main() { // This example establishes a connection to a Bitcoin node, sends the intial @@ -28,8 +29,9 @@ fn main() { let version_message = build_version_message(address); + let magic = Magic::from_bytes(NetworkId::from(1).magic().to_be_bytes()); let first_message = - message::RawNetworkMessage::new(tapyrus::Network::Bitcoin.magic(), version_message); + message::RawNetworkMessage::new(magic , version_message); if let Ok(mut stream) = TcpStream::connect(address) { // Send the message @@ -47,7 +49,7 @@ fn main() { println!("Received version message: {:?}", reply.payload()); let second_message = message::RawNetworkMessage::new( - tapyrus::Network::Bitcoin.magic(), + magic, message::NetworkMessage::Verack, ); diff --git a/tapyrus/examples/taproot-psbt.rs b/tapyrus/examples/taproot-psbt.rs index def52af5..e2b36a2c 100644 --- a/tapyrus/examples/taproot-psbt.rs +++ b/tapyrus/examples/taproot-psbt.rs @@ -101,10 +101,10 @@ fn main() -> Result<(), Box> { // Just some addresses for outputs from our wallets. Not really important. let to_address = Address::from_str("bcrt1p0p3rvwww0v9znrclp00uneq8ytre9kj922v8fxhnezm3mgsmn9usdxaefc")? - .require_network(Network::Regtest)?; + .require_network(Network::Dev)?; let change_address = Address::from_str("bcrt1pz449kexzydh2kaypatup5ultru3ej284t6eguhnkn6wkhswt0l7q3a7j76")? - .require_network(Network::Regtest)?; + .require_network(Network::Dev)?; let amount_to_send_in_sats = Amount::ONE_BTC; let change_amount = UTXO_1 .amount_in_sats diff --git a/tapyrus/src/address/mod.rs b/tapyrus/src/address/mod.rs index 385e7552..7b519459 100644 --- a/tapyrus/src/address/mod.rs +++ b/tapyrus/src/address/mod.rs @@ -16,7 +16,7 @@ //! let public_key = PublicKey::new(s.generate_keypair(&mut rand::thread_rng()).1); //! //! // Generate pay-to-pubkey-hash address. -//! let address = Address::p2pkh(&public_key, Network::Bitcoin); +//! let address = Address::p2pkh(&public_key, Network::Prod); //! # } //! ``` //! @@ -339,15 +339,15 @@ struct AddressInner { /// /// // variant 1 /// let address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap(); -/// let address: Address = address.require_network(Network::Bitcoin).unwrap(); +/// let address: Address = address.require_network(Network::Prod).unwrap(); /// /// // variant 2 /// let address: Address = Address::from_str("32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf").unwrap() -/// .require_network(Network::Bitcoin).unwrap(); +/// .require_network(Network::Prod).unwrap(); /// /// // variant 3 /// let address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse::>() -/// .unwrap().require_network(Network::Bitcoin).unwrap(); +/// .unwrap().require_network(Network::Prod).unwrap(); /// ``` /// /// ### Formatting addresses @@ -486,17 +486,16 @@ impl Address { /// Format the address for the usage by `Debug` and `Display` implementations. fn fmt_internal(&self, fmt: &mut fmt::Formatter) -> fmt::Result { let p2pkh_prefix = match self.network() { - Network::Bitcoin | Network::Paradium => PUBKEY_ADDRESS_PREFIX_MAIN, - Network::Testnet | Network::Signet | Network::Regtest => PUBKEY_ADDRESS_PREFIX_TEST, + Network::Prod => PUBKEY_ADDRESS_PREFIX_MAIN, + Network::Dev => PUBKEY_ADDRESS_PREFIX_TEST, }; let p2sh_prefix = match self.network() { - Network::Bitcoin | Network::Paradium => SCRIPT_ADDRESS_PREFIX_MAIN, - Network::Testnet | Network::Signet | Network::Regtest => SCRIPT_ADDRESS_PREFIX_TEST, + Network::Prod => SCRIPT_ADDRESS_PREFIX_MAIN, + Network::Dev => SCRIPT_ADDRESS_PREFIX_TEST, }; let hrp = match self.network() { - Network::Bitcoin | Network::Paradium => hrp::BC, - Network::Testnet | Network::Signet => hrp::TB, - Network::Regtest => hrp::BCRT, + Network::Prod => hrp::BC, + Network::Dev => hrp::TB, }; let encoding = AddressEncoding { payload: self.payload(), p2pkh_prefix, p2sh_prefix, hrp }; @@ -689,28 +688,18 @@ impl Address { /// use tapyrus::address::NetworkUnchecked; /// /// let address: Address = "2N83imGV3gPwBzKJQvWJ7cRUY2SpUyU6A5e".parse().unwrap(); - /// assert!(address.is_valid_for_network(Network::Testnet)); - /// assert!(address.is_valid_for_network(Network::Regtest)); - /// assert!(address.is_valid_for_network(Network::Signet)); + /// assert!(address.is_valid_for_network(Network::Dev)); /// - /// assert_eq!(address.is_valid_for_network(Network::Bitcoin), false); + /// assert_eq!(address.is_valid_for_network(Network::Prod), false); /// /// let address: Address = "32iVBEu4dxkUQk9dJbZUiBiQdmypcEyJRf".parse().unwrap(); - /// assert!(address.is_valid_for_network(Network::Bitcoin)); - /// assert_eq!(address.is_valid_for_network(Network::Testnet), false); + /// assert!(address.is_valid_for_network(Network::Prod)); + /// assert_eq!(address.is_valid_for_network(Network::Dev), false); /// ``` pub fn is_valid_for_network(&self, network: Network) -> bool { - let is_legacy = matches!( - self.address_type_internal(), - Some(AddressType::P2pkh) | Some(AddressType::P2sh) - ); - match (self.network(), network) { (a, b) if *a == b => true, - (Network::Bitcoin, _) | (_, Network::Bitcoin) => false, - (Network::Paradium, _) | (_, Network::Paradium) => false, - (Network::Regtest, _) | (_, Network::Regtest) if !is_legacy => false, - (Network::Testnet, _) | (Network::Regtest, _) | (Network::Signet, _) => true, + (_, _) => false, } } @@ -793,9 +782,9 @@ impl FromStr for Address { // try bech32 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), // this may also be signet - "bcrt" | "BCRT" => Some(Network::Regtest), + "bc" | "BC" => Some(Network::Prod), + "tb" | "TB" => Some(Network::Prod), + "bcrt" | "BCRT" => Some(Network::Dev), _ => None, }; if let Some(network) = bech32_network { @@ -818,13 +807,13 @@ impl FromStr for Address { let (network, payload) = match data[0] { PUBKEY_ADDRESS_PREFIX_MAIN => - (Network::Bitcoin, Payload::PubkeyHash(PubkeyHash::from_slice(&data[1..]).unwrap())), + (Network::Prod, Payload::PubkeyHash(PubkeyHash::from_slice(&data[1..]).unwrap())), SCRIPT_ADDRESS_PREFIX_MAIN => - (Network::Bitcoin, Payload::ScriptHash(ScriptHash::from_slice(&data[1..]).unwrap())), + (Network::Prod, Payload::ScriptHash(ScriptHash::from_slice(&data[1..]).unwrap())), PUBKEY_ADDRESS_PREFIX_TEST => - (Network::Testnet, Payload::PubkeyHash(PubkeyHash::from_slice(&data[1..]).unwrap())), + (Network::Dev, Payload::PubkeyHash(PubkeyHash::from_slice(&data[1..]).unwrap())), SCRIPT_ADDRESS_PREFIX_TEST => - (Network::Testnet, Payload::ScriptHash(ScriptHash::from_slice(&data[1..]).unwrap())), + (Network::Dev, Payload::ScriptHash(ScriptHash::from_slice(&data[1..]).unwrap())), x => return Err(ParseError::Base58(base58::Error::InvalidAddressVersion(x))), }; @@ -849,7 +838,7 @@ mod tests { use super::*; use crate::crypto::key::PublicKey; - use crate::network::Network::{Bitcoin, Testnet}; + use crate::network::Network::{Dev, Prod}; fn roundtrips(addr: &Address) { assert_eq!( @@ -877,7 +866,7 @@ mod tests { #[test] fn test_p2pkh_address_58() { let addr = Address::new( - Bitcoin, + Prod, Payload::PubkeyHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()), ); @@ -893,13 +882,13 @@ mod tests { #[test] fn test_p2pkh_from_key() { let key = "048d5141948c1702e8c95f438815794b87f706a8d4cd2bffad1dc1570971032c9b6042a0431ded2478b5c9cf2d81c124a5e57347a3c63ef0e7716cf54d613ba183".parse::().unwrap(); - let addr = Address::p2pkh(&key, Bitcoin); + let addr = Address::p2pkh(&key, Prod); assert_eq!(&addr.to_string(), "1QJVDzdqb1VpbDK7uDeyVXy9mR27CJiyhY"); let key = "03df154ebfcf29d29cc10d5c2565018bce2d9edbab267c31d2caf44a63056cf99f" .parse::() .unwrap(); - let addr = Address::p2pkh(&key, Testnet); + let addr = Address::p2pkh(&key, Dev); assert_eq!(&addr.to_string(), "mqkhEMH6NCeYjFybv7pvFC22MFeaNT9AQC"); assert_eq!(addr.address_type(), Some(AddressType::P2pkh)); roundtrips(&addr); @@ -908,7 +897,7 @@ mod tests { #[test] fn test_p2sh_address_58() { let addr = Address::new( - Bitcoin, + Prod, Payload::ScriptHash("162c5ea71c0b23f5b9022ef047c4a86470a5b070".parse().unwrap()), ); @@ -924,7 +913,7 @@ mod tests { #[test] fn test_p2sh_parse() { let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae").unwrap(); - let addr = Address::p2sh(&script, Testnet).unwrap(); + let addr = Address::p2sh(&script, Dev).unwrap(); assert_eq!(&addr.to_string(), "2N3zXjbwdTcPsJiy8sUK9FhWJhqQCxA8Jjr"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); roundtrips(&addr); @@ -933,30 +922,32 @@ mod tests { #[test] fn test_p2sh_parse_for_large_script() { let script = ScriptBuf::from_hex("552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123552103a765fc35b3f210b95223846b36ef62a4e53e34e2925270c2c7906b92c9f718eb2103c327511374246759ec8d0b89fa6c6b23b33e11f92c5bc155409d86de0c79180121038cae7406af1f12f4786d820a1466eec7bc5785a1b5e4a387eca6d797753ef6db2103252bfb9dcaab0cd00353f2ac328954d791270203d66c2be8b430f115f451b8a12103e79412d42372c55dd336f2eb6eb639ef9d74a22041ba79382c74da2338fe58ad21035049459a4ebc00e876a9eef02e72a3e70202d3d1f591fc0dd542f93f642021f82102016f682920d9723c61b27f562eb530c926c00106004798b6471e8c52c60ee02057ae12123122313123123ac1231231231231313123131231231231313212313213123123").unwrap(); - assert_eq!(Address::p2sh(&script, Testnet), Err(Error::ExcessiveScriptSize)); + assert_eq!(Address::p2sh(&script, Dev), Err(Error::ExcessiveScriptSize)); } #[test] + #[ignore] // Segwit address does not support fn test_p2wpkh() { // stolen from Bitcoin transaction: b3c8c2b6cfc335abbcb2c7823a8453f55d64b2b5125a9a61e8737230cdb8ce20 let mut key = "033bc8c83c52df5712229a2f72206d90192366c36428cb0c12b6af98324d97bfbc" .parse::() .unwrap(); - let addr = Address::p2wpkh(&key, Bitcoin).unwrap(); + let addr = Address::p2wpkh(&key, Prod).unwrap(); assert_eq!(&addr.to_string(), "bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw"); assert_eq!(addr.address_type(), Some(AddressType::P2wpkh)); roundtrips(&addr); // Test uncompressed pubkey key.compressed = false; - assert_eq!(Address::p2wpkh(&key, Bitcoin), Err(Error::UncompressedPubkey)); + assert_eq!(Address::p2wpkh(&key, Prod), Err(Error::UncompressedPubkey)); } #[test] + #[ignore] // Segwit address does not support fn test_p2wsh() { // stolen from Bitcoin transaction 5df912fda4becb1c29e928bec8d64d93e9ba8efa9b5b405bd683c86fd2c65667 let script = ScriptBuf::from_hex("52210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f88053ae").unwrap(); - let addr = Address::p2wsh(&script, Bitcoin); + let addr = Address::p2wsh(&script, Prod); assert_eq!( &addr.to_string(), "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej" @@ -971,21 +962,21 @@ mod tests { let mut key = "026c468be64d22761c30cd2f12cbc7de255d592d7904b1bab07236897cc4c2e766" .parse::() .unwrap(); - let addr = Address::p2shwpkh(&key, Bitcoin).unwrap(); + let addr = Address::p2shwpkh(&key, Prod).unwrap(); assert_eq!(&addr.to_string(), "3QBRmWNqqBGme9er7fMkGqtZtp4gjMFxhE"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); roundtrips(&addr); // Test uncompressed pubkey key.compressed = false; - assert_eq!(Address::p2wpkh(&key, Bitcoin), Err(Error::UncompressedPubkey)); + assert_eq!(Address::p2wpkh(&key, Prod), Err(Error::UncompressedPubkey)); } #[test] fn test_p2shwsh() { // stolen from Bitcoin transaction f9ee2be4df05041d0e0a35d7caa3157495ca4f93b233234c9967b6901dacf7a9 let script = ScriptBuf::from_hex("522103e5529d8eaa3d559903adb2e881eb06c86ac2574ffa503c45f4e942e2a693b33e2102e5f10fcdcdbab211e0af6a481f5532536ec61a5fdbf7183770cf8680fe729d8152ae").unwrap(); - let addr = Address::p2shwsh(&script, Bitcoin); + let addr = Address::p2shwsh(&script, Prod); assert_eq!(&addr.to_string(), "36EqgNnsWW94SreZgBWc1ANC6wpFZwirHr"); assert_eq!(addr.address_type(), Some(AddressType::P2sh)); roundtrips(&addr); @@ -998,7 +989,7 @@ mod tests { "654f6ea368e0acdfd92976b7c2103a1b26313f430654f6ea368e0acdfd92976b7c2103a1b26313f4" ); let witness_prog = WitnessProgram::new(WitnessVersion::V13, program.to_vec()).unwrap(); - let addr = Address::new(Bitcoin, Payload::WitnessProgram(witness_prog)); + let addr = Address::new(Prod, Payload::WitnessProgram(witness_prog)); roundtrips(&addr); } @@ -1049,7 +1040,7 @@ mod tests { for (address, expected_type) in &addresses { let addr = Address::from_str(address) .unwrap() - .require_network(Network::Bitcoin) + .require_network(Network::Prod) .expect("mainnet"); assert_eq!(&addr.address_type(), expected_type); } @@ -1088,52 +1079,54 @@ mod tests { ScriptBuf::from_hex("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087").unwrap() ); - let addr: Address = - Address::from_str("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7") - .unwrap(); - let json = serde_json::to_value(addr).unwrap(); - assert_eq!( - json, - serde_json::Value::String( - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7".to_owned() - ) - ); - - let addr = - Address::from_str("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7") - .unwrap() - .assume_checked(); - let json = serde_json::to_value(&addr).unwrap(); - assert_eq!( - json, - serde_json::Value::String( - "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7".to_owned() - ) - ); - let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); - assert_eq!(addr.to_string(), into.to_string()); - assert_eq!( - into.script_pubkey(), - ScriptBuf::from_hex( - "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262" - ) - .unwrap() - ); - - let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl") - .unwrap() - .assume_checked(); - let json = serde_json::to_value(&addr).unwrap(); - assert_eq!( - json, - serde_json::Value::String("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl".to_owned()) - ); - let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); - assert_eq!(addr.to_string(), into.to_string()); - assert_eq!( - into.script_pubkey(), - ScriptBuf::from_hex("001454d26dddb59c7073c6a197946ea1841951fa7a74").unwrap() - ); + // Segwit address does not support + // let addr: Address = + // Address::from_str("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7") + // .unwrap(); + // let json = serde_json::to_value(addr).unwrap(); + // assert_eq!( + // json, + // serde_json::Value::String( + // "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7".to_owned() + // ) + // ); + + // let addr = + // Address::from_str("tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7") + // .unwrap() + // .assume_checked(); + // let json = serde_json::to_value(&addr).unwrap(); + // assert_eq!( + // json, + // serde_json::Value::String( + // "tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7".to_owned() + // ) + // ); + // let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); + // assert_eq!(addr.to_string(), into.to_string()); + // assert_eq!( + // into.script_pubkey(), + // ScriptBuf::from_hex( + // "00201863143c14c5166804bd19203356da136c985678cd4d27a1b8c6329604903262" + // ) + // .unwrap() + // ); + + // Segwit address does not support + // let addr = Address::from_str("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl") + // .unwrap() + // .assume_checked(); + // let json = serde_json::to_value(&addr).unwrap(); + // assert_eq!( + // json, + // serde_json::Value::String("bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl".to_owned()) + // ); + // let into: Address = serde_json::from_value::>(json).unwrap().assume_checked(); + // assert_eq!(addr.to_string(), into.to_string()); + // assert_eq!( + // into.script_pubkey(), + // ScriptBuf::from_hex("001454d26dddb59c7073c6a197946ea1841951fa7a74").unwrap() + // ); } #[test] @@ -1142,19 +1135,20 @@ mod tests { ["132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k"].iter() { let addr = - Address::from_str(el).unwrap().require_network(Network::Bitcoin).expect("mainnet"); + Address::from_str(el).unwrap().require_network(Network::Prod).expect("mainnet"); assert_eq!(addr.to_qr_uri(), format!("tapyrus:{}", el)); } - for el in [ - "bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl", - "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", - ] - .iter() - { - let addr = Address::from_str(el).unwrap().assume_checked(); - assert_eq!(addr.to_qr_uri(), format!("tapyrus:{}", el.to_ascii_uppercase())); - } + // Segwit address does not support + // for el in [ + // "bcrt1q2nfxmhd4n3c8834pj72xagvyr9gl57n5r94fsl", + // "bc1qwqdg6squsna38e46795at95yu9atm8azzmyvckulcc7kytlcckxswvvzej", + // ] + // .iter() + // { + // let addr = Address::from_str(el).unwrap().assume_checked(); + // assert_eq!(addr.to_qr_uri(), format!("tapyrus:{}", el.to_ascii_uppercase())); + // } } #[test] @@ -1175,10 +1169,8 @@ mod tests { }) .collect::>(); - const LEGACY_EQUIVALENCE_CLASSES: &[&[Network]] = - &[&[Network::Bitcoin], &[Network::Testnet, Network::Regtest, Network::Signet]]; - const SEGWIT_EQUIVALENCE_CLASSES: &[&[Network]] = - &[&[Network::Bitcoin], &[Network::Regtest], &[Network::Testnet, Network::Signet]]; + const LEGACY_EQUIVALENCE_CLASSES: &[&[Network]] = &[&[Network::Prod], &[Network::Dev]]; + const SEGWIT_EQUIVALENCE_CLASSES: &[&[Network]] = &[&[Network::Prod], &[Network::Dev]]; fn test_addr_type(payloads: &[Payload], equivalence_classes: &[&[Network]]) { for pl in payloads { @@ -1216,7 +1208,7 @@ mod tests { ) .unwrap(); let secp = Secp256k1::verification_only(); - let address = Address::p2tr(&secp, internal_key, None, Network::Bitcoin); + let address = Address::p2tr(&secp, internal_key, None, Network::Prod); assert_eq!( address.to_string(), "bc1p5cyxnuxmeuwuvkwfem96lqzszd02n6xdcjrs20cac6yqjjwudpxqkedrcr" @@ -1230,7 +1222,7 @@ mod tests { let address_string = "bc1qhvd6suvqzjcu9pxjhrwhtrlj85ny3n2mqql5w4"; let address = Address::from_str(address_string) .expect("address") - .require_network(Network::Bitcoin) + .require_network(Network::Prod) .expect("mainnet"); let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; @@ -1251,7 +1243,7 @@ mod tests { let address_string = "3EZQk4F8GURH5sqVMLTFisD17yNeKa7Dfs"; let address = Address::from_str(address_string) .expect("address") - .require_network(Network::Bitcoin) + .require_network(Network::Prod) .expect("mainnet"); let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; @@ -1272,7 +1264,7 @@ mod tests { let address_string = "1J4LVanjHMu3JkXbVrahNuQCTGCRRgfWWx"; let address = Address::from_str(address_string) .expect("address") - .require_network(Network::Bitcoin) + .require_network(Network::Prod) .expect("mainnet"); let pubkey_string = "0347ff3dacd07a1f43805ec6808e801505a6e18245178609972a68afbc2777ff2b"; @@ -1293,7 +1285,7 @@ mod tests { let address_string = "msvS7KzhReCDpQEJaV2hmGNvuQqVUDuC6p"; let address = Address::from_str(address_string) .expect("address") - .require_network(Network::Testnet) + .require_network(Network::Dev) .expect("testnet"); let pubkey_string = "04e96e22004e3db93530de27ccddfdf1463975d2138ac018fc3e7ba1a2e5e0aad8e424d0b55e2436eb1d0dcd5cb2b8bcc6d53412c22f358de57803a6a655fbbd04"; @@ -1315,13 +1307,13 @@ mod tests { let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(xonly_pubkey); - let address = Address::p2tr_tweaked(tweaked_pubkey, Network::Bitcoin); + let address = Address::p2tr_tweaked(tweaked_pubkey, Network::Prod); assert_eq!( address, Address::from_str("bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e") .expect("address") - .require_network(Network::Bitcoin) + .require_network(Network::Prod) .expect("mainnet") ); @@ -1341,13 +1333,13 @@ mod tests { let pubkey = PublicKey::from_str(pubkey_string).expect("pubkey"); let xonly_pubkey = XOnlyPublicKey::from(pubkey.inner); let tweaked_pubkey = TweakedPublicKey::dangerous_assume_tweaked(xonly_pubkey); - let address = Address::p2tr_tweaked(tweaked_pubkey, Network::Bitcoin); + let address = Address::p2tr_tweaked(tweaked_pubkey, Network::Prod); assert_eq!( address, Address::from_str("bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e") .expect("address") - .require_network(Network::Bitcoin) + .require_network(Network::Prod) .expect("mainnet") ); @@ -1368,10 +1360,10 @@ mod tests { ScriptBuf::from_hex("001161458e330389cd0437ee9fe3641d70cc18").unwrap(); let expected = Err(Error::UnrecognizedScript); - assert_eq!(Address::from_script(&bad_p2wpkh, Network::Bitcoin), expected); - assert_eq!(Address::from_script(&bad_p2wsh, Network::Bitcoin), expected); + assert_eq!(Address::from_script(&bad_p2wpkh, Network::Prod), expected); + assert_eq!(Address::from_script(&bad_p2wsh, Network::Prod), expected); assert_eq!( - Address::from_script(&invalid_segwitv0_script, Network::Bitcoin), + Address::from_script(&invalid_segwitv0_script, Network::Prod), Err(Error::WitnessProgram(witness_program::Error::InvalidSegwitV0Length(17))) ); } @@ -1402,10 +1394,10 @@ mod tests { "bc1pgllnmtxs0g058qz7c6qgaqq4qknwrqj9z7rqn9e2dzhmcfmhlu4sfadf5e", ]; for addr in &addresses { - let addr = Address::from_str(addr).unwrap().require_network(Network::Bitcoin).unwrap(); + let addr = Address::from_str(addr).unwrap().require_network(Network::Prod).unwrap(); for another in &addresses { let another = - Address::from_str(another).unwrap().require_network(Network::Bitcoin).unwrap(); + Address::from_str(another).unwrap().require_network(Network::Prod).unwrap(); assert_eq!(addr.matches_script_pubkey(&another.script_pubkey()), addr == another); } } diff --git a/tapyrus/src/bip32.rs b/tapyrus/src/bip32.rs index 42ba3d40..e161503d 100644 --- a/tapyrus/src/bip32.rs +++ b/tapyrus/src/bip32.rs @@ -27,14 +27,14 @@ use crate::io::Write; use crate::network::Network; use crate::prelude::*; -/// Version bytes for extended public keys on the Bitcoin network. -const VERSION_BYTES_MAINNET_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E]; -/// Version bytes for extended private keys on the Bitcoin network. -const VERSION_BYTES_MAINNET_PRIVATE: [u8; 4] = [0x04, 0x88, 0xAD, 0xE4]; -/// Version bytes for extended public keys on any of the testnet networks. -const VERSION_BYTES_TESTNETS_PUBLIC: [u8; 4] = [0x04, 0x35, 0x87, 0xCF]; -/// Version bytes for extended private keys on any of the testnet networks. -const VERSION_BYTES_TESTNETS_PRIVATE: [u8; 4] = [0x04, 0x35, 0x83, 0x94]; +/// Version bytes for extended public keys on the Tapyrus network. +const VERSION_BYTES_PROD_PUBLIC: [u8; 4] = [0x04, 0x88, 0xB2, 0x1E]; +/// Version bytes for extended private keys on the Tapyrus network. +const VERSION_BYTES_PROD_PRIVATE: [u8; 4] = [0x04, 0x88, 0xAD, 0xE4]; +/// Version bytes for extended public keys on any of the dev networks. +const VERSION_BYTES_DEV_PUBLIC: [u8; 4] = [0x04, 0x35, 0x87, 0xCF]; +/// Version bytes for extended private keys on any of the dev networks. +const VERSION_BYTES_DEV_PRIVATE: [u8; 4] = [0x04, 0x35, 0x83, 0x94]; /// The old name for xpub, extended public key. #[deprecated(since = "0.31.0", note = "use xpub instead")] @@ -651,10 +651,10 @@ impl Xpriv { return Err(Error::WrongExtendedKeyLength(data.len())); } - let network = if data.starts_with(&VERSION_BYTES_MAINNET_PRIVATE) { - Network::Bitcoin - } else if data.starts_with(&VERSION_BYTES_TESTNETS_PRIVATE) { - Network::Testnet + let network = if data.starts_with(&VERSION_BYTES_PROD_PRIVATE) { + Network::Prod + } else if data.starts_with(&VERSION_BYTES_DEV_PRIVATE) { + Network::Dev } else { let (b0, b1, b2, b3) = (data[0], data[1], data[2], data[3]); return Err(Error::UnknownVersion([b0, b1, b2, b3])); @@ -678,8 +678,8 @@ impl Xpriv { pub fn encode(&self) -> [u8; 78] { let mut ret = [0; 78]; ret[0..4].copy_from_slice(&match self.network { - Network::Bitcoin | Network::Paradium => VERSION_BYTES_MAINNET_PRIVATE, - Network::Testnet | Network::Signet | Network::Regtest => VERSION_BYTES_TESTNETS_PRIVATE, + Network::Prod => VERSION_BYTES_PROD_PRIVATE, + Network::Dev => VERSION_BYTES_DEV_PRIVATE, }); ret[4] = self.depth; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); @@ -783,10 +783,10 @@ impl Xpub { return Err(Error::WrongExtendedKeyLength(data.len())); } - let network = if data.starts_with(&VERSION_BYTES_MAINNET_PUBLIC) { - Network::Bitcoin - } else if data.starts_with(&VERSION_BYTES_TESTNETS_PUBLIC) { - Network::Testnet + let network = if data.starts_with(&VERSION_BYTES_PROD_PUBLIC) { + Network::Prod + } else if data.starts_with(&VERSION_BYTES_DEV_PUBLIC) { + Network::Dev } else { let (b0, b1, b2, b3) = (data[0], data[1], data[2], data[3]); return Err(Error::UnknownVersion([b0, b1, b2, b3])); @@ -810,8 +810,8 @@ impl Xpub { pub fn encode(&self) -> [u8; 78] { let mut ret = [0; 78]; ret[0..4].copy_from_slice(&match self.network { - Network::Bitcoin | Network::Paradium => VERSION_BYTES_MAINNET_PUBLIC, - Network::Testnet | Network::Signet | Network::Regtest => VERSION_BYTES_TESTNETS_PUBLIC, + Network::Prod => VERSION_BYTES_PROD_PUBLIC, + Network::Dev => VERSION_BYTES_DEV_PUBLIC, }); ret[4] = self.depth; ret[5..9].copy_from_slice(&self.parent_fingerprint[..]); @@ -891,7 +891,7 @@ mod tests { use super::ChildNumber::{Hardened, Normal}; use super::*; - use crate::network::Network::{self, Bitcoin}; + use crate::network::Network::{self, Prod}; #[test] fn test_parse_derivation_path() { @@ -1067,32 +1067,32 @@ mod tests { let seed = hex!("000102030405060708090a0b0c0d0e0f"); // m - test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), + test_path(&secp, Prod, &seed, "m".parse().unwrap(), "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); // m/0h - test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0h".parse().unwrap(), "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); // m/0h/1 - test_path(&secp, Bitcoin, &seed, "m/0h/1".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0h/1".parse().unwrap(), "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); // m/0h/1/2h - test_path(&secp, Bitcoin, &seed, "m/0h/1/2h".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0h/1/2h".parse().unwrap(), "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); // m/0h/1/2h/2 - test_path(&secp, Bitcoin, &seed, "m/0h/1/2h/2".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0h/1/2h/2".parse().unwrap(), "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); // m/0h/1/2h/2/1000000000 - test_path(&secp, Bitcoin, &seed, "m/0h/1/2h/2/1000000000".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0h/1/2h/2/1000000000".parse().unwrap(), "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); } @@ -1103,32 +1103,32 @@ mod tests { let seed = hex!("fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542"); // m - test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), + test_path(&secp, Prod, &seed, "m".parse().unwrap(), "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); // m/0 - test_path(&secp, Bitcoin, &seed, "m/0".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0".parse().unwrap(), "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); // m/0/2147483647h - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0/2147483647h".parse().unwrap(), "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); // m/0/2147483647h/1 - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h/1".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0/2147483647h/1".parse().unwrap(), "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); // m/0/2147483647h/1/2147483646h - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h/1/2147483646h".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0/2147483647h/1/2147483646h".parse().unwrap(), "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); // m/0/2147483647h/1/2147483646h/2 - test_path(&secp, Bitcoin, &seed, "m/0/2147483647h/1/2147483646h/2".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0/2147483647h/1/2147483646h/2".parse().unwrap(), "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); } @@ -1139,12 +1139,12 @@ mod tests { let seed = hex!("4b381541583be4423346c643850da4b320e46a87ae3d2a4e6da11eba819cd4acba45d239319ac14f863b8d5ab5a0d0c64d2e8a1e7d1457df2e5a3c51c73235be"); // m - test_path(&secp, Bitcoin, &seed, "m".parse().unwrap(), + test_path(&secp, Prod, &seed, "m".parse().unwrap(), "xprv9s21ZrQH143K25QhxbucbDDuQ4naNntJRi4KUfWT7xo4EKsHt2QJDu7KXp1A3u7Bi1j8ph3EGsZ9Xvz9dGuVrtHHs7pXeTzjuxBrCmmhgC6", "xpub661MyMwAqRbcEZVB4dScxMAdx6d4nFc9nvyvH3v4gJL378CSRZiYmhRoP7mBy6gSPSCYk6SzXPTf3ND1cZAceL7SfJ1Z3GC8vBgp2epUt13"); // m/0h - test_path(&secp, Bitcoin, &seed, "m/0h".parse().unwrap(), + test_path(&secp, Prod, &seed, "m/0h".parse().unwrap(), "xprv9uPDJpEQgRQfDcW7BkF7eTya6RPxXeJCqCJGHuCJ4GiRVLzkTXBAJMu2qaMWPrS7AANYqdq6vcBcBUdJCVVFceUvJFjaPdGZ2y9WACViL4L", "xpub68NZiKmJWnxxS6aaHmn81bvJeTESw724CRDs6HbuccFQN9Ku14VQrADWgqbhhTHBaohPX4CjNLf9fq9MYo6oDaPPLPxSb7gwQN3ih19Zm4Y"); } @@ -1207,7 +1207,7 @@ mod tests { } let xpriv = Xpriv { - network: Network::Bitcoin, + network: Network::Prod, depth: 0, parent_fingerprint: Default::default(), child_number: ChildNumber::Normal { index: 0 }, diff --git a/tapyrus/src/blockdata/block.rs b/tapyrus/src/blockdata/block.rs index 378e586f..a7896665 100644 --- a/tapyrus/src/blockdata/block.rs +++ b/tapyrus/src/blockdata/block.rs @@ -20,12 +20,13 @@ use crate::blockdata::transaction::Transaction; use crate::consensus::encode::serialize_hex; use crate::consensus::{encode, serialize, Decodable, Encodable}; use crate::crypto::key::PublicKey; +use crate::crypto; use crate::crypto::schnorr::Signature; pub use crate::hash_types::BlockHash; use crate::hash_types::{BlockSigHash, TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid}; use crate::internal_macros::impl_consensus_encoding; use crate::prelude::*; -use crate::{crypto, io, merkle_tree, VarInt}; +use crate::{io, merkle_tree, VarInt}; /// Bitcoin block header. /// @@ -640,9 +641,8 @@ impl std::error::Error for ValidationError { #[cfg(test)] mod tests { - use std::str::FromStr; - use hex::{test_hex_unwrap as hex, FromHex}; + use core::str::FromStr; use super::*; use crate::consensus::encode::{deserialize, serialize}; diff --git a/tapyrus/src/blockdata/constants.rs b/tapyrus/src/blockdata/constants.rs index 6c9711a6..24d7e427 100644 --- a/tapyrus/src/blockdata/constants.rs +++ b/tapyrus/src/blockdata/constants.rs @@ -14,17 +14,18 @@ use hashes::{sha256d, Hash}; use hex_lit::hex; use internals::impl_array_newtype; -use crate::blockdata::block::{self, Block, XField}; use crate::blockdata::locktime::absolute; -use crate::blockdata::opcodes::all::*; -use crate::blockdata::script; -use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; +use crate::consensus::deserialize; +use crate::opcodes::all::*; +use crate::blockdata::block::{self, Block, XField}; use crate::crypto::key::PublicKey; use crate::crypto::schnorr::Signature; use crate::internal_macros::impl_bytes_newtype; -use crate::network::Network; -use crate::Amount; +use crate::network::{NetworkId, ParseNetworkError}; +use crate::{script, Txid}; +use crate::amount::Amount; +use crate::transaction::{ self, Transaction, TxIn, TxOut, OutPoint, Sequence}; #[deprecated(since = "0.31.0", note = "Use Weight::MAX_BLOCK instead")] /// The maximum allowed weight for a block, see BIP 141 (network rule). @@ -55,8 +56,9 @@ pub const MAX_SCRIPTNUM_VALUE: u32 = 0x80000000; // 2^31 /// Number of blocks needed for an output from a coinbase transaction to be spendable. pub const COINBASE_MATURITY: u32 = 100; -/// Constructs and returns the coinbase (and only) transaction of the Bitcoin genesis block. -fn bitcoin_genesis_tx() -> Transaction { +/// Constructs and returns the coinbase (and only) transaction of the Mainnet genesis block. +/// https://explorer.api.tapyrus.chaintope.com/tx/3231b5798aacd8ea40f3b580e741006a71335ed9a7538768ee4a193bc525c170 +fn mainnet_genesis_tx() -> Transaction { // Base let mut ret = Transaction { version: transaction::Version::ONE, @@ -66,103 +68,105 @@ fn bitcoin_genesis_tx() -> Transaction { }; // Inputs - let in_script = script::Builder::new() - .push_int(486604799) - .push_int_non_minimal(4) - .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") - .into_script(); + let in_script = script::Builder::new().into_script(); ret.input.push(TxIn { - previous_output: OutPoint::null(), + previous_output: OutPoint::new(Txid::all_zeros(), 0), script_sig: in_script, sequence: Sequence::MAX, witness: Witness::default(), }); // Outputs - let script_bytes = hex!("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); + let script_bytes = hex!("314a586d6e436a646453394644366252797a4348376457716844667735486f38794c"); let out_script = - script::Builder::new().push_slice(script_bytes).push_opcode(OP_CHECKSIG).into_script(); + script::Builder::new().push_opcode(OP_DUP).push_opcode(OP_HASH160).push_slice(script_bytes).push_opcode(OP_EQUALVERIFY).push_opcode(OP_CHECKSIG).into_script(); ret.output.push(TxOut { value: Amount::from_sat(50 * 100_000_000), script_pubkey: out_script }); // end ret } -/// Constructs and returns the genesis block. -pub fn genesis_block(network: Network) -> Block { - let txdata = vec![bitcoin_genesis_tx()]; +/// Constructs and returns the coinbase (and only) transaction of the Testnet genesis block. +/// https://testnet-explorer.tapyrus.dev.chaintope.com/tx/846521b8ff0b89fee8b99d089ffe403856e912c7fc34486d9dbbf03625ec188f +fn testnet_genesis_tx() -> Transaction { + // Base + let mut ret = Transaction { + version: transaction::Version::ONE, + lock_time: absolute::LockTime::ZERO, + input: vec![], + output: vec![], + }; + + // Inputs + let in_script = script::Builder::new().into_script(); + ret.input.push(TxIn { + previous_output: OutPoint::new(Txid::all_zeros(), 0), + script_sig: in_script, + sequence: Sequence::MAX, + witness: Witness::default(), + }); + + // Outputs + let script_bytes = hex!("31415132437447336a686f37385372457a4b6533766636647863456b4a74356e7a41"); + let out_script = + script::Builder::new().push_opcode(OP_DUP).push_opcode(OP_HASH160).push_slice(script_bytes).push_opcode(OP_EQUALVERIFY).push_opcode(OP_CHECKSIG).into_script(); + ret.output.push(TxOut { value: Amount::from_sat(50 * 100_000_000), script_pubkey: out_script }); + + // end + ret +} + +/// Constructs and returns the Mainnet genesis block. +/// https://explorer.api.tapyrus.chaintope.com/block/92f729508ee8b0e4f46418f81f89806a952c739df03de1e666a8e2b5c40b549b +pub fn mainnet_genesis_block() -> Block { + let txdata = vec![mainnet_genesis_tx()]; let hash: sha256d::Hash = txdata[0].txid().into(); + let im_merkle_root = txdata[0].malfix_txid().into(); let merkle_root = hash.into(); let public_key = - PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af") + PublicKey::from_str("02bb8a7fbba7da4e6a0519296e30211c33c7307ac19aba4e8f56cce2d3da36b751") .unwrap(); - match network { - Network::Bitcoin => Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - im_merkle_root: txdata[0].ntxid().into(), - time: 1231006505, - xfield: XField::AggregatePublicKey(public_key), - proof: Some(Signature::default()), - }, - txdata, + let sig_data = hex!("fb1edbb9eac53c4a1e67c510c7fe7eefd6f5080c74df88a679cf3853e0784231979b3896b577ed3bb987d1a38fd0901d5f68f38cb0c07aea519885022428cede"); + let sig: Signature = deserialize(&sig_data).unwrap(); + Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: Hash::all_zeros(), + merkle_root, + im_merkle_root, + time: 1637827301, + xfield: XField::AggregatePublicKey(public_key), + proof: Some(sig), }, - Network::Testnet => Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - im_merkle_root: txdata[0].ntxid().into(), - time: 1296688602, - xfield: XField::AggregatePublicKey(public_key), - proof: Some(Signature::default()), - }, - txdata, - }, - Network::Signet => Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - im_merkle_root: txdata[0].ntxid().into(), - time: 1598918400, - xfield: XField::AggregatePublicKey(public_key), - proof: Some(Signature::default()), - }, - txdata, - }, - Network::Regtest => Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - im_merkle_root: txdata[0].ntxid().into(), - time: 1296688602, - xfield: XField::AggregatePublicKey(public_key), - proof: Some(Signature::default()), - }, - txdata, - }, - Network::Paradium => { - let txdata = vec![bitcoin_genesis_tx()]; - Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - im_merkle_root: txdata[0].ntxid().into(), - time: 1562925929, - xfield: XField::AggregatePublicKey(public_key), - proof: Some(Signature::default()), - }, - txdata, - } - } + txdata, } } +/// Constructs and returns the Testnet genesis block. +/// https://testnet-explorer.tapyrus.dev.chaintope.com/block/038b114875c2f78f5a2fd7d8549a905f38ea5faee6e29a3d79e547151d6bdd8a +pub fn testnet_genesis_block() -> Block { + let txdata = vec![testnet_genesis_tx()]; + let hash: sha256d::Hash = txdata[0].txid().into(); + let im_merkle_root = txdata[0].malfix_txid().into(); + let merkle_root = hash.into(); + let public_key = + PublicKey::from_str("0366262690cbdf648132ce0c088962c6361112582364ede120f3780ab73438fc4b") + .unwrap(); + let sig_data = hex!("2b1ed9996920f57a425f6f9797557c0e73d0c9fbafdebcaa796b136e0946ffa98d928f8130b6a572f83da39530b13784eeb7007465b673aa95091619e7ee2085"); + let sig: Signature = deserialize(&sig_data).unwrap(); + Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: Hash::all_zeros(), + merkle_root, + im_merkle_root, + time: 1589269151, + xfield: XField::AggregatePublicKey(public_key), + proof: Some(sig), + }, + txdata, + } +} /// The uniquely identifying hash of the target blockchain. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ChainHash([u8; 32]); @@ -170,40 +174,27 @@ impl_array_newtype!(ChainHash, u8, 32); impl_bytes_newtype!(ChainHash, 32); impl ChainHash { - // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md - /// `ChainHash` for mainnet tapyrus. - pub const BITCOIN: Self = Self([ - 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131, - 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, + /// `ChainHash` for mainnet network. + pub const MAINNET: Self = Self([ + 155, 84, 11, 196, 181, 226, 168, 102, 230, 225, 61, 240, 157, 115, 44, 149, 106, 128, 137, 31, 248, 24, 100, 244, 228, 176, 232, 142, 80, 41, 247, 146 ]); - /// `ChainHash` for testnet tapyrus. + /// `ChainHash` for testnet network. pub const TESTNET: Self = Self([ - 67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, - 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0, - ]); - /// `ChainHash` for signet tapyrus. - pub const SIGNET: Self = Self([ - 246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, - 240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0, - ]); - /// `ChainHash` for regtest tapyrus. - pub const REGTEST: Self = Self([ - 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, - 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15, + 138, 221, 107, 29, 21, 71, 229, 121, 61, 154, 226, 230, 174, 95, 234, 56, 95, 144, 154, 84, 216, 215, 47, 90, 143, 247, 194, 117, 72, 17, 139, 3 ]); - /// `ChainHash` for paradium. - pub const PARADIUM: Self = Self([ - 78, 211, 5, 161, 211, 211, 27, 104, 188, 53, 3, 225, 191, 239, 71, 184, 13, 111, 154, 223, - 143, 185, 20, 76, 57, 231, 161, 17, 182, 77, 190, 120, - ]); - + /// Returns the hash of the `network` genesis block for use as a chain hash. /// /// See [BOLT 0](https://github.com/lightning/bolts/blob/ffeece3dab1c52efdb9b53ae476539320fa44938/00-introduction.md#chain_hash) /// for specification. - pub const fn using_genesis_block(network: Network) -> Self { - let hashes = [Self::BITCOIN, Self::TESTNET, Self::SIGNET, Self::REGTEST, Self::PARADIUM]; - hashes[network as usize] + pub fn using_genesis_block(network_id: NetworkId) -> Result { + // https://github.com/chaintope/tapyrus-core/blob/master/doc/tapyrus/network_id_and_magic_bytes.md + let magic = network_id.magic(); + match magic { + 0x00F0FF01 => Ok(Self::MAINNET), + 0x74839A75 => Ok(Self::TESTNET), + _ => Err(ParseNetworkError("Network id is unknown.".to_owned())), + } } /// Converts genesis block hash into `ChainHash`. @@ -222,136 +213,95 @@ mod test { use crate::blockdata::locktime::absolute; use crate::blockdata::transaction; use crate::consensus::encode::serialize; - use crate::network::Network; #[test] - #[ignore] - fn bitcoin_genesis_first_transaction() { - let gen = bitcoin_genesis_tx(); + fn mainnet_genesis_first_transaction() { + let gen = mainnet_genesis_tx(); assert_eq!(gen.version, transaction::Version::ONE); assert_eq!(gen.input.len(), 1); assert_eq!(gen.input[0].previous_output.txid, Hash::all_zeros()); - assert_eq!(gen.input[0].previous_output.vout, 0xFFFFFFFF); - assert_eq!(serialize(&gen.input[0].script_sig), - hex!("4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73")); + assert_eq!(gen.input[0].previous_output.vout, 0); + assert_eq!(gen.input[0].script_sig, script::Builder::new().into_script()); assert_eq!(gen.input[0].sequence, Sequence::MAX); assert_eq!(gen.output.len(), 1); assert_eq!(serialize(&gen.output[0].script_pubkey), - hex!("434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac")); + hex!("2776a922314a586d6e436a646453394644366252797a4348376457716844667735486f38794c88ac")); assert_eq!(gen.output[0].value, Amount::from_str("50 BTC").unwrap()); assert_eq!(gen.lock_time, absolute::LockTime::ZERO); assert_eq!( - gen.wtxid().to_string(), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + gen.txid().to_string(), + "075565bbdccaefe1c8f9372414767b1a49f4463b01bd9f98c03680bc51ca5bb2" + ); + assert_eq!( + gen.malfix_txid().to_string(), + "3231b5798aacd8ea40f3b580e741006a71335ed9a7538768ee4a193bc525c170" ); } #[test] - #[ignore] - fn bitcoin_genesis_full_block() { - let gen = genesis_block(Network::Bitcoin); + fn mainnet_genesis_full_block() { + let gen = mainnet_genesis_block(); assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!( gen.header.merkle_root.to_string(), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + "075565bbdccaefe1c8f9372414767b1a49f4463b01bd9f98c03680bc51ca5bb2" ); - assert_eq!(gen.header.time, 1231006505); + assert_eq!(gen.header.time, 1637827301); assert_eq!( gen.header.block_hash().to_string(), - "1c184bf287b15f641f8b063aab2af4123519d227e8681463b91d675192f6279c" + "92f729508ee8b0e4f46418f81f89806a952c739df03de1e666a8e2b5c40b549b" ); } #[test] - #[ignore] fn testnet_genesis_full_block() { - let gen = genesis_block(Network::Testnet); + let gen = testnet_genesis_block(); assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); assert_eq!( gen.header.merkle_root.to_string(), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + "51b341a85575219820ad1175f93a22a83f190dfcd1139a995b5ce9d01b18cc44" ); - assert_eq!(gen.header.time, 1296688602); + assert_eq!(gen.header.time, 1589269151); assert_eq!( gen.header.block_hash().to_string(), - "13530b95110ac11ae2d22d82acc5ad00a3510bb340c9667309cb811c2883cdc5" - ); - } - - #[test] - #[ignore] - fn signet_genesis_full_block() { - let gen = genesis_block(Network::Signet); - assert_eq!(gen.header.version, block::Version::ONE); - assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!( - gen.header.merkle_root.to_string(), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" - ); - assert_eq!(gen.header.time, 1598918400); - assert_eq!( - gen.header.block_hash().to_string(), - "abbaa74c35c0467802e1dfd8a20150ea7c0ac529feb245933702832d112c6b16".to_string() - ); - } - - #[test] - #[ignore] - fn paradium_genesis_full_block() { - let gen = genesis_block(Network::Paradium); - assert_eq!(gen.header.version, block::Version::ONE,); - assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!( - gen.header.merkle_root.to_string(), - "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" - ); - assert_eq!(gen.header.time, 1562925929); - assert_eq!( - gen.header.block_hash().to_string(), - "78be4db611a1e7394c14b98fdf9a6f0db847efbfe10335bc681bd3d3a105d34e" + "038b114875c2f78f5a2fd7d8549a905f38ea5faee6e29a3d79e547151d6bdd8a" ); } // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array // representing the genesis block is the same as that created by hashing the genesis block. - fn chain_hash_and_genesis_block(network: Network) { + fn chain_hash_and_genesis_block(network_id: NetworkId) { use hashes::sha256; - // The genesis block hash is a double-sha256 and it is displayed backwards. - let genesis_hash = genesis_block(network).block_hash(); - // We abuse the sha256 hash here so we get a LowerHex impl that does not print the hex backwards. + // // The genesis block hash is a double-sha256 and it is displayed backwards. + let magic = network_id.magic(); + let genesis_hash = match magic { + 0x00F0FF01 => mainnet_genesis_block().block_hash(), + 0x74839A75 => testnet_genesis_block().block_hash(), + _ => panic!("Network ID is not supported"), + }; + // // We abuse the sha256 hash here so we get a LowerHex impl that does not print the hex backwards. let hash = sha256::Hash::from_slice(genesis_hash.as_byte_array()).unwrap(); let want = format!("{:02x}", hash); - let chain_hash = ChainHash::using_genesis_block(network); + let chain_hash = ChainHash::using_genesis_block(network_id).unwrap(); let got = format!("{:02x}", chain_hash); - // Compare strings because the spec specifically states how the chain hash must encode to hex. + // // Compare strings because the spec specifically states how the chain hash must encode to hex. assert_eq!(got, want); - - #[allow(unreachable_patterns)] // This is specifically trying to catch later added variants. - match network { - Network::Bitcoin => {}, - Network::Testnet => {}, - Network::Signet => {}, - Network::Regtest => {}, - Network::Paradium => {} - _ => panic!("Update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants"), - } } macro_rules! chain_hash_genesis_block { ($($test_name:ident, $network:expr);* $(;)*) => { $( #[test] - #[ignore] fn $test_name() { chain_hash_and_genesis_block($network); } @@ -360,18 +310,15 @@ mod test { } chain_hash_genesis_block! { - mainnet_chain_hash_genesis_block, Network::Bitcoin; - testnet_chain_hash_genesis_block, Network::Testnet; - signet_chain_hash_genesis_block, Network::Signet; - regtest_chain_hash_genesis_block, Network::Regtest; - paradium_chain_hash_genesis_block, Network::Paradium; + mainnet_chain_hash_genesis_block, NetworkId::from(1); + testnet_chain_hash_genesis_block, NetworkId::from(1939510133); } // Test vector taken from: https://github.com/lightning/bolts/blob/master/00-introduction.md #[test] fn mainnet_chain_hash_test_vector() { - let got = ChainHash::using_genesis_block(Network::Bitcoin).to_string(); - let want = "6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000"; + let got = ChainHash::using_genesis_block(NetworkId::from(1)).unwrap().to_string(); + let want = "9b540bc4b5e2a866e6e13df09d732c956a80891ff81864f4e4b0e88e5029f792"; assert_eq!(got, want); } } diff --git a/tapyrus/src/blockdata/transaction.rs b/tapyrus/src/blockdata/transaction.rs index 8b6f68cd..6cb1ac34 100644 --- a/tapyrus/src/blockdata/transaction.rs +++ b/tapyrus/src/blockdata/transaction.rs @@ -70,19 +70,6 @@ impl OutPoint { pub fn null() -> OutPoint { OutPoint { txid: Hash::all_zeros(), vout: u32::MAX } } /// Checks if an `OutPoint` is "null". - /// - /// # Examples - /// - /// ```rust - /// use tapyrus::constants::genesis_block; - /// use tapyrus::Network; - /// - /// let block = genesis_block(Network::Bitcoin); - /// let tx = &block.txdata[0]; - /// - /// // Coinbase transactions don't have any previous output. - /// assert!(tx.input[0].previous_output.is_null()); - /// ``` #[inline] pub fn is_null(&self) -> bool { *self == OutPoint::null() } } diff --git a/tapyrus/src/consensus/params.rs b/tapyrus/src/consensus/params.rs index 00c125be..c1082a4a 100644 --- a/tapyrus/src/consensus/params.rs +++ b/tapyrus/src/consensus/params.rs @@ -14,43 +14,11 @@ use crate::network::Network; pub struct Params { /// Network for which parameters are valid. pub network: Network, - /// Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period, - /// (nPowTargetTimespan / nPowTargetSpacing) which is also used for BIP9 deployments. - /// Examples: 1916 for 95%, 1512 for testchains. - pub rule_change_activation_threshold: u32, - /// Number of blocks with the same set of rules. - pub miner_confirmation_window: u32, } impl Params { /// Creates parameters set for the given network. pub fn new(network: Network) -> Self { - match network { - Network::Bitcoin => Params { - network: Network::Bitcoin, - rule_change_activation_threshold: 1916, // 95% - miner_confirmation_window: 2016, - }, - Network::Testnet => Params { - network: Network::Testnet, - rule_change_activation_threshold: 1512, // 75% - miner_confirmation_window: 2016, - }, - Network::Signet => Params { - network: Network::Signet, - rule_change_activation_threshold: 1916, // 95% - miner_confirmation_window: 2016, - }, - Network::Regtest => Params { - network: Network::Regtest, - rule_change_activation_threshold: 108, // 75% - miner_confirmation_window: 144, - }, - Network::Paradium => Params { - network: Network::Paradium, - rule_change_activation_threshold: 108, // 75% - miner_confirmation_window: 144, - }, - } + Params { network, } } } diff --git a/tapyrus/src/crypto/key.rs b/tapyrus/src/crypto/key.rs index eb5e2838..671927d7 100644 --- a/tapyrus/src/crypto/key.rs +++ b/tapyrus/src/crypto/key.rs @@ -320,8 +320,8 @@ impl PrivateKey { pub fn fmt_wif(&self, fmt: &mut dyn fmt::Write) -> fmt::Result { let mut ret = [0; 34]; ret[0] = match self.network { - Network::Bitcoin | Network::Paradium => 128, - Network::Testnet | Network::Signet | Network::Regtest => 239, + Network::Prod => 128, + Network::Dev => 239, }; ret[1..33].copy_from_slice(&self.inner[..]); let privkey = if self.compressed { @@ -354,8 +354,8 @@ impl PrivateKey { }; let network = match data[0] { - 128 => Network::Bitcoin, - 239 => Network::Testnet, + 128 => Network::Prod, + 239 => Network::Dev, x => { return Err(Error::Base58(base58::Error::InvalidAddressVersion(x))); } @@ -788,14 +788,14 @@ mod tests { use super::*; use crate::address::Address; use crate::io; - use crate::network::Network::{Bitcoin, Testnet}; + use crate::network::Network::{Dev, Prod}; #[test] fn test_key_derivation() { // testnet compressed let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); - assert_eq!(sk.network, Testnet); + assert_eq!(sk.network, Dev); assert!(sk.compressed); assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); @@ -812,7 +812,7 @@ mod tests { // mainnet uncompressed let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); - assert_eq!(sk.network, Bitcoin); + assert_eq!(sk.network, Prod); assert!(!sk.compressed); assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3"); diff --git a/tapyrus/src/network.rs b/tapyrus/src/network.rs index 7a90411d..d05cdb3d 100644 --- a/tapyrus/src/network.rs +++ b/tapyrus/src/network.rs @@ -9,16 +9,15 @@ //! # Example: encoding a network's magic bytes //! //! ```rust -//! use tapyrus::Network; +//! use tapyrus::network::NetworkId; //! use tapyrus::consensus::encode::serialize; //! -//! let network = Network::Bitcoin; +//! let network = NetworkId::from(1); //! let bytes = serialize(&network.magic()); //! //! assert_eq!(&bytes[..], &[0x01, 0xFF, 0xF0, 0x00]); //! ``` -use core::convert::TryFrom; use core::fmt; use core::fmt::Display; use core::str::FromStr; @@ -28,57 +27,47 @@ use internals::write_err; use serde::{Deserialize, Serialize}; use crate::constants::ChainHash; -use crate::p2p::Magic; use crate::prelude::{String, ToOwned}; -/// The cryptocurrency network to act on. -#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] -#[non_exhaustive] -pub enum Network { - /// Mainnet Bitcoin. - Bitcoin, - /// Bitcoin's testnet network. - Testnet, - /// Bitcoin's signet network. - Signet, - /// Bitcoin's regtest network. - Regtest, - /// Paradium network - Paradium, -} - -impl Network { - /// Creates a `Network` from the magic bytes. - /// - /// # Examples - /// - /// ```rust - /// use tapyrus::p2p::Magic; - /// use tapyrus::Network; - /// use std::convert::TryFrom; - /// - /// assert_eq!(Ok(Network::Bitcoin), Network::try_from(Magic::from_bytes([0x01, 0xFF, 0xF0, 0x00]))); - /// assert_eq!(None, Network::from_magic(Magic::from_bytes([0xFF, 0xFF, 0xFF, 0xFF]))); - /// ``` - pub fn from_magic(magic: Magic) -> Option { Network::try_from(magic).ok() } +/// Network ID is identifier of the Tapyrus network +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct NetworkId(u32); +impl NetworkId { /// Return the network magic bytes, which should be encoded little-endian /// at the start of every message /// /// # Examples /// /// ```rust - /// use tapyrus::p2p::Magic; - /// use tapyrus::Network; + /// use tapyrus::network::NetworkId; /// - /// let network = Network::Bitcoin; - /// assert_eq!(network.magic(), Magic::from_bytes([0x01, 0xFF, 0xF0, 0x00])); + /// let network = NetworkId::from(1); + /// assert_eq!(network.magic(), 0x00F0FF01); /// ``` - pub fn magic(self) -> Magic { Magic::from(self) } + pub fn magic(&self) -> u32 { (33550335 + self.0).swap_bytes() } +} +impl From for NetworkId { + fn from(n: u32) -> Self { NetworkId(n) } +} + +/// The cryptocurrency network to act on. +#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] +#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] +#[non_exhaustive] +pub enum Network { + /// For production + /// #[strum(serialize = "prod")] + Prod, + /// For development + /// #[strum(serialize = "dev")] + Dev, +} + +impl Network { /// Converts a `Network` to its equivalent `bitcoind -chain` argument name. /// /// ```bash @@ -90,11 +79,8 @@ impl Network { /// ``` pub fn to_core_arg(self) -> &'static str { match self { - Network::Bitcoin => "main", - Network::Testnet => "test", - Network::Signet => "signet", - Network::Regtest => "regtest", - Network::Paradium => "paradium", + Network::Prod => "prod", + Network::Dev => "dev", } } @@ -111,43 +97,12 @@ impl Network { use Network::*; let network = match core_arg { - "main" => Bitcoin, - "test" => Testnet, - "signet" => Signet, - "regtest" => Regtest, - "paradium" => Paradium, + "prod" => Prod, + "dev" => Dev, _ => return Err(ParseNetworkError(core_arg.to_owned())), }; Ok(network) } - - /// Return the network's chain hash (genesis block hash). - /// - /// # Examples - /// - /// ```rust - /// use tapyrus::Network; - /// use tapyrus::blockdata::constants::ChainHash; - /// - /// let network = Network::Bitcoin; - /// assert_eq!(network.chain_hash(), ChainHash::BITCOIN); - /// ``` - pub fn chain_hash(self) -> ChainHash { ChainHash::using_genesis_block(self) } - - /// Creates a `Network` from the chain hash (genesis block hash). - /// - /// # Examples - /// - /// ```rust - /// use tapyrus::Network; - /// use tapyrus::blockdata::constants::ChainHash; - /// use std::convert::TryFrom; - /// - /// assert_eq!(Ok(Network::Bitcoin), Network::try_from(ChainHash::BITCOIN)); - /// ``` - pub fn from_chain_hash(chain_hash: ChainHash) -> Option { - Network::try_from(chain_hash).ok() - } } #[cfg(feature = "serde")] @@ -199,7 +154,7 @@ pub mod as_core_arg { /// An error in parsing network string. #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] -pub struct ParseNetworkError(String); +pub struct ParseNetworkError(pub String); impl fmt::Display for ParseNetworkError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -220,11 +175,8 @@ impl FromStr for Network { use Network::*; let network = match s { - "bitcoin" => Bitcoin, - "testnet" => Testnet, - "signet" => Signet, - "regtest" => Regtest, - "paradium" => Paradium, + "prod" => Prod, + "dev" => Dev, _ => return Err(ParseNetworkError(s.to_owned())), }; Ok(network) @@ -236,11 +188,8 @@ impl fmt::Display for Network { use Network::*; let s = match *self { - Bitcoin => "bitcoin", - Testnet => "testnet", - Signet => "signet", - Regtest => "regtest", - Paradium => "paradium", + Prod => "prod", + Dev => "dev", }; write!(f, "{}", s) } @@ -262,56 +211,46 @@ impl std::error::Error for UnknownChainHashError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } } -impl TryFrom for Network { - type Error = UnknownChainHashError; - - fn try_from(chain_hash: ChainHash) -> Result { - match chain_hash { - // Note: any new network entries must be matched against here. - ChainHash::BITCOIN => Ok(Network::Bitcoin), - ChainHash::TESTNET => Ok(Network::Testnet), - ChainHash::SIGNET => Ok(Network::Signet), - ChainHash::REGTEST => Ok(Network::Regtest), - ChainHash::PARADIUM => Ok(Network::Paradium), - _ => Err(UnknownChainHashError(chain_hash)), - } - } -} - #[cfg(test)] mod tests { - use super::Network; + use super::{Network, NetworkId}; use crate::consensus::encode::{deserialize, serialize}; use crate::p2p::ServiceFlags; #[test] fn serialize_test() { - assert_eq!(serialize(&Network::Bitcoin.magic()), &[0x01, 0xff, 0xf0, 0x00]); - assert_eq!(serialize(&Network::Testnet.magic()), &[0x75, 0x9a, 0x83, 0x74]); - assert_eq!(serialize(&Network::Signet.magic()), &[0x0a, 0x03, 0xcf, 0x40]); - assert_eq!(serialize(&Network::Regtest.magic()), &[0x73, 0x9a, 0x97, 0x74]); - assert_eq!(serialize(&Network::Paradium.magic()), &[0x01, 0xff, 0xf0, 0x64]); - - assert_eq!(deserialize(&[0x01, 0xff, 0xf0, 0x00]).ok(), Some(Network::Bitcoin.magic())); - assert_eq!(deserialize(&[0x75, 0x9a, 0x83, 0x74]).ok(), Some(Network::Testnet.magic())); - assert_eq!(deserialize(&[0x0a, 0x03, 0xcf, 0x40]).ok(), Some(Network::Signet.magic())); - assert_eq!(deserialize(&[0x73, 0x9a, 0x97, 0x74]).ok(), Some(Network::Regtest.magic())); - assert_eq!(deserialize(&[0x01, 0xff, 0xf0, 0x64]).ok(), Some(Network::Paradium.magic())); + // Production + assert_eq!(serialize(&NetworkId::from(1).magic()), &[0x01, 0xff, 0xf0, 0x00]); + // Public Testnet + assert_eq!(serialize(&NetworkId::from(1939510133).magic()), &[0x75, 0x9a, 0x83, 0x74]); + // Regtest + assert_eq!(serialize(&NetworkId::from(1905960821).magic()), &[0x73, 0x9a, 0x97, 0x74]); + // Paradium + assert_eq!(serialize(&NetworkId::from(101).magic()), &[0x01, 0xff, 0xf0, 0x64]); + + // Production + assert_eq!(deserialize(&[0x01, 0xff, 0xf0, 0x00]).ok(), Some(NetworkId::from(1).magic())); + // Public Testnet + assert_eq!( + deserialize(&[0x75, 0x9a, 0x83, 0x74]).ok(), + Some(NetworkId::from(1939510133).magic()) + ); + // Regtest + assert_eq!( + deserialize(&[0x73, 0x9a, 0x97, 0x74]).ok(), + Some(NetworkId::from(1905960821).magic()) + ); + // Paradium + assert_eq!(deserialize(&[0x01, 0xff, 0xf0, 0x64]).ok(), Some(NetworkId::from(101).magic())); } #[test] fn string_test() { - 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!(Network::Paradium.to_string(), "paradium"); - - 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_eq!("paradium".parse::().unwrap(), Network::Paradium); + assert_eq!(Network::Prod.to_string(), "prod"); + assert_eq!(Network::Dev.to_string(), "dev"); + + assert_eq!("prod".parse::().unwrap(), Network::Prod); + assert_eq!("dev".parse::().unwrap(), Network::Dev); assert!("fakenet".parse::().is_err()); } @@ -359,13 +298,7 @@ mod tests { #[cfg(feature = "serde")] fn serde_roundtrip() { use Network::*; - let tests = vec![ - (Bitcoin, "bitcoin"), - (Testnet, "testnet"), - (Signet, "signet"), - (Regtest, "regtest"), - (Paradium, "paradium"), - ]; + let tests = vec![(Prod, "prod"), (Dev, "dev")]; for tc in tests { let network = tc.0; @@ -381,13 +314,7 @@ mod tests { #[test] fn from_to_core_arg() { - let expected_pairs = [ - (Network::Bitcoin, "main"), - (Network::Testnet, "test"), - (Network::Regtest, "regtest"), - (Network::Signet, "signet"), - (Network::Paradium, "paradium"), - ]; + let expected_pairs = [(Network::Prod, "prod"), (Network::Dev, "dev")]; for (net, core_arg) in &expected_pairs { assert_eq!(Network::from_core_arg(core_arg), Ok(*net)); @@ -406,11 +333,11 @@ mod tests { } serde_test::assert_tokens( - &T { network: Network::Bitcoin }, + &T { network: Network::Prod }, &[ serde_test::Token::Struct { name: "T", len: 1 }, serde_test::Token::Str("network"), - serde_test::Token::Str("main"), + serde_test::Token::Str("prod"), serde_test::Token::StructEnd, ], ); diff --git a/tapyrus/src/p2p/message.rs b/tapyrus/src/p2p/message.rs index ff2d71a3..e258721a 100644 --- a/tapyrus/src/p2p/message.rs +++ b/tapyrus/src/p2p/message.rs @@ -554,7 +554,7 @@ mod test { use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::Transaction; use crate::consensus::encode::{deserialize, deserialize_partial, serialize}; - use crate::network::Network; + use crate::network::NetworkId; use crate::p2p::address::{AddrV2, AddrV2Message, Address}; use crate::p2p::message_blockdata::{GetBlocksMessage, GetHeadersMessage, Inventory}; use crate::p2p::message_bloom::{BloomFlags, FilterAdd, FilterLoad}; @@ -709,8 +709,8 @@ mod test { #[test] #[rustfmt::skip] fn serialize_verack_test() { - assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(Network::Bitcoin), NetworkMessage::Verack)), - vec![0x01, 0xff, 0xf0, 0x00, 0x76, 0x65, 0x72, 0x61, + assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(NetworkId::from(1)), NetworkMessage::Verack)), + vec![0x00, 0xf0, 0xff, 0x01, 0x76, 0x65, 0x72, 0x61, 0x63, 0x6B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); } @@ -718,8 +718,8 @@ mod test { #[test] #[rustfmt::skip] fn serialize_ping_test() { - assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(Network::Bitcoin), NetworkMessage::Ping(100))), - vec![0x01, 0xff, 0xf0, 0x00, 0x70, 0x69, 0x6e, 0x67, + assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(NetworkId::from(1)), NetworkMessage::Ping(100))), + vec![0x00, 0xf0, 0xff, 0x01, 0x70, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x24, 0x67, 0xf1, 0x1d, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); @@ -728,8 +728,8 @@ mod test { #[test] #[rustfmt::skip] fn serialize_mempool_test() { - assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(Network::Bitcoin), NetworkMessage::MemPool)), - vec![0x01, 0xff, 0xf0, 0x00, 0x6d, 0x65, 0x6d, 0x70, + assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(NetworkId::from(1)), NetworkMessage::MemPool)), + vec![0x00, 0xf0, 0xff, 0x01, 0x6d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); } @@ -737,8 +737,8 @@ mod test { #[test] #[rustfmt::skip] fn serialize_getaddr_test() { - assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(Network::Bitcoin), NetworkMessage::GetAddr)), - vec![0x01, 0xff, 0xf0, 0x00, 0x67, 0x65, 0x74, 0x61, + assert_eq!(serialize(&RawNetworkMessage::new(Magic::from(NetworkId::from(1)), NetworkMessage::GetAddr)), + vec![0x00, 0xf0, 0xff, 0x01, 0x67, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2]); } @@ -747,12 +747,11 @@ mod test { fn deserialize_getaddr_test() { #[rustfmt::skip] let msg = deserialize(&[ - 0x01, 0xff, 0xf0, 0x00, 0x67, 0x65, 0x74, 0x61, + 0x00, 0xf0, 0xff, 0x01, 0x67, 0x65, 0x74, 0x61, 0x64, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xf6, 0xe0, 0xe2 ]); - let preimage = - RawNetworkMessage::new(Magic::from(Network::Bitcoin), NetworkMessage::GetAddr); + let preimage = RawNetworkMessage::new(Magic::from(NetworkId::from(1)), NetworkMessage::GetAddr); assert!(msg.is_ok()); let msg: RawNetworkMessage = msg.unwrap(); assert_eq!(preimage.magic, msg.magic); @@ -763,7 +762,7 @@ mod test { fn deserialize_version_test() { #[rustfmt::skip] let msg = deserialize::(&[ - 0x01, 0xff, 0xf0, 0x00, 0x76, 0x65, 0x72, 0x73, + 0x00, 0xf0, 0xff, 0x01, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, @@ -783,7 +782,7 @@ mod test { assert!(msg.is_ok()); let msg = msg.unwrap(); - assert_eq!(msg.magic, Magic::from(Network::Bitcoin)); + assert_eq!(msg.magic, Magic::from(NetworkId::from(1))); if let NetworkMessage::Version(version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); assert_eq!( @@ -807,7 +806,7 @@ mod test { fn deserialize_partial_message_test() { #[rustfmt::skip] let data = [ - 0x01, 0xff, 0xf0, 0x00, 0x76, 0x65, 0x72, 0x73, + 0x00, 0xf0, 0xff, 0x01, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0xbe, 0x61, 0xb8, 0x27, 0x7f, 0x11, 0x01, 0x00, 0x0d, 0x04, 0x00, 0x00, @@ -829,7 +828,7 @@ mod test { let (msg, consumed) = msg.unwrap(); assert_eq!(consumed, data.to_vec().len() - 2); - assert_eq!(msg.magic, Magic::from(Network::Bitcoin)); + assert_eq!(msg.magic, Magic::from(NetworkId::from(1))); if let NetworkMessage::Version(version_msg) = msg.payload { assert_eq!(version_msg.version, 70015); assert_eq!( diff --git a/tapyrus/src/p2p/mod.rs b/tapyrus/src/p2p/mod.rs index 17090b97..3ac35a97 100644 --- a/tapyrus/src/p2p/mod.rs +++ b/tapyrus/src/p2p/mod.rs @@ -30,8 +30,9 @@ use hex::FromHex; use internals::{debug_from_display, write_err}; use crate::consensus::encode::{self, Decodable, Encodable}; +use crate::network::NetworkId; use crate::prelude::{Borrow, BorrowMut, String, ToOwned}; -use crate::{io, Network}; +use crate::io; /// Version of the protocol as appearing in network message headers. /// @@ -204,16 +205,10 @@ impl Decodable for ServiceFlags { pub struct Magic([u8; 4]); impl Magic { - /// Bitcoin mainnet network magic bytes. - pub const BITCOIN: Self = Self([0x01, 0xFF, 0xF0, 0x00]); - /// Bitcoin testnet network magic bytes. - pub const TESTNET: Self = Self([0x75, 0x9A, 0x83, 0x74]); - /// Bitcoin signet network magic bytes. - pub const SIGNET: Self = Self([0x0A, 0x03, 0xCF, 0x40]); - /// Bitcoin regtest network magic bytes. - pub const REGTEST: Self = Self([0x73, 0x9A, 0x97, 0x74]); - /// Paradium network magic bytes. - pub const PARADIUM: Self = Self([0x01, 0xff, 0xf0, 0x64]); + /// Tapyrus prod network magic bytes. + pub const PROD: Self = Self([0xF9, 0xBE, 0xB4, 0xD9]); + /// Tapyrus dev network magic bytes. + pub const DEV: Self = Self([0x0B, 0x11, 0x09, 0x07]); /// Create network magic from bytes. pub fn from_bytes(bytes: [u8; 4]) -> Magic { Magic(bytes) } @@ -233,32 +228,18 @@ impl FromStr for Magic { } } -impl From for Magic { - fn from(network: Network) -> Magic { - match network { - // Note: new network entries must explicitly be matched in `try_from` below. - Network::Bitcoin => Magic::BITCOIN, - Network::Testnet => Magic::TESTNET, - Network::Signet => Magic::SIGNET, - Network::Regtest => Magic::REGTEST, - Network::Paradium => Magic::PARADIUM, - } +impl From for Magic { + fn from(network_id: NetworkId) -> Magic { + Magic::from_bytes(network_id.magic().to_be_bytes()) } } -impl TryFrom for Network { +impl TryFrom for NetworkId { type Error = UnknownMagicError; fn try_from(magic: Magic) -> Result { - match magic { - // Note: any new network entries must be matched against here. - Magic::BITCOIN => Ok(Network::Bitcoin), - Magic::TESTNET => Ok(Network::Testnet), - Magic::SIGNET => Ok(Network::Signet), - Magic::REGTEST => Ok(Network::Regtest), - Magic::PARADIUM => Ok(Network::Paradium), - _ => Err(UnknownMagicError(magic)), - } + let n = u32::from_be_bytes(magic.to_bytes()) - 33550335; + Ok(NetworkId::from(n)) } } @@ -412,15 +393,15 @@ mod tests { #[test] fn magic_from_str() { let known_network_magic_strs = [ - ("01fff000", Network::Bitcoin), - ("759a8374", Network::Testnet), - ("739a9774", Network::Regtest), - ("0a03cf40", Network::Signet), - ("01fff064", Network::Paradium), + ("01fff000", NetworkId::from(1)), + ("01fff064", NetworkId::from(101)), + ("759a8374", NetworkId::from(1939510133)), + ("739a9774", NetworkId::from(1905960821)) ]; - for (magic_str, network) in &known_network_magic_strs { + + for (magic_str, network_id) in &known_network_magic_strs { let magic: Magic = Magic::from_str(magic_str).unwrap(); - assert_eq!(Network::try_from(magic).unwrap(), *network); + assert_eq!(NetworkId::try_from(magic).unwrap(), *network_id); assert_eq!(&magic.to_string(), magic_str); } } diff --git a/tapyrus/src/psbt/mod.rs b/tapyrus/src/psbt/mod.rs index a44daa6f..5a4c3370 100644 --- a/tapyrus/src/psbt/mod.rs +++ b/tapyrus/src/psbt/mod.rs @@ -1011,7 +1011,7 @@ mod tests { use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; - use crate::network::Network::Bitcoin; + use crate::network::Network::Prod; use crate::psbt::map::{Input, Output}; use crate::psbt::raw; use crate::psbt::serialize::{Deserialize, Serialize}; @@ -1148,7 +1148,7 @@ mod tests { let mut hd_keypaths: BTreeMap = Default::default(); - let mut sk: Xpriv = Xpriv::new_master(Bitcoin, &seed).unwrap(); + let mut sk: Xpriv = Xpriv::new_master(Prod, &seed).unwrap(); let fprint = sk.fingerprint(secp); @@ -1923,7 +1923,7 @@ mod tests { let secp = Secp256k1::new(); let sk = SecretKey::new(&mut thread_rng()); - let priv_key = PrivateKey::new(sk, crate::Network::Regtest); + let priv_key = PrivateKey::new(sk, crate::Network::Dev); let pk = PublicKey::from_private_key(&secp, &priv_key); (priv_key, pk, secp) diff --git a/tapyrus/src/sign_message.rs b/tapyrus/src/sign_message.rs index 167363f1..13c5695f 100644 --- a/tapyrus/src/sign_message.rs +++ b/tapyrus/src/sign_message.rs @@ -239,14 +239,14 @@ mod tests { assert!(pubkey.compressed); assert_eq!(pubkey.inner, secp256k1::PublicKey::from_secret_key(&secp, &privkey)); - let p2pkh = Address::p2pkh(&pubkey, Network::Bitcoin); + let p2pkh = Address::p2pkh(&pubkey, Network::Prod); assert_eq!(signature2.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(true)); - let p2wpkh = Address::p2wpkh(&pubkey, Network::Bitcoin).unwrap(); + let p2wpkh = Address::p2wpkh(&pubkey, Network::Prod).unwrap(); assert_eq!( signature2.is_signed_by_address(&secp, &p2wpkh, msg_hash), Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2wpkh)) ); - let p2shwpkh = Address::p2shwpkh(&pubkey, Network::Bitcoin).unwrap(); + let p2shwpkh = Address::p2shwpkh(&pubkey, Network::Prod).unwrap(); assert_eq!( signature2.is_signed_by_address(&secp, &p2shwpkh, msg_hash), Err(MessageSignatureError::UnsupportedAddressType(AddressType::P2sh)) @@ -277,7 +277,7 @@ mod tests { PublicKey::from_slice(&BASE64_STANDARD.decode(pubkey_base64).expect("base64 string")) .expect("pubkey slice"); - let p2pkh = Address::p2pkh(&pubkey, Network::Bitcoin); + let p2pkh = Address::p2pkh(&pubkey, Network::Prod); assert_eq!(signature.is_signed_by_address(&secp, &p2pkh, msg_hash), Ok(false)); } } diff --git a/tapyrus/src/taproot.rs b/tapyrus/src/taproot.rs index 53b38097..eb837ee0 100644 --- a/tapyrus/src/taproot.rs +++ b/tapyrus/src/taproot.rs @@ -1964,7 +1964,7 @@ mod test { let tweak = TapTweakHash::from_key_and_tweak(internal_key, merkle_root); let (output_key, _parity) = internal_key.tap_tweak(secp, merkle_root); - let addr = Address::p2tr(secp, internal_key, merkle_root, Network::Bitcoin); + let addr = Address::p2tr(secp, internal_key, merkle_root, Network::Prod); let spk = addr.script_pubkey(); assert_eq!(expected_output_key, output_key.to_inner()); diff --git a/tapyrus/tests/psbt.rs b/tapyrus/tests/psbt.rs index 6812e95c..eec4af80 100644 --- a/tapyrus/tests/psbt.rs +++ b/tapyrus/tests/psbt.rs @@ -18,7 +18,7 @@ use tapyrus::{ Transaction, TxIn, TxOut, Witness, }; -const NETWORK: Network = Network::Testnet; +const NETWORK: Network = Network::Dev; #[track_caller] fn hex_psbt(s: &str) -> Psbt { diff --git a/tapyrus/tests/serde.rs b/tapyrus/tests/serde.rs index 41afdbe5..f9391521 100644 --- a/tapyrus/tests/serde.rs +++ b/tapyrus/tests/serde.rs @@ -146,7 +146,7 @@ fn serde_regression_witness() { fn serde_regression_address() { let s = include_str!("data/serde/public_key_hex"); let pk = PublicKey::from_str(s.trim()).unwrap(); - let addr = Address::p2pkh(&pk, Network::Bitcoin); + let addr = Address::p2pkh(&pk, Network::Prod); let got = serialize(&addr).unwrap(); let want = include_bytes!("data/serde/address_bincode") as &[_];