|
6 | 6 | //! |
7 | 7 | //! ``` |
8 | 8 | //! # use bitcoin::Txid; |
9 | | -//! # use bitcoin::merkle_tree::{MerkleNode as _, TxMerkleNode}; |
| 9 | +//! # use bitcoin::merkle_tree::TxMerkleNode; |
10 | 10 | //! # let tx1 = Txid::from_byte_array([0xAA; 32]); // Arbitrary dummy hash values. |
11 | 11 | //! # let tx2 = Txid::from_byte_array([0xFF; 32]); |
12 | 12 | //! let tx_hashes = [tx1, tx2]; // All the hashes we wish to merkelize. |
|
16 | 16 |
|
17 | 17 | mod block; |
18 | 18 |
|
19 | | -use hashes::{sha256d, HashEngine as _}; |
20 | 19 | use io::{BufRead, Write}; |
21 | 20 |
|
22 | | -use crate::prelude::Vec; |
23 | | -use crate::transaction::TxIdentifier; |
24 | | -use crate::{Txid, Wtxid}; |
25 | | - |
26 | 21 | #[rustfmt::skip] |
27 | 22 | #[doc(inline)] |
28 | 23 | pub use self::block::{MerkleBlock, MerkleBlockError, PartialMerkleTree}; |
@@ -53,105 +48,3 @@ impl Decodable for WitnessMerkleNode { |
53 | 48 | Ok(Self::from_byte_array(<[u8; 32]>::consensus_decode(r)?)) |
54 | 49 | } |
55 | 50 | } |
56 | | - |
57 | | -/// A node in a Merkle tree of transactions or witness data within a block. |
58 | | -/// |
59 | | -/// This trait is used to compute the transaction Merkle root contained in |
60 | | -/// a block header. This is a particularly weird algorithm -- it interprets |
61 | | -/// the list of transactions as a balanced binary tree, duplicating branches |
62 | | -/// as needed to fill out the tree to a power of two size. |
63 | | -/// |
64 | | -/// Other Merkle trees in Bitcoin, such as those used in Taproot commitments, |
65 | | -/// do not use this algorithm and cannot use this trait. |
66 | | -pub trait MerkleNode: Copy + PartialEq { |
67 | | - /// The hash (TXID or WTXID) of a transaction in the tree. |
68 | | - type Leaf: TxIdentifier; |
69 | | - |
70 | | - /// Convert a hash to a leaf node of the tree. |
71 | | - fn from_leaf(leaf: Self::Leaf) -> Self; |
72 | | - /// Combine two nodes to get a single node. The final node of a tree is called the "root". |
73 | | - fn combine(&self, other: &Self) -> Self; |
74 | | - |
75 | | - /// Given an iterator of leaves, compute the Merkle root. |
76 | | - /// |
77 | | - /// Returns `None` if the iterator was empty, or if the transaction list contains |
78 | | - /// consecutive duplicates which would trigger CVE 2012-2459. Blocks with duplicate |
79 | | - /// transactions will always be invalid, so there is no harm in us refusing to |
80 | | - /// compute their merkle roots. |
81 | | - /// |
82 | | - /// Unless you are certain your transaction list is nonempty and has no duplicates, |
83 | | - /// you should not unwrap the `Option` returned by this method! |
84 | | - fn calculate_root<I: Iterator<Item = Self::Leaf>>(iter: I) -> Option<Self> { |
85 | | - let mut stack = Vec::<(usize, Self)>::with_capacity(32); |
86 | | - // Start with a standard Merkle tree root computation... |
87 | | - for (mut n, leaf) in iter.enumerate() { |
88 | | - stack.push((0, Self::from_leaf(leaf))); |
89 | | - |
90 | | - while n & 1 == 1 { |
91 | | - let right = stack.pop().unwrap(); |
92 | | - let left = stack.pop().unwrap(); |
93 | | - if left.1 == right.1 { |
94 | | - // Reject duplicate trees since they are guaranteed-invalid (Bitcoin does |
95 | | - // not allow duplicate transactions in block) but can be used to confuse |
96 | | - // nodes about legitimate blocks. See CVE 2012-2459 and the block comment |
97 | | - // below. |
98 | | - return None; |
99 | | - } |
100 | | - debug_assert_eq!(left.0, right.0); |
101 | | - stack.push((left.0 + 1, left.1.combine(&right.1))); |
102 | | - n >>= 1; |
103 | | - } |
104 | | - } |
105 | | - // ...then, deal with incomplete trees. Bitcoin does a weird thing in |
106 | | - // which it doubles-up nodes of the tree to fill out the tree, rather |
107 | | - // than treating incomplete branches specially. This makes this tree |
108 | | - // construction vulnerable to collisions (see CVE 2012-2459). |
109 | | - // |
110 | | - // (It is also vulnerable to collisions because it does not distinguish |
111 | | - // between internal nodes and transactions, but this collisions of this |
112 | | - // form are probably impractical. It is likely that 64-byte transactions |
113 | | - // will be forbidden in the future which will close this for good.) |
114 | | - // |
115 | | - // This is consensus logic so we cannot fix the Merkle tree construction. |
116 | | - // Instead we just have to reject the clearly-invalid half of the collision |
117 | | - // (see previous comment). |
118 | | - while stack.len() > 1 { |
119 | | - let mut right = stack.pop().unwrap(); |
120 | | - let left = stack.pop().unwrap(); |
121 | | - while right.0 != left.0 { |
122 | | - assert!(right.0 < left.0); |
123 | | - right = (right.0 + 1, right.1.combine(&right.1)); // combine with self |
124 | | - } |
125 | | - stack.push((left.0 + 1, left.1.combine(&right.1))); |
126 | | - } |
127 | | - |
128 | | - stack.pop().map(|(_, h)| h) |
129 | | - } |
130 | | -} |
131 | | - |
132 | | -// These two impl blocks are identical. FIXME once we have nailed down |
133 | | -// our hash traits, it should be possible to put bounds on `MerkleNode` |
134 | | -// and `MerkleNode::Leaf` which are sufficient to turn both methods into |
135 | | -// provided methods in the trait definition. |
136 | | -impl MerkleNode for TxMerkleNode { |
137 | | - type Leaf = Txid; |
138 | | - fn from_leaf(leaf: Self::Leaf) -> Self { Self::from_byte_array(leaf.to_byte_array()) } |
139 | | - |
140 | | - fn combine(&self, other: &Self) -> Self { |
141 | | - let mut encoder = sha256d::Hash::engine(); |
142 | | - encoder.input(self.as_byte_array()); |
143 | | - encoder.input(other.as_byte_array()); |
144 | | - Self::from_byte_array(sha256d::Hash::from_engine(encoder).to_byte_array()) |
145 | | - } |
146 | | -} |
147 | | -impl MerkleNode for WitnessMerkleNode { |
148 | | - type Leaf = Wtxid; |
149 | | - fn from_leaf(leaf: Self::Leaf) -> Self { Self::from_byte_array(leaf.to_byte_array()) } |
150 | | - |
151 | | - fn combine(&self, other: &Self) -> Self { |
152 | | - let mut encoder = sha256d::Hash::engine(); |
153 | | - encoder.input(self.as_byte_array()); |
154 | | - encoder.input(other.as_byte_array()); |
155 | | - Self::from_byte_array(sha256d::Hash::from_engine(encoder).to_byte_array()) |
156 | | - } |
157 | | -} |
0 commit comments