Skip to content

Commit f792401

Browse files
committed
fixes and improvements post swaps PR merge
* add payment_hash to Event::PaymentForwarded * fix handling of more than 1 HTLC output in a commitment * re-enable BTC-only payments in RGB channels * fix handling of RGB payment files when swapping (for channel balance) using inbound/outbound extension
1 parent dacd467 commit f792401

File tree

5 files changed

+74
-31
lines changed

5 files changed

+74
-31
lines changed

lightning/src/events/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,8 @@ pub enum Event {
780780
outbound_amount_forwarded_rgb: Option<u64>,
781781
/// The rgb amount forwarded inbound.
782782
inbound_amount_forwarded_rgb: Option<u64>,
783+
/// The payment hash used for this payment.
784+
payment_hash: PaymentHash,
783785
},
784786
/// Used to indicate that a channel with the given `channel_id` is being opened and pending
785787
/// confirmation on-chain.
@@ -1061,6 +1063,7 @@ impl Writeable for Event {
10611063
&Event::PaymentForwarded {
10621064
fee_earned_msat, prev_channel_id, claim_from_onchain_tx,
10631065
next_channel_id, outbound_amount_forwarded_msat, outbound_amount_forwarded_rgb, inbound_amount_forwarded_rgb,
1066+
payment_hash,
10641067
} => {
10651068
7u8.write(writer)?;
10661069
write_tlv_fields!(writer, {
@@ -1071,6 +1074,7 @@ impl Writeable for Event {
10711074
(5, outbound_amount_forwarded_msat, option),
10721075
(6, outbound_amount_forwarded_rgb, option),
10731076
(7, inbound_amount_forwarded_rgb, option),
1077+
(8, payment_hash, required),
10741078
});
10751079
},
10761080
&Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason,
@@ -1377,6 +1381,7 @@ impl MaybeReadable for Event {
13771381
let mut outbound_amount_forwarded_msat = None;
13781382
let mut outbound_amount_forwarded_rgb = None;
13791383
let mut inbound_amount_forwarded_rgb = None;
1384+
let mut payment_hash = PaymentHash::new_zero();
13801385
read_tlv_fields!(reader, {
13811386
(0, fee_earned_msat, option),
13821387
(1, prev_channel_id, option),
@@ -1385,10 +1390,12 @@ impl MaybeReadable for Event {
13851390
(5, outbound_amount_forwarded_msat, option),
13861391
(6, outbound_amount_forwarded_rgb, option),
13871392
(7, inbound_amount_forwarded_rgb, option),
1393+
(8, payment_hash, required),
13881394
});
13891395
Ok(Some(Event::PaymentForwarded {
13901396
fee_earned_msat, prev_channel_id, claim_from_onchain_tx, next_channel_id,
13911397
outbound_amount_forwarded_msat, outbound_amount_forwarded_rgb, inbound_amount_forwarded_rgb,
1398+
payment_hash,
13921399
}))
13931400
};
13941401
f()

lightning/src/ln/channel.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3528,6 +3528,9 @@ impl<SP: Deref> Channel<SP> where
35283528
if let OutboundHTLCState::LocalAnnounced(_) = htlc.state {
35293529
log_trace!(logger, " ...promoting outbound LocalAnnounced {} to Committed", &htlc.payment_hash);
35303530
htlc.state = OutboundHTLCState::Committed;
3531+
if let Some(amount_rgb) = htlc.amount_rgb {
3532+
rgb_offered_htlc += amount_rgb;
3533+
}
35313534
}
35323535
if let &mut OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref mut outcome) = &mut htlc.state {
35333536
log_trace!(logger, " ...promoting outbound AwaitingRemoteRevokeToRemove {} to AwaitingRemovedRemoteRevoke", &htlc.payment_hash);
@@ -3537,14 +3540,13 @@ impl<SP: Deref> Channel<SP> where
35373540
htlc.state = OutboundHTLCState::AwaitingRemovedRemoteRevoke(reason);
35383541
require_commitment = true;
35393542
}
3540-
if let Some(amount_rgb) = htlc.amount_rgb {
3541-
rgb_offered_htlc += amount_rgb;
3542-
}
35433543
}
35443544
}
35453545
self.context.value_to_self_msat = (self.context.value_to_self_msat as i64 + value_to_self_msat_diff) as u64;
35463546
if self.context.is_colored() {
3547-
update_rgb_channel_amount_pending(&self.context.channel_id, rgb_offered_htlc, rgb_received_htlc, &self.context.ldk_data_dir);
3547+
if rgb_offered_htlc > 0 || rgb_received_htlc > 0 {
3548+
update_rgb_channel_amount_pending(&self.context.channel_id, rgb_offered_htlc, rgb_received_htlc, &self.context.ldk_data_dir);
3549+
}
35483550
}
35493551

35503552
if let Some((feerate, update_state)) = self.context.pending_update_fee {
@@ -5496,7 +5498,9 @@ impl<SP: Deref> Channel<SP> where
54965498
}
54975499
}
54985500
if self.context.is_colored() {
5499-
update_rgb_channel_amount_pending(&self.context.channel_id, 0, rgb_received_htlc, &self.context.ldk_data_dir);
5501+
if rgb_received_htlc > 0 {
5502+
update_rgb_channel_amount_pending(&self.context.channel_id, 0, rgb_received_htlc, &self.context.ldk_data_dir);
5503+
}
55005504
}
55015505
if let Some((feerate, update_state)) = self.context.pending_update_fee {
55025506
if update_state == FeeUpdateState::AwaitingRemoteRevokeToAnnounce {

lightning/src/ln/channelmanager.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ use crate::ln::channel::{Channel, ChannelPhase, ChannelContext, ChannelError, Ch
4848
use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
4949
#[cfg(any(feature = "_test_utils", test))]
5050
use crate::ln::features::Bolt11InvoiceFeatures;
51-
use crate::rgb_utils::{handle_funding, parse_rgb_payment_info};
51+
use crate::rgb_utils::{get_rgb_payment_info_path, handle_funding, parse_rgb_payment_info};
5252
use crate::routing::gossip::NetworkGraph;
5353
use crate::routing::router::{BlindedTail, DefaultRouter, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, Router};
5454
use crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
@@ -3472,11 +3472,10 @@ where
34723472
// The top-level caller should hold the total_consistency_lock read lock.
34733473
debug_assert!(self.total_consistency_lock.try_write().is_err());
34743474

3475-
let htlc_payment_hash = hex::encode(payment_hash.0);
3476-
let rgb_payment_info_hash_path = self.ldk_data_dir.join(htlc_payment_hash);
3477-
let path = if rgb_payment_info_hash_path.exists() {
3478-
let rgb_payment_info = parse_rgb_payment_info(&rgb_payment_info_hash_path);
3479-
if rgb_payment_info.override_route_amount {
3475+
let rgb_payment_info_hash_path_outbound = get_rgb_payment_info_path(payment_hash, &self.ldk_data_dir, false);
3476+
let path = if rgb_payment_info_hash_path_outbound.exists() {
3477+
let rgb_payment_info = parse_rgb_payment_info(&rgb_payment_info_hash_path_outbound);
3478+
if rgb_payment_info.swap_payment {
34803479
let mut path = path.clone();
34813480
for hop in &mut path.hops {
34823481
hop.rgb_amount = Some(rgb_payment_info.amount);
@@ -5810,6 +5809,7 @@ where
58105809
claimed_htlc_value.checked_sub(forwarded_htlc_value)
58115810
} else { None }
58125811
} else { None };
5812+
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
58135813
Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel {
58145814
event: events::Event::PaymentForwarded {
58155815
fee_earned_msat,
@@ -5819,6 +5819,7 @@ where
58195819
outbound_amount_forwarded_msat: forwarded_htlc_value_msat,
58205820
outbound_amount_forwarded_rgb,
58215821
inbound_amount_forwarded_rgb,
5822+
payment_hash,
58225823
},
58235824
downstream_counterparty_and_funding_outpoint: chan_to_release,
58245825
})

lightning/src/ln/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ impl core::fmt::Display for PaymentHash {
8888
}
8989
}
9090

91+
impl PaymentHash {
92+
/// Create a payment hash consisting of all-zeros data (e.g. when uninitialized or a placeholder).
93+
pub fn new_zero() -> Self {
94+
Self([0; 32])
95+
}
96+
}
97+
9198
/// payment_preimage type, use to route payment between hop
9299
///
93100
/// This is not exported to bindings users as we just use [u8; 32] directly

lightning/src/rgb_utils/mod.rs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ pub const BITCOIN_NETWORK_FNAME: &str = "bitcoin_network";
5858
pub const ELECTRUM_URL_FNAME: &str = "electrum_url";
5959
/// Name of the file containing the wallet fingerprint
6060
pub const WALLET_FINGERPRINT_FNAME: &str = "wallet_fingerprint";
61+
const INBOUND_EXT: &str = "inbound";
62+
const OUTBOUND_EXT: &str = "outbound";
6163

6264
/// RGB channel info
6365
#[derive(Debug, Clone, Deserialize, Serialize)]
@@ -82,7 +84,7 @@ pub struct RgbPaymentInfo {
8284
/// RGB remote amount
8385
pub remote_rgb_amount: u64,
8486
/// Whether the RGB amount in route should be overridden
85-
pub override_route_amount: bool,
87+
pub swap_payment: bool,
8688
/// Whether the payment is inbound
8789
pub inbound: bool,
8890
}
@@ -166,15 +168,29 @@ pub(crate) fn color_commitment<SP: Deref>(channel_context: &ChannelContext<SP>,
166168
.assignments_type(&FieldName::from("beneficiary")).expect("valid assignment");
167169

168170
for htlc in commitment_tx.htlcs() {
171+
if htlc.amount_rgb.unwrap_or(0) == 0 {
172+
continue;
173+
}
174+
let htlc_amount_rgb = htlc.amount_rgb.expect("this HTLC has RGB assets");
175+
169176
let htlc_vout = htlc.transaction_output_index.unwrap();
170177

178+
let inbound = htlc.offered == counterparty;
179+
171180
let htlc_payment_hash = hex::encode(htlc.payment_hash.0);
172181
let htlc_proxy_id = format!("{chan_id}{htlc_payment_hash}");
173-
let rgb_payment_info_proxy_id_path = ldk_data_dir.join(htlc_proxy_id);
174-
182+
let mut rgb_payment_info_proxy_id_path = ldk_data_dir.join(htlc_proxy_id);
175183
let rgb_payment_info_path = ldk_data_dir.join(htlc_payment_hash);
176-
let mut rgb_payment_info_tmp_path = rgb_payment_info_path.clone();
177-
rgb_payment_info_tmp_path.set_extension("pending");
184+
let mut rgb_payment_info_path = rgb_payment_info_path.clone();
185+
if inbound {
186+
rgb_payment_info_proxy_id_path.set_extension(INBOUND_EXT);
187+
rgb_payment_info_path.set_extension(INBOUND_EXT);
188+
} else {
189+
rgb_payment_info_proxy_id_path.set_extension(OUTBOUND_EXT);
190+
rgb_payment_info_path.set_extension(OUTBOUND_EXT);
191+
}
192+
let rgb_payment_info_tmp_path = append_pending_extension(&rgb_payment_info_path);
193+
178194
if rgb_payment_info_tmp_path.exists() {
179195
let mut rgb_payment_info = parse_rgb_payment_info(&rgb_payment_info_tmp_path);
180196
rgb_payment_info.local_rgb_amount = rgb_info.local_rgb_amount;
@@ -189,19 +205,19 @@ pub(crate) fn color_commitment<SP: Deref>(channel_context: &ChannelContext<SP>,
189205
} else {
190206
let rgb_payment_info = RgbPaymentInfo {
191207
contract_id: rgb_info.contract_id,
192-
amount: htlc.amount_rgb.unwrap(),
208+
amount: htlc_amount_rgb,
193209
local_rgb_amount: rgb_info.local_rgb_amount,
194210
remote_rgb_amount: rgb_info.remote_rgb_amount,
195-
override_route_amount: false,
196-
inbound: htlc.offered == counterparty,
211+
swap_payment: false,
212+
inbound,
197213
};
198214
let serialized_info = serde_json::to_string(&rgb_payment_info).expect("valid rgb payment info");
199215
fs::write(rgb_payment_info_proxy_id_path, serialized_info.clone()).expect("able to write rgb payment info file");
200216
fs::write(rgb_payment_info_path, serialized_info).expect("able to write rgb payment info file");
201217
rgb_payment_info
202218
};
203219

204-
if htlc.offered == counterparty {
220+
if inbound {
205221
rgb_received_htlc += rgb_payment_info.amount
206222
} else {
207223
rgb_offered_htlc += rgb_payment_info.amount
@@ -328,10 +344,10 @@ pub(crate) fn color_commitment<SP: Deref>(channel_context: &ChannelContext<SP>,
328344

329345
/// Color HTLC transaction
330346
pub(crate) fn color_htlc(htlc_tx: &mut Transaction, htlc: &HTLCOutputInCommitment, ldk_data_dir: &Path) -> Result<(), ChannelError> {
331-
let htlc_amount_rgb = htlc.amount_rgb.expect("this is a rgb channel");
332-
if htlc_amount_rgb == 0 {
347+
if htlc.amount_rgb.unwrap_or(0) == 0 {
333348
return Ok(())
334349
}
350+
let htlc_amount_rgb = htlc.amount_rgb.expect("this HTLC has RGB assets");
335351

336352
htlc_tx.output.push(TxOut { value: 0, script_pubkey: Script::new_op_return(&[1]) });
337353
let psbt = PartiallySignedTransaction::from_unsigned_tx(htlc_tx.clone()).expect("valid transaction");
@@ -511,8 +527,10 @@ pub(crate) fn color_closing(channel_id: &ChannelId, funding_outpoint: &OutPoint,
511527
}
512528

513529
/// Get RgbPaymentInfo file path
514-
pub fn get_rgb_payment_info_path(payment_hash: &PaymentHash, ldk_data_dir: &Path) -> PathBuf {
515-
ldk_data_dir.join(hex::encode(payment_hash.0))
530+
pub fn get_rgb_payment_info_path(payment_hash: &PaymentHash, ldk_data_dir: &Path, inbound: bool) -> PathBuf {
531+
let mut path = ldk_data_dir.join(hex::encode(payment_hash.0));
532+
path.set_extension(if inbound { INBOUND_EXT } else { OUTBOUND_EXT });
533+
path
516534
}
517535

518536
/// Parse RgbPaymentInfo
@@ -559,17 +577,22 @@ pub fn write_rgb_channel_info(path: &PathBuf, rgb_info: &RgbInfo) {
559577
fs::write(path, serialized_info).expect("able to write")
560578
}
561579

580+
fn append_pending_extension(path: &PathBuf) -> PathBuf {
581+
let mut new_path = path.clone();
582+
new_path.set_extension(format!("{}_pending", new_path.extension().unwrap().to_string_lossy()));
583+
new_path
584+
}
585+
562586
/// Write RGB payment info to file
563-
pub fn write_rgb_payment_info_file(ldk_data_dir: &Path, payment_hash: &PaymentHash, contract_id: ContractId, amount_rgb: u64, override_route_amount: bool, inbound: bool) {
564-
let rgb_payment_info_path = get_rgb_payment_info_path(payment_hash, ldk_data_dir);
565-
let mut rgb_payment_info_tmp_path = rgb_payment_info_path.clone();
566-
rgb_payment_info_tmp_path.set_extension("pending");
587+
pub fn write_rgb_payment_info_file(ldk_data_dir: &Path, payment_hash: &PaymentHash, contract_id: ContractId, amount_rgb: u64, swap_payment: bool, inbound: bool) {
588+
let rgb_payment_info_path = get_rgb_payment_info_path(payment_hash, ldk_data_dir, inbound);
589+
let rgb_payment_info_tmp_path = append_pending_extension(&rgb_payment_info_path);
567590
let rgb_payment_info = RgbPaymentInfo {
568591
contract_id,
569592
amount: amount_rgb,
570593
local_rgb_amount: 0,
571594
remote_rgb_amount: 0,
572-
override_route_amount,
595+
swap_payment,
573596
inbound,
574597
};
575598
let serialized_info = serde_json::to_string(&rgb_payment_info).expect("valid rgb payment info");
@@ -716,12 +739,13 @@ pub(crate) fn update_rgb_channel_amount_pending(channel_id: &ChannelId, rgb_offe
716739

717740
/// Whether the payment is colored
718741
pub(crate) fn is_payment_rgb(ldk_data_dir: &Path, payment_hash: &PaymentHash) -> bool {
719-
ldk_data_dir.join(hex::encode(payment_hash.0)).exists()
742+
get_rgb_payment_info_path(payment_hash, ldk_data_dir, false).exists() ||
743+
get_rgb_payment_info_path(payment_hash, ldk_data_dir, true).exists()
720744
}
721745

722746
/// Filter first_hops for contract_id
723747
pub(crate) fn filter_first_hops(ldk_data_dir: &Path, payment_hash: &PaymentHash, first_hops: &mut Vec<&ChannelDetails>) -> ContractId {
724-
let rgb_payment_info_path = ldk_data_dir.join(hex::encode(payment_hash.0));
748+
let rgb_payment_info_path = get_rgb_payment_info_path(payment_hash, ldk_data_dir, false);
725749
let serialized_info = fs::read_to_string(rgb_payment_info_path).expect("valid rgb payment info file");
726750
let rgb_payment_info: RgbPaymentInfo = serde_json::from_str(&serialized_info).expect("valid rgb payment info file");
727751
let contract_id = rgb_payment_info.contract_id;

0 commit comments

Comments
 (0)