From 767f06fe75d014f2db7b71abefa7b97854f4c8f6 Mon Sep 17 00:00:00 2001 From: Hajime Yamaguchi Date: Tue, 24 Dec 2019 13:29:27 +0900 Subject: [PATCH 1/6] Implement Decordable/Encodable for util::key::PublicKey --- src/util/key.rs | 477 ++++++++++++++++++++++++++++++++ tapyrus/src/consensus/encode.rs | 4 + tapyrus/src/consensus/serde.rs | 1 + tapyrus/src/crypto/key.rs | 42 +++ 4 files changed, 524 insertions(+) create mode 100644 src/util/key.rs diff --git a/src/util/key.rs b/src/util/key.rs new file mode 100644 index 00000000..1021a3f2 --- /dev/null +++ b/src/util/key.rs @@ -0,0 +1,477 @@ +// Rust Bitcoin Library +// Written in 2014 by +// Andrew Poelstra +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this software to +// the public domain worldwide. This software is distributed without +// any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication +// along with this software. +// If not, see . +// +// Changes for rust-tapyrus is licensed as below. +// Copyright (c) 2019 Chaintope Inc. +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. +// + +//! Bitcoin Keys +//! +//! Keys used in Bitcoin that can be roundtrip (de)serialized. +//! + +use std::fmt::{self, Write}; +use std::str::FromStr; +use std::{io, ops}; + +use consensus::{encode, Decodable, Encodable}; +use network::constants::Network; +use secp256k1::{self, Secp256k1}; +use util::base58; + +/// A Bitcoin ECDSA public key +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct PublicKey { + /// Whether this public key should be serialized as compressed + pub compressed: bool, + /// The actual ECDSA key + pub key: secp256k1::PublicKey, +} + +impl PublicKey { + /// Write the public key into a writer + pub fn write_into(&self, mut writer: W) { + let write_res: io::Result<()> = if self.compressed { + writer.write_all(&self.key.serialize()) + } else { + writer.write_all(&self.key.serialize_uncompressed()) + }; + debug_assert!(write_res.is_ok()); + } + + /// Serialize the public key to bytes + pub fn to_bytes(&self) -> Vec { + let mut buf = Vec::new(); + self.write_into(&mut buf); + buf + } + + /// Deserialize a public key from a slice + pub fn from_slice(data: &[u8]) -> Result { + let compressed: bool = match data.len() { + 33 => true, + 65 => false, + len => { + return Err(base58::Error::InvalidLength(len).into()); + } + }; + + Ok(PublicKey { + compressed: compressed, + key: secp256k1::PublicKey::from_slice(data)?, + }) + } + + /// Computes the public key as supposed to be used with this secret + pub fn from_private_key( + secp: &Secp256k1, + sk: &PrivateKey, + ) -> PublicKey { + sk.public_key(secp) + } +} + +impl fmt::Display for PublicKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.compressed { + for ch in &self.key.serialize()[..] { + write!(f, "{:02x}", ch)?; + } + } else { + for ch in &self.key.serialize_uncompressed()[..] { + write!(f, "{:02x}", ch)?; + } + } + Ok(()) + } +} + +impl FromStr for PublicKey { + type Err = encode::Error; + fn from_str(s: &str) -> Result { + let key = secp256k1::PublicKey::from_str(s)?; + Ok(PublicKey { + key: key, + compressed: s.len() == 66, + }) + } +} + +#[derive(Copy, Clone, PartialEq, Eq)] +/// A Bitcoin ECDSA private key +pub struct PrivateKey { + /// Whether this private key should be serialized as compressed + pub compressed: bool, + /// The network on which this key should be used + pub network: Network, + /// The actual ECDSA key + pub key: secp256k1::SecretKey, +} + +impl PrivateKey { + /// Creates a public key from this private key + pub fn public_key(&self, secp: &Secp256k1) -> PublicKey { + PublicKey { + compressed: self.compressed, + key: secp256k1::PublicKey::from_secret_key(secp, &self.key), + } + } + + /// Serialize the private key to bytes + pub fn to_bytes(&self) -> Vec { + self.key[..].to_vec() + } + + /// Format the private key to WIF format. + pub fn fmt_wif(&self, fmt: &mut fmt::Write) -> fmt::Result { + let mut ret = [0; 34]; + ret[0] = match self.network { + Network::Bitcoin | Network::Paradium => 128, + Network::Testnet | Network::Regtest => 239, + }; + ret[1..33].copy_from_slice(&self.key[..]); + let privkey = if self.compressed { + ret[33] = 1; + base58::check_encode_slice(&ret[..]) + } else { + base58::check_encode_slice(&ret[..33]) + }; + fmt.write_str(&privkey) + } + + /// Get WIF encoding of this private key. + pub fn to_wif(&self) -> String { + let mut buf = String::new(); + buf.write_fmt(format_args!("{}", self)).unwrap(); + buf.shrink_to_fit(); + buf + } + + /// Parse WIF encoded private key. + pub fn from_wif(wif: &str) -> Result { + let data = base58::from_check(wif)?; + + let compressed = match data.len() { + 33 => false, + 34 => true, + _ => { + return Err(encode::Error::Base58(base58::Error::InvalidLength( + data.len(), + ))); + } + }; + + let network = match data[0] { + 128 => Network::Bitcoin, + 239 => Network::Testnet, + x => { + return Err(encode::Error::Base58(base58::Error::InvalidVersion(vec![ + x, + ]))); + } + }; + + Ok(PrivateKey { + compressed: compressed, + network: network, + key: secp256k1::SecretKey::from_slice(&data[1..33])?, + }) + } +} + +impl fmt::Display for PrivateKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.fmt_wif(f) + } +} + +impl fmt::Debug for PrivateKey { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[private key data]") + } +} + +impl FromStr for PrivateKey { + type Err = encode::Error; + fn from_str(s: &str) -> Result { + PrivateKey::from_wif(s) + } +} + +impl ops::Index for PrivateKey { + type Output = [u8]; + fn index(&self, _: ops::RangeFull) -> &[u8] { + &self.key[..] + } +} + +#[cfg(feature = "serde")] +impl ::serde::Serialize for PrivateKey { + fn serialize(&self, s: S) -> Result { + s.collect_str(self) + } +} + +#[cfg(feature = "serde")] +impl<'de> ::serde::Deserialize<'de> for PrivateKey { + fn deserialize>(d: D) -> Result { + struct WifVisitor; + + impl<'de> ::serde::de::Visitor<'de> for WifVisitor { + type Value = PrivateKey; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("an ASCII WIF string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + if let Ok(s) = ::std::str::from_utf8(v) { + PrivateKey::from_str(s).map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> Result + where + E: ::serde::de::Error, + { + PrivateKey::from_str(v).map_err(E::custom) + } + } + + d.deserialize_str(WifVisitor) + } +} + +#[cfg(feature = "serde")] +impl ::serde::Serialize for PublicKey { + fn serialize(&self, s: S) -> Result { + if s.is_human_readable() { + s.collect_str(self) + } else { + if self.compressed { + s.serialize_bytes(&self.key.serialize()[..]) + } else { + s.serialize_bytes(&self.key.serialize_uncompressed()[..]) + } + } + } +} + +impl Decodable for PublicKey { + #[inline] + fn consensus_decode(d: D) -> Result { + let s: Vec = Decodable::consensus_decode(d)?; + PublicKey::from_slice(&s[..]) + } +} + +impl Encodable for PublicKey { + #[inline] + fn consensus_encode(&self, mut s: S) -> Result { + self.to_bytes().consensus_encode(&mut s) + } +} + +#[cfg(feature = "serde")] +impl<'de> ::serde::Deserialize<'de> for PublicKey { + fn deserialize>(d: D) -> Result { + if d.is_human_readable() { + struct HexVisitor; + + impl<'de> ::serde::de::Visitor<'de> for HexVisitor { + type Value = PublicKey; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("an ASCII hex string") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + if let Ok(hex) = ::std::str::from_utf8(v) { + PublicKey::from_str(hex).map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> Result + where + E: ::serde::de::Error, + { + PublicKey::from_str(v).map_err(E::custom) + } + } + d.deserialize_str(HexVisitor) + } else { + struct BytesVisitor; + + impl<'de> ::serde::de::Visitor<'de> for BytesVisitor { + type Value = PublicKey; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("a bytestring") + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + PublicKey::from_slice(v).map_err(E::custom) + } + } + + d.deserialize_bytes(BytesVisitor) + } + } +} + +#[cfg(test)] +mod tests { + use super::{PrivateKey, PublicKey}; + use network::constants::Network::Bitcoin; + use network::constants::Network::Testnet; + use secp256k1::Secp256k1; + use std::str::FromStr; + use util::address::Address; + + #[test] + fn test_key_derivation() { + // testnet compressed + let sk = + PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); + assert_eq!(sk.network, Testnet); + assert_eq!(sk.compressed, true); + assert_eq!( + &sk.to_wif(), + "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy" + ); + + let secp = Secp256k1::new(); + let pk = Address::p2pkh(&sk.public_key(&secp), sk.network); + assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx"); + + // test string conversion + assert_eq!( + &sk.to_string(), + "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy" + ); + let sk_str = + PrivateKey::from_str("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); + assert_eq!(&sk.to_wif(), &sk_str.to_wif()); + + // mainnet uncompressed + let sk = + PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); + assert_eq!(sk.network, Bitcoin); + assert_eq!(sk.compressed, false); + assert_eq!( + &sk.to_wif(), + "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3" + ); + + let secp = Secp256k1::new(); + let mut pk = sk.public_key(&secp); + assert_eq!(pk.compressed, false); + assert_eq!(&pk.to_string(), "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"); + assert_eq!(pk, PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap()); + let addr = Address::p2pkh(&pk, sk.network); + assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8"); + pk.compressed = true; + assert_eq!( + &pk.to_string(), + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ); + assert_eq!( + pk, + PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ) + .unwrap() + ); + } + + #[cfg(feature = "serde")] + #[test] + fn test_key_serde() { + use serde_test::{assert_tokens, Configure, Token}; + + static KEY_WIF: &'static str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"; + static PK_STR: &'static str = + "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef"; + static PK_STR_U: &'static str = + "\ + 04\ + 9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\ + 87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\ + "; + static PK_BYTES: [u8; 33] = [ + 0x03, 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, 0x93, 0x82, 0x6d, 0xc6, 0x1c, + 0x19, 0xf4, 0x7c, 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, 0x29, 0xce, 0x32, + 0x5a, 0x0f, 0x46, 0x79, 0xef, + ]; + static PK_BYTES_U: [u8; 65] = [ + 0x04, 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, 0x93, 0x82, 0x6d, 0xc6, 0x1c, + 0x19, 0xf4, 0x7c, 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, 0x29, 0xce, 0x32, + 0x5a, 0x0f, 0x46, 0x79, 0xef, 0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4, 0xf5, + 0xc7, 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda, 0x7c, 0xff, 0x3a, 0xff, 0x6e, 0x81, 0x9e, + 0x4e, 0xe9, 0x71, 0xd8, 0x6b, 0x5e, 0x61, 0x87, 0x5d, + ]; + + let s = Secp256k1::new(); + let sk = PrivateKey::from_str(&KEY_WIF).unwrap(); + let pk = PublicKey::from_private_key(&s, &sk); + let pk_u = PublicKey { + key: pk.key, + compressed: false, + }; + + assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]); + assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]); + assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]); + assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]); + assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]); + } + + #[test] + fn test_encode() { + use consensus::encode::{Decodable, Encodable}; + + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); + let mut s = Vec::new(); + // let mut s = String::new(); + pk.consensus_encode(&mut s); + let encoded = s + .iter() + .map(|x| format!("{:02x}", x)) + .collect::>() + .join(""); + assert_eq!( + "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + encoded + ); + + let decoded = PublicKey::consensus_decode(&s[..]).unwrap(); + assert_eq!(decoded, pk); + } +} diff --git a/tapyrus/src/consensus/encode.rs b/tapyrus/src/consensus/encode.rs index b4597096..58a91745 100644 --- a/tapyrus/src/consensus/encode.rs +++ b/tapyrus/src/consensus/encode.rs @@ -41,6 +41,8 @@ use crate::taproot::TapLeafHash; pub enum Error { /// And I/O error. Io(io::Error), + /// key error + Key(crate::crypto::key::Error), /// Tried to allocate an oversized vector. OversizedVectorAllocation { /// The capacity requested. @@ -69,6 +71,7 @@ impl fmt::Display for Error { match *self { Io(ref e) => write_err!(f, "IO error"; e), + Error::Key(ref e) => write!(f, "Key error: {}", e), OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m), InvalidChecksum { expected: ref e, actual: ref a } => @@ -88,6 +91,7 @@ impl std::error::Error for Error { match self { Io(e) => Some(e), + Error::Key(ref e) => Some(e), OversizedVectorAllocation { .. } | InvalidChecksum { .. } | NonMinimalVarInt diff --git a/tapyrus/src/consensus/serde.rs b/tapyrus/src/consensus/serde.rs index bfe7e149..5b05e0f2 100644 --- a/tapyrus/src/consensus/serde.rs +++ b/tapyrus/src/consensus/serde.rs @@ -375,6 +375,7 @@ enum DecodeError { fn consensus_error_into_serde(error: ConsensusError) -> E { match error { ConsensusError::Io(error) => panic!("unexpected IO error {:?}", error), + ConsensusError::Key(error) => E::custom(format_args!("unexpected Key error: {}", error)), ConsensusError::OversizedVectorAllocation { requested, max } => E::custom(format_args!( "the requested allocation of {} items exceeds maximum of {}", requested, max diff --git a/tapyrus/src/crypto/key.rs b/tapyrus/src/crypto/key.rs index ef182721..43bc69ab 100644 --- a/tapyrus/src/crypto/key.rs +++ b/tapyrus/src/crypto/key.rs @@ -21,6 +21,7 @@ use crate::network::Network; use crate::prelude::*; use crate::taproot::{TapNodeHash, TapTweakHash}; use crate::{base58, io}; +use crate::consensus::{encode, Decodable, Encodable}; /// A Bitcoin ECDSA public key #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -429,6 +430,22 @@ impl<'de> serde::Deserialize<'de> for PrivateKey { } } +impl Decodable for PublicKey { + #[inline] + fn consensus_decode(d: &mut D) -> Result { + let s: Vec = Decodable::consensus_decode(d)?; + PublicKey::from_slice(&s[..]).map_err(encode::Error::Key) + } +} + +impl Encodable for PublicKey { + #[inline] + fn consensus_encode(&self, mut s: &mut S) -> Result { + self.to_bytes().consensus_encode(&mut s) + } +} + + #[cfg(feature = "serde")] #[allow(clippy::collapsible_else_if)] // Aids readability. impl serde::Serialize for PublicKey { @@ -1119,4 +1136,29 @@ mod tests { expected.extend(&secp256k1::constants::GENERATOR_Y); assert_eq!(&expected[..], &g.inner.serialize_uncompressed()[..]); } + + #[test] + fn test_encode() { + use crate::consensus::encode::{Decodable, Encodable}; + + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); + let mut s = Vec::new(); + // let mut s = String::new(); + pk.consensus_encode(&mut s); + let encoded = s + .iter() + .map(|x| format!("{:02x}", x)) + .collect::>() + .join(""); + assert_eq!( + "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + encoded + ); + + let decoded = PublicKey::consensus_decode(&mut &s[..]).unwrap(); + assert_eq!(decoded, pk); + } } From 376459fe85c01ce3761fe548bafd77fe6755e2ba Mon Sep 17 00:00:00 2001 From: Yamaguchi Date: Wed, 5 Jun 2024 02:50:38 +0900 Subject: [PATCH 2/6] Add aggregated pubkey to BlockHeader --- tapyrus/src/bip152.rs | 3 +- tapyrus/src/blockdata/block.rs | 45 ++++++++++++++++++++++++++---- tapyrus/src/blockdata/constants.rs | 16 +++++++++-- tapyrus/src/merkle_tree/block.rs | 23 ++++++++------- 4 files changed, 66 insertions(+), 21 deletions(-) diff --git a/tapyrus/src/bip152.rs b/tapyrus/src/bip152.rs index 6ff1534a..01ec2a86 100644 --- a/tapyrus/src/bip152.rs +++ b/tapyrus/src/bip152.rs @@ -158,7 +158,7 @@ pub struct HeaderAndShortIds { pub prefilled_txs: Vec, } impl_consensus_encoding!(HeaderAndShortIds, header, nonce, short_ids, prefilled_txs); - + impl HeaderAndShortIds { /// Create a new [HeaderAndShortIds] from a full block. /// @@ -405,6 +405,7 @@ mod test { merkle_root: TxMerkleNode::hash(&[1]), im_merkle_root: TxMerkleNode::hash(&[1]), time: 2, + aggregated_public_key: Some(PublicKey::generator()), proof: Some(Signature::default()), }, txdata: vec![dummy_tx(&[2]), dummy_tx(&[3]), dummy_tx(&[4])], diff --git a/tapyrus/src/blockdata/block.rs b/tapyrus/src/blockdata/block.rs index 44669551..5137394f 100644 --- a/tapyrus/src/blockdata/block.rs +++ b/tapyrus/src/blockdata/block.rs @@ -22,6 +22,7 @@ use crate::hash_types::{TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxi use crate::internal_macros::impl_consensus_encoding; use crate::{crypto, prelude::*}; use crate::{io, merkle_tree, VarInt}; +use crate::crypto::key::PublicKey; /// Bitcoin block header. /// @@ -47,12 +48,12 @@ pub struct Header { pub im_merkle_root: TxMerkleNode, /// The timestamp of the block, as claimed by the miner. pub time: u32, + ///Aggregate public key of tapyrus-signer used to verify block proof. This field is optional and may be present in all blocks. + pub aggregated_public_key: PublicKeyOpt, /// Collection holds a signature for block hash which is consisted of block header without Proof. pub proof: Option, } -impl_consensus_encoding!(Header, version, prev_blockhash, merkle_root, im_merkle_root, time, proof); - impl Header { /// The number of bytes that the block header contributes to the size of a block. // Serialized length of fields (version, prev_blockhash, merkle_root, im_merkle_root, time) @@ -66,6 +67,8 @@ impl Header { } } +impl_consensus_encoding!(Header, version, prev_blockhash, merkle_root, im_merkle_root, time, aggregated_public_key, proof); + impl fmt::Debug for Header { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Header") @@ -162,6 +165,33 @@ impl Decodable for Version { } } + +/// Optional aggregated public key +pub type PublicKeyOpt = Option; + +impl Decodable for PublicKeyOpt { + #[inline] + fn consensus_decode(mut d: D) -> Result { + match Decodable::consensus_decode(&mut d) { + Ok(pk) => Ok(Some(pk)), + Err(_) => Ok(None), + } + } +} + +impl Encodable for PublicKeyOpt { + #[inline] + fn consensus_encode(&self, mut s: S) -> Result { + match self { + Some(pk) => pk.consensus_encode(&mut s), + None => { + let v = Vec::::new(); + v.consensus_encode(&mut s) + } + } + } +} + /// Bitcoin block. /// /// A collection of transactions with an attached proof of work. @@ -446,6 +476,7 @@ impl std::error::Error for ValidationError { #[cfg(test)] mod tests { use hex::{test_hex_unwrap as hex, FromHex}; + use std::str::FromStr; use super::*; use crate::consensus::encode::{deserialize, serialize}; @@ -473,12 +504,15 @@ mod tests { #[test] fn block_test() { // Mainnet block 00000000b0c5a240b2a61d2e75692224efd4cbecdf6eaf4cc2cf477ca7c270e7 - let some_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e49000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000"); - let cutoff_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e49000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac"); + let some_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e4921032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000"); + let cutoff_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e4921032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac"); let prevhash = hex!("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000"); let merkle = hex!("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c"); - + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); let decode: Result = deserialize(&some_block); let bad_decode: Result = deserialize(&cutoff_block); @@ -491,6 +525,7 @@ mod tests { assert_eq!(real_decode.header.im_merkle_root, real_decode.immutable_merkle_root().unwrap()); assert_eq!(serialize(&real_decode.header.merkle_root), merkle); assert_eq!(real_decode.header.time, 1231965655); + assert_eq!(real_decode.header.aggregated_public_key.unwrap(), pk); // [test] TODO: check the transaction data assert_eq!(real_decode.total_size(), some_block.len()); diff --git a/tapyrus/src/blockdata/constants.rs b/tapyrus/src/blockdata/constants.rs index 0c5a8b83..6a678eb1 100644 --- a/tapyrus/src/blockdata/constants.rs +++ b/tapyrus/src/blockdata/constants.rs @@ -8,6 +8,7 @@ //! use core::default::Default; +use std::str::FromStr; use hashes::{sha256d, Hash}; use hex_lit::hex; @@ -23,6 +24,7 @@ use crate::crypto::schnorr::Signature; use crate::internal_macros::impl_bytes_newtype; use crate::network::Network; use crate::Amount; +use crate::crypto::key::PublicKey; #[deprecated(since = "0.31.0", note = "Use Weight::MAX_BLOCK instead")] /// The maximum allowed weight for a block, see BIP 141 (network rule). @@ -91,6 +93,9 @@ pub fn genesis_block(network: Network) -> Block { let txdata = vec![bitcoin_genesis_tx()]; let hash: sha256d::Hash = txdata[0].txid().into(); let merkle_root = hash.into(); + let public_key = + PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af") + .unwrap(); match network { Network::Bitcoin => Block { header: block::Header { @@ -99,6 +104,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1231006505, + aggregated_public_key: Some(public_key), proof: Some(Signature::default()), }, txdata, @@ -110,6 +116,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1296688602, + aggregated_public_key: Some(public_key), proof: Some(Signature::default()), }, txdata, @@ -121,6 +128,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1598918400, + aggregated_public_key: Some(public_key), proof: Some(Signature::default()), }, txdata, @@ -132,6 +140,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1296688602, + aggregated_public_key: Some(public_key), proof: Some(Signature::default()), }, txdata, @@ -145,6 +154,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1562925929, + aggregated_public_key: Some(public_key), proof: Some(Signature::default()), }, txdata, @@ -254,7 +264,7 @@ mod test { assert_eq!(gen.header.time, 1231006505); assert_eq!( gen.header.block_hash().to_string(), - "3c8890361aca183ecb0059ae78e4e57dc514a689588aa7cb97fdc3a6601d08a4" + "1c184bf287b15f641f8b063aab2af4123519d227e8681463b91d675192f6279c" ); } @@ -271,7 +281,7 @@ mod test { assert_eq!(gen.header.time, 1296688602); assert_eq!( gen.header.block_hash().to_string(), - "2f90e0d9843be35112f9830d6e86bf2ef4dd92836979ac4aae1a6f41e0797588" + "13530b95110ac11ae2d22d82acc5ad00a3510bb340c9667309cb811c2883cdc5" ); } @@ -288,7 +298,7 @@ mod test { assert_eq!(gen.header.time, 1598918400); assert_eq!( gen.header.block_hash().to_string(), - "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6" + "27136d27aba81a18449dfdeca2d0c2a973dfc0cdf0a2527b4860ed1f816145d4".to_string() ); } diff --git a/tapyrus/src/merkle_tree/block.rs b/tapyrus/src/merkle_tree/block.rs index 16c2597a..8274bc21 100644 --- a/tapyrus/src/merkle_tree/block.rs +++ b/tapyrus/src/merkle_tree/block.rs @@ -20,10 +20,9 @@ //! // $ TXID="5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2" //! // $ tapyrus-cli gettxoutproof [\"$TXID\"] //! let mb_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b913719\ -//! 0000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38fa323afa6d43f36\ -//! 4667ed377d3b500c1622d911c3a5b0ab10ca0e2ac89c9460cb33a5914c000200000002252bf9d75c4f481ebb\ -//! 6278d708257d1f12beb6dd30301d26c623f789b2ba6fc0e2d32adb5f8ca820731dff234a84e78ec30bce4ec6\ -//! 9dbd562d0b2b8266bf4e5a0105").unwrap(); +//! 4667ed377d3b500c1622d911c3a5b0ab10ca0e2ac89c9460cb33a5914c00000200000002252bf9d75c4f481e\ +//! bb6278d708257d1f12beb6dd30301d26c623f789b2ba6fc0e2d32adb5f8ca820731dff234a84e78ec30bce4e\ +//! c69dbd562d0b2b8266bf4e5a0105").unwrap(); //! let mb: MerkleBlock = tapyrus::consensus::deserialize(&mb_bytes).unwrap(); //! //! // Authenticate and extract matched transaction ids @@ -80,14 +79,14 @@ impl MerkleBlock { /// // Block 80000 /// let block_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad2\ /// 7b9137190000000000190760b278fe7b8565fda3b968b918d5fd997f993b23674c0af3b6fde300b38fa3\ - /// 23afa6d43f364667ed377d3b500c1622d911c3a5b0ab10ca0e2ac89c9460cb33a5914c00020100000001\ - /// 0000000000000000000000000000000000000000000000000000000000000000ffffffff0704e6ed5b1b\ - /// 014effffffff0100f2052a01000000434104b68a50eaa0287eff855189f949c1c6e5f58b37c88231373d\ - /// 8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413bba7fbff9bc762419a76d87b16086eac00\ - /// 0000000100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f50000\ - /// 00004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db0221\ - /// 00e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f205\ - /// 2a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000").unwrap(); + /// 23afa6d43f364667ed377d3b500c1622d911c3a5b0ab10ca0e2ac89c9460cb33a5914c00000201000000\ + /// 010000000000000000000000000000000000000000000000000000000000000000ffffffff0704e6ed5b\ + /// 1b014effffffff0100f2052a01000000434104b68a50eaa0287eff855189f949c1c6e5f58b37c8823137\ + /// 3d8a59809cbae83059cc6469d65c665ccfd1cfeb75c6e8e19413bba7fbff9bc762419a76d87b16086eac\ + /// 000000000100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f500\ + /// 0000004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db02\ + /// 2100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f2\ + /// 052a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000").unwrap(); /// let block: Block = tapyrus::consensus::deserialize(&block_bytes).unwrap(); /// /// // Create a merkle block containing a single transaction From 87bc8cc8719a193f8f3fe9dcb0e552d3a9fac1f4 Mon Sep 17 00:00:00 2001 From: Hajime Yamaguchi Date: Wed, 25 Dec 2019 16:34:11 +0900 Subject: [PATCH 3/6] Fix build error on Rust 1.22.0 --- src/util/key.rs | 477 --------------------------------- tapyrus/src/blockdata/block.rs | 2 +- 2 files changed, 1 insertion(+), 478 deletions(-) delete mode 100644 src/util/key.rs diff --git a/src/util/key.rs b/src/util/key.rs deleted file mode 100644 index 1021a3f2..00000000 --- a/src/util/key.rs +++ /dev/null @@ -1,477 +0,0 @@ -// Rust Bitcoin Library -// Written in 2014 by -// Andrew Poelstra -// To the extent possible under law, the author(s) have dedicated all -// copyright and related and neighboring rights to this software to -// the public domain worldwide. This software is distributed without -// any warranty. -// -// You should have received a copy of the CC0 Public Domain Dedication -// along with this software. -// If not, see . -// -// Changes for rust-tapyrus is licensed as below. -// Copyright (c) 2019 Chaintope Inc. -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. -// - -//! Bitcoin Keys -//! -//! Keys used in Bitcoin that can be roundtrip (de)serialized. -//! - -use std::fmt::{self, Write}; -use std::str::FromStr; -use std::{io, ops}; - -use consensus::{encode, Decodable, Encodable}; -use network::constants::Network; -use secp256k1::{self, Secp256k1}; -use util::base58; - -/// A Bitcoin ECDSA public key -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct PublicKey { - /// Whether this public key should be serialized as compressed - pub compressed: bool, - /// The actual ECDSA key - pub key: secp256k1::PublicKey, -} - -impl PublicKey { - /// Write the public key into a writer - pub fn write_into(&self, mut writer: W) { - let write_res: io::Result<()> = if self.compressed { - writer.write_all(&self.key.serialize()) - } else { - writer.write_all(&self.key.serialize_uncompressed()) - }; - debug_assert!(write_res.is_ok()); - } - - /// Serialize the public key to bytes - pub fn to_bytes(&self) -> Vec { - let mut buf = Vec::new(); - self.write_into(&mut buf); - buf - } - - /// Deserialize a public key from a slice - pub fn from_slice(data: &[u8]) -> Result { - let compressed: bool = match data.len() { - 33 => true, - 65 => false, - len => { - return Err(base58::Error::InvalidLength(len).into()); - } - }; - - Ok(PublicKey { - compressed: compressed, - key: secp256k1::PublicKey::from_slice(data)?, - }) - } - - /// Computes the public key as supposed to be used with this secret - pub fn from_private_key( - secp: &Secp256k1, - sk: &PrivateKey, - ) -> PublicKey { - sk.public_key(secp) - } -} - -impl fmt::Display for PublicKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.compressed { - for ch in &self.key.serialize()[..] { - write!(f, "{:02x}", ch)?; - } - } else { - for ch in &self.key.serialize_uncompressed()[..] { - write!(f, "{:02x}", ch)?; - } - } - Ok(()) - } -} - -impl FromStr for PublicKey { - type Err = encode::Error; - fn from_str(s: &str) -> Result { - let key = secp256k1::PublicKey::from_str(s)?; - Ok(PublicKey { - key: key, - compressed: s.len() == 66, - }) - } -} - -#[derive(Copy, Clone, PartialEq, Eq)] -/// A Bitcoin ECDSA private key -pub struct PrivateKey { - /// Whether this private key should be serialized as compressed - pub compressed: bool, - /// The network on which this key should be used - pub network: Network, - /// The actual ECDSA key - pub key: secp256k1::SecretKey, -} - -impl PrivateKey { - /// Creates a public key from this private key - pub fn public_key(&self, secp: &Secp256k1) -> PublicKey { - PublicKey { - compressed: self.compressed, - key: secp256k1::PublicKey::from_secret_key(secp, &self.key), - } - } - - /// Serialize the private key to bytes - pub fn to_bytes(&self) -> Vec { - self.key[..].to_vec() - } - - /// Format the private key to WIF format. - pub fn fmt_wif(&self, fmt: &mut fmt::Write) -> fmt::Result { - let mut ret = [0; 34]; - ret[0] = match self.network { - Network::Bitcoin | Network::Paradium => 128, - Network::Testnet | Network::Regtest => 239, - }; - ret[1..33].copy_from_slice(&self.key[..]); - let privkey = if self.compressed { - ret[33] = 1; - base58::check_encode_slice(&ret[..]) - } else { - base58::check_encode_slice(&ret[..33]) - }; - fmt.write_str(&privkey) - } - - /// Get WIF encoding of this private key. - pub fn to_wif(&self) -> String { - let mut buf = String::new(); - buf.write_fmt(format_args!("{}", self)).unwrap(); - buf.shrink_to_fit(); - buf - } - - /// Parse WIF encoded private key. - pub fn from_wif(wif: &str) -> Result { - let data = base58::from_check(wif)?; - - let compressed = match data.len() { - 33 => false, - 34 => true, - _ => { - return Err(encode::Error::Base58(base58::Error::InvalidLength( - data.len(), - ))); - } - }; - - let network = match data[0] { - 128 => Network::Bitcoin, - 239 => Network::Testnet, - x => { - return Err(encode::Error::Base58(base58::Error::InvalidVersion(vec![ - x, - ]))); - } - }; - - Ok(PrivateKey { - compressed: compressed, - network: network, - key: secp256k1::SecretKey::from_slice(&data[1..33])?, - }) - } -} - -impl fmt::Display for PrivateKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.fmt_wif(f) - } -} - -impl fmt::Debug for PrivateKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[private key data]") - } -} - -impl FromStr for PrivateKey { - type Err = encode::Error; - fn from_str(s: &str) -> Result { - PrivateKey::from_wif(s) - } -} - -impl ops::Index for PrivateKey { - type Output = [u8]; - fn index(&self, _: ops::RangeFull) -> &[u8] { - &self.key[..] - } -} - -#[cfg(feature = "serde")] -impl ::serde::Serialize for PrivateKey { - fn serialize(&self, s: S) -> Result { - s.collect_str(self) - } -} - -#[cfg(feature = "serde")] -impl<'de> ::serde::Deserialize<'de> for PrivateKey { - fn deserialize>(d: D) -> Result { - struct WifVisitor; - - impl<'de> ::serde::de::Visitor<'de> for WifVisitor { - type Value = PrivateKey; - - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - formatter.write_str("an ASCII WIF string") - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: ::serde::de::Error, - { - if let Ok(s) = ::std::str::from_utf8(v) { - PrivateKey::from_str(s).map_err(E::custom) - } else { - Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) - } - } - - fn visit_str(self, v: &str) -> Result - where - E: ::serde::de::Error, - { - PrivateKey::from_str(v).map_err(E::custom) - } - } - - d.deserialize_str(WifVisitor) - } -} - -#[cfg(feature = "serde")] -impl ::serde::Serialize for PublicKey { - fn serialize(&self, s: S) -> Result { - if s.is_human_readable() { - s.collect_str(self) - } else { - if self.compressed { - s.serialize_bytes(&self.key.serialize()[..]) - } else { - s.serialize_bytes(&self.key.serialize_uncompressed()[..]) - } - } - } -} - -impl Decodable for PublicKey { - #[inline] - fn consensus_decode(d: D) -> Result { - let s: Vec = Decodable::consensus_decode(d)?; - PublicKey::from_slice(&s[..]) - } -} - -impl Encodable for PublicKey { - #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - self.to_bytes().consensus_encode(&mut s) - } -} - -#[cfg(feature = "serde")] -impl<'de> ::serde::Deserialize<'de> for PublicKey { - fn deserialize>(d: D) -> Result { - if d.is_human_readable() { - struct HexVisitor; - - impl<'de> ::serde::de::Visitor<'de> for HexVisitor { - type Value = PublicKey; - - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - formatter.write_str("an ASCII hex string") - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: ::serde::de::Error, - { - if let Ok(hex) = ::std::str::from_utf8(v) { - PublicKey::from_str(hex).map_err(E::custom) - } else { - Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) - } - } - - fn visit_str(self, v: &str) -> Result - where - E: ::serde::de::Error, - { - PublicKey::from_str(v).map_err(E::custom) - } - } - d.deserialize_str(HexVisitor) - } else { - struct BytesVisitor; - - impl<'de> ::serde::de::Visitor<'de> for BytesVisitor { - type Value = PublicKey; - - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - formatter.write_str("a bytestring") - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: ::serde::de::Error, - { - PublicKey::from_slice(v).map_err(E::custom) - } - } - - d.deserialize_bytes(BytesVisitor) - } - } -} - -#[cfg(test)] -mod tests { - use super::{PrivateKey, PublicKey}; - use network::constants::Network::Bitcoin; - use network::constants::Network::Testnet; - use secp256k1::Secp256k1; - use std::str::FromStr; - use util::address::Address; - - #[test] - fn test_key_derivation() { - // testnet compressed - let sk = - PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); - assert_eq!(sk.network, Testnet); - assert_eq!(sk.compressed, true); - assert_eq!( - &sk.to_wif(), - "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy" - ); - - let secp = Secp256k1::new(); - let pk = Address::p2pkh(&sk.public_key(&secp), sk.network); - assert_eq!(&pk.to_string(), "mqwpxxvfv3QbM8PU8uBx2jaNt9btQqvQNx"); - - // test string conversion - assert_eq!( - &sk.to_string(), - "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy" - ); - let sk_str = - PrivateKey::from_str("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); - assert_eq!(&sk.to_wif(), &sk_str.to_wif()); - - // mainnet uncompressed - let sk = - PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); - assert_eq!(sk.network, Bitcoin); - assert_eq!(sk.compressed, false); - assert_eq!( - &sk.to_wif(), - "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3" - ); - - let secp = Secp256k1::new(); - let mut pk = sk.public_key(&secp); - assert_eq!(pk.compressed, false); - assert_eq!(&pk.to_string(), "042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133"); - assert_eq!(pk, PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap()); - let addr = Address::p2pkh(&pk, sk.network); - assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8"); - pk.compressed = true; - assert_eq!( - &pk.to_string(), - "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" - ); - assert_eq!( - pk, - PublicKey::from_str( - "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" - ) - .unwrap() - ); - } - - #[cfg(feature = "serde")] - #[test] - fn test_key_serde() { - use serde_test::{assert_tokens, Configure, Token}; - - static KEY_WIF: &'static str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"; - static PK_STR: &'static str = - "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef"; - static PK_STR_U: &'static str = - "\ - 04\ - 9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\ - 87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\ - "; - static PK_BYTES: [u8; 33] = [ - 0x03, 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, 0x93, 0x82, 0x6d, 0xc6, 0x1c, - 0x19, 0xf4, 0x7c, 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, 0x29, 0xce, 0x32, - 0x5a, 0x0f, 0x46, 0x79, 0xef, - ]; - static PK_BYTES_U: [u8; 65] = [ - 0x04, 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, 0x93, 0x82, 0x6d, 0xc6, 0x1c, - 0x19, 0xf4, 0x7c, 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, 0x29, 0xce, 0x32, - 0x5a, 0x0f, 0x46, 0x79, 0xef, 0x87, 0x28, 0x8e, 0xd7, 0x3c, 0xe4, 0x7f, 0xc4, 0xf5, - 0xc7, 0x9d, 0x19, 0xeb, 0xfa, 0x57, 0xda, 0x7c, 0xff, 0x3a, 0xff, 0x6e, 0x81, 0x9e, - 0x4e, 0xe9, 0x71, 0xd8, 0x6b, 0x5e, 0x61, 0x87, 0x5d, - ]; - - let s = Secp256k1::new(); - let sk = PrivateKey::from_str(&KEY_WIF).unwrap(); - let pk = PublicKey::from_private_key(&s, &sk); - let pk_u = PublicKey { - key: pk.key, - compressed: false, - }; - - assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]); - assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]); - assert_tokens(&pk.readable(), &[Token::BorrowedStr(PK_STR)]); - assert_tokens(&pk_u.compact(), &[Token::BorrowedBytes(&PK_BYTES_U[..])]); - assert_tokens(&pk_u.readable(), &[Token::BorrowedStr(PK_STR_U)]); - } - - #[test] - fn test_encode() { - use consensus::encode::{Decodable, Encodable}; - - let pk = PublicKey::from_str( - "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", - ) - .unwrap(); - let mut s = Vec::new(); - // let mut s = String::new(); - pk.consensus_encode(&mut s); - let encoded = s - .iter() - .map(|x| format!("{:02x}", x)) - .collect::>() - .join(""); - assert_eq!( - "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", - encoded - ); - - let decoded = PublicKey::consensus_decode(&s[..]).unwrap(); - assert_eq!(decoded, pk); - } -} diff --git a/tapyrus/src/blockdata/block.rs b/tapyrus/src/blockdata/block.rs index 5137394f..1e39fe72 100644 --- a/tapyrus/src/blockdata/block.rs +++ b/tapyrus/src/blockdata/block.rs @@ -182,7 +182,7 @@ impl Decodable for PublicKeyOpt { impl Encodable for PublicKeyOpt { #[inline] fn consensus_encode(&self, mut s: S) -> Result { - match self { + match *self { Some(pk) => pk.consensus_encode(&mut s), None => { let v = Vec::::new(); From 012f1fca66c0879615ec06daf922995133f3054e Mon Sep 17 00:00:00 2001 From: Yamaguchi Date: Wed, 5 Jun 2024 14:40:35 +0900 Subject: [PATCH 4/6] Support xfield for rust-tapyrus * Define new enum ExtraField to hold data in BlockHeader(b0cb001c922634127f39fdd418c01c2e9bded73f) * Add extra field to BlockHeader(d6131bb645fb06025cdb5bf48ae9c8e5479cc077) * Add field_type method to ExtraField(81b32eff569a1d601d3aabd5473cf09372536066) * Serde support for ExtraField(0c3a1dacd052a212f82874ec02238932c0c6ba9a) * Allow unknown xfield type(32b7ff1a16ec26d10abdc9613c6c4b2cf268e417) * Rename ExtraField to XField(b15ff3efc64e2748b728888fd7c2a865cc77004c) * Fix test(ca94746a72d7fd3af611bbbbe6195782a8a53238) --- tapyrus/src/address/mod.rs | 4 +- tapyrus/src/bip152.rs | 12 +- tapyrus/src/blockdata/block.rs | 254 +++++++++++++++--- tapyrus/src/blockdata/constants.rs | 32 ++- tapyrus/src/blockdata/transaction.rs | 19 +- tapyrus/src/consensus/encode.rs | 13 +- tapyrus/src/consensus/params.rs | 2 +- tapyrus/src/crypto/key.rs | 17 +- tapyrus/src/crypto/mod.rs | 4 +- tapyrus/src/crypto/prime.rs | 28 +- tapyrus/src/crypto/rfc6979.rs | 28 +- tapyrus/src/crypto/schnorr.rs | 93 ++++--- tapyrus/src/crypto/test_helpers.rs | 13 +- tapyrus/src/merkle_tree/block.rs | 34 +-- tapyrus/src/merkle_tree/mod.rs | 8 +- tapyrus/src/p2p/message.rs | 7 +- tapyrus/tests/data/block_3ec84b_hex | 1 + tapyrus/tests/data/merkle_block.hex | 2 +- ...f8e072e60c0ca436323d95116dda5278ff94f9_hex | 1 - 19 files changed, 384 insertions(+), 188 deletions(-) create mode 100644 tapyrus/tests/data/block_3ec84b_hex delete mode 100644 tapyrus/tests/data/testnet_block_0ad80d57a3fec290b939d03d87f8e072e60c0ca436323d95116dda5278ff94f9_hex diff --git a/tapyrus/src/address/mod.rs b/tapyrus/src/address/mod.rs index 0a73ad64..385e7552 100644 --- a/tapyrus/src/address/mod.rs +++ b/tapyrus/src/address/mod.rs @@ -490,11 +490,11 @@ impl Address { Network::Testnet | Network::Signet | Network::Regtest => PUBKEY_ADDRESS_PREFIX_TEST, }; let p2sh_prefix = match self.network() { - Network::Bitcoin | Network::Paradium => SCRIPT_ADDRESS_PREFIX_MAIN, + Network::Bitcoin | Network::Paradium => SCRIPT_ADDRESS_PREFIX_MAIN, Network::Testnet | Network::Signet | Network::Regtest => SCRIPT_ADDRESS_PREFIX_TEST, }; let hrp = match self.network() { - Network::Bitcoin | Network::Paradium => hrp::BC, + Network::Bitcoin | Network::Paradium => hrp::BC, Network::Testnet | Network::Signet => hrp::TB, Network::Regtest => hrp::BCRT, }; diff --git a/tapyrus/src/bip152.rs b/tapyrus/src/bip152.rs index 01ec2a86..62f62a6f 100644 --- a/tapyrus/src/bip152.rs +++ b/tapyrus/src/bip152.rs @@ -158,7 +158,7 @@ pub struct HeaderAndShortIds { pub prefilled_txs: Vec, } impl_consensus_encoding!(HeaderAndShortIds, header, nonce, short_ids, prefilled_txs); - + impl HeaderAndShortIds { /// Create a new [HeaderAndShortIds] from a full block. /// @@ -232,7 +232,7 @@ impl HeaderAndShortIds { } Ok(HeaderAndShortIds { - header: block.header, + header: block.header.clone(), nonce, // Provide coinbase prefilled. prefilled_txs: prefilled, @@ -376,12 +376,10 @@ mod test { use crate::blockdata::locktime::absolute; use crate::blockdata::transaction; use crate::consensus::encode::{deserialize, serialize}; + use crate::crypto::key::PublicKey; use crate::crypto::schnorr::Signature; use crate::hash_types::TxMerkleNode; - use crate::{ - Amount, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, - Witness, - }; + use crate::{Amount, OutPoint, ScriptBuf, Sequence, Transaction, TxIn, TxOut, Txid, Witness}; fn dummy_tx(nonce: &[u8]) -> Transaction { Transaction { @@ -405,7 +403,7 @@ mod test { merkle_root: TxMerkleNode::hash(&[1]), im_merkle_root: TxMerkleNode::hash(&[1]), time: 2, - aggregated_public_key: Some(PublicKey::generator()), + xfield: block::XField::AggregatePublicKey(PublicKey::generator()), proof: Some(Signature::default()), }, txdata: vec![dummy_tx(&[2]), dummy_tx(&[3]), dummy_tx(&[4])], diff --git a/tapyrus/src/blockdata/block.rs b/tapyrus/src/blockdata/block.rs index 1e39fe72..1803298e 100644 --- a/tapyrus/src/blockdata/block.rs +++ b/tapyrus/src/blockdata/block.rs @@ -9,20 +9,23 @@ //! use core::fmt; +use std::str::FromStr; +use hashes::hex::FromHex; use hashes::{Hash, HashEngine}; use super::Weight; use crate::blockdata::script; use crate::blockdata::transaction::Transaction; +use crate::consensus::encode::serialize_hex; use crate::consensus::{encode, Decodable, Encodable}; +use crate::crypto::key::PublicKey; use crate::crypto::schnorr::Signature; pub use crate::hash_types::BlockHash; use crate::hash_types::{TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid}; use crate::internal_macros::impl_consensus_encoding; -use crate::{crypto, prelude::*}; -use crate::{io, merkle_tree, VarInt}; -use crate::crypto::key::PublicKey; +use crate::prelude::*; +use crate::{crypto, io, merkle_tree, VarInt}; /// Bitcoin block header. /// @@ -34,7 +37,7 @@ use crate::crypto::key::PublicKey; /// ### Bitcoin Core References /// /// * [CBlockHeader definition](https://github.com/bitcoin/bitcoin/blob/345457b542b6a980ccfbc868af0970a6f91d1b82/src/primitives/block.h#L20) -#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] +#[derive(PartialEq, Eq, Clone, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Header { @@ -48,8 +51,8 @@ pub struct Header { pub im_merkle_root: TxMerkleNode, /// The timestamp of the block, as claimed by the miner. pub time: u32, - ///Aggregate public key of tapyrus-signer used to verify block proof. This field is optional and may be present in all blocks. - pub aggregated_public_key: PublicKeyOpt, + /// Extra field. This field can host any type of data defined in Tapyrus protocol. + pub xfield: XField, /// Collection holds a signature for block hash which is consisted of block header without Proof. pub proof: Option, } @@ -67,7 +70,16 @@ impl Header { } } -impl_consensus_encoding!(Header, version, prev_blockhash, merkle_root, im_merkle_root, time, aggregated_public_key, proof); +impl_consensus_encoding!( + Header, + version, + prev_blockhash, + merkle_root, + im_merkle_root, + time, + xfield, + proof +); impl fmt::Debug for Header { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -78,6 +90,7 @@ impl fmt::Debug for Header { .field("merkle_root", &self.merkle_root) .field("im_merkle_root", &self.im_merkle_root) .field("time", &self.time) + .field("xfield", &self.xfield) .field("proof", &self.proof) .finish() } @@ -96,7 +109,7 @@ impl fmt::Debug for Header { /// /// * [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) /// * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki) -#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Version(i32); @@ -165,28 +178,140 @@ impl Decodable for Version { } } +impl Header { + /// Return the Aggregate public key in this BlockHeader + pub fn aggregated_public_key(&self) -> Option { + match self.xfield { + XField::AggregatePublicKey(pk) => Some(pk), + _ => None, + } + } +} + +/// An extra field that allows the block header to hold arbitrary data. +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +pub enum XField { + /// xfield isn't used. + None, + /// Aggregate public key used to verify block proof. + AggregatePublicKey(PublicKey), + /// Unknown type + Unknown(u8, Vec), +} + +impl XField { + /// Return xfieldType. + pub fn field_type(&self) -> u8 { + match self { + XField::None => 0u8, + XField::AggregatePublicKey(_) => 1u8, + XField::Unknown(x_type, _) => *x_type, + } + } + /// Return field size + pub fn size(&self) -> usize { + match self { + XField::None => 1, + XField::AggregatePublicKey(_) => 1 + 1 + 33, + XField::Unknown(_, data) => 1 + VarInt::from(data.len()).size() + data.len(), + } + } +} + +impl FromStr for XField { + type Err = encode::Error; + fn from_str(s: &str) -> Result { + let bytes: Vec = + Vec::from_hex(s).map_err(|_| encode::Error::ParseFailed("invalid hex string"))?; + XField::consensus_decode(&mut &bytes[..]) + } +} + +impl std::fmt::Display for XField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", serialize_hex(self)) + } +} -/// Optional aggregated public key -pub type PublicKeyOpt = Option; +#[cfg(feature = "serde")] +impl serde::Serialize for XField { + /// User-facing serialization for `Script`. + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.collect_str(&self) + } +} + +#[cfg(feature = "serde")] +impl<'de> ::serde::Deserialize<'de> for XField { + fn deserialize>(d: D) -> Result { + struct XFieldVisitor; + + impl<'de> ::serde::de::Visitor<'de> for XFieldVisitor { + type Value = XField; + + fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + formatter.write_str("hex string") + } -impl Decodable for PublicKeyOpt { + fn visit_bytes(self, v: &[u8]) -> Result + where + E: ::serde::de::Error, + { + if let Ok(s) = ::std::str::from_utf8(v) { + XField::from_str(s).map_err(E::custom) + } else { + Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) + } + } + + fn visit_str(self, v: &str) -> Result + where + E: ::serde::de::Error, + { + XField::from_str(v).map_err(E::custom) + } + } + + d.deserialize_str(XFieldVisitor) + } +} + +impl Decodable for XField { #[inline] - fn consensus_decode(mut d: D) -> Result { - match Decodable::consensus_decode(&mut d) { - Ok(pk) => Ok(Some(pk)), - Err(_) => Ok(None), + fn consensus_decode(mut d: &mut D) -> Result { + let x_type: u8 = Decodable::consensus_decode(&mut d)?; + match x_type { + 0 => Ok(XField::None), + 1 => { + let bytes: Vec = Decodable::consensus_decode(&mut d)?; + let pk = PublicKey::from_slice(&bytes) + .map_err(|_| encode::Error::ParseFailed("aggregate public key"))?; + Ok(XField::AggregatePublicKey(pk)) + } + _ => { + let data: Vec = Decodable::consensus_decode(&mut d)?; + Ok(XField::Unknown(x_type, data)) + } } } } -impl Encodable for PublicKeyOpt { +impl Encodable for XField { #[inline] - fn consensus_encode(&self, mut s: S) -> Result { - match *self { - Some(pk) => pk.consensus_encode(&mut s), - None => { - let v = Vec::::new(); - v.consensus_encode(&mut s) + fn consensus_encode(&self, mut s: &mut S) -> Result { + self.field_type().consensus_encode(&mut s)?; + match self { + XField::None => Ok(1), + XField::AggregatePublicKey(pk) => { + let len = pk.to_bytes().consensus_encode(&mut s)?; + Ok(1 + len) + } + XField::Unknown(_type, data) => { + let len = data.consensus_encode(&mut s)?; + Ok(1 + len) } } } @@ -318,6 +443,7 @@ impl Block { /// > any witness-related data, as seen by a non-upgraded node. fn base_size(&self) -> usize { let mut size = Header::SIZE; + size += self.header.xfield.size(); size += 1; // length of proof field if self.header.proof.is_some() { size += 2 * crypto::schnorr::SECP256K1_SCALAR_SIZE; @@ -334,6 +460,7 @@ impl Block { /// > including base data and witness data. pub fn total_size(&self) -> usize { let mut size = Header::SIZE; + size += self.header.xfield.size(); size += 1; // length of proof field if self.header.proof.is_some() { size += 2 * crypto::schnorr::SECP256K1_SCALAR_SIZE; @@ -475,9 +602,10 @@ impl std::error::Error for ValidationError { #[cfg(test)] mod tests { - use hex::{test_hex_unwrap as hex, FromHex}; use std::str::FromStr; + use hex::{test_hex_unwrap as hex, FromHex}; + use super::*; use crate::consensus::encode::{deserialize, serialize}; @@ -504,15 +632,15 @@ mod tests { #[test] fn block_test() { // Mainnet block 00000000b0c5a240b2a61d2e75692224efd4cbecdf6eaf4cc2cf477ca7c270e7 - let some_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e4921032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000"); - let cutoff_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e4921032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac"); + let some_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e490121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af40f1453cd332262d74edf65f96688724b80a15c852fd50151e4aabc41a0d9560d2cd38f0746c3d9c9e18b236f20e37d0ae1bda457ea029db8a55b20f38143517d00201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000"); + let cutoff_block = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e490121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac"); let prevhash = hex!("4ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000"); let merkle = hex!("bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c"); let pk = PublicKey::from_str( - "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", - ) - .unwrap(); + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); let decode: Result = deserialize(&some_block); let bad_decode: Result = deserialize(&cutoff_block); @@ -525,7 +653,7 @@ mod tests { assert_eq!(real_decode.header.im_merkle_root, real_decode.immutable_merkle_root().unwrap()); assert_eq!(serialize(&real_decode.header.merkle_root), merkle); assert_eq!(real_decode.header.time, 1231965655); - assert_eq!(real_decode.header.aggregated_public_key.unwrap(), pk); + assert_eq!(real_decode.header.aggregated_public_key().unwrap(), pk); // [test] TODO: check the transaction data assert_eq!(real_decode.total_size(), some_block.len()); @@ -541,10 +669,68 @@ mod tests { assert_eq!(serialize(&real_decode), some_block); } + #[test] + fn xfield_none_test() { + let bytes = Vec::from_hex("00").unwrap(); + let decode: XField = deserialize(&bytes).unwrap(); + assert_eq!(serialize(&decode), bytes); + + assert_eq!(decode, XField::None); + + let xfield = XField::from_str("00"); + assert_eq!(xfield.unwrap(), XField::None); + } + + #[test] + fn xfield_aggregate_public_key_test() { + let bytes = + Vec::from_hex("0121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af") + .unwrap(); + let decode: XField = deserialize(&bytes).unwrap(); + assert_eq!(serialize(&decode), bytes); + + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); + assert_eq!(decode, XField::AggregatePublicKey(pk)); + + let xfield = XField::from_str( + "0121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ); + assert_eq!(xfield.unwrap(), XField::AggregatePublicKey(pk)); + } + + #[test] + fn xfield_unsupported_type_test() { + let bytes = Vec::from_hex("ff0101").unwrap(); + let decode: XField = deserialize(&bytes).unwrap(); + assert_eq!(serialize(&decode), bytes); + + assert_eq!(decode, XField::Unknown(0xff, vec![0x01])); + + let xfield = XField::from_str("ff0101"); + assert_eq!(xfield.unwrap(), XField::Unknown(0xff, vec![0x01])); + } + + #[cfg(feature = "serde")] + #[test] + fn xfield_serialize_test() { + let xfield = Vec::from_hex("00").unwrap(); + let decode: XField = deserialize(&xfield).unwrap(); + serde_round_trip!(decode); + + let xfield = + Vec::from_hex("0121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af") + .unwrap(); + let decode: XField = deserialize(&xfield).unwrap(); + serde_round_trip!(decode); + } + // Check testnet block 000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b #[test] fn segwit_block_test() { - let segwit_block = hex!("000000202aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d7490600000000000010bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67eda3486f183ebe5fcbd343331abaec9fec7eb3ec2a087e543f3a92385e78bdc5b5503bd57000f010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a3983704012000000000000000000000000000000000000000000000000000000000000000000000000001000000017e4f81175332a733e26d4ba4e29f53f67b7a5d7c2adebb276e447ca71d130b55000000006b483045022100cac809cd1a3d9ad5d5e31a84e2e1d8ec5542841e4d14c6b52e8b38cbe1ff1728022064470b7fb0c2efeccb2e84bfa36ec5f9e434c84b1101c00f7ee32f726371b7410121020e62280798b6b8c37f068df0915b0865b63fabc401c2457cbc3ef96887dd3647ffffffff02ca2f780c000000001976a914c6b5545b3592cb477d709896fa705592c9b6113a88ac663b2a06000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac0000000001000000011e99f5a785e677e017d36b50aa4fd10010ffd039f38f42f447ca8895250e121f01000000d90047304402200d3d296ad641a281dd5c0d68b9ab0d1ad5f7052bec148c1fb81fb1ba69181ec502201a372bb16fb8e054ee9bef41e300d292153830f841a4db0ab7f7407f6581b9bc01473044022002584f313ae990236b6bebb82fbbb006a2b02a448dd5c93434428991eae960d60220491d67d2660c4dde19025cf86e5164a559e2c79c3b98b40e146fab974acd24690147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9140ffdcf96700455074292a821c74922e8652993998788997bc60000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000010000000113100b09e6a78d63ec4850654ab0f68806de29710b09172eddfef730652b155501000000da00473044022015389408e3446a3f36a05060e0e4a3c8b92ff3901ba2511aa944ec91a537a1cb022045a33b6ec47605b1718ed2e753263e54918edbf6126508ff039621fb928d28a001483045022100bb952fde81f216f7063575c0bb2bedc050ce08c96d9b437ea922f5eb98c882da02201b7cbf3a2f94ea4c5eb7f0df3af2ebcafa8705af7f410ab5d3d4bac13d6bc6120147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914d3db9a20312c3ab896a316eb108dbd01e47e17d687e0ba7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000016e3cca1599cde54878e2f27f434df69df0afd1f313cb6e38c08d3ffb57f97a6c01000000da0048304502210095623b70ec3194fa4037a1c1106c2580caedc390e25e5b330bbeb3111e8184bc02205ae973c4a4454be2a3a03beb66297143c1044a3c4743742c5cdd1d516a1ad3040147304402202f3d6d89996f5b42773dd6ebaf367f1af1f3a95c7c7b487ec040131c40f4a4a30220524ffbb0b563f37b3eb1341228f792e8f84111b7c4a9f49cdd998e052ee42efa0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9141ade6b95896dde8ec4dee9e59af8849d3797348e8728af7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000011d9dc3a5df9b5b2eeb2bd11a2db243be9e8cc23e2f180bf317d32a499904c15501000000db00483045022100ebbd1c9a8ce626edbb1a7881df81e872ef8c6424feda36faa8a5745157400c6a02206eb463bc8acd5ea06a289e86115e1daae0c2cf10d9cbbd199e1311170d5543ef01483045022100809411a917dc8cf4f3a777f0388fdea6de06243ef7691e500c60abd1c7f19ae602205255d2b1191d8adedb77b814ccb66471eb8486cb4ff8727824254ee5589f176b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914759a49c772347be81c49517f9e1e6def6a88d4dd87800b85c60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704f0000006a47304402201be0d485f6a3ce871be80064c593c5327b3fd7e450f05ab7fae38385bc40cfbe02206e2a6c9970b5d1d10207892376733757486634fce4f352e772149c486857612101210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704e0000006b483045022100ccc8c0ac90bdb0402842aec91830c765cdead7a728552a6a34de7d13a6dab28e02206c96f8640cf3444054e9632b197be30598a09c3d5defcd95750bdb922a60d64801210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000011b436669c06cbf3442e21a2fe3edc20cd3cf13c358c53234bc4d88bfd8c4bd2a000000006a47304402204a63410ee13db52c7609ab08e25b7fe3c608cc21cc1755ad13460685eb55193202204cd1ea80c06a81571119be0b8cccd96ef7cdd90f62c1fe2d538622feb08e22ba0121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d64523365345261445653324d436a736e536171734a5753324465655446624238354541794a4d5843784c7934000000000100000001be4a95ed36316cada5118b1982e4cb4a07f93e7a4153e227466f1cb0776de995000000006b483045022100a22d5251deea0470806bab817013d675a63cd52218d6e477ab0c9d601d018b7f022042121b46afcdcd0c66f189398212b66085e88c6973ae560f1810c13e55e2bee40121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d57484d57504e5248515872504c7338554c586b4d483746745356413675366b5a6b4a4e3851796e4e583751340000000001000000016c061a65b49edec21acdbc22f97dc853aa872302aeef13fabf0bf6807de1b8bd010000006b483045022100dd80381f2d158b4dad7f98d2d97317c533fb36e737542473feb05fa74d0b73bb02207097d4331196069167e525b61d132532292fd75cc039a5839c04c2545d427e2b0121035e9a597df8b417bef66811882a2844604fc591c427f642628f0fef46be19a4c9feffffff0280a4bf07000000001976a914573b9106e16ee0b5c143dc40f0724f77dd0e282088ac9533b22c000000001976a9149c4da607efb1d759d33da71778bc6cafa56acb5988acd31b0e0001000000017dae20994b69b28534e5b22f3d7c50f9d7541348cbf6f43fcc654263ebaf8f68000000006b483045022100a85300eb94b24b044877d0b0d61e08e16dbc82ec7d69c723a8a45519f95c35b002203d78376e6bee31b455c097557af7fe4d6b620bc74269e9a75e2aad2b545abddb012103b0d08aba2a5ac6cf2788fda941c386040e35e49d3a57d2aefb16c0438fb98acbfeffffff022222305f000000001976a914cfda30dd836b596db6a9c230c45ae2179107f04888ac80a4bf07000000001976a91442dfcf5823aacb185844e663873c35fb98bfd21b88acd31b0e000100000002ad3e85e4af30678a330f8941ed7a9ca17cd0236368d238cac4e9ff09c466fed1020000006b483045022100d1196c48a0392e09592f1b96b4aec32ab0cecb6fd17b1d0c85ab3250a2fe45d9022059217c82f684fcdecdbe660a2077ea956dfbbb964d2648bc1e8ae0f0fe565449012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff34f0a71c1c2cd610522e9c18c67931cded5e9647d4419c49b99715e2a0795f3d020000006a4730440220316e81d8242abf3c5f885d200feca12c3adb63cf2cd4dc74602f7b8b0cba50340220210d525758df77ccdca6908311c1895275e07bbb29b45963a19252acde55873f012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff0510270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788ac10270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788aca0860100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac70110100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac0000000000000000026a000000000001000000018e33fecc2ddbd86c5ea919f7bd5a5acf8a09f3e0cdaaaf4f08c5ef095161ef1100000000fdfe0000483045022100d2489b225d39b7d8b6767a6928c8029a2a1297c08fdf00d683ba0c1987e7d7000220176cb66c8a243806bb7421f658325a69a51c82c0c3314e37f2400f33626390210148304502210096cfa57662a545830d0e29610becd41ea031e256339913718ce18dbb1a27bdb00220482911c851d15adcd37097dff99a9ff1f97d953bcebc528835118f447412553e014c695221028d9889862b29430278c084b5c4090b7b807b31e047bcd212ebc2c4e43fc0e3c52103160949a7c8c81f2c25d7763f57eb1cb407d867c5b7c290331bd2dc4b1182c6d32103fbef3b60914bda9173765902013a251ec89450c75d0b5a96a143db1dabf98d9553aeffffffff0220e8891c0100000017a914d996715e081c50f8f6b1b4e7fb6ca214f9924fdf87809698000000000017a9145611d812263f32960228cb5f85329bce4770a218870000000001000000017720507dcbe6c69f652b0c0ce19406f482372d1a8abc05d45fb7acf97fb80eec00000000fdfe00004830450221009821d8e117de44b1202c829c0f5063997acf007cf9b561c6fb8d1212cddb6c40022010ff5067b0d9d4eca2da0ceb876e9a16f1a2142da866d3042a7bae8968813e8001483045022100dea759d14a8a1c5da5f3dcc5509871aaa2c1e3be03752c1b858d80fa4227163702205183d70cc28dcb6df9b037714c8b6442ef84e0ddce07711a30c731e9f0925090014c695221028d70ea66fe7a7def282df7b2b498007e5072933e42c18f63ce85975dcbcf1a8821037e8f842b1e47e21d88002c5aab2559212a4c2c9dbe5ef5347f2a29afd0510ec1210251259cb9fd4f6206488408286e4475c9c9fe887e57a3e32ae4da222778a2aedf53aeffffffff023380cb020000000017a9143b5a7e85b22656a34d43187ac8dd09acd7109d2487809698000000000017a914b9b4b555f594a34deec3ad61d5c5f3738b17ee158700000000"); + let segwit_block = hex!("000000202aa2f2ca794ccbd40c16e2f3333f6b8b683f9e7179b2c4d7490600000000000010bc26e70a2f672ad420a6153dd0c28b40a6002c55531bfc99bf8994a8e8f67eda3486f183ebe5fcbd343331abaec9fec7eb3ec2a087e543f3a92385e78bdc5b5503bd5700000f010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3603da1b0e00045503bd5704c7dd8a0d0ced13bb5785010800000000000a636b706f6f6c122f4e696e6a61506f6f6c2f5345475749542fffffffff02b4e5a212000000001976a914876fbb82ec05caa6af7a3b5e5a983aae6c6cc6d688ac0000000000000000266a24aa21a9edf91c46b49eb8a29089980f02ee6b57e7d63d33b18b4fddac2bcd7db2a3983704012000000000000000000000000000000000000000000000000000000000000000000000000001000000017e4f81175332a733e26d4ba4e29f53f67b7a5d7c2adebb276e447ca71d130b55000000006b483045022100cac809cd1a3d9ad5d5e31a84e2e1d8ec5542841e4d14c6b52e8b38cbe1ff1728022064470b7fb0c2efeccb2e84bfa36ec5f9e434c84b1101c00f7ee32f726371b7410121020e62280798b6b8c37f068df0915b0865b63fabc401c2457cbc3ef96887dd3647ffffffff02ca2f780c000000001976a914c6b5545b3592cb477d709896fa705592c9b6113a88ac663b2a06000000001976a914e7c1345fc8f87c68170b3aa798a956c2fe6a9eff88ac0000000001000000011e99f5a785e677e017d36b50aa4fd10010ffd039f38f42f447ca8895250e121f01000000d90047304402200d3d296ad641a281dd5c0d68b9ab0d1ad5f7052bec148c1fb81fb1ba69181ec502201a372bb16fb8e054ee9bef41e300d292153830f841a4db0ab7f7407f6581b9bc01473044022002584f313ae990236b6bebb82fbbb006a2b02a448dd5c93434428991eae960d60220491d67d2660c4dde19025cf86e5164a559e2c79c3b98b40e146fab974acd24690147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9140ffdcf96700455074292a821c74922e8652993998788997bc60000000017a9148ce5408cfeaddb7ccb2545ded41ef478109454848700000000010000000113100b09e6a78d63ec4850654ab0f68806de29710b09172eddfef730652b155501000000da00473044022015389408e3446a3f36a05060e0e4a3c8b92ff3901ba2511aa944ec91a537a1cb022045a33b6ec47605b1718ed2e753263e54918edbf6126508ff039621fb928d28a001483045022100bb952fde81f216f7063575c0bb2bedc050ce08c96d9b437ea922f5eb98c882da02201b7cbf3a2f94ea4c5eb7f0df3af2ebcafa8705af7f410ab5d3d4bac13d6bc6120147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914d3db9a20312c3ab896a316eb108dbd01e47e17d687e0ba7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000016e3cca1599cde54878e2f27f434df69df0afd1f313cb6e38c08d3ffb57f97a6c01000000da0048304502210095623b70ec3194fa4037a1c1106c2580caedc390e25e5b330bbeb3111e8184bc02205ae973c4a4454be2a3a03beb66297143c1044a3c4743742c5cdd1d516a1ad3040147304402202f3d6d89996f5b42773dd6ebaf367f1af1f3a95c7c7b487ec040131c40f4a4a30220524ffbb0b563f37b3eb1341228f792e8f84111b7c4a9f49cdd998e052ee42efa0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a9141ade6b95896dde8ec4dee9e59af8849d3797348e8728af7ac60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000011d9dc3a5df9b5b2eeb2bd11a2db243be9e8cc23e2f180bf317d32a499904c15501000000db00483045022100ebbd1c9a8ce626edbb1a7881df81e872ef8c6424feda36faa8a5745157400c6a02206eb463bc8acd5ea06a289e86115e1daae0c2cf10d9cbbd199e1311170d5543ef01483045022100809411a917dc8cf4f3a777f0388fdea6de06243ef7691e500c60abd1c7f19ae602205255d2b1191d8adedb77b814ccb66471eb8486cb4ff8727824254ee5589f176b0147522102632178d046673c9729d828cfee388e121f497707f810c131e0d3fc0fe0bd66d62103a0951ec7d3a9da9de171617026442fcd30f34d66100fab539853b43f508787d452aeffffffff0240420f000000000017a914759a49c772347be81c49517f9e1e6def6a88d4dd87800b85c60000000017a9148ce5408cfeaddb7ccb2545ded41ef47810945484870000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704f0000006a47304402201be0d485f6a3ce871be80064c593c5327b3fd7e450f05ab7fae38385bc40cfbe02206e2a6c9970b5d1d10207892376733757486634fce4f352e772149c486857612101210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000018c51902affd8e5247dfcc2e5d0528a3815f53c8b6d2c200ff290b2b2b486d7704e0000006b483045022100ccc8c0ac90bdb0402842aec91830c765cdead7a728552a6a34de7d13a6dab28e02206c96f8640cf3444054e9632b197be30598a09c3d5defcd95750bdb922a60d64801210350c33bc9a790c9495195761577b34912a949b73d5bc5ae5343f5ba08b33220ccffffffff0110270000000000001976a9142ab1c62710a7bdfdb4bb6394bbedc58b32b4d5a388ac0000000001000000011b436669c06cbf3442e21a2fe3edc20cd3cf13c358c53234bc4d88bfd8c4bd2a000000006a47304402204a63410ee13db52c7609ab08e25b7fe3c608cc21cc1755ad13460685eb55193202204cd1ea80c06a81571119be0b8cccd96ef7cdd90f62c1fe2d538622feb08e22ba0121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d64523365345261445653324d436a736e536171734a5753324465655446624238354541794a4d5843784c7934000000000100000001be4a95ed36316cada5118b1982e4cb4a07f93e7a4153e227466f1cb0776de995000000006b483045022100a22d5251deea0470806bab817013d675a63cd52218d6e477ab0c9d601d018b7f022042121b46afcdcd0c66f189398212b66085e88c6973ae560f1810c13e55e2bee40121024baa8b67cc9ed8a97d90895e3716b25469b67cb26d3324d7aff213f507764765ffffffff010000000000000000306a2e516d57484d57504e5248515872504c7338554c586b4d483746745356413675366b5a6b4a4e3851796e4e583751340000000001000000016c061a65b49edec21acdbc22f97dc853aa872302aeef13fabf0bf6807de1b8bd010000006b483045022100dd80381f2d158b4dad7f98d2d97317c533fb36e737542473feb05fa74d0b73bb02207097d4331196069167e525b61d132532292fd75cc039a5839c04c2545d427e2b0121035e9a597df8b417bef66811882a2844604fc591c427f642628f0fef46be19a4c9feffffff0280a4bf07000000001976a914573b9106e16ee0b5c143dc40f0724f77dd0e282088ac9533b22c000000001976a9149c4da607efb1d759d33da71778bc6cafa56acb5988acd31b0e0001000000017dae20994b69b28534e5b22f3d7c50f9d7541348cbf6f43fcc654263ebaf8f68000000006b483045022100a85300eb94b24b044877d0b0d61e08e16dbc82ec7d69c723a8a45519f95c35b002203d78376e6bee31b455c097557af7fe4d6b620bc74269e9a75e2aad2b545abddb012103b0d08aba2a5ac6cf2788fda941c386040e35e49d3a57d2aefb16c0438fb98acbfeffffff022222305f000000001976a914cfda30dd836b596db6a9c230c45ae2179107f04888ac80a4bf07000000001976a91442dfcf5823aacb185844e663873c35fb98bfd21b88acd31b0e000100000002ad3e85e4af30678a330f8941ed7a9ca17cd0236368d238cac4e9ff09c466fed1020000006b483045022100d1196c48a0392e09592f1b96b4aec32ab0cecb6fd17b1d0c85ab3250a2fe45d9022059217c82f684fcdecdbe660a2077ea956dfbbb964d2648bc1e8ae0f0fe565449012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff34f0a71c1c2cd610522e9c18c67931cded5e9647d4419c49b99715e2a0795f3d020000006a4730440220316e81d8242abf3c5f885d200feca12c3adb63cf2cd4dc74602f7b8b0cba50340220210d525758df77ccdca6908311c1895275e07bbb29b45963a19252acde55873f012103b64e32e5f62e03701428fb1e3151e9a57f149c67708f6164a235c8199fe17cc2ffffffff0510270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788ac10270000000000001976a914449d2394dde057bc199f23fb8aa2e400f344611788aca0860100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac70110100000000001976a91413d35ad337dd80a055757e5ea0a45b59fee3060c88ac0000000000000000026a000000000001000000018e33fecc2ddbd86c5ea919f7bd5a5acf8a09f3e0cdaaaf4f08c5ef095161ef1100000000fdfe0000483045022100d2489b225d39b7d8b6767a6928c8029a2a1297c08fdf00d683ba0c1987e7d7000220176cb66c8a243806bb7421f658325a69a51c82c0c3314e37f2400f33626390210148304502210096cfa57662a545830d0e29610becd41ea031e256339913718ce18dbb1a27bdb00220482911c851d15adcd37097dff99a9ff1f97d953bcebc528835118f447412553e014c695221028d9889862b29430278c084b5c4090b7b807b31e047bcd212ebc2c4e43fc0e3c52103160949a7c8c81f2c25d7763f57eb1cb407d867c5b7c290331bd2dc4b1182c6d32103fbef3b60914bda9173765902013a251ec89450c75d0b5a96a143db1dabf98d9553aeffffffff0220e8891c0100000017a914d996715e081c50f8f6b1b4e7fb6ca214f9924fdf87809698000000000017a9145611d812263f32960228cb5f85329bce4770a218870000000001000000017720507dcbe6c69f652b0c0ce19406f482372d1a8abc05d45fb7acf97fb80eec00000000fdfe00004830450221009821d8e117de44b1202c829c0f5063997acf007cf9b561c6fb8d1212cddb6c40022010ff5067b0d9d4eca2da0ceb876e9a16f1a2142da866d3042a7bae8968813e8001483045022100dea759d14a8a1c5da5f3dcc5509871aaa2c1e3be03752c1b858d80fa4227163702205183d70cc28dcb6df9b037714c8b6442ef84e0ddce07711a30c731e9f0925090014c695221028d70ea66fe7a7def282df7b2b498007e5072933e42c18f63ce85975dcbcf1a8821037e8f842b1e47e21d88002c5aab2559212a4c2c9dbe5ef5347f2a29afd0510ec1210251259cb9fd4f6206488408286e4475c9c9fe887e57a3e32ae4da222778a2aedf53aeffffffff023380cb020000000017a9143b5a7e85b22656a34d43187ac8dd09acd7109d2487809698000000000017a914b9b4b555f594a34deec3ad61d5c5f3738b17ee158700000000"); let decode: Result = deserialize(&segwit_block); @@ -562,8 +748,8 @@ mod tests { // [test] TODO: check the transaction data assert_eq!(real_decode.total_size(), segwit_block.len()); - assert_eq!(real_decode.base_size(), 4308); - assert_eq!(real_decode.weight(), Weight::from_wu(17268)); + assert_eq!(real_decode.base_size(), 4309); + assert_eq!(real_decode.weight(), Weight::from_wu(17272)); assert!(real_decode.check_witness_commitment()); @@ -572,13 +758,13 @@ mod tests { #[test] fn block_version_test() { - let block = hex!("ffffff7f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let block = hex!("ffffff7f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); let decode: Result = deserialize(&block); assert!(decode.is_ok()); let real_decode = decode.unwrap(); assert_eq!(real_decode.header.version, Version(2147483647)); - let block2 = hex!("00000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let block2 = hex!("0000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); let decode2: Result = deserialize(&block2); assert!(decode2.is_ok()); let real_decode2 = decode2.unwrap(); diff --git a/tapyrus/src/blockdata/constants.rs b/tapyrus/src/blockdata/constants.rs index 6a678eb1..300e1d3d 100644 --- a/tapyrus/src/blockdata/constants.rs +++ b/tapyrus/src/blockdata/constants.rs @@ -14,17 +14,17 @@ use hashes::{sha256d, Hash}; use hex_lit::hex; use internals::impl_array_newtype; -use crate::blockdata::block::{self, Block}; +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::crypto::key::PublicKey; use crate::crypto::schnorr::Signature; use crate::internal_macros::impl_bytes_newtype; use crate::network::Network; use crate::Amount; -use crate::crypto::key::PublicKey; #[deprecated(since = "0.31.0", note = "Use Weight::MAX_BLOCK instead")] /// The maximum allowed weight for a block, see BIP 141 (network rule). @@ -104,7 +104,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1231006505, - aggregated_public_key: Some(public_key), + xfield: XField::AggregatePublicKey(public_key), proof: Some(Signature::default()), }, txdata, @@ -116,7 +116,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1296688602, - aggregated_public_key: Some(public_key), + xfield: XField::AggregatePublicKey(public_key), proof: Some(Signature::default()), }, txdata, @@ -128,7 +128,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1598918400, - aggregated_public_key: Some(public_key), + xfield: XField::AggregatePublicKey(public_key), proof: Some(Signature::default()), }, txdata, @@ -140,7 +140,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1296688602, - aggregated_public_key: Some(public_key), + xfield: XField::AggregatePublicKey(public_key), proof: Some(Signature::default()), }, txdata, @@ -154,7 +154,7 @@ pub fn genesis_block(network: Network) -> Block { merkle_root, im_merkle_root: txdata[0].ntxid().into(), time: 1562925929, - aggregated_public_key: Some(public_key), + xfield: XField::AggregatePublicKey(public_key), proof: Some(Signature::default()), }, txdata, @@ -193,8 +193,8 @@ impl ChainHash { ]); /// `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 + 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. @@ -298,7 +298,7 @@ mod test { assert_eq!(gen.header.time, 1598918400); assert_eq!( gen.header.block_hash().to_string(), - "27136d27aba81a18449dfdeca2d0c2a973dfc0cdf0a2527b4860ed1f816145d4".to_string() + "abbaa74c35c0467802e1dfd8a20150ea7c0ac529feb245933702832d112c6b16".to_string() ); } @@ -308,11 +308,15 @@ mod test { 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.merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); assert_eq!(gen.header.time, 1562925929); - assert_eq!(gen.header.block_hash().to_string(), - "78be4db611a1e7394c14b98fdf9a6f0db847efbfe10335bc681bd3d3a105d34e"); + assert_eq!( + gen.header.block_hash().to_string(), + "78be4db611a1e7394c14b98fdf9a6f0db847efbfe10335bc681bd3d3a105d34e" + ); } // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array diff --git a/tapyrus/src/blockdata/transaction.rs b/tapyrus/src/blockdata/transaction.rs index aa2bfc6e..b9e865f5 100644 --- a/tapyrus/src/blockdata/transaction.rs +++ b/tapyrus/src/blockdata/transaction.rs @@ -700,7 +700,7 @@ impl Transaction { Wtxid::from_engine(enc) } - /// Computes an "immutable TXID". The double SHA256 taken from a transaction + /// Computes an "immutable TXID". The double SHA256 taken from a transaction /// after stripping it of all input scripts including their length prefixes. pub fn malfix_txid(&self) -> sha256d::Hash { let mut enc = sha256d::Hash::engine(); @@ -1781,11 +1781,20 @@ mod tests { 111825061110d38b3d5b849dd24323d1f5559d88ac00000000" ); let tx: Transaction = deserialize(&hex_tx).unwrap(); - assert_eq!(format!("{:x}", tx.txid()), "efaf069367948e9e4c99ca04cf885f41cd8dce6b9dddd310c9034f5e65396323"); - assert_eq!(format!("{:x}", tx.ntxid()), "c12d06b287c4d95968071733c9e0ab33d93e2c354bc77a56dc6119913732a5dc"); - assert_eq!(format!("{:x}", tx.malfix_txid()), "18ab15aaa859c9030f8c449fa074a90eb04b02fc2aca5de0ebbe851e6886efd0"); + assert_eq!( + format!("{:x}", tx.txid()), + "efaf069367948e9e4c99ca04cf885f41cd8dce6b9dddd310c9034f5e65396323" + ); + assert_eq!( + format!("{:x}", tx.ntxid()), + "c12d06b287c4d95968071733c9e0ab33d93e2c354bc77a56dc6119913732a5dc" + ); + assert_eq!( + format!("{:x}", tx.malfix_txid()), + "18ab15aaa859c9030f8c449fa074a90eb04b02fc2aca5de0ebbe851e6886efd0" + ); } - + #[test] #[cfg(feature = "serde")] fn txn_encode_decode() { diff --git a/tapyrus/src/consensus/encode.rs b/tapyrus/src/consensus/encode.rs index 58a91745..9d7a58dd 100644 --- a/tapyrus/src/consensus/encode.rs +++ b/tapyrus/src/consensus/encode.rs @@ -859,7 +859,10 @@ macro_rules! impl_option { ($type: ty) => { impl Encodable for Option<$type> { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode( + &self, + w: &mut W, + ) -> Result { let mut len = 0; match self { Some(c) => { @@ -1298,11 +1301,9 @@ mod tests { let some: Option = Some(Default::default()); let expected = vec![ - 64, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, + 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, ]; assert_eq!(expected, serialize(&some)); } diff --git a/tapyrus/src/consensus/params.rs b/tapyrus/src/consensus/params.rs index daefbcef..00c125be 100644 --- a/tapyrus/src/consensus/params.rs +++ b/tapyrus/src/consensus/params.rs @@ -50,7 +50,7 @@ impl Params { network: Network::Paradium, rule_change_activation_threshold: 108, // 75% miner_confirmation_window: 144, - } + }, } } } diff --git a/tapyrus/src/crypto/key.rs b/tapyrus/src/crypto/key.rs index 43bc69ab..eb5e2838 100644 --- a/tapyrus/src/crypto/key.rs +++ b/tapyrus/src/crypto/key.rs @@ -16,12 +16,12 @@ use internals::write_err; pub use secp256k1::rand; pub use secp256k1::{self, constants, Keypair, Parity, Secp256k1, Verification, XOnlyPublicKey}; +use crate::consensus::{encode, Decodable, Encodable}; use crate::crypto::ecdsa; use crate::network::Network; use crate::prelude::*; use crate::taproot::{TapNodeHash, TapTweakHash}; use crate::{base58, io}; -use crate::consensus::{encode, Decodable, Encodable}; /// A Bitcoin ECDSA public key #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -445,7 +445,6 @@ impl Encodable for PublicKey { } } - #[cfg(feature = "serde")] #[allow(clippy::collapsible_else_if)] // Aids readability. impl serde::Serialize for PublicKey { @@ -1146,17 +1145,9 @@ mod tests { ) .unwrap(); let mut s = Vec::new(); - // let mut s = String::new(); - pk.consensus_encode(&mut s); - let encoded = s - .iter() - .map(|x| format!("{:02x}", x)) - .collect::>() - .join(""); - assert_eq!( - "21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", - encoded - ); + let _ = pk.consensus_encode(&mut s); + let encoded = s.iter().map(|x| format!("{:02x}", x)).collect::>().join(""); + assert_eq!("21032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", encoded); let decoded = PublicKey::consensus_decode(&mut &s[..]).unwrap(); assert_eq!(decoded, pk); diff --git a/tapyrus/src/crypto/mod.rs b/tapyrus/src/crypto/mod.rs index b6c9b57c..8c197ca9 100644 --- a/tapyrus/src/crypto/mod.rs +++ b/tapyrus/src/crypto/mod.rs @@ -9,10 +9,10 @@ pub mod ecdsa; pub mod key; pub mod sighash; // Contents re-exported in `tapyrus::taproot`. -pub(crate) mod taproot; -pub mod schnorr; mod prime; mod rfc6979; +pub mod schnorr; +pub(crate) mod taproot; #[cfg(test)] mod test_helpers; diff --git a/tapyrus/src/crypto/prime.rs b/tapyrus/src/crypto/prime.rs index 1955b53d..b32a77ea 100644 --- a/tapyrus/src/crypto/prime.rs +++ b/tapyrus/src/crypto/prime.rs @@ -6,15 +6,13 @@ //! //! -use rug::Integer; use rug::integer::Order; +use rug::Integer; /// Prime number for secp256k1 field element. pub const P: [u8; 32] = [ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xfc, 0x2f, ]; /// Calculate jacobi symbol @@ -40,20 +38,14 @@ fn jacobi_inner(a: &Integer, n: &Integer) -> i8 { a1 = a1.div_exact_u(2); e += 1; } - let mut s: i8 = if e & 1 == 0 - || n.mod_u(8) == 1 - || n.mod_u(8) == 7 - { + let mut s: i8 = if e & 1 == 0 || n.mod_u(8) == 1 || n.mod_u(8) == 7 { 1 - } else if n.mod_u(8) == 3 - || n.mod_u(8) == 5 - { + } else if n.mod_u(8) == 3 || n.mod_u(8) == 5 { -1 } else { 0 }; - if n.mod_u(4) == 3 && a1.mod_u(4) == 3 - { + if n.mod_u(4) == 3 && a1.mod_u(4) == 3 { s = -s } @@ -66,9 +58,10 @@ fn jacobi_inner(a: &Integer, n: &Integer) -> i8 { #[cfg(test)] mod tests { - use super::*; use hex::FromHex; + use super::*; + #[test] fn test_jacobi() { assert_eq!(1, jacobi_inner(&Integer::from(1), &Integer::from(3))); @@ -77,8 +70,9 @@ mod tests { let a = <[u8; 32]>::from_hex( "388f7b0f632de8140fe337e62a37f3566500a99934c2231b6cb9fd7584b8e672", - ).unwrap(); + ) + .unwrap(); assert_eq!(-1, jacobi(&a[..])); } -} \ No newline at end of file +} diff --git a/tapyrus/src/crypto/rfc6979.rs b/tapyrus/src/crypto/rfc6979.rs index 35bb81a8..0627467c 100644 --- a/tapyrus/src/crypto/rfc6979.rs +++ b/tapyrus/src/crypto/rfc6979.rs @@ -5,11 +5,11 @@ //! RFC6979 //! -use crate::hashes::{HmacEngine, HashEngine, Hmac, Hash}; -use crate::hashes::sha256::Hash as SHA256; -use crate::prelude::*; use secp256k1::SecretKey; +use crate::hashes::sha256::Hash as SHA256; +use crate::hashes::{Hash, HashEngine, Hmac, HmacEngine}; +use crate::prelude::*; /// Generate nonce pub fn nonce_rfc6979( @@ -18,8 +18,7 @@ pub fn nonce_rfc6979( algo16: &[u8; 16], data: Option<&[u8; 32]>, counter: u32, -) -> [u8; 32] -{ +) -> [u8; 32] { let mut keydata: Vec = Vec::new(); keydata.extend(&key[..]); @@ -102,21 +101,24 @@ impl RFC6979 { #[cfg(test)] mod tests { + use hex::FromHex; + use super::*; use crate::crypto::test_helpers::{decode_message, decode_sk}; - use hex::FromHex; #[test] fn test() { - let message = decode_message("0000000000000000000000000000000000000000000000000000000000000000"); + let message = + decode_message("0000000000000000000000000000000000000000000000000000000000000000"); let sk = decode_sk("0000000000000000000000000000000000000000000000000000000000000001"); // "SCHNORR + SHA256" - static ALGO16: [u8; 16] = [ - 83, 67, 72, 78, 79, 82, 82, 32, 43, 32, 83, 72, 65, 50, 53, 54 - ]; + static ALGO16: [u8; 16] = [83, 67, 72, 78, 79, 82, 82, 32, 43, 32, 83, 72, 65, 50, 53, 54]; - assert_eq!(nonce_rfc6979(&message, &sk, &ALGO16, None, 0), - &Vec::from_hex("e9766e06045ef351d82f09d5d8707fd9a3f1f10cd5c596ce34b88b1aa19c7aea").unwrap()[..]); + assert_eq!( + nonce_rfc6979(&message, &sk, &ALGO16, None, 0), + &Vec::from_hex("e9766e06045ef351d82f09d5d8707fd9a3f1f10cd5c596ce34b88b1aa19c7aea") + .unwrap()[..] + ); } -} \ No newline at end of file +} diff --git a/tapyrus/src/crypto/schnorr.rs b/tapyrus/src/crypto/schnorr.rs index 4e619da3..b9c2e94e 100644 --- a/tapyrus/src/crypto/schnorr.rs +++ b/tapyrus/src/crypto/schnorr.rs @@ -9,22 +9,19 @@ use core::fmt; +use hashes::{sha256, Hash, HashEngine}; +use secp256k1::{Scalar, SecretKey}; + use crate::crypto::prime::jacobi; -use crate::{PrivateKey, PublicKey}; use crate::crypto::rfc6979::nonce_rfc6979; use crate::internal_macros::impl_consensus_encoding; - -use secp256k1::SecretKey; -use secp256k1::Scalar; -use hashes::{sha256, HashEngine, Hash}; +use crate::{PrivateKey, PublicKey}; /// The size of scalar value on secp256k1 curve pub const SECP256K1_SCALAR_SIZE: usize = 32; /// "SCHNORR + SHA256" -pub const ALGO16: [u8; 16] = [ - 83, 67, 72, 78, 79, 82, 82, 32, 43, 32, 83, 72, 65, 50, 53, 54 -]; +pub const ALGO16: [u8; 16] = [83, 67, 72, 78, 79, 82, 82, 32, 43, 32, 83, 72, 65, 50, 53, 54]; /// Schnorr signature struct #[derive(Eq, PartialEq, Copy, Clone, Debug, PartialOrd, Ord, Hash)] @@ -122,7 +119,11 @@ impl Signature { } /// Compute e - fn compute_e(r_x: &[u8], pk: &secp256k1::PublicKey, message: &[u8; 32]) -> Result { + fn compute_e( + r_x: &[u8], + pk: &secp256k1::PublicKey, + message: &[u8; 32], + ) -> Result { let mut engine = sha256::Hash::engine(); engine.input(r_x); engine.input(&pk.serialize()[..]); @@ -136,13 +137,7 @@ impl Signature { let mut count: u32 = 0; loop { - let nonce = nonce_rfc6979( - message, - sk, - &ALGO16, - None, - count - ); + let nonce = nonce_rfc6979(message, sk, &ALGO16, None, count); count += 1; if let Ok(k) = SecretKey::from_slice(&nonce[..]) { @@ -160,10 +155,7 @@ fn to_bytes(sk: &secp256k1::SecretKey) -> [u8; 32] { impl Default for Signature { fn default() -> Self { - Signature { - sigma: [0u8; SECP256K1_SCALAR_SIZE], - r_x: [0u8; SECP256K1_SCALAR_SIZE], - } + Signature { sigma: [0u8; SECP256K1_SCALAR_SIZE], r_x: [0u8; SECP256K1_SCALAR_SIZE] } } } @@ -180,18 +172,14 @@ pub enum Error { #[doc(hidden)] impl From for Error { - fn from(e: secp256k1::Error) -> Error { - Error::Secp256k1Error(e) - } + fn from(e: secp256k1::Error) -> Error { Error::Secp256k1Error(e) } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Secp256k1Error(ref e) => fmt::Display::fmt(e, f), - Error::InvalidSignature => { - f.write_str("Invalid signature") - } + Error::InvalidSignature => f.write_str("Invalid signature"), } } } @@ -208,10 +196,13 @@ impl std::error::Error for Error { #[cfg(test)] mod tests { - use super::*; use hex::{DisplayHex, FromHex}; - use crate::crypto::test_helpers::{decode_message, decode_pk, decode_sk, decode_signature, pk_from}; + + use super::*; use crate::consensus::encode::{deserialize, serialize}; + use crate::crypto::test_helpers::{ + decode_message, decode_pk, decode_signature, decode_sk, pk_from, + }; use crate::hashes::Hash; #[test] @@ -223,7 +214,8 @@ mod tests { hash.to_byte_array() }; - let key = PrivateKey::from_wif("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj").unwrap(); + let key = PrivateKey::from_wif("5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj") + .unwrap(); let sign = Signature::sign(&key, &msg).unwrap(); @@ -235,13 +227,16 @@ mod tests { /// these test vectors from here https://github.com/chaintope/tapyrus-schnorr-signature-test-vectors #[test] fn test_signing_and_verification() { - let default_message = decode_message("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); - let default_pk = decode_pk("02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"); + let default_message = + decode_message("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); + let default_pk = + decode_pk("02DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659"); // test vector 0 let sk = decode_sk("0000000000000000000000000000000000000000000000000000000000000001"); let pk = pk_from(&sk); - let message = decode_message("0000000000000000000000000000000000000000000000000000000000000000"); + let message = + decode_message("0000000000000000000000000000000000000000000000000000000000000000"); let sign = Signature::sign_inner(&sk, &message).unwrap(); assert_eq!("06705D6B7FD5A7A34EA47B6A8D0CE8372A83D2129A65458E2BEF6F45892E7D5DBB13B346C6937CB76D25EFB18979B6523C72B56DD13B8F9D2F180893D20ECF45", @@ -251,7 +246,8 @@ mod tests { // test vector 1 let sk = decode_sk("B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF"); let pk = pk_from(&sk); - let message = decode_message("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); + let message = + decode_message("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89"); let sign = Signature::sign_inner(&sk, &message).unwrap(); assert_eq!("28C528B8E405F81CE9B396755849E24A316A12A0B7BC77CEBCB8C01DAD63AB53C79B5363B04C1046F021F5E28A20D2506C38B1598F3BE79235C5421AC98400B9", @@ -261,7 +257,8 @@ mod tests { // test vector 2 let sk = decode_sk("C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9"); let pk = pk_from(&sk); - let message = decode_message("5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C"); + let message = + decode_message("5E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C"); let sign = Signature::sign_inner(&sk, &message).unwrap(); assert_eq!("028CD7B45D8C265C9EA76A3633F09E48A3594558EBA0E2A10186ED1BFA1C8E0702B1EE67112B6CE4F5DD1CDFB4709B7628D71C6C74E8EA65B793A5267CA667F7", @@ -271,7 +268,8 @@ mod tests { // test vector 3, test fails if msg is reduced modulo p or n let sk = decode_sk("0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710"); let pk = pk_from(&sk); - let message = decode_message("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); + let message = + decode_message("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); let sign = Signature::sign_inner(&sk, &message).unwrap(); assert_eq!("E56D33673C16E2FCB1C8ABFE1065D1058109C1B051BBC0E7450DC6DE9A3C78B5ADCAFC135086D9DED95E3794E3B24F81E01ED232C9F0C59161E1930939FB05D7", @@ -280,12 +278,15 @@ mod tests { // test vector 4 let pk = decode_pk("03D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9"); - let message = decode_message("4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703"); + let message = + decode_message("4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703"); let sign = decode_signature("00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C63BAFC1D697AADBEB208CB8249CC7D9725A0FF8DA59AE04F68349A1EA06D072266"); assert!(sign.verify_inner(&message, &pk).is_ok()); // test vector 5, public key not on the curve - let pk = &Vec::from_hex("02EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34").unwrap(); + let pk = + &Vec::from_hex("02EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34") + .unwrap(); assert!(secp256k1::PublicKey::from_slice(&pk[..]).is_err()); // test vector 6, has_square_y(R) is false @@ -321,7 +322,9 @@ mod tests { assert!(sign.verify_inner(&default_message, &default_pk).is_err()); // test vector 14, public key is not a valid X coordinate because it exceeds the field size - let pk = &Vec::from_hex("02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30").unwrap(); + let pk = + &Vec::from_hex("02FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30") + .unwrap(); assert!(secp256k1::PublicKey::from_slice(&pk[..]).is_err()); } @@ -330,10 +333,14 @@ mod tests { let sig_data = Vec::from_hex("6ba8aee2e8cee077cb4a799c770e417fb750586ee5dd9f61db65f5158a596e77aaa87e4fec16c70b102bbe99a6c4fe77be424a44a2f5cfdc5fe04d5b4bca799c").unwrap(); - let r_x = - <[u8; 32]>::from_hex("6ba8aee2e8cee077cb4a799c770e417fb750586ee5dd9f61db65f5158a596e77").unwrap(); - let sigma = - <[u8; 32]>::from_hex("aaa87e4fec16c70b102bbe99a6c4fe77be424a44a2f5cfdc5fe04d5b4bca799c").unwrap(); + let r_x = <[u8; 32]>::from_hex( + "6ba8aee2e8cee077cb4a799c770e417fb750586ee5dd9f61db65f5158a596e77", + ) + .unwrap(); + let sigma = <[u8; 32]>::from_hex( + "aaa87e4fec16c70b102bbe99a6c4fe77be424a44a2f5cfdc5fe04d5b4bca799c", + ) + .unwrap(); let decode: Result = deserialize(&sig_data); assert!(decode.is_ok()); @@ -343,4 +350,4 @@ mod tests { assert_eq!(real_decode.r_x, r_x); assert_eq!(serialize(&real_decode), sig_data); } -} \ No newline at end of file +} diff --git a/tapyrus/src/crypto/test_helpers.rs b/tapyrus/src/crypto/test_helpers.rs index 972e797d..497b5e28 100644 --- a/tapyrus/src/crypto/test_helpers.rs +++ b/tapyrus/src/crypto/test_helpers.rs @@ -6,25 +6,26 @@ //! //! -use secp256k1::SecretKey; use hex::FromHex; -use crate::crypto::schnorr::Signature; +use secp256k1::SecretKey; + use crate::consensus::encode::deserialize; +use crate::crypto::schnorr::Signature; pub fn decode_sk(sk_hex: &str) -> SecretKey { - let sk = <[u8; 32]>::from_hex(sk_hex,).unwrap(); + let sk = <[u8; 32]>::from_hex(sk_hex).unwrap(); SecretKey::from_slice(&sk[..]).unwrap() } pub fn decode_message(message_hex: &str) -> [u8; 32] { - let vec = <[u8; 32]>::from_hex(message_hex,).unwrap(); + let vec = <[u8; 32]>::from_hex(message_hex).unwrap(); let mut r = [0u8; 32]; r.clone_from_slice(&vec[..]); r } pub fn decode_pk(pk_hex: &str) -> secp256k1::PublicKey { - let pk = <[u8; 33]>::from_hex(pk_hex,).unwrap(); + let pk = <[u8; 33]>::from_hex(pk_hex).unwrap(); secp256k1::PublicKey::from_slice(&pk[..]).unwrap() } @@ -36,4 +37,4 @@ pub fn pk_from(sk: &SecretKey) -> secp256k1::PublicKey { pub fn decode_signature(sig_hex: &str) -> Signature { let sig = Vec::from_hex(sig_hex).unwrap(); deserialize(&sig[..]).unwrap() -} \ No newline at end of file +} diff --git a/tapyrus/src/merkle_tree/block.rs b/tapyrus/src/merkle_tree/block.rs index 8274bc21..5e5c82e1 100644 --- a/tapyrus/src/merkle_tree/block.rs +++ b/tapyrus/src/merkle_tree/block.rs @@ -17,24 +17,28 @@ //! use tapyrus::{Block, MerkleBlock}; //! //! // Get the proof from a bitcoind by running in the terminal: -//! // $ TXID="5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2" +//! // $ TXID="57e1df6a71dcf4fc9535f4d23b15fef372613dfa0ad9b80b6fcd00bf50ce123c" //! // $ tapyrus-cli gettxoutproof [\"$TXID\"] -//! let mb_bytes = Vec::from_hex("01000000ba8b9cda965dd8e536670f9ddec10e53aab14b20bacad27b913719\ -//! 4667ed377d3b500c1622d911c3a5b0ab10ca0e2ac89c9460cb33a5914c00000200000002252bf9d75c4f481e\ -//! bb6278d708257d1f12beb6dd30301d26c623f789b2ba6fc0e2d32adb5f8ca820731dff234a84e78ec30bce4e\ -//! c69dbd562d0b2b8266bf4e5a0105").unwrap(); +//! let mb_bytes = Vec::from_hex("0100000096574bdcf9fca26560e5ddf07812c8e64841cb56e6453bf689277e\ +//! 47e0de40d4acd63fe13a8e957e37396beb969a3c54169ba154085ac6933d92c048b8ac01d139b453897c252f\ +//! 18b1258327ff99e923acabe1ce5c8340d19e1098445c1b8cb7a7b57c62004020fd9cd7dc16bedcba8925e358\ +//! 485db06b915c97b3ebfffde128ff5739a01955d21db9f1f4a92f94c77433f01d4b94247902724d70a342a90b\ +//! 5f44d7d0ee70880900000005b5c5945cc9908afb0a0cb2910b6623857e46d04df470e5a1ab482d2b7a119bc9\ +//! 02bff69aa3707c3317d35beb0f9bbfbca793bdf57869ec16b142880489fa025b431bbc09b76450aa05184574\ +//! 7dafb19876528d23814abef113fd032765be4d721ba6f4b8499fec71f8950a0e4fd22c9b623fb8c14106fec0\ +//! 37f498f3f628bc04f541d68b460a5247b1e1ecacff7b66aaa11b66c0ede3d0c58a835d6ca100c4d6022f0f").unwrap(); //! let mb: MerkleBlock = tapyrus::consensus::deserialize(&mb_bytes).unwrap(); //! //! // Authenticate and extract matched transaction ids //! let mut matches: Vec = vec![]; //! let mut index: Vec = vec![]; //! assert!(mb.extract_matches(&mut matches, &mut index).is_ok()); -//! assert_eq!(1, matches.len()); +//! assert_eq!(2, matches.len()); //! assert_eq!( -//! "5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2".parse::().unwrap(), +//! "5b02fa89048842b116ec6978f5bd93a7bcbf9b0feb5bd317337c70a39af6bf02".parse::().unwrap(), //! matches[0] //! ); -//! assert_eq!(1, index.len()); +//! assert_eq!(2, index.len()); //! assert_eq!(1, index[0]); //! ``` @@ -123,7 +127,7 @@ impl MerkleBlock { let matches: Vec = block_txids.iter().map(match_txids).collect(); let pmt = PartialMerkleTree::from_txids(block_txids, &matches); - MerkleBlock { header: *header, txn: pmt } + MerkleBlock { header: header.clone(), txn: pmt } } /// Extract the matching txid's represented by this partial merkle tree @@ -681,8 +685,6 @@ mod tests { #[test] fn merkleblock_serialization() { - // Got it by running the rpc call - // `gettxoutproof '["220ebc64e21abece964927322cba69180ed853bb187fbc6923bac7d010b9d87a"]'` let mb_hex = include_str!("../../tests/data/merkle_block.hex"); let mb: MerkleBlock = deserialize(&hex!(mb_hex)).unwrap(); @@ -701,9 +703,10 @@ mod tests { fn merkleblock_construct_from_txids_found() { let block = get_block_13b8a(); + // These txids are not `Immutable Txid`. let txids: Vec = [ - "74d681e0e03bafa802c8aa084379aa98d9fcd632ddc2ed9782b586ec87451f20", - "f9fc751cb7dc372406a9f8d738d5e6f8f63bab71986a39cf36ee70ee17036d07", + "d6c400a16c5d838ac5d0e3edc0661ba1aa667bffacece1b147520a468bd641f5", + "5b02fa89048842b116ec6978f5bd93a7bcbf9b0feb5bd317337c70a39af6bf02", ] .iter() .map(|hex| hex.parse::().unwrap()) @@ -719,7 +722,6 @@ mod tests { let mut matches: Vec = vec![]; let mut index: Vec = vec![]; - assert_eq!( merkle_block.txn.extract_matches(&mut matches, &mut index).unwrap(), block.header.merkle_root @@ -771,11 +773,11 @@ mod tests { } } - /// Returns a real block (0000000000013b8ab2cd513b0261a14096412195a72a0c4827d229dcc7e0f7af) + /// Returns a real block in Testnet(3ec84be4559f8ada97bd934b9772ad25ecb8c1762df758c324a19f1cf28749be) /// with 9 txs. fn get_block_13b8a() -> Block { use hex::FromHex; - let block_hex = include_str!("../../tests/data/block_13b8a.hex"); + let block_hex = include_str!("../../tests/data/block_3ec84b_hex"); deserialize(&Vec::from_hex(block_hex).unwrap()).unwrap() } diff --git a/tapyrus/src/merkle_tree/mod.rs b/tapyrus/src/merkle_tree/mod.rs index 512e19c3..898a9c76 100644 --- a/tapyrus/src/merkle_tree/mod.rs +++ b/tapyrus/src/merkle_tree/mod.rs @@ -110,22 +110,22 @@ where #[cfg(test)] mod tests { use hashes::sha256d; + use hex::test_hex_unwrap as hex; use super::*; - use hex::test_hex_unwrap as hex; use crate::blockdata::block::Block; use crate::consensus::encode::deserialize; #[test] fn both_merkle_root_functions_return_the_same_result() { - // testnet block 0ad80d57a3fec290b939d03d87f8e072e60c0ca436323d95116dda5278ff94f9 - let block_hex = include_str!("../../tests/data/testnet_block_0ad80d57a3fec290b939d03d87f8e072e60c0ca436323d95116dda5278ff94f9_hex"); + // testnet block 3ec84be4559f8ada97bd934b9772ad25ecb8c1762df758c324a19f1cf28749be + let block_hex = include_str!("../../tests/data/block_3ec84b_hex"); let block: Block = deserialize(&hex!(block_hex)).expect("Failed to deserialize block"); assert!(block.check_merkle_root()); // Sanity check. let hashes_iter = block.txdata.iter().map(|obj| obj.txid().to_raw_hash()); - let mut hashes_array: [sha256d::Hash; 25] = [Hash::all_zeros(); 25]; + let mut hashes_array: [sha256d::Hash; 9] = [Hash::all_zeros(); 9]; for (i, hash) in hashes_iter.clone().enumerate() { hashes_array[i] = hash; } diff --git a/tapyrus/src/p2p/message.rs b/tapyrus/src/p2p/message.rs index 373a777f..ff2d71a3 100644 --- a/tapyrus/src/p2p/message.rs +++ b/tapyrus/src/p2p/message.rs @@ -549,7 +549,8 @@ mod test { use super::message_network::{Reject, RejectReason, VersionMessage}; use super::{CommandString, NetworkMessage, RawNetworkMessage, *}; use crate::bip152::BlockTransactionsRequest; - use crate::blockdata::block::{self, Block}; + use crate::block::Header; + use crate::blockdata::block::Block; use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::Transaction; use crate::consensus::encode::{deserialize, deserialize_partial, serialize}; @@ -571,8 +572,8 @@ mod test { // TODO: Impl Rand traits here to easily generate random values. let version_msg: VersionMessage = deserialize(&hex!("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001")).unwrap(); let tx: Transaction = deserialize(&hex!("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000")).unwrap(); - let block: Block = deserialize(&include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap(); - let header: block::Header = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b")).unwrap(); + let block: Block = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e490121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af000201000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0804ffff001d026e04ffffffff0100f2052a0100000043410446ef0102d1ec5240f0d061a4246c1bdef63fc3dbab7733052fbbf0ecd8f41fc26bf049ebb4f9527f374280259e7cfa99c48b0e3f39c51347a19a5819651503a5ac00000000010000000321f75f3139a013f50f315b23b0c9a2b6eac31e2bec98e5891c924664889942260000000049483045022100cb2c6b346a978ab8c61b18b5e9397755cbd17d6eb2fe0083ef32e067fa6c785a02206ce44e613f31d9a6b0517e46f3db1576e9812cc98d159bfdaf759a5014081b5c01ffffffff79cda0945903627c3da1f85fc95d0b8ee3e76ae0cfdc9a65d09744b1f8fc85430000000049483045022047957cdd957cfd0becd642f6b84d82f49b6cb4c51a91f49246908af7c3cfdf4a022100e96b46621f1bffcf5ea5982f88cef651e9354f5791602369bf5a82a6cd61a62501fffffffffe09f5fe3ffbf5ee97a54eb5e5069e9da6b4856ee86fc52938c2f979b0f38e82000000004847304402204165be9a4cbab8049e1af9723b96199bfd3e85f44c6b4c0177e3962686b26073022028f638da23fc003760861ad481ead4099312c60030d4cb57820ce4d33812a5ce01ffffffff01009d966b01000000434104ea1feff861b51fe3f5f8a3b12d0f4712db80e919548a80839fc47c6a21e66d957e9c5d8cd108c7a2d2324bad71f9904ac0ae7336507d785b17a2c115e427a32fac00000000")).unwrap(); + let header: Header = deserialize(&hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914c364243a74762685f916378ce87c5384ad39b594aca206426d9d244ef51d644d2d74d6e490121032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af00")).unwrap(); let script: ScriptBuf = deserialize(&hex!("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac")).unwrap(); let merkle_block: MerkleBlock = deserialize(&hex!("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101")).unwrap(); diff --git a/tapyrus/tests/data/block_3ec84b_hex b/tapyrus/tests/data/block_3ec84b_hex new file mode 100644 index 00000000..e015f72e --- /dev/null +++ b/tapyrus/tests/data/block_3ec84b_hex @@ -0,0 +1 @@ +0100000096574bdcf9fca26560e5ddf07812c8e64841cb56e6453bf689277e47e0de40d4acd63fe13a8e957e37396beb969a3c54169ba154085ac6933d92c048b8ac01d139b453897c252f18b1258327ff99e923acabe1ce5c8340d19e1098445c1b8cb7a7b57c62004020fd9cd7dc16bedcba8925e358485db06b915c97b3ebfffde128ff5739a01955d21db9f1f4a92f94c77433f01d4b94247902724d70a342a90b5f44d7d0ee70880901000000010000000000000000000000000000000000000000000000000000000000000000afff02000603afff020101ffffffff01677f062a010000001976a9146713b478d99432aac667b7d8e87f9d06edca03bb88ac000000000100000001b5e25bfc6a926d40d80c3865498c6ab185f3cae0233b91a819f45658cee2f9c6010000006a47304402207cb0e7ede03b83c4deb5ad6d71903f57cda09eb0b6f97e919d4eaa124c5bd8730220347f2ec003273ec788a86403e159384a655df48eef42445a3c74cadd88805d1f012103aa5fc5940661a0c6dadb3e36cbea6181247694be5643e7ce83e427da40250734feffffff02204e0000000000001976a914deaddb55dc932d16de90fbf96f987432acdc637b88ace44f1d00000000001976a914bcd851477d05ffe580ed0ff8ffcf200bb8d0a8eb88acaeff0200010000000108d66153f19129c0c5cb0188bca1190806abc4ed346a638a4b53ca509a02d38e000000006a473044022057df051795bf5a116d212a7413bb40f9b26981826b5dac6e14db19086135a1a50220429036498cc2d909241229a894abb38f5be6bf76e4d07d7eb92de3e9f977125e012102701261865950c0dc9832813d43edf674b42b0762f48d472df85674c29c84019bfeffffff0240420f00000000001976a914699609c2ccf022f1c60a48266af244f9f4a3757388ac2c8de605000000001976a914b73199c0c34591bd9d67fbb93809baa8fd4df7d288acaeff02000100000003be37c4a6482263e7fd6c81bdb70e3c9f36b6e7ad63b09dd0f75c87db7d5b6fec000000006a473044022065778c1fab051479df50ead8ff4351a1cb84ee0047cc7df174e836a906372c2f02202a59beaf94f42713074959bd86aa09021e65e5b799145ac5394b7631b6c6d391012103a643f80ed6e0fd909425bcfab4e032f42f151ba6eb1431f86436f58be124d1eefeffffffe8275f1a27bd2b4dadda690267146e662ae6399b779bcc0239e0fe3316626d53000000006a47304402206abfc5d506de71156a6504634ac53a851d255ceba0624238fa97e7f873e43aee02205314c4d0bf94aac14e5e8c4d7f22b7bbfe2d9a78657ebbfdf854d245c0145fbe0121034789f8f2cc0d9e55b15d6a72288ee30d0a7c08b8c7bcc88e5194c74f65eb551afeffffffe6818ae25ab33ec09180c003fbd8d9457d876d8f3ec4b18b2f74f7f96d14bc16000000006a4730440220206ce5d28d830b56e7f4fbb31b43473f1532e0b13a9154b4502fcb7bf7a10a73022040abd6b26af9761a3842020543bc6d38b7d1feb407eecf36ff016566cf28a3ee012103e1395c734b0cd860330d58f99a0c78b921c9603a7a8af1504ca8801b8292ff54feffffff0240420f00000000001976a914699609c2ccf022f1c60a48266af244f9f4a3757388ac9c1d0f00000000001976a914af6d292c5441153731c9d2735795ea063de371b988acaeff020001000000013c12ce50bf00cd6f0bb8d90afa3d6172f3fe153bd2f43595fcf4dc716adfe157000000006a473044022064c88992458a8530553f09da8398e94d5b832dce11f50ebfcbfec03ed266acb5022052d044265cdd85306dfb3b51df56d92dcb9675e98917e5b69ef58df5841bcf1b012103b7f45464e5dc3ebb30a8b6bbb82d8e1c65fdfd76526afe6b1bc67fb296911ab6feffffff020a000000000000003a21c1c55f60274daa83aeeca3aeae797b79db0dd4b05cc1dfaaeb06d6d8e1d741797dbca91489854bee352cc0b67062868b2442607da51e0bdc87f8390000000000001976a914067871710ba26c57f41f4d02f29b2a630e98210a88acaeff020001000000035d68eb033820e9d792e5e53263e2e4870f6fbf79c469d0ab2a39a80dbb20c3b2010000006a47304402201bd8fefaf4e22df6abfd91224391318503db46352fc4284ddc46acb28b93f7ff02205e585bc5c54ce8272c8ef840b25d8d8ab883ac422db379bb972c5b9a359ad185012103789b70df8cb78cec5a237ee85c24b090973b3604aa9ad4eb648c9408d4aa65abfeffffff4197999ecfad794adffa5070d14f972e2c609d3f23e972d8f0b0997bf7e03a0a000000006a47304402207bece0e9c8f9687c0a6b5ae0860c0a4787e4a8996e84db29d1f317a5512136cb0220216321b1af7c0ac333ec3e98c40f62c86b6d95e3644fdad1309678a5bfdc09800121036bf42c0b921eedb19af280b740bc5cf560409b23f8aa4b5a99a2a84c1c2ec177fefffffff4c59344b2510e64796e85f979bca94d3064fced5c1a1988abafa51fea63ee63010000006a4730440220420e97da3f369caafd2a28ba9b460352d6eda0af69149650036da6a4910feef0022001d69490892267048975df83b8bc26c0fc08bd9d59c4046097c03ee9707cbeca012103578694382cd82fb49ba938e8df2c6f67f6040d1e67ee9efdd3de6d3d08e7b8eefeffffff0240420f00000000001976a914699609c2ccf022f1c60a48266af244f9f4a3757388ac2b2f0f00000000001976a914769a4f732564165e45d26a5bf798285fd36faa5a88acaeff02000100000002ba3a59a92f18010aa54ff7c1820bb205de4eaef0f2ef47b176e5cf939b03a9d3010000006a47304402200a3a2bb243e6252ceaf2637b4b3671d53876dd495f56020c9b774f89d59ae418022017df60389ec9e02dca20e42983ee0fed381506cd833a1764613376f8a6ac23d7012102b4c01249745907c0ac66fd73ee26a9aac53f3a128fa1f5d1616d26fc9f5c6052fefffffff4906ee31b538f9f145985aba12ceb6be1234e3798c46dd80977a5d0b85a4e28010000006a47304402205879b2635d1926bb03e174bc858962b35b910608940647d25f94ec82e730f81502204994aa065a9e557b52504b2808ac698de5bf63f88200c32efb225ba819797158012103eab3dd4a277a7d57d005156d731738c963071e9589115bb2062bd20734c4c930feffffff0301000000000000003c21c2b2ca2005cb28fba871e586011e7f0b6381baa0018dc2acfd932804f065fb7d2dbc76a914a701165461a1fc6b22993d02dec49a2d01e4ac5488ac65030000000000003c21c2b2ca2005cb28fba871e586011e7f0b6381baa0018dc2acfd932804f065fb7d2dbc76a9148d1f042d7e51510c38d9c8716adb38b414417c1488ac0e9e1700000000001976a9148d1f042d7e51510c38d9c8716adb38b414417c1488acaeff02000100000002d7e012dfcc8f951b86cfe843240d571d15df8940e227a9059258c092b2f8c3cc010000006a473044022025ba2c91d30663e1f2b4bfe32b7cd92ea164d8435a7fa390da0c583c33922919022068855c3d1b308d85ef6177eaff1c67e7a0fdaaf39386b24ee7fe8f67c84cc60c0121028fd8b76c5235dabb335c0ea2699243926fe0331cc5bca911209209205199faaafeffffffef8bc3b54c9a1f3d9cca9c663d49251a9c06c792dd2957b1b04597587f84a16a000000006a47304402200e03818b6a5332ae972869de980eb3e5ddf38aa8ef5175701e9642a36622c67302205ba51b4a44030851d9e94cd027beef30747ffb036dd3941cea6308fdcceb31210121039d84994ae2a261e294a44b6e12701d6bf8da3780cf1f506a1fc7bea6e42e4443feffffff0301000000000000003c21c18052819dfb017498f89e82cb233073c4b6fabf20605e2ab9ef021eb008a15fd5bc76a9141be44b7a343bef453c2db508f6b7c7236152abe388acc4030000000000003c21c18052819dfb017498f89e82cb233073c4b6fabf20605e2ab9ef021eb008a15fd5bc76a91465717c1bb91fb362f3da4b1301c6678674cd71c588acea991900000000001976a91465717c1bb91fb362f3da4b1301c6678674cd71c588acaeff0200010000000251ecf97744484ca5f362a02941da9d93e9402875d64524ccfe353889f75b5ffe000000001a1976a91413beaa62e10430d77c1d55f7e278d757bd10f6e388acfeffffff422e6f5275fac3babc0fc202e6cdf590e4ce42b048652d85580ad7da5fbc96d7010000006a473044022074ebd91e011217af2ef0dceac56648327a7218981c4caa171c33c7f049a5a0c6022035678084c94e7255f206430befc101e319cd63d1915a11ab67630f48d8deac3901210265116d6b5e1f8a30151b0d0586451d9f3a898fe8dfdf962eaf81de47118e3e9afeffffff0201000000000000003c21c3ec69b8d4b045a6e1bd3752c021c011f0329eea96190745a7d041389cebc06c36bc76a9149085f7724297b5dec96dbaec93f33873e92fabac88ac26511000000000001976a9147d40aec936c898a16664684ba1e342bf791eb32488acaeff0200 \ No newline at end of file diff --git a/tapyrus/tests/data/merkle_block.hex b/tapyrus/tests/data/merkle_block.hex index 58d1706c..9844ad3b 100644 --- a/tapyrus/tests/data/merkle_block.hex +++ b/tapyrus/tests/data/merkle_block.hex @@ -1 +1 @@ -0100000090f0a9f110702f808219ebea1173056042a714bad51b916cb6800000000000005275289558f51c9966699404ae2294730c3c9f9bda53523ce50e9b95e558da2f0eab2fe48aeabac617a676aeea740f07e868e3441f2641c1bc040acc07966a45db261b4d000900000005fac7708a6e81b2a986dea60db2663840ed141130848162eb1bd1dee54f309a1b2ee1e12587e497ada70d9bd10d31e83f0a924825b96cb8d04e8936d793fb60db7ad8b910d0c7ba2369bc7f18bb53d80e1869ba2c32274996cebe1ae264bc0e2289189ff0316cdc10511da71da757e553cada9f3b5b1434f3923673adb57d83caac392c38af156d6fc30b55fad4112df2b95531e68114e9ad10011e72f7b7cfdb025700 \ No newline at end of file +0100000096574bdcf9fca26560e5ddf07812c8e64841cb56e6453bf689277e47e0de40d4acd63fe13a8e957e37396beb969a3c54169ba154085ac6933d92c048b8ac01d139b453897c252f18b1258327ff99e923acabe1ce5c8340d19e1098445c1b8cb7a7b57c62004020fd9cd7dc16bedcba8925e358485db06b915c97b3ebfffde128ff5739a01955d21db9f1f4a92f94c77433f01d4b94247902724d70a342a90b5f44d7d0ee70880900000005b5c5945cc9908afb0a0cb2910b6623857e46d04df470e5a1ab482d2b7a119bc902bff69aa3707c3317d35beb0f9bbfbca793bdf57869ec16b142880489fa025b431bbc09b76450aa051845747dafb19876528d23814abef113fd032765be4d721ba6f4b8499fec71f8950a0e4fd22c9b623fb8c14106fec037f498f3f628bc04f541d68b460a5247b1e1ecacff7b66aaa11b66c0ede3d0c58a835d6ca100c4d6022f0f \ No newline at end of file diff --git a/tapyrus/tests/data/testnet_block_0ad80d57a3fec290b939d03d87f8e072e60c0ca436323d95116dda5278ff94f9_hex b/tapyrus/tests/data/testnet_block_0ad80d57a3fec290b939d03d87f8e072e60c0ca436323d95116dda5278ff94f9_hex deleted file mode 100644 index 88e42a52..00000000 --- a/tapyrus/tests/data/testnet_block_0ad80d57a3fec290b939d03d87f8e072e60c0ca436323d95116dda5278ff94f9_hex +++ /dev/null @@ -1 +0,0 @@ -01000000e5e8047788a55c727c279ba01bb29fe4eb29213b9f386973c5f81bda6844ed633c32047cb52e15735fc9a2546d39f4376eb759aaabcb52d2453a36f7ca4ee42bbdef2a3753be663c657f61fa3b116769d9aac018b8466f0712e599ebe86207c3c96bb3654085b87fbcc8d4b15bddb8ede17d682ec01e10024cdb6366d99109edce16407825215ed1d5d5db822d961c7edf70daa4f988c39d781c9bd9d47e4e29e0175205c519010000000100000000000000000000000000000000000000000000000000000000000000009b10060006039b10060101ffffffff0124880395000000001976a9146713b478d99432aac667b7d8e87f9d06edca03bb88ac000000000100000001c93eed9da24cba97bd7cd083d56797626dd4f851fdfc00f9e5a64f67e8a8aed2050000006441a7f7a4e6a31932167bc692a56c6ed4a1fd4623df69dc78cb57436d62e64b3ea42bb3fd3ba66e51b56f828c57c87e390fb7ceb7838e5c3ef327d8c9d0ea86e5360121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff01d0070000000000001976a914b4bc1e1d0867aa6a1f2c9e2676492d183b71069988ac000000000100000001f025bd082178776b4d46fbec5cc73a2930956d1eb062eeb15e48d8b667f2e74d0c000000644162c544a9854f06f90ff94c9a1346c8cca73bbb3e7b6a0f0f132d9e1c545bdc95adc2734f4aae684c824ad2f36cf1e3085a51bf83c804b81b65862901d63f8bf00121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff01d0070000000000001976a914b1ea9e6d1e0b715d3ae2bf89a08e5459b0b4606088ac0000000001000000016be51b72e9095f79c74df1b6705b1b2937c83f0ca035d21419c5c9dfcff4d49b05000000644169e892d7d3690e680c07aab56fba39d7c801b78dd80cd711c00460466a4a9cc5298f5654d3c14f955177ce1c9b59e7114155b272c9e052c40072f3ae9326af5b0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff0258020000000000001976a9144188d77b92ef0dc0efb168e61ca7cc82b3f04edf88ac78050000000000001976a914f2ecf9d645588fd9eaf3cdba5a0a630b78677aab88ac00000000010000000125e5280c462ee9380f83368b27d0c4f4d37d663efe28ad0cb3a45f16b96c12d70e00000064413245be684de577bf8458b91a0b02799262b0d61da13e0cf2edd6b04c8cf121203f5ff5b81965ade5ffe72340e4098b8fac0620996453d23b7ed53915947b9b350121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff0258020000000000001976a9144188d77b92ef0dc0efb168e61ca7cc82b3f04edf88ac78050000000000001976a914a7a9871897b5295ff7f7bf19eca5ffc7ed928cca88ac000000000100000001dd5f81d85c4c4b748866571f7589a538833f36466dbf08735083b0aca766981e000000006441bc7ba59f6fb702b2f68dfd8d30c432defed8f0d7c641c254eaa0a86f2ec3c710f041a6a4996069f4cb292dcd4acde38586baaa0e34166ad6cb182a201f319a370121030bb7322b64925b1a62bd89e9f62f131308e85959d452cd99dcc612bfc0edf446ffffffff0101000000000000003c21c3aa08a7ecf6964f865f31de282b6f231ace840ad53eacd32c06e8f7668fa202d6bc76a9149e4fbe6e86cd210e2e4593dd77fc11689723989588ac000000000100000001a62e6f4b649ae200a8fbe550d5f562eadcfec528f28de76b19519e9ad0b373e7000000006441ce6080e2318064e06efcdb4a858c87eb3f4a0bbdb754174f07bec1f4629874da4d0c1914c1610c4a3f380793ad26fee7054380e47248d60662fd8968c648bebf012103e4e6789131d0b30112d2f72012cce2a5da4d6ee76f3ec116585c4ddc5c164be1ffffffff0101000000000000003c21c32a18a82b9e650ab060ef3411aee77d566f07e427aacf343520578b9af26c8b00bc76a91421e23d1382f46d94fb09890363f79e259f18e8cd88ac000000000100000002f96a6e00768a65a9959fb8db22abf1748cd123b3560b1fb19e62cd9623eb3b360400000064412dc41ff4f2f97d7422bffd9659248b957f1ccfebf74c24ad15f117a47be790aa1c1b88a82d2c6740cfd6fb039bfc76e99a51a3976c4ad35853f8f03f6dc380e60121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff863537aca2fd0b22eaa33b4817517cc0b2b83a3efa40b8096bfec5e9100a34190700000064410f63c2f837c9e06d2880b94aef4f89772572e370a5f896a436a2677776a0d1fccc0ab15645e4c7669ebfcd003fcc27b1f05aa757f4ec4587658f67356e9464520121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff02b80b0000000000001976a914783812f45e7e6228f17c4b4dd347eb260aa2dbec88acb80b0000000000001976a9146615c04ef3d714367c8a54bc2b8fa996392af91388ac0000000001000000018f61162c5bc37cf7f82902304b43ce9c8a84de994debb0315993e79f27342947000000006441fa3f30ed44bbd1f9e5a1d2b3537198796c7c280665e9e0d3b5f90a43902d34b5a2c1753ed9fc49fb0f175d84f7928fae95546019ef089d7954ec8f9ce1908d8f01210321f96675f96e490177742bd78e241ebe61837d8dea4c5b549a14743356a28728ffffffff01e8030000000000001976a9148e8d1bd500a957a73e9e463379f8911c4d8ab46688ac000000000100000002867cb380b7a41b6f0c3f9b489214d9b57be2072c47c2150e96576ea695256e7b12000000644174d3979594b2ee07e30368822c99da68213dc41c371b24b7ab0dfb382b07723c4acfc6cf2e970497628c7853dada4a44b422b285edd152cb25528b45967b76a70121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffffd227fca48aeb6ccd7a8cc99463be7dd420a64fc0d541a9eacd8e90c5f2cbe1652a00000064413bd37b63211e2f65de3b912c3e704fa040e86177640c9e42cde0f998ad7cbd7066feda1e7d977d25205ded9ece22f5735496590847326f904d3e58fe3f4351ba0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff02b80b0000000000001976a914dd28e07ca4bd7e1ff4f7f20949092596192728b588acb80b0000000000001976a91451a90b56e80ec8d0b1fd3c8ddb3552769a7f367388ac0000000001000000019b8ab3ddcfac4dd5660dbd8adc3dabb8380c1b68f8b9e938ba94b1099f2d245b000000006441c171b712f6a82d1cd6ede9efc5b026d133379d557a3254c54b36f6056e95a24719c1c6783a089cfd74bbf66cc701cab0f72b57e941cec4a9b08d428e41ee25cc01210369f99beafcbf69a3740672366a97b7b205e0dbad623b32506f2029bb6c54bd30ffffffff01e8030000000000001976a914f5719e54fe451dc9a381bba7bdad12f369e3090388ac0000000001000000022cf4bd4bd61cd59e51bf4075a0cfbeee37fb33ed1e6e07c8f5faabe1b2cf27d1070000006441682eb63c647ef4a2b69f53cb9726691ab698ee468724e608dbaf5c40bc7bf6b42619d6bf2acd3403d872cbeaf0eb83f399e481263241f43c820e4e72437305d70121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff6d0b49fc92d85ceb933ab8b49ee35993d09623d77159cdd62b80fb2bf407a90d0300000064419df2e207ea46837b02086cab1096670a3afc103d8980ed8aa36a7e3e14bdd3550725940ca7ebfe304f7a146f7c8bfa7bc89004cb4526d136bdc8a1ea03e7d78b0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff02b80b0000000000001976a91463168cb9581173181bee04c5813742a50d433d4c88acb80b0000000000001976a914995f48531836cc86b4104cd813982442c8e9ed3088ac000000000100000001ef774c2ee3fa0af76cd00950838595d4babe2f23c5bdb1e0269929407dd22d9a0000000064413ee2a8703fe3627dd5f605a6f5b18fd4b5db1fe22d6b0fa89d23c73f385604e382ec5281cc9983c5b4d5e9f0889f46c97f3b81357119a6684e9b8fe1db05df50012102215bb6200d34364e9d26319e4f00b79c733349c83d910211b9299f5957478547ffffffff01e8030000000000001976a9149f2a4955768f627bf7eca76fd390deea2daf3e7288ac00000000010000000225e5280c462ee9380f83368b27d0c4f4d37d663efe28ad0cb3a45f16b96c12d71e0000006441aa7131dc7459ceb750ca597043f70f31d01e799c475419cd931d3446fe53fc2e8478ead403cd7d48665a02b835f3a326e4a755ca014d21febc194beecd21a2ba0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff867cb380b7a41b6f0c3f9b489214d9b57be2072c47c2150e96576ea695256e7b110000006441b7020be92528361cb3278026d2d8c6b6719f9a8c9563e836632f0637d9c4dd2abb0180718c22e29c33d1317863885a59b0c11320c63bc28a90df61f4365ba0080121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff02b80b0000000000001976a914cc8509f266d963ed99bad61e97967385f1771c6288acb80b0000000000001976a91452359d6cc31f801460d09d193964d7a4ec0494de88ac000000000100000001fa04222fe535c4b5cea34ac535bb8e11cbd56341bcd6d5cc5dccdaf37eeb46a0000000006441e7c0dfb8f43d64e27a2a1fa2695916c8e95b3aec70b6b4fcd21fb4a150083d7ecdd7dd850b1829875dfa5804e5a5a00e4b63ac68993eb86ecde0351bb2281fd10121025b43b0f267d770b435173e0b895169ee840decc35b6c72b20f482f014feebd6bffffffff01e8030000000000001976a9145cbe5a7be8aaba7ab26ae3b369698dbba01255f288ac000000000100000002b8dea4302556ba3b9d5cf1505087d96d3643c662daa0bcfbeb66323404fbe3ff030000006441415d6b55dcb47f979c3b0ba64e9fa71de15a9a306c1f7e007c993e752593d6d95a6ba23df76174ad95efaea2cf8eb7be5b7a10f03fb2ccf4ab164620b293e4ce0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff6be51b72e9095f79c74df1b6705b1b2937c83f0ca035d21419c5c9dfcff4d49b140000006441986a6b086f97849b223d8b13435864c961e64ccf3ca02be5a9d2d6a263a3bccad868eea29fae09042ff37fa005d39e279babbcac0bb1819e8b1f55bf49d01a310121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff02b80b0000000000001976a914d1b545a74815e3a5592d67832cada3fffb5591f388acb80b0000000000001976a914f57ae3c0f92d114fb606ab5c65a677052d6370e788ac0000000001000000018f76c4ef8c93ced0763f2dc667d56b4ce5697c3e80c77639b3b85c8d761875d5000000006441e1257f86707acaa9ba2094197ed0a421dcdd0e480b87e7a59153da3b8f2b50586a3cddf84d096bb9a468ab4f70b181e9d9c56ce7935e219464c68f1e0b07bd94012103538fe595d1dc2c05775c52a7688af1ee7196a5c2d38a1a8783c82c0e3a49bb10ffffffff01e8030000000000001976a914dc1d097e6e60e843fa96043fa2911019af98c9da88ac000000000100000002bbef3abf64f1bdf058d6f15b9e8f04e0f36bf22a3e0c20a3f2262ca77fb581b6000000006441ba0086cc030c006800384043b81ae6e2edea34e59ec328aff2a19abad490c63c9f1af888c1b642ea3716c6e8ccaf3cd5e1881571c424fbc9dbeb0d3f322f7f2e01210216babad19533aec85cc596d907fa251cbf45435b00a20cf2f08c5b4183e12a5bffffffffd227fca48aeb6ccd7a8cc99463be7dd420a64fc0d541a9eacd8e90c5f2cbe1651900000064414dc63bf9adc146fe69eb75b326a8157834a4c36f3355130b9fae6e875bd79ad9f66bc0ff4410733d78ab2a7a9cc0c96b89a1fb3df1c85ba34f6e19d3f5ad85380121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff0201000000000000003c21c32a18a82b9e650ab060ef3411aee77d566f07e427aacf343520578b9af26c8b00bc76a914ee6f8d0a0ad77a07dbd5305cc94117831341e5e088ac140e0000000000001976a914e67a09de58f1608ac634470dfb5c7485e25daacf88ac00000000010000000254325a548b9c774eb8931ec93e460f2b837e3654e44d2bd478405ee50ad6d5f7000000006441b009def0b62d83617ab38829961367ff5b2ab8b83d889df38c5b69ab70767a55b9c50f8f6917798bb081590f0e961dcd5833eb1fa582ab8cd80755453a3ab157012102089508b2d26c4c1ad128e11ffc5b89c10b9c9b4ceaa059c127180ccb7e2267f9ffffffff6b59695c7c0752a8d634e5011c75f233307dda42021be45fa704e154657c870e140000006441437140744b8952ddd5d4c09c62d7a2369a4871f0b13e159ed331b7bc083134fb90f4c53f5075165f8507213f4b6de458825aa548ff507ba5ce584f1bfb749bfb0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff0201000000000000003c21c32a18a82b9e650ab060ef3411aee77d566f07e427aacf343520578b9af26c8b00bc76a914ccd0cb966dd5983f276328f1b4a2e9193d416f7788ac140e0000000000001976a9145268aab9ab6216d77ad04ec72128243ef4de729c88ac0000000001000000026bdc216083964a70391ef72b32ad298a271fc3e71202521d5631591039f997e500000000644150efda8f2aee9f41e2f57690f2329efa93edb42fdf2465c38d7f8420c060aa3285027288642b8ad031311b2115c61162c4d850631497e64ef2de735703ac07130121023a97dae49a5c89380a2638605b5d6eb8039f61e21512779a7f9b0cbfa662f967ffffffff581fd951505a193344e487e5793467fd34ab6698f43b0272b235309e0d58c166090000006441aec46a1c84b024bb5444d962ebd0514108615db1ad75fad88432d98be94fc296613ba944fe8cff4cfa9d5bab69372b1a44392c958fb4913ebead7b88ab6ca5e30121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff0201000000000000003c21c3aa08a7ecf6964f865f31de282b6f231ace840ad53eacd32c06e8f7668fa202d6bc76a914ee6f8d0a0ad77a07dbd5305cc94117831341e5e088ac140e0000000000001976a9140d97bdbcf9e99ad2fbc5ea6772ecc87a0a8a0b3f88ac000000000100000002687243943510f214ecfa1a6c9a42cfd84192c9f6989c2b41e1466e45045b29f700000000644107bb99c6809c22ee18babfa56b212e43bfadb398dba6a20b9a097dbaa50782bb5ab99f45a298229473d052b1a69963510ebfcad027ff448efb20c1fd26240c82012102089508b2d26c4c1ad128e11ffc5b89c10b9c9b4ceaa059c127180ccb7e2267f9ffffffff581fd951505a193344e487e5793467fd34ab6698f43b0272b235309e0d58c166130000006441eff6eeb0d569bfdc5d06f198e2b9f59948a14010541be11a34d67f624fc48572677eacf3064d02ac17fec7e5bf25e3cea97f597996be0578a79075a22a43042c0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff0201000000000000003c21c3aa08a7ecf6964f865f31de282b6f231ace840ad53eacd32c06e8f7668fa202d6bc76a914ccd0cb966dd5983f276328f1b4a2e9193d416f7788ac140e0000000000001976a914509a4ed5b37d4734ad8a0837fef00e5e13e1d24088ac000000000100000002a06b52770f7204077c20ad42a7fd1679186b8161dcb02f7f9a78f242b04f16b6000000006441e17e4da4393464974801fb6d1d012cf06ccfb32e237919845ca4e4a70b14347210bb01c156253364331b462ada0df1a1e6d51a0544f10c81f25cd89b3bddba99012103edc4f7477d8558a60597c700e642fe065f97863fbfb2d0bc80ccedad4b40c817fffffffff7cc615bf669bc64dbf661dde0f99800f43b37cdfc15bba3f79d98c4402fe7c1050000006441f4728f5960de51228f146505ace9b65c82e281a00cf048d6819698d73035204310bb0e4f30212df5ded52386f34861e70ffd868647b1d50f722a31c63690e64e0121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff030000000000000000fd8a016a4d8601545001fd80012d32d8e0b7c69519a5d2cb7c5436f6703a04950dfa378114324057ab61f25272b5ad5b625398c48b770453473a34d2e54e2c31201172de45190a63087a65ba93d9e86c4161dbebe5d84a6a559a90645c86252a868df92b07ac52be5f45cd5b035898c4ffde46603e53af03e02cf6c9f0eda611cca9dd72435e89dd9d034343d6f2ab81c3ddbde8aa46dc5bb9fcb842b9170a27b9019f759d42ab0fc010cdbda9c2b3a28e806fabbb40c26407e925f3a134a3128755ad0308488ff17a5af2fd178d12055174e5c88609fa38902f740628ac2d71a344a254446be62ca44a2f269e14a7a340895aec12ca896f9b1e9db2a6871122bb9aa1df97911dbf96a5a75626c2167043c7ad379faad03571caf6fdd3d7eb0bf97b7453cad6e18f52134007fc07aaf1b7164b8a237beb504e41e6fd76b9443d1c7021496e3385b0e3888aef0cb3de6aba80bd13536d22d440e9073f65edaa4f44cd6aace937a5d9a3ea96855812f528c8b65c5cf29ffbc7730d17decdda08db86bb7879800c26f5b60018bf8758020000000000001976a9144188d77b92ef0dc0efb168e61ca7cc82b3f04edf88aca30c0000000000001976a91460d803488b59ca22e48fb3e8ee0e489ac14e3e6c88ac0000000001000000023104b54df06cc3cb26080e1481ec9fdd7c184356b3422ad4601b47da41d84de90100000064410427ad406330649131b1b3ef0231cb83283835720baf212765407843b293120ad2cc5d22a3aedbc7b36390b94f81db1f942e355765265fef55604d23a98430e2012103edc4f7477d8558a60597c700e642fe065f97863fbfb2d0bc80ccedad4b40c817ffffffff6398b818877efe830a95e0a2bba7c8e019b292c330ac991948796d6ed3ae722701000000644161b488ee4908a0ae98a5a6279b28d1538328a087dfd5e4356854863fa4c7853421a63c3380e12861436b5f10b6a026605a8cf7dc8b81b21de8cf6fad4d7a04470121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff030000000000000000fd8a016a4d8601545001fd80012d32d8e0b7c69519a5d2cb7c5436f6703a04950dfa378114324057ab61f25272b5ad5b625398c48b770453473a34d2e54e2c31201172de45190a63087a65ba93d9e86c4161dbebe5d84a6a559a90645c86252a868df92b07ac52be5f45cd5b035898c4ffde46603e53af03e02cf6c9f0eda611cca9dd72435e89dd9d034343d6f2ab81c3ddbde8aa46dc5bb9fcb842b9170a27b9019f759d42ab0fc010cdbda9c2b3a28e806fabbb40c26407e925f3a134a3128755ad0308488ff17a5af2fd178d12055174e5c88609fa38902f740628ac2d71a344a254446be62ca44a2f269e14a7a340895aec12ca896f9b1e9db2a6871122bb9aa1df97911dbf96a5a75626c2167043c7ad379faad03571caf6fdd3d7eb0bf97b7453cad6e18f52134007fc07aaf1b7164b8a237beb504e41e6fd76b9443d1c7021496e3385b0e3888aef0cb3de6aba80bd13536d22d440e9073f65edaa4f44cd6aace937a5d9a3ea96855812f528c8b65c5cf29ffbc7730d17decdda08db86bb7879800c26f5b60018bf8758020000000000001976a9147a7895d0531181449490342fbdb47d0cadcb6d0088aca30c0000000000001976a914df8a84b56515fff469c635fcef17176047b5c4e888ac000000000100000002c2edaaa83d33759e5bf86070527829d301e49f7035150a1691786f5184fea1510000000064410fccb4f2de9dd55f589f0ee412b08679b0b710c7301dcc7a415fed7f3153abfecd5e4540c89097d03bc1eb2c7e6b6e878672293bca18e20e9dee9467c77ae51e012103edc4f7477d8558a60597c700e642fe065f97863fbfb2d0bc80ccedad4b40c817ffffffff81281c5fc1011fd54c77a9c8b9a975636a4fecbf2e926f1302e12c90f435ee73110000006441bb1b791b8686415c2863fb28866e97fe32fc8ba7fa2ebf65dced82cbd02ce61fc15d1780e9b1e17f1476e96de144c1b8e9404aba9b27e39a696c412897be57170121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff030000000000000000fd8a016a4d8601545001fd8001400f41738fad3b47a1f00872b75a623e635eb81195a595bcef5db5b065b3c03341b15345582cc4649b0ba256360f6505aff536057aedfddf975482979aaf39ee0e58f2c6375038009fdd6be38e14b7f41a012e79c9ade20f32a616dcb6598486c1cdfeb14d4fcabfdc1af57d4dba6e1db66514bbdbc6d6cbf8e9b416e350bb24151944f74cc19fb352b19832c4551576b14f7ddf7a36c36429a6c195e4cbb4f46e9083429bc5ed9a8991ac1633d534987a23347a911ccf7a2360976ed408448ac21bf561b6c515311b3b277e78b0c2b797abf18efdc0f1aeca92bbba7ba5551a63a0e4f8df4b2d6132dca22354c49d733499aa2a90608bc282fae9c93004118ec2b2eb6ad5546201074e3855de9510910e146c66e35c839edbd6001abd39a35f45924c6781d05acec8920d900708497f5b3422aac1f8e3c1a53b408ba2d2df83625623d4fe81db808d3fbded68d2fe5e142cee1de90e6925664acc4ce3a51238d8a6522bc12d51b91a436836063e4828ad31008106adefb8ce09698af9aa36ce58020000000000001976a9147a7895d0531181449490342fbdb47d0cadcb6d0088aca30c0000000000001976a9146251c36c58aa1d6e197e1912fdea06921f0f676388ac000000000100000002f8a2869eb095d0f3a43726cd7bfc4b17a58c3cb47acf009206f042aedb335af50100000064411be49e55efb3f00f2b2d13fbcb938705b800ef649e9c475f47588008e37fe8abfe72073845273e266dc1e2664738911a672f48f30b7df266adabbe1c91030ec5012103c0a4aa34363108a46a60656801a7ed6eb936f490155289a88006b6f475f69ee0ffffffff867cb380b7a41b6f0c3f9b489214d9b57be2072c47c2150e96576ea695256e7b1d000000644111ae4d722eedb242c05a42bd9daf9dde341c77fb14a8b6430a67ab31e27c570b56ede88fbd8eae2c9a62514f9e98e1ef2b9d7ed209255d8c27f4a62ef69ad5220121039a77f4e4e45847e413617099b1b4e26d73f372d824432db3c005cabab28c4cccffffffff030000000000000000fd8a016a4d8601545001fd8001400f41738fad3b47a1f00872b75a623e635eb81195a595bcef5db5b065b3c03341b15345582cc4649b0ba256360f6505aff536057aedfddf975482979aaf39ee0e58f2c6375038009fdd6be38e14b7f41a012e79c9ade20f32a616dcb6598486c1cdfeb14d4fcabfdc1af57d4dba6e1db66514bbdbc6d6cbf8e9b416e350bb24151944f74cc19fb352b19832c4551576b14f7ddf7a36c36429a6c195e4cbb4f46e9083429bc5ed9a8991ac1633d534987a23347a911ccf7a2360976ed408448ac21bf561b6c515311b3b277e78b0c2b797abf18efdc0f1aeca92bbba7ba5551a63a0e4f8df4b2d6132dca22354c49d733499aa2a90608bc282fae9c93004118ec2b2eb6ad5546201074e3855de9510910e146c66e35c839edbd6001abd39a35f45924c6781d05acec8920d900708497f5b3422aac1f8e3c1a53b408ba2d2df83625623d4fe81db808d3fbded68d2fe5e142cee1de90e6925664acc4ce3a51238d8a6522bc12d51b91a436836063e4828ad31008106adefb8ce09698af9aa36ce58020000000000001976a9147a7895d0531181449490342fbdb47d0cadcb6d0088aca30c0000000000001976a914814c0a405453d28dbde44cdf37b7d3f42e9d2be188ac00000000 \ No newline at end of file From 136de32e4b3bbd5f1d3b7e8ad0e3b7168ce1bfb3 Mon Sep 17 00:00:00 2001 From: Yamaguchi Date: Mon, 10 Jun 2024 15:41:34 +0900 Subject: [PATCH 5/6] Use core crate instead of std crate --- tapyrus/src/blockdata/block.rs | 10 +++++----- tapyrus/src/blockdata/constants.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tapyrus/src/blockdata/block.rs b/tapyrus/src/blockdata/block.rs index 1803298e..d212f334 100644 --- a/tapyrus/src/blockdata/block.rs +++ b/tapyrus/src/blockdata/block.rs @@ -9,7 +9,7 @@ //! use core::fmt; -use std::str::FromStr; +use core::str::FromStr; use hashes::hex::FromHex; use hashes::{Hash, HashEngine}; @@ -227,8 +227,8 @@ impl FromStr for XField { } } -impl std::fmt::Display for XField { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl core::fmt::Display for XField { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { write!(f, "{}", serialize_hex(self)) } } @@ -252,7 +252,7 @@ impl<'de> ::serde::Deserialize<'de> for XField { impl<'de> ::serde::de::Visitor<'de> for XFieldVisitor { type Value = XField; - fn expecting(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { formatter.write_str("hex string") } @@ -260,7 +260,7 @@ impl<'de> ::serde::Deserialize<'de> for XField { where E: ::serde::de::Error, { - if let Ok(s) = ::std::str::from_utf8(v) { + if let Ok(s) = ::core::str::from_utf8(v) { XField::from_str(s).map_err(E::custom) } else { Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self)) diff --git a/tapyrus/src/blockdata/constants.rs b/tapyrus/src/blockdata/constants.rs index 300e1d3d..6c9711a6 100644 --- a/tapyrus/src/blockdata/constants.rs +++ b/tapyrus/src/blockdata/constants.rs @@ -8,7 +8,7 @@ //! use core::default::Default; -use std::str::FromStr; +use core::str::FromStr; use hashes::{sha256d, Hash}; use hex_lit::hex; From 6190d2aa3dd0351f7fbb3b725f865bc71d2394d9 Mon Sep 17 00:00:00 2001 From: Yamaguchi Date: Mon, 10 Jun 2024 18:39:22 +0900 Subject: [PATCH 6/6] Version in block header should implement std::marker::Copy --- tapyrus/src/blockdata/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tapyrus/src/blockdata/block.rs b/tapyrus/src/blockdata/block.rs index d212f334..318930c6 100644 --- a/tapyrus/src/blockdata/block.rs +++ b/tapyrus/src/blockdata/block.rs @@ -109,7 +109,7 @@ impl fmt::Debug for Header { /// /// * [BIP9 - Version bits with timeout and delay](https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki) (current usage) /// * [BIP34 - Block v2, Height in Coinbase](https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki) -#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] +#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct Version(i32);