mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-01-19 05:43:55 +01:00
Return ExpandedKey from NodeSigner
NodeSinger::get_inbound_payment_key_material returns KeyMaterial, which is used for constructing an ExpandedKey. Change the trait to return an ExpandedKey directly instead. This allows for direct access to the ExpandedKey when a NodeSigner referenced is available. Otherwise, it would either need to be reconstructed or passed in separately.
This commit is contained in:
parent
bd0dd9b9a8
commit
09bec6eee9
@ -50,6 +50,7 @@ use lightning::ln::channelmanager::{
|
||||
ChainParameters, ChannelManager, ChannelManagerReadArgs, PaymentId, RecipientOnionFields, Retry,
|
||||
};
|
||||
use lightning::ln::functional_test_utils::*;
|
||||
use lightning::ln::inbound_payment::ExpandedKey;
|
||||
use lightning::ln::msgs::{
|
||||
self, ChannelMessageHandler, CommitmentUpdate, DecodeError, Init, UpdateAddHTLC,
|
||||
};
|
||||
@ -334,10 +335,10 @@ impl NodeSigner for KeyProvider {
|
||||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
#[rustfmt::skip]
|
||||
let random_bytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, self.node_secret[31]];
|
||||
KeyMaterial(random_bytes)
|
||||
ExpandedKey::new(&KeyMaterial(random_bytes))
|
||||
}
|
||||
|
||||
fn sign_invoice(
|
||||
|
@ -43,6 +43,7 @@ use lightning::ln::channelmanager::{
|
||||
ChainParameters, ChannelManager, InterceptId, PaymentId, RecipientOnionFields, Retry,
|
||||
};
|
||||
use lightning::ln::functional_test_utils::*;
|
||||
use lightning::ln::inbound_payment::ExpandedKey;
|
||||
use lightning::ln::msgs::{self, DecodeError};
|
||||
use lightning::ln::peer_handler::{
|
||||
IgnoringMessageHandler, MessageHandler, PeerManager, SocketDescriptor,
|
||||
@ -79,7 +80,6 @@ use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey}
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::convert::TryInto;
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@ -364,7 +364,7 @@ impl<'a> Drop for MoneyLossDetector<'a> {
|
||||
|
||||
struct KeyProvider {
|
||||
node_secret: SecretKey,
|
||||
inbound_payment_key: KeyMaterial,
|
||||
inbound_payment_key: ExpandedKey,
|
||||
counter: AtomicU64,
|
||||
signer_state: RefCell<HashMap<u8, (bool, Arc<Mutex<EnforcementState>>)>>,
|
||||
}
|
||||
@ -402,8 +402,8 @@ impl NodeSigner for KeyProvider {
|
||||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
|
||||
self.inbound_payment_key.clone()
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
self.inbound_payment_key
|
||||
}
|
||||
|
||||
fn sign_invoice(
|
||||
@ -636,7 +636,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc<dyn Logger>) {
|
||||
|
||||
let keys_manager = Arc::new(KeyProvider {
|
||||
node_secret: our_network_key.clone(),
|
||||
inbound_payment_key: KeyMaterial(inbound_payment_key.try_into().unwrap()),
|
||||
inbound_payment_key: ExpandedKey::new(&KeyMaterial(inbound_payment_key)),
|
||||
counter: AtomicU64::new(0),
|
||||
signer_state: RefCell::new(new_hash_map()),
|
||||
});
|
||||
|
@ -9,6 +9,7 @@ use lightning::blinded_path::message::{
|
||||
AsyncPaymentsContext, BlindedMessagePath, MessageContext, OffersContext,
|
||||
};
|
||||
use lightning::blinded_path::EmptyNodeIdLookUp;
|
||||
use lightning::ln::inbound_payment::ExpandedKey;
|
||||
use lightning::ln::msgs::{self, DecodeError, OnionMessageHandler};
|
||||
use lightning::ln::peer_handler::IgnoringMessageHandler;
|
||||
use lightning::ln::script::ShutdownScript;
|
||||
@ -22,7 +23,7 @@ use lightning::onion_message::messenger::{
|
||||
};
|
||||
use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler};
|
||||
use lightning::onion_message::packet::OnionMessageContents;
|
||||
use lightning::sign::{EntropySource, KeyMaterial, NodeSigner, Recipient, SignerProvider};
|
||||
use lightning::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
|
||||
use lightning::types::features::InitFeatures;
|
||||
use lightning::util::logger::Logger;
|
||||
use lightning::util::ser::{Readable, Writeable, Writer};
|
||||
@ -223,7 +224,7 @@ impl NodeSigner for KeyProvider {
|
||||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ use crate::ln::channelmanager;
|
||||
use crate::ln::channelmanager::{HTLCFailureMsg, PaymentId, RecipientOnionFields};
|
||||
use crate::types::features::{BlindedHopFeatures, ChannelFeatures, NodeFeatures};
|
||||
use crate::ln::functional_test_utils::*;
|
||||
use crate::ln::inbound_payment::ExpandedKey;
|
||||
use crate::ln::msgs;
|
||||
use crate::ln::msgs::{ChannelMessageHandler, UnsignedGossipMessage};
|
||||
use crate::ln::onion_payment;
|
||||
@ -29,7 +30,7 @@ use crate::ln::outbound_payment::{Retry, IDEMPOTENCY_TIMEOUT_TICKS};
|
||||
use crate::offers::invoice::UnsignedBolt12Invoice;
|
||||
use crate::prelude::*;
|
||||
use crate::routing::router::{BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters};
|
||||
use crate::sign::{KeyMaterial, NodeSigner, Recipient};
|
||||
use crate::sign::{NodeSigner, Recipient};
|
||||
use crate::util::config::UserConfig;
|
||||
use crate::util::ser::WithoutLength;
|
||||
use crate::util::test_utils;
|
||||
@ -1221,9 +1222,7 @@ fn blinded_keysend() {
|
||||
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
|
||||
let chan_upd_1_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0).0.contents;
|
||||
|
||||
let inbound_payment_key = inbound_payment::ExpandedKey::new(
|
||||
&nodes[2].keys_manager.get_inbound_payment_key_material()
|
||||
);
|
||||
let inbound_payment_key = nodes[2].keys_manager.get_inbound_payment_key();
|
||||
let payment_secret = inbound_payment::create_for_spontaneous_payment(
|
||||
&inbound_payment_key, None, u32::MAX, nodes[2].node.duration_since_epoch().as_secs(), None
|
||||
).unwrap();
|
||||
@ -1262,9 +1261,7 @@ fn blinded_mpp_keysend() {
|
||||
let chan_1_3 = create_announced_chan_between_nodes(&nodes, 1, 3);
|
||||
let chan_2_3 = create_announced_chan_between_nodes(&nodes, 2, 3);
|
||||
|
||||
let inbound_payment_key = inbound_payment::ExpandedKey::new(
|
||||
&nodes[3].keys_manager.get_inbound_payment_key_material()
|
||||
);
|
||||
let inbound_payment_key = nodes[3].keys_manager.get_inbound_payment_key();
|
||||
let payment_secret = inbound_payment::create_for_spontaneous_payment(
|
||||
&inbound_payment_key, None, u32::MAX, nodes[3].node.duration_since_epoch().as_secs(), None
|
||||
).unwrap();
|
||||
@ -1528,7 +1525,7 @@ fn route_blinding_spec_test_vector() {
|
||||
}
|
||||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial { unreachable!() }
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey { unreachable!() }
|
||||
fn get_node_id(&self, _recipient: Recipient) -> Result<PublicKey, ()> { unreachable!() }
|
||||
fn sign_invoice(
|
||||
&self, _invoice: &RawBolt11Invoice, _recipient: Recipient,
|
||||
|
@ -233,7 +233,7 @@ pub enum PendingHTLCRouting {
|
||||
requires_blinded_error: bool,
|
||||
/// Set if we are receiving a keysend to a blinded path, meaning we created the
|
||||
/// [`PaymentSecret`] and should verify it using our
|
||||
/// [`NodeSigner::get_inbound_payment_key_material`].
|
||||
/// [`NodeSigner::get_inbound_payment_key`].
|
||||
has_recipient_created_payment_secret: bool,
|
||||
},
|
||||
}
|
||||
@ -3494,8 +3494,7 @@ where
|
||||
) -> Self {
|
||||
let mut secp_ctx = Secp256k1::new();
|
||||
secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
|
||||
let inbound_pmt_key_material = node_signer.get_inbound_payment_key_material();
|
||||
let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
|
||||
let expanded_inbound_key = node_signer.get_inbound_payment_key();
|
||||
ChannelManager {
|
||||
default_configuration: config.clone(),
|
||||
chain_hash: ChainHash::using_genesis_block(params.network),
|
||||
@ -13902,8 +13901,7 @@ where
|
||||
}, None));
|
||||
}
|
||||
|
||||
let inbound_pmt_key_material = args.node_signer.get_inbound_payment_key_material();
|
||||
let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
|
||||
let expanded_inbound_key = args.node_signer.get_inbound_payment_key();
|
||||
|
||||
let mut claimable_payments = hash_map_with_capacity(claimable_htlcs_list.len());
|
||||
if let Some(purposes) = claimable_htlc_purposes {
|
||||
|
@ -37,10 +37,10 @@ const AMT_MSAT_LEN: usize = 8;
|
||||
// retrieve said payment type bits.
|
||||
const METHOD_TYPE_OFFSET: usize = 5;
|
||||
|
||||
/// A set of keys that were HKDF-expanded from an initial call to
|
||||
/// [`NodeSigner::get_inbound_payment_key_material`].
|
||||
/// A set of keys that were HKDF-expanded. Returned by [`NodeSigner::get_inbound_payment_key`].
|
||||
///
|
||||
/// [`NodeSigner::get_inbound_payment_key_material`]: crate::sign::NodeSigner::get_inbound_payment_key_material
|
||||
/// [`NodeSigner::get_inbound_payment_key`]: crate::sign::NodeSigner::get_inbound_payment_key
|
||||
#[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct ExpandedKey {
|
||||
/// The key used to encrypt the bytes containing the payment metadata (i.e. the amount and
|
||||
/// expiry, included for payment verification on decryption).
|
||||
@ -129,9 +129,8 @@ fn min_final_cltv_expiry_delta_from_metadata(bytes: [u8; METADATA_LEN]) -> u16 {
|
||||
/// `ChannelManager` is required. Useful for generating invoices for [phantom node payments] without
|
||||
/// a `ChannelManager`.
|
||||
///
|
||||
/// `keys` is generated by calling [`NodeSigner::get_inbound_payment_key_material`] and then
|
||||
/// calling [`ExpandedKey::new`] with its result. It is recommended to cache this value and not
|
||||
/// regenerate it for each new inbound payment.
|
||||
/// `keys` is generated by calling [`NodeSigner::get_inbound_payment_key`]. It is recommended to
|
||||
/// cache this value and not regenerate it for each new inbound payment.
|
||||
///
|
||||
/// `current_time` is a Unix timestamp representing the current time.
|
||||
///
|
||||
@ -139,7 +138,7 @@ fn min_final_cltv_expiry_delta_from_metadata(bytes: [u8; METADATA_LEN]) -> u16 {
|
||||
/// on versions of LDK prior to 0.0.114.
|
||||
///
|
||||
/// [phantom node payments]: crate::sign::PhantomKeysManager
|
||||
/// [`NodeSigner::get_inbound_payment_key_material`]: crate::sign::NodeSigner::get_inbound_payment_key_material
|
||||
/// [`NodeSigner::get_inbound_payment_key`]: crate::sign::NodeSigner::get_inbound_payment_key
|
||||
pub fn create<ES: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>,
|
||||
invoice_expiry_delta_secs: u32, entropy_source: &ES, current_time: u64,
|
||||
min_final_cltv_expiry_delta: Option<u16>) -> Result<(PaymentHash, PaymentSecret), ()>
|
||||
@ -281,7 +280,7 @@ fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METAD
|
||||
/// For payments including a custom `min_final_cltv_expiry_delta`, the metadata is constructed as:
|
||||
/// payment method (3 bits) || payment amount (8 bytes - 3 bits) || min_final_cltv_expiry_delta (2 bytes) || expiry (6 bytes)
|
||||
///
|
||||
/// In both cases the result is then encrypted using a key derived from [`NodeSigner::get_inbound_payment_key_material`].
|
||||
/// In both cases the result is then encrypted using a key derived from [`NodeSigner::get_inbound_payment_key`].
|
||||
///
|
||||
/// Then on payment receipt, we verify in this method that the payment preimage and payment secret
|
||||
/// match what was constructed.
|
||||
@ -302,7 +301,7 @@ fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METAD
|
||||
///
|
||||
/// See [`ExpandedKey`] docs for more info on the individual keys used.
|
||||
///
|
||||
/// [`NodeSigner::get_inbound_payment_key_material`]: crate::sign::NodeSigner::get_inbound_payment_key_material
|
||||
/// [`NodeSigner::get_inbound_payment_key`]: crate::sign::NodeSigner::get_inbound_payment_key
|
||||
/// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
|
||||
/// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
|
||||
pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: &msgs::FinalOnionHopData,
|
||||
|
@ -12,7 +12,7 @@ use crate::sign::{Recipient, NodeSigner, SignerProvider, EntropySource};
|
||||
use crate::types::payment::PaymentHash;
|
||||
use crate::ln::channel_state::ChannelDetails;
|
||||
use crate::ln::channelmanager::{Bolt11InvoiceParameters, ChannelManager, PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA, MIN_FINAL_CLTV_EXPIRY_DELTA};
|
||||
use crate::ln::inbound_payment::{create, create_from_hash, ExpandedKey};
|
||||
use crate::ln::inbound_payment::{create, create_from_hash};
|
||||
use crate::routing::gossip::RoutingFees;
|
||||
use crate::routing::router::{RouteHint, RouteHintHop, Router};
|
||||
use crate::onion_message::messenger::MessageRouter;
|
||||
@ -165,8 +165,7 @@ where
|
||||
Bolt11InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0),
|
||||
};
|
||||
|
||||
// If we ever see performance here being too slow then we should probably take this ExpandedKey as a parameter instead.
|
||||
let keys = ExpandedKey::new(&node_signer.get_inbound_payment_key_material());
|
||||
let keys = node_signer.get_inbound_payment_key();
|
||||
let (payment_hash, payment_secret) = if let Some(payment_hash) = payment_hash {
|
||||
let payment_secret = create_from_hash(
|
||||
&keys,
|
||||
|
@ -51,7 +51,6 @@ use crate::events::{ClosureReason, Event, MessageSendEventsProvider, PaymentFail
|
||||
use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self};
|
||||
use crate::types::features::Bolt12InvoiceFeatures;
|
||||
use crate::ln::functional_test_utils::*;
|
||||
use crate::ln::inbound_payment::ExpandedKey;
|
||||
use crate::ln::msgs::{ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement};
|
||||
use crate::ln::outbound_payment::IDEMPOTENCY_TIMEOUT_TICKS;
|
||||
use crate::offers::invoice::Bolt12Invoice;
|
||||
@ -2218,7 +2217,7 @@ fn fails_paying_invoice_with_unknown_required_features() {
|
||||
let payment_paths = invoice.payment_paths().to_vec();
|
||||
let payment_hash = invoice.payment_hash();
|
||||
|
||||
let expanded_key = ExpandedKey::new(&alice.keys_manager.get_inbound_payment_key_material());
|
||||
let expanded_key = alice.keys_manager.get_inbound_payment_key();
|
||||
let secp_ctx = Secp256k1::new();
|
||||
|
||||
let created_at = alice.node.duration_since_epoch();
|
||||
|
@ -51,6 +51,7 @@ use crate::ln::channel_keys::{
|
||||
add_public_key_tweak, DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, HtlcKey,
|
||||
RevocationBasepoint, RevocationKey,
|
||||
};
|
||||
use crate::ln::inbound_payment::ExpandedKey;
|
||||
#[cfg(taproot)]
|
||||
use crate::ln::msgs::PartialSignatureWithNonce;
|
||||
use crate::ln::msgs::{UnsignedChannelAnnouncement, UnsignedGossipMessage};
|
||||
@ -820,7 +821,7 @@ pub trait EntropySource {
|
||||
|
||||
/// A trait that can handle cryptographic operations at the scope level of a node.
|
||||
pub trait NodeSigner {
|
||||
/// Get secret key material as bytes for use in encrypting and decrypting inbound payment data.
|
||||
/// Get the [`ExpandedKey`] for use in encrypting and decrypting inbound payment data.
|
||||
///
|
||||
/// If the implementor of this trait supports [phantom node payments], then every node that is
|
||||
/// intended to be included in the phantom invoice route hints must return the same value from
|
||||
@ -832,7 +833,7 @@ pub trait NodeSigner {
|
||||
/// This method must return the same value each time it is called.
|
||||
///
|
||||
/// [phantom node payments]: PhantomKeysManager
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial;
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey;
|
||||
|
||||
/// Get node id based on the provided [`Recipient`].
|
||||
///
|
||||
@ -1852,7 +1853,7 @@ pub struct KeysManager {
|
||||
secp_ctx: Secp256k1<secp256k1::All>,
|
||||
node_secret: SecretKey,
|
||||
node_id: PublicKey,
|
||||
inbound_payment_key: KeyMaterial,
|
||||
inbound_payment_key: ExpandedKey,
|
||||
destination_script: ScriptBuf,
|
||||
shutdown_pubkey: PublicKey,
|
||||
channel_master_key: Xpriv,
|
||||
@ -1938,7 +1939,7 @@ impl KeysManager {
|
||||
secp_ctx,
|
||||
node_secret,
|
||||
node_id,
|
||||
inbound_payment_key: KeyMaterial(inbound_pmt_key_bytes),
|
||||
inbound_payment_key: ExpandedKey::new(&KeyMaterial(inbound_pmt_key_bytes)),
|
||||
|
||||
destination_script,
|
||||
shutdown_pubkey,
|
||||
@ -2175,7 +2176,7 @@ impl NodeSigner for KeysManager {
|
||||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
self.inbound_payment_key.clone()
|
||||
}
|
||||
|
||||
@ -2312,7 +2313,7 @@ pub struct PhantomKeysManager {
|
||||
pub(crate) inner: KeysManager,
|
||||
#[cfg(not(test))]
|
||||
inner: KeysManager,
|
||||
inbound_payment_key: KeyMaterial,
|
||||
inbound_payment_key: ExpandedKey,
|
||||
phantom_secret: SecretKey,
|
||||
phantom_node_id: PublicKey,
|
||||
}
|
||||
@ -2344,7 +2345,7 @@ impl NodeSigner for PhantomKeysManager {
|
||||
Ok(SharedSecret::new(other_key, &node_secret))
|
||||
}
|
||||
|
||||
fn get_inbound_payment_key_material(&self) -> KeyMaterial {
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
self.inbound_payment_key.clone()
|
||||
}
|
||||
|
||||
@ -2444,7 +2445,7 @@ impl PhantomKeysManager {
|
||||
let phantom_node_id = PublicKey::from_secret_key(&inner.secp_ctx, &phantom_secret);
|
||||
Self {
|
||||
inner,
|
||||
inbound_payment_key: KeyMaterial(inbound_key),
|
||||
inbound_payment_key: ExpandedKey::new(&KeyMaterial(inbound_key)),
|
||||
phantom_secret,
|
||||
phantom_node_id,
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ use crate::ln::channelmanager;
|
||||
#[cfg(test)]
|
||||
use crate::ln::chan_utils::CommitmentTransaction;
|
||||
use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures};
|
||||
use crate::ln::inbound_payment::ExpandedKey;
|
||||
use crate::ln::{msgs, wire};
|
||||
use crate::ln::msgs::LightningError;
|
||||
use crate::ln::script::ShutdownScript;
|
||||
@ -1188,7 +1189,7 @@ impl TestNodeSigner {
|
||||
}
|
||||
|
||||
impl NodeSigner for TestNodeSigner {
|
||||
fn get_inbound_payment_key_material(&self) -> crate::sign::KeyMaterial {
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
@ -1254,8 +1255,8 @@ impl NodeSigner for TestKeysInterface {
|
||||
self.backing.ecdh(recipient, other_key, tweak)
|
||||
}
|
||||
|
||||
fn get_inbound_payment_key_material(&self) -> sign::KeyMaterial {
|
||||
self.backing.get_inbound_payment_key_material()
|
||||
fn get_inbound_payment_key(&self) -> ExpandedKey {
|
||||
self.backing.get_inbound_payment_key()
|
||||
}
|
||||
|
||||
fn sign_invoice(&self, invoice: &RawBolt11Invoice, recipient: Recipient) -> Result<RecoverableSignature, ()> {
|
||||
|
Loading…
Reference in New Issue
Block a user