1
2use bitcoin::absolute::LockTime;
3use bitcoin::hashes::sha256;
4use bitcoin::key::constants::SCHNORR_SIGNATURE_SIZE;
5use bitcoin::secp256k1::schnorr;
6use bitcoin::taproot::{self, ControlBlock};
7use bitcoin::{Sequence, VarInt, Witness};
8use bitcoin::{secp256k1::PublicKey, ScriptBuf};
9
10use bitcoin_ext::{BlockDelta, BlockHeight};
11
12use crate::vtxo::policy::Policy;
13use crate::Vtxo;
14use crate::scripts;
15
16pub trait TapScriptClause: Sized + Clone {
21 type WitnessData;
23
24 fn tapscript(&self) -> ScriptBuf;
26
27 fn control_block<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> ControlBlock {
29 vtxo.output_taproot()
30 .control_block(&(self.tapscript(), taproot::LeafVersion::TapScript))
31 .expect("clause is not in taproot tree")
32 }
33
34 fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize;
36
37 fn witness(
39 &self,
40 data: &Self::WitnessData,
41 control_block: &ControlBlock,
42 ) -> Witness;
43}
44
45#[derive(Debug, Clone)]
48pub struct DelayedSignClause {
49 pub pubkey: PublicKey,
50 pub block_delta: BlockDelta,
51}
52
53impl DelayedSignClause {
54 pub fn sequence(&self) -> Sequence {
56 Sequence::from_height(self.block_delta)
57 }
58}
59
60impl TapScriptClause for DelayedSignClause {
61 type WitnessData = schnorr::Signature;
62
63 fn tapscript(&self) -> ScriptBuf {
64 scripts::delayed_sign(self.block_delta, self.pubkey.x_only_public_key().0)
65 }
66
67 fn witness(
68 &self,
69 signature: &Self::WitnessData,
70 control_block: &ControlBlock,
71 ) -> Witness {
72 Witness::from_slice(&[
73 &signature[..],
74 self.tapscript().as_bytes(),
75 &control_block.serialize()[..],
76 ])
77 }
78
79
80 fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize {
81 let cb_size = self.control_block(vtxo).size();
82 let tapscript_size = self.tapscript().as_bytes().len();
83
84 1 + 1 + SCHNORR_SIGNATURE_SIZE + VarInt::from(tapscript_size).size() + tapscript_size + VarInt::from(cb_size).size() + cb_size }
92}
93
94impl Into<VtxoClause> for DelayedSignClause {
95 fn into(self) -> VtxoClause {
96 VtxoClause::DelayedSign(self)
97 }
98}
99
100#[derive(Debug, Clone)]
103pub struct TimelockSignClause {
104 pub pubkey: PublicKey,
105 pub timelock_height: BlockHeight,
106}
107
108impl TimelockSignClause {
109 pub fn locktime(&self) -> LockTime {
111 LockTime::from_height(self.timelock_height).expect("timelock height is valid")
112 }
113}
114
115impl TapScriptClause for TimelockSignClause {
116 type WitnessData = schnorr::Signature;
117
118 fn tapscript(&self) -> ScriptBuf {
119 scripts::timelock_sign(self.timelock_height, self.pubkey.x_only_public_key().0)
120 }
121
122 fn witness(
123 &self,
124 signature: &Self::WitnessData,
125 control_block: &ControlBlock,
126 ) -> Witness {
127 Witness::from_slice(&[
128 &signature[..],
129 self.tapscript().as_bytes(),
130 &control_block.serialize()[..],
131 ])
132 }
133
134 fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize {
135 let cb_size = self.control_block(vtxo).size();
136 let tapscript_size = self.tapscript().as_bytes().len();
137
138 1 + 1 + SCHNORR_SIGNATURE_SIZE + VarInt::from(tapscript_size).size() + tapscript_size + VarInt::from(cb_size).size() + cb_size }
146}
147
148impl Into<VtxoClause> for TimelockSignClause {
149 fn into(self) -> VtxoClause {
150 VtxoClause::TimelockSign(self)
151 }
152}
153
154#[derive(Debug, Clone)]
157pub struct DelayedTimelockSignClause {
158 pub pubkey: PublicKey,
159 pub timelock_height: BlockHeight,
160 pub block_delta: BlockDelta,
161}
162
163impl DelayedTimelockSignClause {
164 pub fn sequence(&self) -> Sequence {
166 Sequence::from_height(self.block_delta)
167 }
168
169 pub fn locktime(&self) -> LockTime {
171 LockTime::from_height(self.timelock_height).expect("timelock height is valid")
172 }
173}
174
175impl TapScriptClause for DelayedTimelockSignClause {
176 type WitnessData = schnorr::Signature;
177
178 fn tapscript(&self) -> ScriptBuf {
179 scripts::delay_timelock_sign(
180 self.block_delta,
181 self.timelock_height,
182 self.pubkey.x_only_public_key().0,
183 )
184 }
185
186 fn witness(
187 &self,
188 signature: &Self::WitnessData,
189 control_block: &ControlBlock,
190 ) -> Witness {
191 Witness::from_slice(&[
192 &signature[..],
193 self.tapscript().as_bytes(),
194 &control_block.serialize()[..],
195 ])
196 }
197
198 fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize {
199 let cb_size = self.control_block(vtxo).size();
200 let tapscript_size = self.tapscript().as_bytes().len();
201
202 1 + 1 + SCHNORR_SIGNATURE_SIZE + VarInt::from(tapscript_size).size() + tapscript_size + VarInt::from(cb_size).size() + cb_size }
210}
211
212impl Into<VtxoClause> for DelayedTimelockSignClause {
213 fn into(self) -> VtxoClause {
214 VtxoClause::DelayedTimelockSign(self)
215 }
216}
217
218#[derive(Debug, Clone)]
221pub struct HashDelaySignClause {
222 pub pubkey: PublicKey,
223 pub hash: sha256::Hash,
224 pub block_delta: BlockDelta,
225}
226
227impl HashDelaySignClause {
228 pub fn sequence(&self) -> Sequence {
230 Sequence::from_height(self.block_delta)
231 }
232}
233
234impl TapScriptClause for HashDelaySignClause {
235 type WitnessData = (schnorr::Signature, [u8; 32]);
236
237 fn tapscript(&self) -> ScriptBuf {
238 scripts::hash_delay_sign(
239 self.hash,
240 self.block_delta,
241 self.pubkey.x_only_public_key().0,
242 )
243 }
244
245 fn witness(
246 &self,
247 data: &Self::WitnessData,
248 control_block: &ControlBlock,
249 ) -> Witness {
250 let (signature, preimage) = data;
251 Witness::from_slice(&[
252 &signature[..],
253 &preimage[..],
254 self.tapscript().as_bytes(),
255 &control_block.serialize()[..],
256 ])
257 }
258
259 fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize {
260 let cb_size = self.control_block(vtxo).size();
261 let tapscript_size = self.tapscript().as_bytes().len();
262
263 1 + 1 + SCHNORR_SIGNATURE_SIZE + 1 + 32 + VarInt::from(tapscript_size).size() + tapscript_size + VarInt::from(cb_size).size() + cb_size }
273}
274
275impl Into<VtxoClause> for HashDelaySignClause {
276 fn into(self) -> VtxoClause {
277 VtxoClause::HashDelaySign(self)
278 }
279}
280
281#[derive(Debug, Clone)]
286pub struct HashSignClause {
287 pub pubkey: PublicKey,
288 pub hash: sha256::Hash,
289}
290
291impl TapScriptClause for HashSignClause {
292 type WitnessData = (schnorr::Signature, [u8; 32]);
293
294 fn tapscript(&self) -> ScriptBuf {
295 scripts::hash_and_sign(self.hash, self.pubkey.x_only_public_key().0)
296 }
297
298 fn witness(
299 &self,
300 data: &Self::WitnessData,
301 control_block: &ControlBlock,
302 ) -> Witness {
303 let (signature, preimage) = data;
304 Witness::from_slice(&[
305 &signature[..],
306 &preimage[..],
307 self.tapscript().as_bytes(),
308 &control_block.serialize()[..],
309 ])
310 }
311
312 fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize {
313 let cb_size = self.control_block(vtxo).size();
314 let tapscript_size = 57;
315
316 debug_assert_eq!(tapscript_size, self.tapscript().as_bytes().len());
317
318 1 + 1 + SCHNORR_SIGNATURE_SIZE + 1 + 32 + VarInt::from(tapscript_size).size() + tapscript_size + VarInt::from(cb_size).size() + cb_size }
328}
329
330impl Into<VtxoClause> for HashSignClause {
331 fn into(self) -> VtxoClause {
332 VtxoClause::HashSign(self)
333 }
334}
335
336#[derive(Debug, Clone)]
337pub enum VtxoClause {
338 DelayedSign(DelayedSignClause),
339 TimelockSign(TimelockSignClause),
340 DelayedTimelockSign(DelayedTimelockSignClause),
341 HashDelaySign(HashDelaySignClause),
342 HashSign(HashSignClause),
343}
344
345impl VtxoClause {
346 pub fn pubkey(&self) -> PublicKey {
348 match self {
349 Self::DelayedSign(c) => c.pubkey,
350 Self::TimelockSign(c) => c.pubkey,
351 Self::DelayedTimelockSign(c) => c.pubkey,
352 Self::HashDelaySign(c) => c.pubkey,
353 Self::HashSign(c) => c.pubkey,
354 }
355 }
356
357
358 pub fn tapscript(&self) -> ScriptBuf {
360 match self {
361 Self::DelayedSign(c) => c.tapscript(),
362 Self::TimelockSign(c) => c.tapscript(),
363 Self::DelayedTimelockSign(c) => c.tapscript(),
364 Self::HashDelaySign(c) => c.tapscript(),
365 Self::HashSign(c) => c.tapscript(),
366 }
367 }
368
369 pub fn sequence(&self) -> Option<Sequence> {
371 match self {
372 Self::DelayedSign(c) => Some(c.sequence()),
373 Self::TimelockSign(_) => None,
374 Self::DelayedTimelockSign(c) => Some(c.sequence()),
375 Self::HashDelaySign(c) => Some(c.sequence()),
376 Self::HashSign(_) => None,
377 }
378 }
379
380 pub fn control_block<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> ControlBlock {
382 match self {
383 Self::DelayedSign(c) => c.control_block(vtxo),
384 Self::TimelockSign(c) => c.control_block(vtxo),
385 Self::DelayedTimelockSign(c) => c.control_block(vtxo),
386 Self::HashDelaySign(c) => c.control_block(vtxo),
387 Self::HashSign(c) => c.control_block(vtxo),
388 }
389 }
390
391 pub fn witness_size<G, P: Policy>(&self, vtxo: &Vtxo<G, P>) -> usize {
393 match self {
394 Self::DelayedSign(c) => c.witness_size(vtxo),
395 Self::TimelockSign(c) => c.witness_size(vtxo),
396 Self::DelayedTimelockSign(c) => c.witness_size(vtxo),
397 Self::HashDelaySign(c) => c.witness_size(vtxo),
398 Self::HashSign(c) => c.witness_size(vtxo),
399 }
400 }
401}
402
403#[cfg(test)]
404mod tests {
405 use std::str::FromStr;
406
407 use bitcoin::taproot::TaprootSpendInfo;
408 use bitcoin::{Amount, OutPoint, Transaction, TxIn, TxOut, Txid, sighash};
409 use bitcoin::hashes::Hash;
410 use bitcoin::key::Keypair;
411 use bitcoin_ext::{TaprootSpendInfoExt, fee};
412
413 use crate::{SECP, musig};
414 use crate::test_util::verify_tx;
415
416 use super::*;
417
418 lazy_static! {
419 static ref USER_KEYPAIR: Keypair = Keypair::from_str("5255d132d6ec7d4fc2a41c8f0018bb14343489ddd0344025cc60c7aa2b3fda6a").unwrap();
420 static ref SERVER_KEYPAIR: Keypair = Keypair::from_str("1fb316e653eec61de11c6b794636d230379509389215df1ceb520b65313e5426").unwrap();
421 }
422
423 #[allow(unused)]
424 fn all_clause_tested(clause: VtxoClause) -> bool {
425 match clause {
427 VtxoClause::DelayedSign(_) => true,
428 VtxoClause::TimelockSign(_) => true,
429 VtxoClause::DelayedTimelockSign(_) => true,
430 VtxoClause::HashDelaySign(_) => true,
431 VtxoClause::HashSign(_) => true,
432 }
433 }
434
435 fn transaction() -> Transaction {
436 let address = bitcoin::Address::from_str("tb1q00h5delzqxl7xae8ufmsegghcl4jwfvdnd8530")
437 .unwrap().assume_checked();
438
439 Transaction {
440 version: bitcoin::transaction::Version(3),
441 lock_time: bitcoin::absolute::LockTime::ZERO,
442 input: vec![],
443 output: vec![TxOut {
444 script_pubkey: address.script_pubkey(),
445 value: Amount::from_sat(900_000),
446 }, fee::fee_anchor()]
447 }
448 }
449
450 fn taproot_material(clause_spk: ScriptBuf) -> (TaprootSpendInfo, ControlBlock) {
451 let user_pubkey = USER_KEYPAIR.public_key();
452 let server_pubkey = SERVER_KEYPAIR.public_key();
453
454 let combined_pk = musig::combine_keys([user_pubkey, server_pubkey])
455 .x_only_public_key().0;
456 let taproot = taproot::TaprootBuilder::new()
457 .add_leaf(0, clause_spk.clone()).unwrap()
458 .finalize(&SECP, combined_pk).unwrap();
459
460 let cb = taproot
461 .control_block(&(clause_spk.clone(), taproot::LeafVersion::TapScript))
462 .expect("script is in taproot");
463
464 (taproot, cb)
465 }
466
467 fn signature(tx: &Transaction, input: &TxOut, clause_spk: ScriptBuf) -> schnorr::Signature {
468 let leaf_hash = taproot::TapLeafHash::from_script(
469 &clause_spk,
470 taproot::LeafVersion::TapScript,
471 );
472
473 let mut shc = sighash::SighashCache::new(tx);
474 let sighash = shc.taproot_script_spend_signature_hash(
475 0, &sighash::Prevouts::All(&[input.clone()]), leaf_hash, sighash::TapSighashType::Default,
476 ).expect("all prevouts provided");
477
478 SECP.sign_schnorr(&sighash.into(), &*USER_KEYPAIR)
479 }
480
481 #[test]
482 fn test_delayed_sign_clause() {
483 let clause = DelayedSignClause {
484 pubkey: USER_KEYPAIR.public_key(),
485 block_delta: 100,
486 };
487
488 let (taproot, cb) = taproot_material(clause.tapscript());
490 let tx_in = TxOut {
491 script_pubkey: taproot.script_pubkey(),
492 value: Amount::from_sat(1_000_000),
493 };
494
495 let mut tx = transaction();
497 tx.input.push(TxIn {
498 previous_output: OutPoint::new(Txid::all_zeros(), 0),
499 script_sig: ScriptBuf::default(),
500 sequence: clause.sequence(),
501 witness: Witness::new(),
502 });
503
504 let signature = signature(&tx, &tx_in, clause.tapscript());
506 tx.input[0].witness = clause.witness(&signature, &cb);
507
508 verify_tx(&[tx_in], 0, &tx).expect("transaction is invalid");
510 }
511
512 #[test]
513 fn test_timelock_sign_clause() {
514 let clause = TimelockSignClause {
515 pubkey: USER_KEYPAIR.public_key(),
516 timelock_height: 100,
517 };
518
519 let (taproot, cb) = taproot_material(clause.tapscript());
521 let tx_in = TxOut {
522 script_pubkey: taproot.script_pubkey(),
523 value: Amount::from_sat(1_000_000),
524 };
525
526 let mut tx = transaction();
528 tx.lock_time = clause.locktime();
529 tx.input.push(TxIn {
530 previous_output: OutPoint::new(Txid::all_zeros(), 0),
531 script_sig: ScriptBuf::default(),
532 sequence: Sequence::ZERO,
533 witness: Witness::new(),
534 });
535
536 let signature = signature(&tx, &tx_in, clause.tapscript());
538 tx.input[0].witness = clause.witness(&signature, &cb);
539
540 verify_tx(&[tx_in], 0, &tx).expect("transaction is invalid");
542 }
543
544 #[test]
545 fn test_delayed_timelock_clause() {
546 let clause = DelayedTimelockSignClause {
547 pubkey: USER_KEYPAIR.public_key(),
548 timelock_height: 100,
549 block_delta: 24,
550 };
551
552 let (taproot, cb) = taproot_material(clause.tapscript());
554 let tx_in = TxOut {
555 script_pubkey: taproot.script_pubkey(),
556 value: Amount::from_sat(1_000_000),
557 };
558
559 let mut tx = transaction();
561 tx.lock_time = clause.locktime();
562 tx.input.push(TxIn {
563 previous_output: OutPoint::new(Txid::all_zeros(), 0),
564 script_sig: ScriptBuf::default(),
565 sequence: clause.sequence(),
566 witness: Witness::new(),
567 });
568
569 let signature = signature(&tx, &tx_in, clause.tapscript());
571 tx.input[0].witness = clause.witness(&signature, &cb);
572
573 verify_tx(&[tx_in], 0, &tx).expect("transaction is invalid");
575 }
576
577 #[test]
578 fn test_hash_delay_clause() {
579 let preimage = [0; 32];
580
581 let clause = HashDelaySignClause {
582 pubkey: USER_KEYPAIR.public_key(),
583 hash: sha256::Hash::hash(&preimage),
584 block_delta: 24,
585 };
586
587 let (taproot, cb) = taproot_material(clause.tapscript());
589 let tx_in = TxOut {
590 script_pubkey: taproot.script_pubkey(),
591 value: Amount::from_sat(1_000_000),
592 };
593
594 let mut tx = transaction();
596 tx.input.push(TxIn {
597 previous_output: OutPoint::new(Txid::all_zeros(), 0),
598 script_sig: ScriptBuf::default(),
599 sequence: clause.sequence(),
600 witness: Witness::new(),
601 });
602
603 let signature = signature(&tx, &tx_in, clause.tapscript());
605 tx.input[0].witness = clause.witness(&(signature, preimage), &cb);
606
607 verify_tx(&[tx_in], 0, &tx).expect("transaction is invalid");
609 }
610
611 #[test]
612 fn test_hash_sign_clause() {
613 let preimage = [0u8; 32];
614 let hash = sha256::Hash::hash(&preimage);
615
616 let agg_pk = musig::combine_keys([USER_KEYPAIR.public_key(), SERVER_KEYPAIR.public_key()]);
618
619 let clause = HashSignClause {
620 pubkey: agg_pk,
621 hash,
622 };
623
624 let (taproot, cb) = taproot_material(clause.tapscript());
626 let tx_in = TxOut {
627 script_pubkey: taproot.script_pubkey(),
628 value: Amount::from_sat(1_000_000),
629 };
630
631 let mut tx = transaction();
633 tx.input.push(TxIn {
634 previous_output: OutPoint::new(Txid::all_zeros(), 0),
635 script_sig: ScriptBuf::default(),
636 sequence: Sequence::ZERO, witness: Witness::new(),
638 });
639
640 let leaf_hash = taproot::TapLeafHash::from_script(
642 &clause.tapscript(),
643 taproot::LeafVersion::TapScript,
644 );
645
646 let mut shc = sighash::SighashCache::new(&tx);
647 let sighash = shc.taproot_script_spend_signature_hash(
648 0, &sighash::Prevouts::All(&[tx_in.clone()]), leaf_hash, sighash::TapSighashType::Default,
649 ).expect("all prevouts provided");
650
651 let (user_sec_nonce, user_pub_nonce) = musig::nonce_pair(&*USER_KEYPAIR);
653 let (server_pub_nonce, server_part_sig) = musig::deterministic_partial_sign(
654 &*SERVER_KEYPAIR,
655 [USER_KEYPAIR.public_key()],
656 &[&user_pub_nonce],
657 sighash.to_byte_array(),
658 None,
659 );
660 let agg_nonce = musig::nonce_agg(&[&user_pub_nonce, &server_pub_nonce]);
661
662 let (_user_part_sig, final_sig) = musig::partial_sign(
663 [USER_KEYPAIR.public_key(), SERVER_KEYPAIR.public_key()],
664 agg_nonce,
665 &*USER_KEYPAIR,
666 user_sec_nonce,
667 sighash.to_byte_array(),
668 None,
669 Some(&[&server_part_sig]),
670 );
671 let final_sig = final_sig.expect("should have final signature");
672
673 tx.input[0].witness = clause.witness(&(final_sig, preimage), &cb);
674
675 verify_tx(&[tx_in], 0, &tx).expect("transaction is invalid");
677 }
678}