Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 24 additions & 24 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ default = []
#lightning-liquidity = { version = "0.2.0", features = ["std"] }
#lightning-macros = { version = "0.2.0" }

lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["std"] }
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7" }
lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["std"] }
lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7" }
lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["tokio"] }
lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7" }
lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7" }
lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["rest-client", "rpc-client", "tokio"] }
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["std"] }
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7" }
lightning = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["std"] }
lightning-types = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-invoice = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["std"] }
lightning-net-tokio = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-persister = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["tokio"] }
lightning-background-processor = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-rapid-gossip-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-block-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["rest-client", "rpc-client", "tokio"] }
lightning-transaction-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
lightning-liquidity = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["std"] }
lightning-macros = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }

bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
Expand Down Expand Up @@ -85,7 +85,7 @@ bitcoin-payment-instructions = { git = "https://github.com/joostjager/bitcoin-pa
winapi = { version = "0.3", features = ["winbase"] }

[dev-dependencies]
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "dcf0c203e166da2348bef12b2e5eff4a250cdec7", features = ["std", "_test_utils"] }
lightning = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085", features = ["std", "_test_utils"] }
rand = { version = "0.9.2", default-features = false, features = ["std", "thread_rng", "os_rng"] }
proptest = "1.0.0"
regex = "1.5.6"
Expand Down Expand Up @@ -172,15 +172,15 @@ harness = false
#vss-client-ng = { path = "../vss-client" }
#vss-client-ng = { git = "https://github.com/lightningdevkit/vss-client", branch = "main" }
#
#[patch."https://github.com/lightningdevkit/rust-lightning"]
#lightning = { path = "../rust-lightning/lightning" }
#lightning-types = { path = "../rust-lightning/lightning-types" }
#lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
#lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
#lightning-persister = { path = "../rust-lightning/lightning-persister" }
#lightning-background-processor = { path = "../rust-lightning/lightning-background-processor" }
#lightning-rapid-gossip-sync = { path = "../rust-lightning/lightning-rapid-gossip-sync" }
#lightning-block-sync = { path = "../rust-lightning/lightning-block-sync" }
#lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync" }
#lightning-liquidity = { path = "../rust-lightning/lightning-liquidity" }
#lightning-macros = { path = "../rust-lightning/lightning-macros" }
[patch."https://github.com/lightningdevkit/rust-lightning"]
lightning = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-types = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-invoice = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-net-tokio = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-persister = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-background-processor = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-rapid-gossip-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-block-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-transaction-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-liquidity = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
lightning-macros = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "c8363950d753f954b47d2bf4aaff07928c86b085" }
3 changes: 3 additions & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ enum NodeError {
"FeerateEstimationUpdateTimeout",
"WalletOperationFailed",
"WalletOperationTimeout",
"PayerProofCreationFailed",
"PayerProofUnavailable",
"OnchainTxSigningFailed",
"TxSyncFailed",
"TxSyncTimeout",
Expand Down Expand Up @@ -225,6 +227,7 @@ enum NodeError {
"LnurlAuthFailed",
"LnurlAuthTimeout",
"InvalidLnurl",
"InvalidPayerProof",
};

typedef dictionary NodeStatus;
Expand Down
9 changes: 6 additions & 3 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ use crate::runtime::{Runtime, RuntimeSpawner};
use crate::tx_broadcaster::TransactionBroadcaster;
use crate::types::{
AsyncPersister, ChainMonitor, ChannelManager, DynStore, DynStoreRef, DynStoreWrapper,
GossipSync, Graph, KeysManager, MessageRouter, OnionMessenger, PaymentStore, PeerManager,
PendingPaymentStore, SyncAndAsyncKVStore,
GossipSync, Graph, KeysManager, MessageRouter, OnionMessenger, PayerProofContextStore,
PaymentStore, PeerManager, PendingPaymentStore, SyncAndAsyncKVStore,
};
use crate::wallet::persist::KVStoreWalletPersister;
use crate::wallet::Wallet;
Expand Down Expand Up @@ -1265,7 +1265,7 @@ fn build_with_store_internal(
tokio::join!(
read_payments(&*kv_store_ref, Arc::clone(&logger_ref)),
read_node_metrics(&*kv_store_ref, Arc::clone(&logger_ref)),
read_pending_payments(&*kv_store_ref, Arc::clone(&logger_ref))
read_pending_payments(&*kv_store_ref, Arc::clone(&logger_ref)),
)
});

Expand Down Expand Up @@ -1296,6 +1296,8 @@ fn build_with_store_internal(
},
};

let payer_proof_context_store = Arc::new(PayerProofContextStore::new());

let (chain_source, chain_tip_opt) = match chain_data_source_config {
Some(ChainDataSourceConfig::Esplora { server_url, headers, sync_config }) => {
let sync_config = sync_config.unwrap_or(EsploraSyncConfig::default());
Expand Down Expand Up @@ -1987,6 +1989,7 @@ fn build_with_store_internal(
scorer,
peer_store,
payment_store,
payer_proof_context_store,
lnurl_auth,
is_running,
node_metrics,
Expand Down
11 changes: 11 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ pub enum Error {
WalletOperationFailed,
/// A wallet operation timed out.
WalletOperationTimeout,
/// Creating a payer proof failed.
PayerProofCreationFailed,
/// A payer proof is unavailable for the requested payment.
PayerProofUnavailable,
/// A signing operation for transaction failed.
OnchainTxSigningFailed,
/// A transaction sync operation failed.
Expand Down Expand Up @@ -137,6 +141,8 @@ pub enum Error {
LnurlAuthTimeout,
/// The provided lnurl is invalid.
InvalidLnurl,
/// The provided payer proof is invalid.
InvalidPayerProof,
}

impl fmt::Display for Error {
Expand Down Expand Up @@ -168,6 +174,10 @@ impl fmt::Display for Error {
},
Self::WalletOperationFailed => write!(f, "Failed to conduct wallet operation."),
Self::WalletOperationTimeout => write!(f, "A wallet operation timed out."),
Self::PayerProofCreationFailed => write!(f, "Failed to create payer proof."),
Self::PayerProofUnavailable => {
write!(f, "A payer proof is unavailable for the requested payment.")
},
Self::OnchainTxSigningFailed => write!(f, "Failed to sign given transaction."),
Self::TxSyncFailed => write!(f, "Failed to sync transactions."),
Self::TxSyncTimeout => write!(f, "Syncing transactions timed out."),
Expand Down Expand Up @@ -222,6 +232,7 @@ impl fmt::Display for Error {
Self::LnurlAuthFailed => write!(f, "LNURL-auth authentication failed."),
Self::LnurlAuthTimeout => write!(f, "LNURL-auth authentication timed out."),
Self::InvalidLnurl => write!(f, "The provided lnurl is invalid."),
Self::InvalidPayerProof => write!(f, "The provided payer proof is invalid."),
}
}
}
Expand Down
75 changes: 53 additions & 22 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ use bitcoin::blockdata::locktime::absolute::LockTime;
use bitcoin::secp256k1::PublicKey;
use bitcoin::{Amount, OutPoint};
use lightning::events::bump_transaction::BumpTransactionEvent;
#[cfg(not(feature = "uniffi"))]
use lightning::events::PaidBolt12Invoice;
use lightning::events::{
ClosureReason, Event as LdkEvent, FundingInfo, PaymentFailureReason, PaymentPurpose,
ReplayEvent,
};
use lightning::impl_writeable_tlv_based_enum;
use lightning::ln::channelmanager::PaymentId;
use lightning::ln::types::ChannelId;
#[cfg(not(feature = "uniffi"))]
use lightning::offers::payer_proof::Bolt12InvoiceType;
use lightning::offers::payer_proof::PaidBolt12Invoice;
use lightning::routing::gossip::NodeId;
use lightning::sign::EntropySource;
use lightning::util::config::{
Expand All @@ -40,7 +41,7 @@ use crate::connection::ConnectionManager;
use crate::data_store::DataStoreUpdateResult;
use crate::fee_estimator::ConfirmationTarget;
#[cfg(feature = "uniffi")]
use crate::ffi::PaidBolt12Invoice;
use crate::ffi::PaidBolt12Invoice as FfiPaidBolt12Invoice;
use crate::io::{
EVENT_QUEUE_PERSISTENCE_KEY, EVENT_QUEUE_PERSISTENCE_PRIMARY_NAMESPACE,
EVENT_QUEUE_PERSISTENCE_SECONDARY_NAMESPACE,
Expand All @@ -54,13 +55,19 @@ use crate::payment::store::{
};
use crate::runtime::Runtime;
use crate::types::{
CustomTlvRecord, DynStore, KeysManager, OnionMessenger, PaymentStore, Sweeper, Wallet,
CustomTlvRecord, DynStore, KeysManager, OnionMessenger, PayerProofContextStore, PaymentStore,
Sweeper, Wallet,
};
use crate::{
hex_utils, BumpTransactionEventHandler, ChannelManager, Error, Graph, PeerInfo, PeerStore,
UserChannelId,
};

#[cfg(not(feature = "uniffi"))]
type Bolt12InvoiceInfo = Bolt12InvoiceType;
#[cfg(feature = "uniffi")]
type Bolt12InvoiceInfo = FfiPaidBolt12Invoice;

/// An event emitted by [`Node`], which should be handled by the user.
///
/// [`Node`]: [`crate::Node`]
Expand All @@ -83,17 +90,16 @@ pub enum Event {
payment_preimage: Option<PaymentPreimage>,
/// The total fee which was spent at intermediate hops in this payment.
fee_paid_msat: Option<u64>,
/// The BOLT12 invoice that was paid.
/// The BOLT12 invoice type that was paid.
///
/// This is useful for proof of payment. A third party can verify that the payment was made
/// by checking that the `payment_hash` in the invoice matches `sha256(payment_preimage)`.
///
/// Will be `None` for non-BOLT12 payments.
///
/// Note that static invoices (indicated by [`PaidBolt12Invoice::StaticInvoice`], used for
/// async payments) do not support proof of payment as the payment hash is not derived
/// from a preimage known only to the recipient.
bolt12_invoice: Option<PaidBolt12Invoice>,
/// Note that static invoices (via [`Bolt12InvoiceType::StaticInvoice`], used for
/// async payments) do not support payer proofs.
bolt12_invoice: Option<Bolt12InvoiceInfo>,
},
/// A sent payment has failed.
PaymentFailed {
Expand Down Expand Up @@ -507,6 +513,7 @@ where
network_graph: Arc<Graph>,
liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
payment_store: Arc<PaymentStore>,
payer_proof_context_store: Arc<PayerProofContextStore>,
peer_store: Arc<PeerStore<L>>,
keys_manager: Arc<KeysManager>,
runtime: Arc<Runtime>,
Expand All @@ -527,10 +534,11 @@ where
channel_manager: Arc<ChannelManager>, connection_manager: Arc<ConnectionManager<L>>,
output_sweeper: Arc<Sweeper>, network_graph: Arc<Graph>,
liquidity_source: Option<Arc<LiquiditySource<Arc<Logger>>>>,
payment_store: Arc<PaymentStore>, peer_store: Arc<PeerStore<L>>,
keys_manager: Arc<KeysManager>, static_invoice_store: Option<StaticInvoiceStore>,
onion_messenger: Arc<OnionMessenger>, om_mailbox: Option<Arc<OnionMessageMailbox>>,
runtime: Arc<Runtime>, logger: L, config: Arc<Config>,
payment_store: Arc<PaymentStore>, payer_proof_context_store: Arc<PayerProofContextStore>,
peer_store: Arc<PeerStore<L>>, keys_manager: Arc<KeysManager>,
static_invoice_store: Option<StaticInvoiceStore>, onion_messenger: Arc<OnionMessenger>,
om_mailbox: Option<Arc<OnionMessageMailbox>>, runtime: Arc<Runtime>, logger: L,
config: Arc<Config>,
) -> Self {
Self {
event_queue,
Expand All @@ -542,6 +550,7 @@ where
network_graph,
liquidity_source,
payment_store,
payer_proof_context_store,
peer_store,
keys_manager,
logger,
Expand All @@ -553,6 +562,16 @@ where
}
}

fn persist_payer_proof_context(
&self, payment_id: PaymentId, paid_invoice: &Option<PaidBolt12Invoice>,
) {
if let Some(paid_invoice) = paid_invoice {
if paid_invoice.bolt12_invoice().is_some() {
self.payer_proof_context_store.insert_or_update(payment_id, paid_invoice.clone());
}
}
}

pub async fn handle_event(&self, event: LdkEvent) -> Result<(), ReplayEvent> {
match event {
LdkEvent::FundingGenerationReady {
Expand Down Expand Up @@ -860,6 +879,7 @@ where
offer_id,
payer_note,
quantity,
bolt12_invoice: None,
};

let payment = PaymentDetails::new(
Expand Down Expand Up @@ -1074,11 +1094,28 @@ where
return Ok(());
};

self.persist_payer_proof_context(payment_id, &bolt12_invoice);

#[cfg(not(feature = "uniffi"))]
let bolt12_invoice_info: Option<Bolt12InvoiceInfo> = bolt12_invoice
.as_ref()
.and_then(|p| {
p.bolt12_invoice().map(|i| Bolt12InvoiceType::Bolt12Invoice(i.clone()))
})
.or_else(|| {
bolt12_invoice.as_ref().and_then(|p| {
p.static_invoice().map(|i| Bolt12InvoiceType::StaticInvoice(i.clone()))
})
});
#[cfg(feature = "uniffi")]
let bolt12_invoice_info: Option<Bolt12InvoiceInfo> = bolt12_invoice.map(|p| p.into());

let update = PaymentDetailsUpdate {
hash: Some(Some(payment_hash)),
preimage: Some(Some(payment_preimage)),
fee_paid_msat: Some(fee_paid_msat),
status: Some(PaymentStatus::Succeeded),
bolt12_invoice: Some(bolt12_invoice_info.clone()),
..PaymentDetailsUpdate::new(payment_id)
};

Expand Down Expand Up @@ -1110,7 +1147,7 @@ where
payment_hash,
payment_preimage: Some(payment_preimage),
fee_paid_msat,
bolt12_invoice: bolt12_invoice.map(Into::into),
bolt12_invoice: bolt12_invoice_info,
};

match self.event_queue.add_event(event).await {
Expand Down Expand Up @@ -1562,20 +1599,14 @@ where
};
},
LdkEvent::DiscardFunding { channel_id, funding_info } => {
if let FundingInfo::Contribution { inputs: _, outputs } = funding_info {
if let FundingInfo::Tx { transaction } = funding_info {
log_info!(
self.logger,
"Reclaiming unused addresses from channel {} funding",
channel_id,
);

let tx = bitcoin::Transaction {
version: bitcoin::transaction::Version::TWO,
lock_time: bitcoin::absolute::LockTime::ZERO,
input: vec![],
output: outputs,
};
if let Err(e) = self.wallet.cancel_tx(&tx) {
if let Err(e) = self.wallet.cancel_tx(&transaction) {
log_error!(self.logger, "Failed reclaiming unused addresses: {}", e);
return Err(ReplayEvent());
}
Expand Down
Loading
Loading