vls_protocol_client/
dyn_signer.rs

1use std::any::Any;
2use std::io::Read;
3
4use delegate::delegate;
5
6use crate::HTLCDescriptor;
7use bitcoin::bech32::u5;
8use bitcoin::{secp256k1, Transaction, TxOut};
9use lightning::ln::chan_utils::{
10    ChannelPublicKeys, ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction,
11    HTLCOutputInCommitment, HolderCommitmentTransaction,
12};
13use lightning::ln::msgs::{DecodeError, UnsignedChannelAnnouncement, UnsignedGossipMessage};
14use lightning::ln::script::ShutdownScript;
15use lightning::ln::PaymentPreimage;
16use lightning::sign::ecdsa::EcdsaChannelSigner;
17use lightning::sign::ecdsa::WriteableEcdsaChannelSigner;
18use lightning::sign::ChannelSigner;
19use lightning::sign::InMemorySigner;
20use lightning::sign::{
21    KeyMaterial, NodeSigner, Recipient, SignerProvider, SpendableOutputDescriptor,
22};
23use lightning::util::ser::Readable;
24use lightning::util::ser::{Writeable, Writer};
25use lightning_signer::bitcoin::secp256k1::All;
26use lightning_signer::bitcoin::{self, ScriptBuf};
27use lightning_signer::lightning;
28use secp256k1::ecdsa::RecoverableSignature;
29use secp256k1::{ecdh::SharedSecret, ecdsa::Signature, PublicKey, Scalar, Secp256k1, SecretKey};
30
31use crate::bitcoin::Address;
32use lightning_signer::util::loopback::LoopbackChannelSigner;
33
34/// Helper to allow DynSigner to clone itself
35pub trait InnerSign: EcdsaChannelSigner + Send + Sync {
36    fn box_clone(&self) -> Box<dyn InnerSign>;
37    fn as_any(&self) -> &dyn Any;
38    fn vwrite(&self, writer: &mut Vec<u8>) -> Result<(), std::io::Error>;
39}
40
41/// A ChannelSigner derived struct allowing run-time selection of a signer
42pub struct DynSigner {
43    pub inner: Box<dyn InnerSign>,
44}
45
46impl DynSigner {
47    pub fn new<S: InnerSign + 'static>(inner: S) -> Self {
48        DynSigner { inner: Box::new(inner) }
49    }
50}
51
52impl WriteableEcdsaChannelSigner for DynSigner {}
53
54impl Clone for DynSigner {
55    fn clone(&self) -> Self {
56        DynSigner { inner: self.inner.box_clone() }
57    }
58}
59
60// This is taken care of by KeysInterface
61impl Readable for DynSigner {
62    fn read<R: Read>(_reader: &mut R) -> Result<Self, DecodeError> {
63        unimplemented!()
64    }
65}
66
67impl EcdsaChannelSigner for DynSigner {
68    delegate! {
69        to self.inner {
70            fn sign_counterparty_commitment(
71                &self,
72                commitment_tx: &CommitmentTransaction,
73                inbound_htlc_preimages: Vec<PaymentPreimage>,
74                outbound_htlc_preimages: Vec<PaymentPreimage>,
75                secp_ctx: &Secp256k1<secp256k1::All>,
76            ) -> Result<(Signature, Vec<Signature>), ()>;
77
78            fn sign_holder_commitment(
79                &self,
80                commitment_tx: &HolderCommitmentTransaction,
81                secp_ctx: &Secp256k1<secp256k1::All>,
82            ) -> Result<Signature, ()>;
83
84            fn unsafe_sign_holder_commitment(
85                &self,
86                commitment_tx: &HolderCommitmentTransaction,
87                secp_ctx: &Secp256k1<secp256k1::All>,
88            ) -> Result<Signature, ()>;
89
90            fn sign_justice_revoked_output(
91                &self,
92                justice_tx: &Transaction,
93                input: usize,
94                amount: u64,
95                per_commitment_key: &SecretKey,
96                secp_ctx: &Secp256k1<secp256k1::All>,
97            ) -> Result<Signature, ()>;
98
99            fn sign_justice_revoked_htlc(
100                &self,
101                justice_tx: &Transaction,
102                input: usize,
103                amount: u64,
104                per_commitment_key: &SecretKey,
105                htlc: &HTLCOutputInCommitment,
106                secp_ctx: &Secp256k1<secp256k1::All>,
107            ) -> Result<Signature, ()>;
108
109            fn sign_counterparty_htlc_transaction(
110                &self,
111                htlc_tx: &Transaction,
112                input: usize,
113                amount: u64,
114                per_commitment_point: &PublicKey,
115                htlc: &HTLCOutputInCommitment,
116                secp_ctx: &Secp256k1<secp256k1::All>,
117            ) -> Result<Signature, ()>;
118
119            fn sign_closing_transaction(
120                &self,
121                closing_tx: &ClosingTransaction,
122                secp_ctx: &Secp256k1<secp256k1::All>,
123            ) -> Result<Signature, ()>;
124
125            fn sign_channel_announcement_with_funding_key(
126                &self,
127                msg: &UnsignedChannelAnnouncement,
128                secp_ctx: &Secp256k1<secp256k1::All>,
129            ) -> Result<Signature, ()>;
130
131            fn sign_holder_anchor_input(
132                &self, anchor_tx: &Transaction, input: usize, secp_ctx: &Secp256k1<secp256k1::All>,
133            ) -> Result<Signature, ()>;
134
135            fn sign_holder_htlc_transaction(&self, htlc_tx: &Transaction, input: usize, htlc_descriptor: &HTLCDescriptor, secp_ctx: &Secp256k1<All>) -> Result<Signature, ()>;
136        }
137    }
138}
139
140impl ChannelSigner for DynSigner {
141    delegate! {
142        to self.inner {
143            fn validate_counterparty_revocation(&self, idx: u64, sk: &SecretKey) -> Result<(), ()>;
144
145            fn get_per_commitment_point(
146                &self,
147                idx: u64,
148                secp_ctx: &Secp256k1<secp256k1::All>,
149            ) -> PublicKey;
150
151            fn release_commitment_secret(&self, idx: u64) -> [u8; 32];
152
153            fn validate_holder_commitment(
154                &self,
155                holder_tx: &HolderCommitmentTransaction,
156                preimages: Vec<PaymentPreimage>,
157            ) -> Result<(), ()>;
158
159            fn pubkeys(&self) -> &ChannelPublicKeys;
160
161            fn channel_keys_id(&self) -> [u8; 32];
162
163            fn provide_channel_parameters(&mut self, channel_parameters: &ChannelTransactionParameters);
164        }
165    }
166}
167
168impl Writeable for DynSigner {
169    fn write<W: Writer>(&self, writer: &mut W) -> Result<(), std::io::Error> {
170        let inner = self.inner.as_ref();
171        let mut buf = Vec::new();
172        inner.vwrite(&mut buf)?;
173        writer.write_all(&buf)
174    }
175}
176
177impl InnerSign for InMemorySigner {
178    fn box_clone(&self) -> Box<dyn InnerSign> {
179        Box::new(self.clone())
180    }
181
182    fn as_any(&self) -> &dyn Any {
183        self
184    }
185
186    fn vwrite(&self, writer: &mut Vec<u8>) -> Result<(), std::io::Error> {
187        self.write(writer)
188    }
189}
190
191impl InnerSign for LoopbackChannelSigner {
192    fn box_clone(&self) -> Box<dyn InnerSign> {
193        Box::new(self.clone())
194    }
195
196    fn as_any(&self) -> &dyn Any {
197        self
198    }
199
200    fn vwrite(&self, writer: &mut Vec<u8>) -> Result<(), std::io::Error> {
201        self.write(writer)
202    }
203}
204
205pub struct DynKeysInterface {
206    pub inner: Box<dyn SpendableKeysInterface<EcdsaSigner = DynSigner>>,
207}
208
209impl DynKeysInterface {
210    pub fn new(inner: Box<dyn SpendableKeysInterface<EcdsaSigner = DynSigner>>) -> Self {
211        DynKeysInterface { inner }
212    }
213}
214
215impl NodeSigner for DynKeysInterface {
216    delegate! {
217        to self.inner {
218            fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()>;
219            fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()>;
220            fn ecdh(&self, recipient: Recipient, other_key: &PublicKey, tweak: Option<&Scalar>) -> Result<SharedSecret, ()>;
221
222            fn sign_invoice(
223                &self,
224                hrp_bytes: &[u8],
225                invoice_data: &[u5],
226                recipient: Recipient,
227            ) -> Result<RecoverableSignature, ()>;
228
229            fn sign_bolt12_invoice(
230                &self, invoice: &lightning::offers::invoice::UnsignedBolt12Invoice
231            ) -> Result<bitcoin::secp256k1::schnorr::Signature, ()>;
232
233            fn sign_bolt12_invoice_request(
234                &self, invoice_request: &lightning::offers::invoice_request::UnsignedInvoiceRequest
235            ) -> Result<bitcoin::secp256k1::schnorr::Signature, ()>;
236
237            fn get_inbound_payment_key_material(&self) -> KeyMaterial;
238        }
239    }
240}
241
242impl SignerProvider for DynKeysInterface {
243    type EcdsaSigner = DynSigner;
244
245    delegate! {
246        to self.inner {
247            fn get_destination_script(&self, buf: [u8; 32]) -> Result<ScriptBuf, ()>;
248
249            fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()>;
250
251            fn generate_channel_keys_id(&self, _inbound: bool, _channel_value_satoshis: u64, _user_channel_id: u128) -> [u8; 32];
252
253            fn derive_channel_signer(&self, _channel_value_satoshis: u64, _channel_keys_id: [u8; 32]) -> Self::EcdsaSigner;
254
255            fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::EcdsaSigner, DecodeError>;
256        }
257    }
258}
259
260// TODO(devrandom) why is spend_spendable_outputs not in KeysInterface?
261pub trait SpendableKeysInterface: NodeSigner + SignerProvider + Send + Sync {
262    fn spend_spendable_outputs(
263        &self,
264        descriptors: &[&SpendableOutputDescriptor],
265        outputs: Vec<TxOut>,
266        change_destination_script: ScriptBuf,
267        feerate_sat_per_1000_weight: u32,
268        secp_ctx: &Secp256k1<All>,
269    ) -> anyhow::Result<Transaction>;
270
271    /// Swept funds from closed channels are sent here
272    /// This is implemented by setting the change destination to spend_spendable_outputs to this address.
273    fn get_sweep_address(&self) -> Address;
274}
275
276impl SpendableKeysInterface for DynKeysInterface {
277    delegate! {
278        to self.inner {
279            fn spend_spendable_outputs(
280                &self,
281                descriptors: &[&SpendableOutputDescriptor],
282                outputs: Vec<TxOut>,
283                change_destination_script: ScriptBuf,
284                feerate_sat_per_1000_weight: u32,
285                secp_ctx: &Secp256k1<All>,
286            ) -> anyhow::Result<Transaction>;
287
288            fn get_sweep_address(&self) -> Address;
289        }
290    }
291}