Merge rust-bitcoin/rust-bitcoin#1351: Improve block version

248f9a3b4b Use capital letters for Bitcoin Core (Tobin C. Harding)
832169eb8d Add to/from_consensus methods to Version type (Tobin C. Harding)
24984f095f Make block::Version inner value private (Tobin C. Harding)
7e146ede96 Make types in block module more terse (Tobin C. Harding)

Pull request description:

  After initial attempt and review this PR has been re-written.

  - Patch 1: Make types in `block` more terse, this is preparatory clean up based on suggestion below.
  - Patch 2: Make inner value of `Version` private to hide the i32/u32 discrepancy

  This is a follow up to #1240

ACKs for top commit:
  Kixunil:
    ACK 248f9a3b4b
  apoelstra:
    ACK 248f9a3b4b

Tree-SHA512: ee031035288a2bcc246a9837a6028c254c51daf78a5cc2441b467ab7f183f1700a63911a2e78b84a20674ce0a83851a7c3bb7e46644a56fdd255685b9a0bf7f2
This commit is contained in:
Andrew Poelstra 2022-11-06 14:16:36 +00:00
commit 4bce69db27
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
10 changed files with 84 additions and 63 deletions

View File

@ -16,7 +16,7 @@ use crate::consensus::encode::{self, Decodable, Encodable, VarInt};
use crate::hashes::{sha256, siphash24, Hash};
use crate::internal_macros::{impl_bytes_newtype, impl_consensus_encoding};
use crate::prelude::*;
use crate::{io, Block, BlockHash, BlockHeader, Transaction};
use crate::{io, block, Block, BlockHash, Transaction};
/// A BIP-152 error
#[derive(Clone, PartialEq, Eq, Debug, Copy, PartialOrd, Ord, Hash)]
@ -100,7 +100,7 @@ impl_bytes_newtype!(ShortId, 6);
impl ShortId {
/// Calculate the SipHash24 keys used to calculate short IDs.
pub fn calculate_siphash_keys(header: &BlockHeader, nonce: u64) -> (u64, u64) {
pub fn calculate_siphash_keys(header: &block::Header, nonce: u64) -> (u64, u64) {
// 1. single-SHA256 hashing the block header with the nonce appended (in little-endian)
let h = {
let mut engine = sha256::Hash::engine();
@ -147,7 +147,7 @@ impl Decodable for ShortId {
#[derive(PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
pub struct HeaderAndShortIds {
/// The header of the block being provided.
pub header: BlockHeader,
pub header: block::Header,
/// A nonce for use in short transaction ID calculations.
pub nonce: u64,
/// The short transaction IDs calculated from the transactions
@ -374,7 +374,7 @@ mod test {
use crate::consensus::encode::{deserialize, serialize};
use crate::hashes::hex::FromHex;
use crate::{
Block, BlockHash, BlockHeader, BlockVersion, CompactTarget, OutPoint, Script, Sequence,
CompactTarget, OutPoint, Script, Sequence,
Transaction, TxIn, TxMerkleNode, TxOut, Txid, Witness,
};
@ -394,8 +394,8 @@ mod test {
fn dummy_block() -> Block {
Block {
header: BlockHeader {
version: BlockVersion(1),
header: block::Header {
version: block::Version::ONE,
prev_blockhash: BlockHash::hash(&[0]),
merkle_root: TxMerkleNode::hash(&[1]),
time: 2,

View File

@ -16,7 +16,7 @@ use core::fmt;
use crate::{merkle_tree, util};
use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork};
use crate::hashes::{Hash, HashEngine};
use crate::hash_types::{Wtxid, BlockHash, TxMerkleNode, WitnessMerkleNode, WitnessCommitment};
use crate::hash_types::{Wtxid, TxMerkleNode, WitnessMerkleNode, WitnessCommitment};
use crate::consensus::{encode, Encodable, Decodable};
use crate::blockdata::transaction::Transaction;
use crate::blockdata::constants::WITNESS_SCALE_FACTOR;
@ -26,6 +26,8 @@ use crate::VarInt;
use crate::internal_macros::impl_consensus_encoding;
use crate::io;
pub use crate::hash_types::BlockHash;
/// Bitcoin block header.
///
/// Contains all the block's information except the actual transactions, but
@ -39,9 +41,9 @@ use crate::io;
#[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 BlockHeader {
pub struct Header {
/// Block version, now repurposed for soft fork signalling.
pub version: BlockVersion,
pub version: Version,
/// Reference to the previous block in the chain.
pub prev_blockhash: BlockHash,
/// The root hash of the merkle tree of transactions in the block.
@ -54,9 +56,9 @@ pub struct BlockHeader {
pub nonce: u32,
}
impl_consensus_encoding!(BlockHeader, version, prev_blockhash, merkle_root, time, bits, nonce);
impl_consensus_encoding!(Header, version, prev_blockhash, merkle_root, time, bits, nonce);
impl BlockHeader {
impl Header {
/// Returns the block hash.
pub fn block_hash(&self) -> BlockHash {
let mut engine = BlockHash::engine();
@ -110,18 +112,40 @@ impl BlockHeader {
#[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 BlockVersion(pub i32);
pub struct Version(i32);
impl Version {
/// The original Bitcoin Block v1.
pub const ONE: Self = Self(1);
/// BIP-34 Block v2.
pub const TWO: Self = Self(2);
impl BlockVersion {
/// BIP-9 compatible version number that does not signal for any softforks.
pub const NO_SOFT_FORK_SIGNALLING: Self = Self(Self::USE_VERSION_BITS as i32);
/// BIP-9 soft fork signal bits mask.
const VERSION_BITS_MASK: u32 = 0x1FFF_FFFF;
/// 32bit value starting with `001` to use version bits.
///
/// The value has the top three bits `001` which enables the use of version bits to signal for soft forks.
const USE_VERSION_BITS: u32 = 0x2000_0000;
/// Creates a [`Version`] from a signed 32 bit integer value.
///
/// This is the data type used in consensus code in Bitcoin Core.
pub fn from_consensus(v: i32) -> Self {
Version(v)
}
/// Returns the inner `i32` value.
///
/// This is the data type used in consensus code in Bitcoin Core.
pub fn to_consensus(self) -> i32 {
self.0
}
/// Check whether the version number is signalling a soft fork at the given bit.
///
/// A block is signalling for a soft fork under BIP-9 if the first 3 bits are `001` and
@ -142,21 +166,21 @@ impl BlockVersion {
}
}
impl Default for BlockVersion {
fn default() -> BlockVersion {
impl Default for Version {
fn default() -> Version {
Self::NO_SOFT_FORK_SIGNALLING
}
}
impl Encodable for BlockVersion {
impl Encodable for Version {
fn consensus_encode<W: io::Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
self.0.consensus_encode(w)
}
}
impl Decodable for BlockVersion {
impl Decodable for Version {
fn consensus_decode<R: io::Read + ?Sized>(r: &mut R) -> Result<Self, encode::Error> {
Decodable::consensus_decode(r).map(BlockVersion)
Decodable::consensus_decode(r).map(Version)
}
}
@ -176,7 +200,7 @@ impl Decodable for BlockVersion {
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct Block {
/// The block header
pub header: BlockHeader,
pub header: Header,
/// List of transactions contained in the block
pub txdata: Vec<Transaction>
}
@ -300,7 +324,7 @@ impl Block {
// number (including a sign bit). Height is the height of the mined
// block in the block chain, where the genesis block is height zero (0).
if self.header.version < BlockVersion(2) {
if self.header.version < Version::TWO {
return Err(Bip34Error::Unsupported);
}
@ -364,14 +388,14 @@ impl std::error::Error for Bip34Error {
}
}
impl From<BlockHeader> for BlockHash {
fn from(header: BlockHeader) -> BlockHash {
impl From<Header> for BlockHash {
fn from(header: Header) -> BlockHash {
header.block_hash()
}
}
impl From<&BlockHeader> for BlockHash {
fn from(header: &BlockHeader) -> BlockHash {
impl From<&Header> for BlockHash {
fn from(header: &Header) -> BlockHash {
header.block_hash()
}
}
@ -393,10 +417,7 @@ mod tests {
use super::*;
use crate::hashes::hex::FromHex;
use crate::blockdata::block::{Block, BlockHeader, BlockVersion};
use crate::consensus::encode::{deserialize, serialize};
use crate::util::Error::{BlockBadTarget, BlockBadProofOfWork};
#[test]
fn test_coinbase_and_bip34() {
@ -434,7 +455,7 @@ mod tests {
assert!(decode.is_ok());
assert!(bad_decode.is_err());
let real_decode = decode.unwrap();
assert_eq!(real_decode.header.version, BlockVersion(1));
assert_eq!(real_decode.header.version, Version(1));
assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash);
assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap());
assert_eq!(serialize(&real_decode.header.merkle_root), merkle);
@ -469,7 +490,7 @@ mod tests {
assert!(decode.is_ok());
let real_decode = decode.unwrap();
assert_eq!(real_decode.header.version, BlockVersion(BlockVersion::USE_VERSION_BITS as i32)); // VERSIONBITS but no bits set
assert_eq!(real_decode.header.version, Version(Version::USE_VERSION_BITS as i32)); // VERSIONBITS but no bits set
assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash);
assert_eq!(serialize(&real_decode.header.merkle_root), merkle);
assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap());
@ -496,19 +517,19 @@ mod tests {
let decode: Result<Block, _> = deserialize(&block);
assert!(decode.is_ok());
let real_decode = decode.unwrap();
assert_eq!(real_decode.header.version, BlockVersion(2147483647));
assert_eq!(real_decode.header.version, Version(2147483647));
let block2 = Vec::from_hex("000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let decode2: Result<Block, _> = deserialize(&block2);
assert!(decode2.is_ok());
let real_decode2 = decode2.unwrap();
assert_eq!(real_decode2.header.version, BlockVersion(-2147483648));
assert_eq!(real_decode2.header.version, Version(-2147483648));
}
#[test]
fn validate_pow_test() {
let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap();
let some_header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header");
let some_header: Header = deserialize(&some_header).expect("Can't deserialize correct block header");
assert_eq!(some_header.validate_pow(some_header.target()).unwrap(), some_header.block_hash());
// test with zero target
@ -518,7 +539,7 @@ mod tests {
}
// test with modified header
let mut invalid_header: BlockHeader = some_header;
let mut invalid_header: Header = some_header;
invalid_header.version.0 += 1;
match invalid_header.validate_pow(invalid_header.target()) {
Err(BlockBadProofOfWork) => (),
@ -530,7 +551,7 @@ mod tests {
fn compact_roundrtip_test() {
let some_header = Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap();
let header: BlockHeader = deserialize(&some_header).expect("Can't deserialize correct block header");
let header: Header = deserialize(&some_header).expect("Can't deserialize correct block header");
assert_eq!(header.bits, header.target().to_compact_lossy());
}
@ -539,7 +560,7 @@ mod tests {
fn soft_fork_signalling() {
for i in 0..31 {
let version_int = (0x20000000u32 ^ 1<<i) as i32;
let version = BlockVersion(version_int);
let version = Version(version_int);
if i < 29 {
assert!(version.is_signalling_soft_fork(i));
} else {
@ -547,7 +568,7 @@ mod tests {
}
}
let segwit_signal = BlockVersion(0x20000000 ^ 1<<1);
let segwit_signal = Version(0x20000000 ^ 1<<1);
assert!(!segwit_signal.is_signalling_soft_fork(0));
assert!(segwit_signal.is_signalling_soft_fork(1));
assert!(!segwit_signal.is_signalling_soft_fork(2));

View File

@ -20,7 +20,7 @@ use crate::blockdata::script;
use crate::blockdata::opcodes::all::*;
use crate::blockdata::locktime::absolute;
use crate::blockdata::transaction::{OutPoint, Transaction, TxOut, TxIn, Sequence};
use crate::blockdata::block::{Block, BlockHeader, BlockVersion};
use crate::blockdata::block::{self, Block};
use crate::blockdata::witness::Witness;
use crate::network::constants::Network;
use crate::pow::CompactTarget;
@ -111,8 +111,8 @@ pub fn genesis_block(network: Network) -> Block {
match network {
Network::Bitcoin => {
Block {
header: BlockHeader {
version: BlockVersion(1),
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1231006505,
@ -124,8 +124,8 @@ pub fn genesis_block(network: Network) -> Block {
}
Network::Testnet => {
Block {
header: BlockHeader {
version: BlockVersion(1),
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1296688602,
@ -137,8 +137,8 @@ pub fn genesis_block(network: Network) -> Block {
}
Network::Signet => {
Block {
header: BlockHeader {
version: BlockVersion(1),
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1598918400,
@ -150,8 +150,8 @@ pub fn genesis_block(network: Network) -> Block {
}
Network::Regtest => {
Block {
header: BlockHeader {
version: BlockVersion(1),
header: block::Header {
version: block::Version::ONE,
prev_blockhash: Hash::all_zeros(),
merkle_root,
time: 1296688602,
@ -224,7 +224,7 @@ mod test {
fn bitcoin_genesis_full_block() {
let gen = genesis_block(Network::Bitcoin);
assert_eq!(gen.header.version, BlockVersion(1));
assert_eq!(gen.header.version, block::Version::ONE);
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
@ -237,7 +237,7 @@ mod test {
#[test]
fn testnet_genesis_full_block() {
let gen = genesis_block(Network::Testnet);
assert_eq!(gen.header.version, BlockVersion(1));
assert_eq!(gen.header.version, block::Version::ONE);
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
assert_eq!(gen.header.time, 1296688602);
@ -249,7 +249,7 @@ mod test {
#[test]
fn signet_genesis_full_block() {
let gen = genesis_block(Network::Signet);
assert_eq!(gen.header.version, BlockVersion(1));
assert_eq!(gen.header.version, block::Version::ONE);
assert_eq!(gen.header.prev_blockhash, Hash::all_zeros());
assert_eq!(gen.header.merkle_root.to_hex(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b");
assert_eq!(gen.header.time, 1598918400);

View File

@ -318,7 +318,7 @@ pub fn read_scriptint(v: &[u8]) -> Result<i64, Error> {
Some(last) => last,
None => return Ok(0),
};
// Comment and code copied from bitcoin core:
// Comment and code copied from Bitcoin Core:
// https://github.com/bitcoin/bitcoin/blob/447f50e4aed9a8b1d80e1891cda85801aeb80b4e/src/script/script.h#L247-L262
// If the most-significant-byte - excluding the sign bit - is zero
// then we're not minimal. Note how this test also rejects the

View File

@ -115,7 +115,7 @@ use std::io;
use core2::io;
pub use crate::address::{Address, AddressType};
pub use crate::blockdata::block::{self, Block, BlockHeader, BlockVersion};
pub use crate::blockdata::block::{self, Block};
pub use crate::blockdata::locktime::{self, absolute, relative};
pub use crate::blockdata::script::{self, Script};
pub use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut};

View File

@ -182,7 +182,7 @@ pub enum NetworkMessage {
/// `block`
Block(block::Block),
/// `headers`
Headers(Vec<block::BlockHeader>),
Headers(Vec<block::Header>),
/// `sendheaders`
SendHeaders,
/// `getaddr`
@ -317,7 +317,7 @@ impl RawNetworkMessage {
}
}
struct HeaderSerializationWrapper<'a>(&'a Vec<block::BlockHeader>);
struct HeaderSerializationWrapper<'a>(&'a Vec<block::Header>);
impl<'a> Encodable for HeaderSerializationWrapper<'a> {
#[inline]
@ -380,7 +380,7 @@ impl Encodable for RawNetworkMessage {
}
}
struct HeaderDeserializationWrapper(Vec<block::BlockHeader>);
struct HeaderDeserializationWrapper(Vec<block::Header>);
impl Decodable for HeaderDeserializationWrapper {
#[inline]
@ -479,7 +479,7 @@ mod test {
use crate::network::address::{Address, AddrV2, AddrV2Message};
use super::message_network::{Reject, RejectReason, VersionMessage};
use crate::network::message_blockdata::{Inventory, GetBlocksMessage, GetHeadersMessage};
use crate::blockdata::block::{Block, BlockHeader};
use crate::blockdata::block::{self, Block};
use crate::network::message_filter::{GetCFilters, CFilter, GetCFHeaders, CFHeaders, GetCFCheckpt, CFCheckpt};
use crate::blockdata::transaction::Transaction;
use crate::blockdata::script::Script;
@ -498,7 +498,7 @@ mod test {
let version_msg: VersionMessage = deserialize(&Vec::from_hex("721101000100000000000000e6e0845300000000010000000000000000000000000000000000ffff0000000000000100000000000000fd87d87eeb4364f22cf54dca59412db7208d47d920cffce83ee8102f5361746f7368693a302e392e39392f2c9f040001").unwrap()).unwrap();
let tx: Transaction = deserialize(&Vec::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap()).unwrap();
let block: Block = deserialize(&include_bytes!("../../tests/data/testnet_block_000000000000045e0b1660b6445b5e5c5ab63c9a4f956be7e1e69be04fa4497b.raw")[..]).unwrap();
let header: BlockHeader = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap();
let header: block::Header = deserialize(&Vec::from_hex("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b").unwrap()).unwrap();
let script: Script = deserialize(&Vec::from_hex("1976a91431a420903c05a0a7de2de40c9f02ebedbacdc17288ac").unwrap()).unwrap();
let merkle_block: MerkleBlock = deserialize(&Vec::from_hex("0100000079cda856b143d9db2c1caff01d1aecc8630d30625d10e8b4b8b0000000000000b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f196367291b4d4c86041b8fa45d630100000001b50cc069d6a3e33e3ff84a5c41d9d3febe7c770fdcc96b2c3ff60abe184f19630101").unwrap()).unwrap();
let cmptblock = deserialize(&Vec::from_hex("00000030d923ad36ff2d955abab07f8a0a6e813bc6e066b973e780c5e36674cad5d1cd1f6e265f2a17a0d35cbe701fe9d06e2c6324cfe135f6233e8b767bfa3fb4479b71115dc562ffff7f2006000000000000000000000000010002000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0302ee00ffffffff0100f9029500000000015100000000").unwrap()).unwrap();

View File

@ -237,7 +237,7 @@ impl Target {
/// `0xffff_ffff_ffff_ffff_ffff_ffff` `difficulty()` will saturate at `u128::MAX`.
///
/// [max]: Target::max
/// [target]: crate::blockdata::block::BlockHeader::target
/// [target]: crate::blockdata::block::Header::target
pub fn difficulty(&self) -> u128 {
let d = Target::MAX.0 / self.0;
d.saturating_to_u128()

View File

@ -1152,7 +1152,7 @@ mod tests {
#[test]
fn test_sighashes_keyspending() {
// following test case has been taken from bitcoin core test framework
// following test case has been taken from Bitcoin Core test framework
test_taproot_sighash(
"020000000164eb050a5e3da0c2a65e4786f26d753b7bc69691fabccafb11f7acef36641f1846010000003101b2b404392a22000000000017a9147f2bde86fe78bf68a0544a4f290e12f0b7e0a08c87580200000000000017a91425d11723074ecfb96a0a83c3956bfaf362ae0c908758020000000000001600147e20f938993641de67bb0cdd71682aa34c4d29ad5802000000000000160014c64984dc8761acfa99418bd6bedc79b9287d652d72000000",

View File

@ -49,11 +49,11 @@ use crate::io;
use crate::hashes::Hash;
use crate::hash_types::{Txid, TxMerkleNode};
use crate::blockdata::block::{self, Block};
use crate::blockdata::transaction::Transaction;
use crate::blockdata::constants::{MAX_BLOCK_WEIGHT, MIN_TRANSACTION_WEIGHT};
use crate::consensus::encode::{self, Decodable, Encodable};
use crate::util::merkleblock::MerkleBlockError::*;
use crate::{Block, BlockHeader};
/// An error when verifying the merkle block.
#[derive(Clone, PartialEq, Eq, Debug)]
@ -408,7 +408,7 @@ impl Decodable for PartialMerkleTree {
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct MerkleBlock {
/// The block header
pub header: BlockHeader,
pub header: block::Header,
/// Transactions making up a partial merkle tree
pub txn: PartialMerkleTree,
}
@ -464,7 +464,7 @@ impl MerkleBlock {
/// The `header` is the block header, `block_txids` is the full list of txids included in the block and
/// `match_txids` is a function that returns true for the ids that should be included in the partial merkle tree.
pub fn from_header_txids_with_predicate<F>(
header: &BlockHeader,
header: &block::Header,
block_txids: &[Txid],
match_txids: F,
) -> Self

View File

@ -336,12 +336,12 @@ impl From<&TaprootSpendInfo> for TapTweakHash {
/// in a depth-first search (DFS) walk order to construct this tree.
///
/// See Wikipedia for more details on [DFS](https://en.wikipedia.org/wiki/Depth-first_search).
// Similar to Taproot Builder in bitcoin core.
// Similar to Taproot Builder in Bitcoin Core.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct TaprootBuilder {
// The following doc-comment is from bitcoin core, but modified for Rust. It describes the
// The following doc-comment is from Bitcoin Core, but modified for Rust. It describes the
// current state of the builder for a given tree.
//
// For each level in the tree, one NodeInfo object may be present. Branch at index 0 is
@ -1248,7 +1248,7 @@ mod test {
#[test]
fn control_block_verify() {
let secp = Secp256k1::verification_only();
// test vectors obtained from printing values in feature_taproot.py from bitcoin core
// test vectors obtained from printing values in feature_taproot.py from Bitcoin Core
_verify_tap_commitments(&secp, "51205dc8e62b15e0ebdf44751676be35ba32eed2e84608b290d4061bbff136cd7ba9", "6a", "c1a9d6f66cd4b25004f526bfa873e56942f98e8e492bd79ed6532b966104817c2bda584e7d32612381cf88edc1c02e28a296e807c16ad22f591ee113946e48a71e0641e660d1e5392fb79d64838c2b84faf04b7f5f283c9d8bf83e39e177b64372a0cd22eeab7e093873e851e247714eff762d8a30be699ba4456cfe6491b282e193a071350ae099005a5950d74f73ba13077a57bc478007fb0e4d1099ce9cf3d4");
_verify_tap_commitments(&secp, "5120e208c869c40d8827101c5ad3238018de0f3f5183d77a0c53d18ac28ddcbcd8ad", "f4", "c0a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f40090ab1f4890d51115998242ebce636efb9ede1b516d9eb8952dc1068e0335306199aaf103cceb41d9bc37ec231aca89b984b5fd3c65977ce764d51033ac65adb4da14e029b1e154a85bfd9139e7aa2720b6070a4ceba8264ca61d5d3ac27aceb9ef4b54cd43c2d1fd5e11b5c2e93cf29b91ea3dc5b832201f02f7473a28c63246");
_verify_tap_commitments(&secp, "5120567666e7df90e0450bb608e17c01ed3fbcfa5355a5f8273e34e583bfaa70ce09", "203455139bf238a3067bd72ed77e0ab8db590330f55ed58dba7366b53bf4734279ac", "c1a0eb12e60a52614986c623cbb6621dcdba3a47e3be6b37e032b7a11c7b98f400");