1
2use bitcoin::secp256k1::schnorr;
3use bitcoin::{taproot, TapSighash, Witness};
4use bitcoin::key::Keypair;
5use log::error;
6
7use ark::VtxoPolicy;
8use ark::vtxo::{TapScriptClause, Vtxo, VtxoClause};
9use ark::vtxo::policy::signing::VtxoSigner;
10
11use crate::{SECP, Wallet};
12
13impl Wallet {
14 pub (crate) async fn clause_keypair(&self, clause: &VtxoClause) -> Option<Keypair> {
15 let clause_pubkey = clause.pubkey();
16 self.pubkey_keypair(&clause_pubkey).await.ok()
17 .flatten().map(|(_, keypair)| keypair)
18 }
19}
20
21#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
22#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
23impl VtxoSigner for Wallet {
24 async fn sign_keyspend<G: Sync + Send>(
25 &self,
26 vtxo: &Vtxo<G, VtxoPolicy>,
27 _sighash: TapSighash,
28 ) -> Option<schnorr::Signature> {
29 error!(
30 "CODE BUG: wallet was asked to sign a keyspend clause but that should never happen \
31 (VTXO ID: {}; policy type: {})", vtxo.id(), vtxo.policy_type(),
32 );
33 None
34 }
35
36 async fn witness(
37 &self,
38 clause: &VtxoClause,
39 control_block: &taproot::ControlBlock,
40 sighash: TapSighash,
41 ) -> Option<Witness> {
42 let signature = match self.clause_keypair(clause).await {
43 Some(keypair) => {
44 SECP.sign_schnorr_with_aux_rand(&sighash.into(), &keypair, &rand::random())
45 },
46 None => return None,
47 };
48
49 match clause {
50 VtxoClause::DelayedSign(c) => Some(c.witness(&signature, control_block)),
51 VtxoClause::DelayedTimelockSign(c) => Some(c.witness(&signature, &control_block)),
52 VtxoClause::TimelockSign(c) => Some(c.witness(&signature, &control_block)),
53 VtxoClause::HashDelaySign(c) => {
54 let receive = self.db.fetch_lightning_receive_by_payment_hash(c.hash.into())
55 .await.ok().flatten();
56
57 receive.map(|r| c.witness(
58 &(signature, r.payment_preimage.to_byte_array()), &control_block,
59 ))
60 },
61 VtxoClause::HashSign(_) => None, }
63 }
64}