Skip to content

Commit 4e593b7

Browse files
feat: add BOLT12 payer proof support
Add payer-proof creation for outbound BOLT12 payments, persist the invoice context needed to build the proof, and expose the new types through the public and UniFFI surfaces. AI-assisted-by: Codex
1 parent e3379fa commit 4e593b7

File tree

14 files changed

+575
-59
lines changed

14 files changed

+575
-59
lines changed

Cargo.toml

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,17 @@ default = []
3939
#lightning-liquidity = { version = "0.2.0", features = ["std"] }
4040
#lightning-macros = { version = "0.2.0" }
4141

42-
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["std"] }
43-
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953" }
44-
lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["std"] }
45-
lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953" }
46-
lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["tokio"] }
47-
lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953" }
48-
lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953" }
49-
lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["rest-client", "rpc-client", "tokio"] }
50-
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
51-
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["std"] }
52-
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953" }
42+
lightning = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["std"] }
43+
lightning-types = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
44+
lightning-invoice = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["std"] }
45+
lightning-net-tokio = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
46+
lightning-persister = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["tokio"] }
47+
lightning-background-processor = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
48+
lightning-rapid-gossip-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
49+
lightning-block-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["rest-client", "rpc-client", "tokio"] }
50+
lightning-transaction-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
51+
lightning-liquidity = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["std"] }
52+
lightning-macros = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
5353

5454
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
5555
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
@@ -85,7 +85,7 @@ bitcoin-payment-instructions = { git = "https://github.com/tnull/bitcoin-payment
8585
winapi = { version = "0.3", features = ["winbase"] }
8686

8787
[dev-dependencies]
88-
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "49912057895ddfbd69d503de67c80d5576c09953", features = ["std", "_test_utils"] }
88+
lightning = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6", features = ["std", "_test_utils"] }
8989
rand = { version = "0.9.2", default-features = false, features = ["std", "thread_rng", "os_rng"] }
9090
proptest = "1.0.0"
9191
regex = "1.5.6"
@@ -172,15 +172,15 @@ harness = false
172172
#vss-client-ng = { path = "../vss-client" }
173173
#vss-client-ng = { git = "https://github.com/lightningdevkit/vss-client", branch = "main" }
174174
#
175-
#[patch."https://github.com/lightningdevkit/rust-lightning"]
176-
#lightning = { path = "../rust-lightning/lightning" }
177-
#lightning-types = { path = "../rust-lightning/lightning-types" }
178-
#lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
179-
#lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
180-
#lightning-persister = { path = "../rust-lightning/lightning-persister" }
181-
#lightning-background-processor = { path = "../rust-lightning/lightning-background-processor" }
182-
#lightning-rapid-gossip-sync = { path = "../rust-lightning/lightning-rapid-gossip-sync" }
183-
#lightning-block-sync = { path = "../rust-lightning/lightning-block-sync" }
184-
#lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync" }
185-
#lightning-liquidity = { path = "../rust-lightning/lightning-liquidity" }
186-
#lightning-macros = { path = "../rust-lightning/lightning-macros" }
175+
[patch."https://github.com/lightningdevkit/rust-lightning"]
176+
lightning = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
177+
lightning-types = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
178+
lightning-invoice = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
179+
lightning-net-tokio = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
180+
lightning-persister = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
181+
lightning-background-processor = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
182+
lightning-rapid-gossip-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
183+
lightning-block-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
184+
lightning-transaction-sync = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
185+
lightning-liquidity = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }
186+
lightning-macros = { git = "https://github.com/vincenzopalazzo/rust-lightning", rev = "d5baee83aee0e2674020700f77918f46b3925ab6" }

bindings/ldk_node.udl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ enum NodeError {
185185
"FeerateEstimationUpdateTimeout",
186186
"WalletOperationFailed",
187187
"WalletOperationTimeout",
188+
"PayerProofCreationFailed",
189+
"PayerProofUnavailable",
188190
"OnchainTxSigningFailed",
189191
"TxSyncFailed",
190192
"TxSyncTimeout",
@@ -225,6 +227,7 @@ enum NodeError {
225227
"LnurlAuthFailed",
226228
"LnurlAuthTimeout",
227229
"InvalidLnurl",
230+
"InvalidPayerProof",
228231
};
229232

230233
typedef dictionary NodeStatus;

src/builder.rs

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,14 @@ use crate::gossip::GossipSource;
5656
use crate::io::sqlite_store::SqliteStore;
5757
use crate::io::utils::{
5858
read_event_queue, read_external_pathfinding_scores_from_cache, read_network_graph,
59-
read_node_metrics, read_output_sweeper, read_payments, read_peer_info, read_pending_payments,
60-
read_scorer, write_node_metrics,
59+
read_node_metrics, read_output_sweeper, read_payer_proof_contexts, read_payments,
60+
read_peer_info, read_pending_payments, read_scorer, write_node_metrics,
6161
};
6262
use crate::io::vss_store::VssStoreBuilder;
6363
use crate::io::{
64-
self, PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE, PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
64+
self, PAYER_PROOF_CONTEXT_PERSISTENCE_PRIMARY_NAMESPACE,
65+
PAYER_PROOF_CONTEXT_PERSISTENCE_SECONDARY_NAMESPACE,
66+
PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE, PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
6567
PENDING_PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE,
6668
PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
6769
};
@@ -77,8 +79,8 @@ use crate::runtime::{Runtime, RuntimeSpawner};
7779
use crate::tx_broadcaster::TransactionBroadcaster;
7880
use crate::types::{
7981
AsyncPersister, ChainMonitor, ChannelManager, DynStore, DynStoreWrapper, GossipSync, Graph,
80-
KeysManager, MessageRouter, OnionMessenger, PaymentStore, PeerManager, PendingPaymentStore,
81-
Persister, SyncAndAsyncKVStore,
82+
KeysManager, MessageRouter, OnionMessenger, PayerProofContextStore, PaymentStore, PeerManager,
83+
PendingPaymentStore, Persister, SyncAndAsyncKVStore,
8284
};
8385
use crate::wallet::persist::KVStoreWalletPersister;
8486
use crate::wallet::Wallet;
@@ -1260,14 +1262,19 @@ fn build_with_store_internal(
12601262

12611263
let kv_store_ref = Arc::clone(&kv_store);
12621264
let logger_ref = Arc::clone(&logger);
1263-
let (payment_store_res, node_metris_res, pending_payment_store_res) =
1264-
runtime.block_on(async move {
1265-
tokio::join!(
1266-
read_payments(&*kv_store_ref, Arc::clone(&logger_ref)),
1267-
read_node_metrics(&*kv_store_ref, Arc::clone(&logger_ref)),
1268-
read_pending_payments(&*kv_store_ref, Arc::clone(&logger_ref))
1269-
)
1270-
});
1265+
let (
1266+
payment_store_res,
1267+
node_metris_res,
1268+
pending_payment_store_res,
1269+
payer_proof_context_store_res,
1270+
) = runtime.block_on(async move {
1271+
tokio::join!(
1272+
read_payments(&*kv_store_ref, Arc::clone(&logger_ref)),
1273+
read_node_metrics(&*kv_store_ref, Arc::clone(&logger_ref)),
1274+
read_pending_payments(&*kv_store_ref, Arc::clone(&logger_ref)),
1275+
read_payer_proof_contexts(&*kv_store_ref, Arc::clone(&logger_ref))
1276+
)
1277+
});
12711278

12721279
// Initialize the status fields.
12731280
let node_metrics = match node_metris_res {
@@ -1296,6 +1303,20 @@ fn build_with_store_internal(
12961303
},
12971304
};
12981305

1306+
let payer_proof_context_store = match payer_proof_context_store_res {
1307+
Ok(contexts) => Arc::new(PayerProofContextStore::new(
1308+
contexts,
1309+
PAYER_PROOF_CONTEXT_PERSISTENCE_PRIMARY_NAMESPACE.to_string(),
1310+
PAYER_PROOF_CONTEXT_PERSISTENCE_SECONDARY_NAMESPACE.to_string(),
1311+
Arc::clone(&kv_store),
1312+
Arc::clone(&logger),
1313+
)),
1314+
Err(e) => {
1315+
log_error!(logger, "Failed to read payer proof contexts from store: {}", e);
1316+
return Err(BuildError::ReadFailed);
1317+
},
1318+
};
1319+
12991320
let (chain_source, chain_tip_opt) = match chain_data_source_config {
13001321
Some(ChainDataSourceConfig::Esplora { server_url, headers, sync_config }) => {
13011322
let sync_config = sync_config.unwrap_or(EsploraSyncConfig::default());
@@ -1547,6 +1568,7 @@ fn build_with_store_internal(
15471568
Arc::clone(&persister),
15481569
Arc::clone(&keys_manager),
15491570
peer_storage_key,
1571+
false,
15501572
));
15511573

15521574
// Initialize the network graph, scorer, and router
@@ -1992,6 +2014,7 @@ fn build_with_store_internal(
19922014
scorer,
19932015
peer_store,
19942016
payment_store,
2017+
payer_proof_context_store,
19952018
lnurl_auth,
19962019
is_running,
19972020
node_metrics,

src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ pub(crate) fn default_user_config(config: &Config) -> UserConfig {
342342
user_config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx =
343343
config.anchor_channels_config.is_some();
344344
user_config.reject_inbound_splices = false;
345+
user_config.manually_handle_bolt12_invoices = true;
345346

346347
if may_announce_channel(config).is_err() {
347348
user_config.accept_forwards_to_priv_channels = false;

src/error.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ pub enum Error {
5757
WalletOperationFailed,
5858
/// A wallet operation timed out.
5959
WalletOperationTimeout,
60+
/// Creating a payer proof failed.
61+
PayerProofCreationFailed,
62+
/// A payer proof is unavailable for the requested payment.
63+
PayerProofUnavailable,
6064
/// A signing operation for transaction failed.
6165
OnchainTxSigningFailed,
6266
/// A transaction sync operation failed.
@@ -137,6 +141,8 @@ pub enum Error {
137141
LnurlAuthTimeout,
138142
/// The provided lnurl is invalid.
139143
InvalidLnurl,
144+
/// The provided payer proof is invalid.
145+
InvalidPayerProof,
140146
}
141147

142148
impl fmt::Display for Error {
@@ -168,6 +174,10 @@ impl fmt::Display for Error {
168174
},
169175
Self::WalletOperationFailed => write!(f, "Failed to conduct wallet operation."),
170176
Self::WalletOperationTimeout => write!(f, "A wallet operation timed out."),
177+
Self::PayerProofCreationFailed => write!(f, "Failed to create payer proof."),
178+
Self::PayerProofUnavailable => {
179+
write!(f, "A payer proof is unavailable for the requested payment.")
180+
},
171181
Self::OnchainTxSigningFailed => write!(f, "Failed to sign given transaction."),
172182
Self::TxSyncFailed => write!(f, "Failed to sync transactions."),
173183
Self::TxSyncTimeout => write!(f, "Syncing transactions timed out."),
@@ -222,6 +232,7 @@ impl fmt::Display for Error {
222232
Self::LnurlAuthFailed => write!(f, "LNURL-auth authentication failed."),
223233
Self::LnurlAuthTimeout => write!(f, "LNURL-auth authentication timed out."),
224234
Self::InvalidLnurl => write!(f, "The provided lnurl is invalid."),
235+
Self::InvalidPayerProof => write!(f, "The provided payer proof is invalid."),
225236
}
226237
}
227238
}

0 commit comments

Comments
 (0)