vls_protocol_client/
lib.rs

1use std::any::Any;
2use std::convert::{TryFrom, TryInto};
3use std::sync::atomic::{AtomicU64, Ordering};
4use std::sync::Arc;
5
6use bitcoin::bip32::ChildNumber;
7use bitcoin::bip32::Xpub;
8use bitcoin::hashes::Hash;
9use bitcoin::psbt::Psbt;
10use bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
11use bitcoin::secp256k1::rand::rngs::OsRng;
12use bitcoin::secp256k1::rand::RngCore;
13use bitcoin::secp256k1::{
14    ecdh::SharedSecret, ecdsa::Signature, All, PublicKey, Scalar, Secp256k1, SecretKey,
15};
16use bitcoin::WPubkeyHash;
17use bitcoin::{Transaction, TxOut};
18use lightning::ln::chan_utils::{
19    ChannelPublicKeys, ChannelTransactionParameters, ClosingTransaction, CommitmentTransaction,
20    HTLCOutputInCommitment, HolderCommitmentTransaction,
21};
22use lightning::ln::inbound_payment::ExpandedKey;
23use lightning::ln::msgs::DecodeError;
24use lightning::ln::msgs::UnsignedChannelAnnouncement;
25use lightning::ln::msgs::UnsignedGossipMessage;
26use lightning::ln::script::ShutdownScript;
27use lightning::sign::ecdsa::EcdsaChannelSigner;
28use lightning::sign::{ChannelSigner, NodeSigner};
29use lightning::sign::{EntropySource, SignerProvider};
30use lightning::sign::{Recipient, SpendableOutputDescriptor};
31use lightning::types::payment::PaymentPreimage;
32use lightning::util::ser::Readable;
33use lightning::util::ser::{Writeable, Writer};
34use lightning_signer::bitcoin::absolute::LockTime;
35use lightning_signer::bitcoin::sighash::EcdsaSighashType;
36use lightning_signer::bitcoin::{self, ScriptBuf, Witness};
37use lightning_signer::channel::{ChannelId, CommitmentType};
38use lightning_signer::lightning;
39use lightning_signer::lightning::sign::HTLCDescriptor;
40use lightning_signer::lightning::sign::OutputSpender;
41use lightning_signer::signer::derive::KeyDerivationStyle;
42use lightning_signer::util::transaction_utils::create_spending_transaction;
43use lightning_signer::util::INITIAL_COMMITMENT_NUMBER;
44use log::{debug, error};
45
46use vls_protocol::model::{
47    Basepoints, BitcoinSignature, CloseInfo, DisclosedSecret, Htlc, PubKey, Utxo,
48};
49use vls_protocol::msgs::{
50    DeBolt, Ecdh, EcdhReply, GetChannelBasepoints, GetChannelBasepointsReply,
51    GetPerCommitmentPoint, GetPerCommitmentPoint2, GetPerCommitmentPoint2Reply,
52    GetPerCommitmentPointReply, HsmdInit2, HsmdInit2Reply, NewChannel, NewChannelReply, SerBolt,
53    SetupChannel, SetupChannelReply, SignChannelAnnouncement, SignChannelAnnouncementReply,
54    SignCommitmentTxReply, SignCommitmentTxWithHtlcsReply, SignGossipMessage,
55    SignGossipMessageReply, SignInvoice, SignInvoiceReply, SignLocalCommitmentTx2,
56    SignLocalHtlcTx2, SignMutualCloseTx2, SignRemoteCommitmentTx2, SignTxReply, SignWithdrawal,
57    SignWithdrawalReply, ValidateCommitmentTx2, ValidateCommitmentTxReply, ValidateRevocation,
58    ValidateRevocationReply,
59};
60#[cfg(feature = "developer")]
61use vls_protocol::msgs::{HsmdDevPreinit, HsmdDevPreinitReply};
62use vls_protocol::serde_bolt::{Array, ArrayBE, Octets, WireString, WithSize};
63use vls_protocol::{model, Error as ProtocolError};
64use vls_protocol_signer::util::commitment_type_to_channel_type;
65
66mod dyn_signer;
67pub mod signer_port;
68
69pub use dyn_signer::{DynKeysInterface, DynSigner, InnerSign, SpendableKeysInterface};
70use lightning_signer::bitcoin::secp256k1::Signing;
71use lightning_signer::lightning_invoice::RawBolt11Invoice;
72pub use signer_port::SignerPort;
73use vls_protocol::psbt::StreamedPSBT;
74
75#[derive(Debug, PartialEq)]
76pub enum Error {
77    Protocol(ProtocolError),
78    Transport,
79    TransportTransient,
80}
81
82pub type ClientResult<T> = Result<T, Error>;
83
84impl From<ProtocolError> for Error {
85    fn from(e: ProtocolError) -> Self {
86        Error::Protocol(e)
87    }
88}
89
90pub trait Transport: Send + Sync {
91    /// Perform a call for the node API
92    fn node_call(&self, message: Vec<u8>) -> Result<Vec<u8>, Error>;
93    /// Perform a call for the channel API
94    fn call(&self, dbid: u64, peer_id: PubKey, message: Vec<u8>) -> Result<Vec<u8>, Error>;
95}
96
97#[derive(Clone)]
98pub struct SignerClient {
99    transport: Arc<dyn Transport>,
100    peer_id: [u8; 33],
101    dbid: u64,
102    channel_keys: ChannelPublicKeys,
103    channel_value: u64,
104}
105
106fn to_pubkey(pubkey: PublicKey) -> PubKey {
107    PubKey(pubkey.serialize())
108}
109
110fn to_bitcoin_sig(sig: &Signature) -> BitcoinSignature {
111    BitcoinSignature {
112        signature: model::Signature(sig.serialize_compact()),
113        sighash: EcdsaSighashType::All as u8,
114    }
115}
116
117pub fn call<T: SerBolt, R: DeBolt>(
118    dbid: u64,
119    peer_id: PubKey,
120    transport: &dyn Transport,
121    message: T,
122) -> Result<R, Error> {
123    assert_ne!(dbid, 0, "dbid 0 is reserved");
124    let message_ser = message.as_vec();
125    debug!("signer call {:?}", message);
126    let result_ser = transport.call(dbid, peer_id, message_ser)?;
127    let result = R::from_vec(result_ser)?;
128    debug!("signer result {:?}", result);
129    Ok(result)
130}
131
132pub fn node_call<T: SerBolt, R: DeBolt>(transport: &dyn Transport, message: T) -> Result<R, Error> {
133    debug!("signer call {:?}", message);
134    let message_ser = message.as_vec();
135    let result_ser = transport.node_call(message_ser)?;
136    let result = R::from_vec(result_ser)?;
137    debug!("signer result {:?}", result);
138    Ok(result)
139}
140
141fn to_htlcs(htlcs: &Vec<HTLCOutputInCommitment>, is_remote: bool) -> Array<Htlc> {
142    let htlcs = htlcs
143        .iter()
144        .map(|h| Htlc {
145            side: if h.offered != is_remote { Htlc::LOCAL } else { Htlc::REMOTE },
146            amount: h.amount_msat,
147            payment_hash: model::Sha256(h.payment_hash.0),
148            ctlv_expiry: h.cltv_expiry,
149        })
150        .collect();
151    Array(htlcs)
152}
153
154fn dest_wallet_path() -> ArrayBE<u32> {
155    let result = vec![1];
156    // elsewhere we assume that the path has a single component
157    assert_eq!(result.len(), 1);
158    result.into()
159}
160
161impl SignerClient {
162    fn call<T: SerBolt, R: DeBolt>(&self, message: T) -> Result<R, Error> {
163        call(self.dbid, PubKey(self.peer_id), &*self.transport, message).map_err(|e| {
164            error!("transport error: {:?}", e);
165            e
166        })
167    }
168
169    fn new(
170        transport: Arc<dyn Transport>,
171        peer_id: [u8; 33],
172        dbid: u64,
173        channel_value: u64,
174        channel_keys: ChannelPublicKeys,
175    ) -> Self {
176        SignerClient { transport, peer_id, dbid, channel_keys, channel_value }
177    }
178}
179
180impl Writeable for SignerClient {
181    fn write<W: Writer>(&self, writer: &mut W) -> Result<(), bitcoin::io::Error> {
182        self.peer_id.write(writer)?;
183        self.dbid.write(writer)?;
184        self.channel_keys.write(writer)?;
185        self.channel_value.write(writer)?;
186        Ok(())
187    }
188}
189
190impl EcdsaChannelSigner for SignerClient {
191    fn sign_counterparty_commitment(
192        &self,
193        commitment_tx: &CommitmentTransaction,
194        _preimages: Vec<PaymentPreimage>,
195        _preimages_ount: Vec<PaymentPreimage>,
196        _secp_ctx: &Secp256k1<All>,
197    ) -> Result<(Signature, Vec<Signature>), ()> {
198        // TODO preimage handling
199        let tx = commitment_tx.trust();
200        let htlcs = to_htlcs(tx.htlcs(), true);
201        let message = SignRemoteCommitmentTx2 {
202            remote_per_commitment_point: to_pubkey(tx.keys().per_commitment_point),
203            commitment_number: INITIAL_COMMITMENT_NUMBER - tx.commitment_number(),
204            feerate: tx.feerate_per_kw(),
205            to_local_value_sat: tx.to_countersignatory_value_sat(),
206            to_remote_value_sat: tx.to_broadcaster_value_sat(),
207            htlcs,
208        };
209        let result: SignCommitmentTxWithHtlcsReply = self.call(message).map_err(|_| ())?;
210        let signature = Signature::from_compact(&result.signature.signature.0).map_err(|_| ())?;
211        let htlc_signatures = result
212            .htlc_signatures
213            .iter()
214            .map(|s| Signature::from_compact(&s.signature.0))
215            .collect::<Result<Vec<_>, _>>()
216            .map_err(|_| ())?;
217        Ok((signature, htlc_signatures))
218    }
219
220    fn sign_holder_commitment(
221        &self,
222        commitment_tx: &HolderCommitmentTransaction,
223        _secp_ctx: &Secp256k1<All>,
224    ) -> Result<Signature, ()> {
225        let message = SignLocalCommitmentTx2 {
226            commitment_number: INITIAL_COMMITMENT_NUMBER - commitment_tx.commitment_number(),
227        };
228        let result: SignCommitmentTxReply = self.call(message).map_err(|_| ())?;
229        let signature = Signature::from_compact(&result.signature.signature.0).map_err(|_| ())?;
230        Ok(signature)
231    }
232
233    fn unsafe_sign_holder_commitment(
234        &self,
235        _commitment_tx: &HolderCommitmentTransaction,
236        _secp_ctx: &Secp256k1<All>,
237    ) -> Result<Signature, ()> {
238        unimplemented!()
239    }
240
241    #[allow(unused)]
242    fn sign_justice_revoked_output(
243        &self,
244        justice_tx: &Transaction,
245        input: usize,
246        amount: u64,
247        per_commitment_key: &SecretKey,
248        _secp_ctx: &Secp256k1<All>,
249    ) -> Result<Signature, ()> {
250        // onchain
251        todo!()
252    }
253
254    #[allow(unused)]
255    fn sign_justice_revoked_htlc(
256        &self,
257        justice_tx: &Transaction,
258        input: usize,
259        amount: u64,
260        per_commitment_key: &SecretKey,
261        htlc: &HTLCOutputInCommitment,
262        _secp_ctx: &Secp256k1<All>,
263    ) -> Result<Signature, ()> {
264        // onchain
265        todo!()
266    }
267
268    fn sign_holder_htlc_transaction(
269        &self,
270        htlc_tx: &Transaction,
271        input: usize,
272        htlc_descriptor: &HTLCDescriptor,
273        _secp_ctx: &Secp256k1<All>,
274    ) -> Result<Signature, ()> {
275        let htlc = &htlc_descriptor.htlc;
276        let message = SignLocalHtlcTx2 {
277            per_commitment_number: htlc_descriptor.per_commitment_number,
278            offered: htlc.offered,
279            cltv_expiry: htlc.cltv_expiry,
280            tx: WithSize(htlc_tx.clone()),
281            input: input as u32,
282            payment_hash: model::Sha256(htlc.payment_hash.0),
283            htlc_amount_msat: htlc_descriptor.htlc.amount_msat,
284        };
285        let result: SignTxReply = self.call(message).map_err(|_| ())?;
286        Ok(Signature::from_compact(&result.signature.signature.0).unwrap())
287    }
288
289    #[allow(unused)]
290    fn sign_counterparty_htlc_transaction(
291        &self,
292        htlc_tx: &Transaction,
293        input: usize,
294        amount: u64,
295        per_commitment_point: &PublicKey,
296        htlc: &HTLCOutputInCommitment,
297        _secp_ctx: &Secp256k1<All>,
298    ) -> Result<Signature, ()> {
299        // onchain
300        todo!()
301    }
302
303    fn sign_closing_transaction(
304        &self,
305        tx: &ClosingTransaction,
306        _secp_ctx: &Secp256k1<All>,
307    ) -> Result<Signature, ()> {
308        let message = SignMutualCloseTx2 {
309            to_local_value_sat: tx.to_holder_value_sat(),
310            to_remote_value_sat: tx.to_counterparty_value_sat(),
311            local_script: tx.to_holder_script().to_bytes().into(),
312            remote_script: tx.to_counterparty_script().to_bytes().into(),
313            local_wallet_path_hint: dest_wallet_path(),
314        };
315        let result: SignTxReply = self.call(message).map_err(|_| ())?;
316        Ok(Signature::from_compact(&result.signature.signature.0).unwrap())
317    }
318
319    fn sign_holder_anchor_input(
320        &self,
321        _anchor_tx: &Transaction,
322        _input: usize,
323        _secp_ctx: &Secp256k1<All>,
324    ) -> Result<Signature, ()> {
325        todo!()
326    }
327
328    fn sign_channel_announcement_with_funding_key(
329        &self,
330        msg: &UnsignedChannelAnnouncement,
331        _secp_ctx: &Secp256k1<All>,
332    ) -> Result<Signature, ()> {
333        // Prepend a fake prefix to match CLN behavior
334        let mut announcement = [0u8; 258].to_vec();
335        announcement.extend(msg.encode());
336        let message = SignChannelAnnouncement { announcement: announcement.into() };
337        let result: SignChannelAnnouncementReply = self.call(message).map_err(|_| ())?;
338        Ok(Signature::from_compact(&result.bitcoin_signature.0).unwrap())
339    }
340
341    fn sign_splicing_funding_input(
342        &self,
343        _tx: &Transaction,
344        _input_index: usize,
345        _input_value: u64,
346        _secp_ctx: &Secp256k1<All>,
347    ) -> Result<Signature, ()> {
348        todo!("sign_splicing_funding_input - #538")
349    }
350}
351
352impl ChannelSigner for SignerClient {
353    fn get_per_commitment_point(
354        &self,
355        idx: u64,
356        _secp_ctx: &Secp256k1<All>,
357    ) -> Result<PublicKey, ()> {
358        let message = GetPerCommitmentPoint2 { commitment_number: INITIAL_COMMITMENT_NUMBER - idx };
359        let result: GetPerCommitmentPoint2Reply =
360            self.call(message).expect("get_per_commitment_point");
361        Ok(PublicKey::from_slice(&result.point.0).expect("public key"))
362    }
363
364    fn validate_counterparty_revocation(&self, idx: u64, secret: &SecretKey) -> Result<(), ()> {
365        let message = ValidateRevocation {
366            commitment_number: INITIAL_COMMITMENT_NUMBER - idx,
367            commitment_secret: DisclosedSecret(secret[..].try_into().unwrap()),
368        };
369        let _: ValidateRevocationReply = self.call(message).map_err(|_| ())?;
370        Ok(())
371    }
372
373    fn release_commitment_secret(&self, idx: u64) -> Result<[u8; 32], ()> {
374        // Getting the point at idx + 2 releases the secret at idx
375        let message =
376            GetPerCommitmentPoint { commitment_number: INITIAL_COMMITMENT_NUMBER - idx + 2 };
377        let result: GetPerCommitmentPointReply =
378            self.call(message).expect("get_per_commitment_point");
379        let secret = result.secret.expect("secret not released");
380        Ok(secret.0)
381    }
382
383    fn validate_holder_commitment(
384        &self,
385        holder_tx: &HolderCommitmentTransaction,
386        _preimages: Vec<PaymentPreimage>,
387    ) -> Result<(), ()> {
388        // TODO preimage handling
389        let tx = holder_tx.trust();
390        let htlcs = to_htlcs(tx.htlcs(), false);
391        let message = ValidateCommitmentTx2 {
392            commitment_number: INITIAL_COMMITMENT_NUMBER - tx.commitment_number(),
393            feerate: tx.feerate_per_kw(),
394            to_local_value_sat: tx.to_broadcaster_value_sat(),
395            to_remote_value_sat: tx.to_countersignatory_value_sat(),
396            htlcs,
397            signature: to_bitcoin_sig(&holder_tx.counterparty_sig),
398            htlc_signatures: Array(
399                holder_tx.counterparty_htlc_sigs.iter().map(|s| to_bitcoin_sig(s)).collect(),
400            ),
401        };
402        let _: ValidateCommitmentTxReply = self.call(message).map_err(|_| ())?;
403        Ok(())
404    }
405
406    fn pubkeys(&self) -> &ChannelPublicKeys {
407        &self.channel_keys
408    }
409
410    fn channel_keys_id(&self) -> [u8; 32] {
411        ChannelId::new_from_oid(self.dbid).ldk_channel_keys_id()
412    }
413
414    fn provide_channel_parameters(&mut self, p: &ChannelTransactionParameters) {
415        let funding = p.funding_outpoint.expect("funding should exist at this point");
416        let cp = p
417            .counterparty_parameters
418            .as_ref()
419            .expect("counterparty params should exist at this point");
420
421        let features = &p.channel_type_features;
422        let commitment_type = if features.supports_anchors_zero_fee_htlc_tx() {
423            CommitmentType::AnchorsZeroFeeHtlc
424        } else if features.supports_anchors_nonzero_fee_htlc_tx() {
425            CommitmentType::Anchors
426        } else {
427            CommitmentType::StaticRemoteKey
428        };
429
430        let ser_channel_type = commitment_type_to_channel_type(commitment_type);
431        let message = SetupChannel {
432            is_outbound: p.is_outbound_from_holder,
433            channel_value: self.channel_value,
434            push_value: 0, // TODO
435            funding_txid: funding.txid,
436            funding_txout: funding.index,
437            to_self_delay: p.holder_selected_contest_delay,
438            local_shutdown_script: Octets::EMPTY, // TODO
439            local_shutdown_wallet_index: None,
440            remote_basepoints: Basepoints {
441                revocation: to_pubkey(cp.pubkeys.revocation_basepoint.0),
442                payment: to_pubkey(cp.pubkeys.payment_point),
443                htlc: to_pubkey(cp.pubkeys.htlc_basepoint.0),
444                delayed_payment: to_pubkey(cp.pubkeys.delayed_payment_basepoint.0),
445            },
446            remote_funding_pubkey: to_pubkey(cp.pubkeys.funding_pubkey),
447            remote_to_self_delay: cp.selected_contest_delay,
448            remote_shutdown_script: Octets::EMPTY, // TODO
449            channel_type: ser_channel_type.into(),
450        };
451
452        let _: SetupChannelReply = self.call(message).expect("setup channel");
453    }
454}
455
456pub struct KeysManagerClient {
457    transport: Arc<dyn Transport>,
458    next_dbid: AtomicU64,
459    key_material: ExpandedKey,
460    xpub: Xpub,
461    node_id: PublicKey,
462}
463
464impl KeysManagerClient {
465    /// Create a new VLS client with the given transport
466    pub fn new(
467        transport: Arc<dyn Transport>,
468        network: String,
469        key_derivation_style: Option<KeyDerivationStyle>,
470        dev_allowlist: Option<Array<WireString>>,
471    ) -> Self {
472        let mut rng = OsRng;
473        let mut key_material_bytes = [0; 32];
474        rng.fill_bytes(&mut key_material_bytes);
475
476        let key_derivation_style = key_derivation_style.unwrap_or(KeyDerivationStyle::Native);
477
478        #[cfg(not(feature = "developer"))]
479        assert!(dev_allowlist.is_none(), "dev_allowlist is only available in developer mode");
480
481        #[cfg(feature = "developer")]
482        if let Some(allowlist) = dev_allowlist {
483            let preinit_message = HsmdDevPreinit {
484                derivation_style: key_derivation_style as u8,
485                network_name: WireString(network.clone().into_bytes()),
486                seed: None,
487                allowlist,
488            };
489            let _: HsmdDevPreinitReply =
490                node_call(&*transport, preinit_message).expect("HsmdDevPreinit should succeed");
491        }
492
493        let init_message = HsmdInit2 {
494            derivation_style: key_derivation_style as u8,
495            network_name: WireString(network.into_bytes()),
496            dev_seed: None,
497            dev_allowlist: Array::new(),
498        };
499        let result: HsmdInit2Reply = node_call(&*transport, init_message).expect("HsmdInit");
500        let xpub = Xpub::decode(&result.bip32.0).expect("xpub");
501        let node_id = PublicKey::from_slice(&result.node_id.0).expect("node id");
502
503        Self {
504            transport,
505            next_dbid: AtomicU64::new(1),
506            key_material: ExpandedKey::new(key_material_bytes),
507            xpub,
508            node_id,
509        }
510    }
511
512    pub fn call<T: SerBolt, R: DeBolt>(&self, message: T) -> Result<R, Error> {
513        node_call(&*self.transport, message)
514    }
515
516    fn get_channel_basepoints(&self, dbid: u64, peer_id: [u8; 33]) -> ChannelPublicKeys {
517        let message = GetChannelBasepoints { node_id: PubKey(peer_id), dbid };
518        let result: GetChannelBasepointsReply = self.call(message).expect("pubkeys");
519        let channel_keys = ChannelPublicKeys {
520            funding_pubkey: result.funding.into(),
521            revocation_basepoint: result.basepoints.revocation.into(),
522            payment_point: result.basepoints.payment.into(),
523            delayed_payment_basepoint: result.basepoints.delayed_payment.into(),
524            htlc_basepoint: result.basepoints.htlc.into(),
525        };
526        channel_keys
527    }
528
529    pub fn sign_onchain_tx(
530        &self,
531        tx: &Transaction,
532        descriptors: &[&SpendableOutputDescriptor],
533    ) -> Vec<Vec<Vec<u8>>> {
534        assert_eq!(tx.input.len(), descriptors.len());
535
536        let mut psbt = Psbt::from_unsigned_tx(tx.clone()).expect("create PSBT");
537        for i in 0..psbt.inputs.len() {
538            psbt.inputs[i].witness_utxo = Self::descriptor_to_txout(descriptors[i]);
539        }
540
541        let streamed_psbt = StreamedPSBT::new(psbt).into();
542        let utxos = Array(descriptors.into_iter().map(|d| Self::descriptor_to_utxo(*d)).collect());
543
544        let message = SignWithdrawal { utxos, psbt: streamed_psbt };
545        let result: SignWithdrawalReply = self.call(message).expect("sign failed");
546        let psbt = result.psbt.0.inner;
547        psbt.inputs.into_iter().map(|i| i.final_script_witness.unwrap().to_vec()).collect()
548    }
549
550    fn descriptor_to_txout(d: &SpendableOutputDescriptor) -> Option<TxOut> {
551        match d {
552            SpendableOutputDescriptor::StaticOutput { output, .. } => Some(output.clone()),
553            SpendableOutputDescriptor::DelayedPaymentOutput(o) => Some(o.output.clone()),
554            SpendableOutputDescriptor::StaticPaymentOutput(o) => Some(o.output.clone()),
555        }
556    }
557
558    fn descriptor_to_utxo(d: &SpendableOutputDescriptor) -> Utxo {
559        let (outpoint, amount, keyindex, close_info) = match d {
560            // Mutual close - we are spending a non-delayed output to us on the shutdown key
561            SpendableOutputDescriptor::StaticOutput { output, outpoint, .. } =>
562                (outpoint.clone(), output.value, dest_wallet_path()[0], None), // FIXME this makes some assumptions
563            // We force-closed - we are spending a delayed output to us
564            SpendableOutputDescriptor::DelayedPaymentOutput(o) => (
565                o.outpoint,
566                o.output.value,
567                0,
568                Some(CloseInfo {
569                    channel_id: ChannelId::new(&o.channel_keys_id).oid(),
570                    peer_id: PubKey([0; 33]),
571                    commitment_point: Some(to_pubkey(o.per_commitment_point)),
572                    is_anchors: false,
573                    csv: o.to_self_delay as u32,
574                }),
575            ),
576            // Remote force-closed - we are spending an non-delayed output to us
577            SpendableOutputDescriptor::StaticPaymentOutput(o) => (
578                o.outpoint,
579                o.output.value,
580                0,
581                Some(CloseInfo {
582                    channel_id: ChannelId::new(&o.channel_keys_id).oid(),
583                    peer_id: PubKey([0; 33]),
584                    commitment_point: None,
585                    is_anchors: false,
586                    csv: 0,
587                }),
588            ),
589        };
590        let is_in_coinbase = false; // FIXME - set this for real
591        Utxo {
592            txid: outpoint.txid,
593            outnum: outpoint.index as u32,
594            amount: amount.to_sat(),
595            keyindex,
596            is_p2sh: false,
597            script: Octets::EMPTY,
598            close_info,
599            is_in_coinbase,
600        }
601    }
602}
603
604impl EntropySource for KeysManagerClient {
605    fn get_secure_random_bytes(&self) -> [u8; 32] {
606        let mut rng = OsRng;
607        let mut bytes = [0; 32];
608        rng.fill_bytes(&mut bytes);
609        bytes
610    }
611}
612
613impl NodeSigner for KeysManagerClient {
614    fn get_inbound_payment_key(&self) -> ExpandedKey {
615        self.key_material
616    }
617    fn get_node_id(&self, recipient: Recipient) -> Result<PublicKey, ()> {
618        match recipient {
619            Recipient::Node => {}
620            Recipient::PhantomNode => {
621                unimplemented!("phantom nodes not supported")
622            }
623        }
624        Ok(self.node_id)
625    }
626
627    fn ecdh(
628        &self,
629        recipient: Recipient,
630        other_key: &PublicKey,
631        tweak: Option<&Scalar>,
632    ) -> Result<SharedSecret, ()> {
633        match recipient {
634            Recipient::Node => {}
635            Recipient::PhantomNode => unimplemented!("PhantomNode"),
636        }
637
638        if tweak.is_some() {
639            unimplemented!("tweak is not supported");
640        }
641        let message = Ecdh { point: PubKey(other_key.serialize()) };
642        let result: EcdhReply = self.call(message).expect("ecdh");
643        Ok(SharedSecret::from_bytes(result.secret.0))
644    }
645
646    fn sign_invoice(
647        &self,
648        invoice: &RawBolt11Invoice,
649        recipient: Recipient,
650    ) -> Result<RecoverableSignature, ()> {
651        match recipient {
652            Recipient::Node => {}
653            Recipient::PhantomNode => {
654                unimplemented!("phantom nodes not supported")
655            }
656        }
657        let (hrp, invoice_data) = invoice.to_raw();
658        let hrp_bytes = hrp.into_bytes();
659
660        let message = SignInvoice {
661            u5bytes: Octets(invoice_data.iter().map(|u| u.to_u8()).collect()),
662            hrp: hrp_bytes.into(),
663        };
664        let result: SignInvoiceReply = self.call(message).expect("sign_invoice");
665        let rid = RecoveryId::from_i32(result.signature.0[64] as i32).expect("recovery ID");
666        let sig = &result.signature.0[0..64];
667        RecoverableSignature::from_compact(sig, rid).map_err(|_| ())
668    }
669
670    fn sign_bolt12_invoice(
671        &self,
672        _invoice: &lightning::offers::invoice::UnsignedBolt12Invoice,
673    ) -> Result<bitcoin::secp256k1::schnorr::Signature, ()> {
674        unimplemented!()
675    }
676
677    fn sign_gossip_message(&self, msg: UnsignedGossipMessage) -> Result<Signature, ()> {
678        let message = SignGossipMessage { message: Octets(msg.encode()) };
679        let result: SignGossipMessageReply = self.call(message).expect("sign_gossip_message");
680        Ok(Signature::from_compact(&result.signature.0).expect("signature"))
681    }
682}
683
684impl SignerProvider for KeysManagerClient {
685    type EcdsaSigner = SignerClient;
686
687    fn generate_channel_keys_id(
688        &self,
689        _inbound: bool,
690        _channel_value_satoshis: u64,
691        _user_channel_id: u128,
692    ) -> [u8; 32] {
693        let dbid = self.next_dbid.fetch_add(1, Ordering::AcqRel);
694        ChannelId::new_from_oid(dbid).ldk_channel_keys_id()
695    }
696
697    fn derive_channel_signer(
698        &self,
699        channel_value_satoshis: u64,
700        channel_keys_id: [u8; 32],
701    ) -> Self::EcdsaSigner {
702        // We don't use the peer_id, because it's not easy to get at this point within the LDK framework.
703        // The dbid is unique, so that's enough for our purposes.
704        let peer_id = [0u8; 33];
705        let dbid = ChannelId::new(&channel_keys_id).oid();
706
707        let message = NewChannel { peer_id: PubKey(peer_id.clone()), dbid };
708        let _: NewChannelReply = self.call(message).expect("NewChannel");
709
710        let channel_keys = self.get_channel_basepoints(dbid, peer_id);
711
712        SignerClient::new(
713            self.transport.clone(),
714            peer_id,
715            dbid,
716            channel_value_satoshis,
717            channel_keys,
718        )
719    }
720
721    fn read_chan_signer(&self, mut reader: &[u8]) -> Result<Self::EcdsaSigner, DecodeError> {
722        let peer_id = Readable::read(&mut reader)?;
723        let dbid = Readable::read(&mut reader)?;
724        let channel_keys = Readable::read(&mut reader)?;
725        let channel_value = Readable::read(&mut reader)?;
726
727        Ok(SignerClient {
728            transport: self.transport.clone(),
729            peer_id,
730            dbid,
731            channel_keys,
732            channel_value,
733        })
734    }
735
736    fn get_destination_script(&self, _: [u8; 32]) -> Result<ScriptBuf, ()> {
737        let secp_ctx = Secp256k1::new();
738        let wallet_path = dest_wallet_path();
739        let mut key = self.xpub;
740        for i in wallet_path.iter() {
741            key = key.ckd_pub(&secp_ctx, ChildNumber::from_normal_idx(*i).unwrap()).unwrap();
742        }
743        let pubkey = key.public_key;
744        Ok(ScriptBuf::new_p2wpkh(&WPubkeyHash::hash(&pubkey.serialize())))
745    }
746
747    fn get_shutdown_scriptpubkey(&self) -> Result<ShutdownScript, ()> {
748        Ok(ShutdownScript::try_from(self.get_destination_script([0; 32])?).expect("script"))
749    }
750}
751
752impl OutputSpender for KeysManagerClient {
753    fn spend_spendable_outputs<C: Signing>(
754        &self,
755        descriptors: &[&SpendableOutputDescriptor],
756        outputs: Vec<TxOut>,
757        change_destination_script: ScriptBuf,
758        feerate_sat_per_1000_weight: u32,
759        locktime: Option<LockTime>,
760        _secp_ctx: &Secp256k1<C>,
761    ) -> Result<Transaction, ()> {
762        let mut tx = create_spending_transaction(
763            descriptors,
764            outputs,
765            change_destination_script,
766            feerate_sat_per_1000_weight,
767        )
768        .unwrap();
769        tx.lock_time = locktime.unwrap_or(LockTime::ZERO);
770        let witnesses = self.sign_onchain_tx(&tx, descriptors);
771        for (idx, w) in witnesses.into_iter().enumerate() {
772            tx.input[idx].witness = Witness::from_slice(&w);
773        }
774        Ok(tx)
775    }
776}
777
778impl InnerSign for SignerClient {
779    fn box_clone(&self) -> Box<dyn InnerSign> {
780        Box::new(self.clone())
781    }
782
783    fn as_any(&self) -> &dyn Any {
784        self
785    }
786
787    fn vwrite(&self, writer: &mut Vec<u8>) -> Result<(), bitcoin::io::Error> {
788        self.write(writer)
789    }
790}