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