1use crate::error::TaprootError;
6use crate::tagged_hash::TapNodeHash;
7use crate::taptree::{LeafVersion, TapLeaf, TapTree};
8use crate::xonly::{Parity, XOnlyPublicKey};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
12pub struct ControlBlock {
13 pub leaf_version: LeafVersion,
15 pub output_key_parity: Parity,
17 pub internal_key: XOnlyPublicKey,
19 pub merkle_path: Vec<TapNodeHash>,
21}
22
23impl ControlBlock {
24 pub fn new(
26 leaf_version: LeafVersion,
27 output_key_parity: Parity,
28 internal_key: XOnlyPublicKey,
29 merkle_path: Vec<TapNodeHash>,
30 ) -> Self {
31 Self {
32 leaf_version,
33 output_key_parity,
34 internal_key,
35 merkle_path,
36 }
37 }
38
39 pub fn for_leaf(
41 tree: &TapTree,
42 leaf: &TapLeaf,
43 internal_key: XOnlyPublicKey,
44 output_key_parity: Parity,
45 ) -> Result<Self, TaprootError> {
46 let merkle_path = tree
47 .merkle_path(leaf)
48 .ok_or(TaprootError::InvalidMerklePath)?;
49
50 Ok(Self {
51 leaf_version: leaf.version,
52 output_key_parity,
53 internal_key,
54 merkle_path,
55 })
56 }
57
58 pub fn serialize(&self) -> Vec<u8> {
60 let mut bytes = Vec::with_capacity(33 + self.merkle_path.len() * 32);
61
62 let first_byte = self.leaf_version.0 | self.output_key_parity.to_u8();
64 bytes.push(first_byte);
65
66 bytes.extend_from_slice(&self.internal_key.serialize());
68
69 for hash in &self.merkle_path {
71 bytes.extend_from_slice(hash.as_bytes());
72 }
73
74 bytes
75 }
76
77 pub fn from_slice(data: &[u8]) -> Result<Self, TaprootError> {
79 if data.len() < 33 {
80 return Err(TaprootError::InvalidControlBlock(
81 "Control block too short".into(),
82 ));
83 }
84
85 if !(data.len() - 33).is_multiple_of(32) {
86 return Err(TaprootError::InvalidControlBlock(
87 "Invalid merkle path length".into(),
88 ));
89 }
90
91 let first_byte = data[0];
92 let leaf_version = LeafVersion(first_byte & 0xfe);
93 let output_key_parity = Parity::from_u8(first_byte & 0x01)?;
94
95 let internal_key = XOnlyPublicKey::from_slice(&data[1..33])?;
96
97 let path_count = (data.len() - 33) / 32;
98 let mut merkle_path = Vec::with_capacity(path_count);
99 for i in 0..path_count {
100 let start = 33 + i * 32;
101 let mut hash = [0u8; 32];
102 hash.copy_from_slice(&data[start..start + 32]);
103 merkle_path.push(TapNodeHash::from_bytes(hash));
104 }
105
106 Ok(Self {
107 leaf_version,
108 output_key_parity,
109 internal_key,
110 merkle_path,
111 })
112 }
113
114 pub fn verify(
116 &self,
117 output_key: &XOnlyPublicKey,
118 script: &[u8],
119 ) -> Result<bool, TaprootError> {
120 use crate::tweak::tweak_public_key;
121
122 let leaf_hash = crate::tagged_hash::TapLeafHash::from_script(
124 self.leaf_version.0,
125 script,
126 );
127
128 let mut current = TapNodeHash::from_leaf(leaf_hash);
130 for sibling in &self.merkle_path {
131 current = TapNodeHash::from_children(¤t, sibling);
132 }
133
134 let (expected_output, expected_parity) = tweak_public_key(
136 &self.internal_key,
137 Some(¤t),
138 )?;
139
140 Ok(expected_output == *output_key && expected_parity == self.output_key_parity)
142 }
143
144 pub fn size(&self) -> usize {
146 33 + self.merkle_path.len() * 32
147 }
148
149 pub fn depth(&self) -> usize {
151 self.merkle_path.len()
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::taptree::two_leaf_tree;
159 use crate::tweak::tweak_public_key;
160 use secp256k1::{Secp256k1, SecretKey};
161
162 fn get_test_internal_key() -> XOnlyPublicKey {
163 let secp = Secp256k1::new();
164 let secret = [
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
169 ];
170 let sk = SecretKey::from_slice(&secret).unwrap();
171 let pk = sk.public_key(&secp);
172 let (xonly, _) = pk.x_only_public_key();
173 XOnlyPublicKey::from_inner(xonly)
174 }
175
176 #[test]
177 fn test_control_block_roundtrip() {
178 let internal_key = get_test_internal_key();
179 let merkle_path = vec![TapNodeHash::from_bytes([0x42; 32])];
180
181 let cb = ControlBlock::new(
182 LeafVersion::TAPSCRIPT,
183 Parity::Even,
184 internal_key,
185 merkle_path,
186 );
187
188 let bytes = cb.serialize();
189 let parsed = ControlBlock::from_slice(&bytes).unwrap();
190
191 assert_eq!(cb.leaf_version, parsed.leaf_version);
192 assert_eq!(cb.output_key_parity, parsed.output_key_parity);
193 assert_eq!(cb.internal_key, parsed.internal_key);
194 assert_eq!(cb.merkle_path, parsed.merkle_path);
195 }
196
197 #[test]
198 fn test_control_block_size() {
199 let internal_key = get_test_internal_key();
200
201 let cb = ControlBlock::new(
203 LeafVersion::TAPSCRIPT,
204 Parity::Even,
205 internal_key,
206 vec![],
207 );
208 assert_eq!(cb.size(), 33);
209
210 let cb = ControlBlock::new(
212 LeafVersion::TAPSCRIPT,
213 Parity::Even,
214 internal_key,
215 vec![TapNodeHash::from_bytes([0; 32])],
216 );
217 assert_eq!(cb.size(), 65);
218 }
219
220 #[test]
221 fn test_control_block_verify() {
222 let internal_key = get_test_internal_key();
223 let script1 = vec![0x51]; let script2 = vec![0x52]; let tree = two_leaf_tree(script1.clone(), script2);
227 let merkle_root = tree.root_hash();
228
229 let (output_key, parity) = tweak_public_key(&internal_key, Some(&merkle_root)).unwrap();
230
231 let leaf = crate::taptree::TapLeaf::new(script1.clone());
232 let cb = ControlBlock::for_leaf(&tree, &leaf, internal_key, parity).unwrap();
233
234 assert!(cb.verify(&output_key, &script1).unwrap());
235 }
236
237 #[test]
238 fn test_first_byte_encoding() {
239 let internal_key = get_test_internal_key();
240
241 let cb = ControlBlock::new(
243 LeafVersion::TAPSCRIPT,
244 Parity::Even,
245 internal_key,
246 vec![],
247 );
248 let bytes = cb.serialize();
249 assert_eq!(bytes[0], 0xc0); let cb = ControlBlock::new(
253 LeafVersion::TAPSCRIPT,
254 Parity::Odd,
255 internal_key,
256 vec![],
257 );
258 let bytes = cb.serialize();
259 assert_eq!(bytes[0], 0xc1); }
261}