Skip to content

Commit 07f18c9

Browse files
committed
Implement RGB KVStore Integration
1 parent 961313c commit 07f18c9

8 files changed

Lines changed: 557 additions & 169 deletions

File tree

lightning/src/chain/channelmonitor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7107,7 +7107,9 @@ mod tests {
71077107
SecretKey::from_slice(&[41; 32]).unwrap(),
71087108
[41; 32],
71097109
[0; 32],
7110+
std::path::PathBuf::new(),
71107111
[0; 32],
7112+
None,
71117113
);
71127114

71137115
let counterparty_pubkeys = ChannelPublicKeys {
@@ -7370,7 +7372,9 @@ mod tests {
73707372
SecretKey::from_slice(&[41; 32]).unwrap(),
73717373
[41; 32],
73727374
[0; 32],
7375+
std::path::PathBuf::new(),
73737376
[0; 32],
7377+
None,
73747378
);
73757379

73767380
let counterparty_pubkeys = ChannelPublicKeys {

lightning/src/chain/onchaintx.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,7 +1304,9 @@ mod tests {
13041304
SecretKey::from_slice(&[41; 32]).unwrap(),
13051305
[41; 32],
13061306
[0; 32],
1307+
std::path::PathBuf::new(),
13071308
[0; 32],
1309+
None,
13081310
);
13091311
let counterparty_pubkeys = ChannelPublicKeys {
13101312
funding_pubkey: PublicKey::from_secret_key(

lightning/src/ln/chan_utils.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! largely of interest for those implementing the traits on [`crate::sign`] by hand.
1212
1313
use std::path::PathBuf;
14+
use std::sync::Arc;
1415

1516
use bitcoin::amount::Amount;
1617
use bitcoin::constants::WITNESS_SCALE_FACTOR;
@@ -36,6 +37,7 @@ use crate::ln::msgs::DecodeError;
3637
use crate::rgb_utils::{color_htlc, is_tx_colored};
3738
use crate::sign::EntropySource;
3839
use crate::types::payment::{PaymentHash, PaymentPreimage};
40+
use crate::util::persist::KVStoreSync;
3941
use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, Writeable, Writer};
4042
use crate::util::transaction_utils;
4143

@@ -2156,6 +2158,7 @@ impl<'a> TrustedCommitmentTransaction<'a> {
21562158
pub fn get_htlc_sigs<T: secp256k1::Signing, ES: Deref>(
21572159
&self, htlc_base_key: &SecretKey, channel_parameters: &DirectedChannelTransactionParameters,
21582160
entropy_source: &ES, secp_ctx: &Secp256k1<T>, ldk_data_dir: &PathBuf,
2161+
rgb_kv_store: Option<&Arc<dyn KVStoreSync + Send + Sync>>,
21592162
) -> Result<Vec<Signature>, ()> where ES::Target: EntropySource {
21602163
let inner = self.inner;
21612164
let keys = &inner.keys;
@@ -2167,7 +2170,7 @@ impl<'a> TrustedCommitmentTransaction<'a> {
21672170
assert!(this_htlc.transaction_output_index.is_some());
21682171
let mut htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, &self.channel_type_features, &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
21692172
if inner.is_colored() {
2170-
if let Err(_e) = color_htlc(&mut htlc_tx, this_htlc, ldk_data_dir) {
2173+
if let Err(_e) = color_htlc(&mut htlc_tx, this_htlc, ldk_data_dir, rgb_kv_store) {
21712174
return Err(());
21722175
}
21732176
}

lightning/src/ln/channel.rs

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ use crate::ln::LN_MAX_MSG_LEN;
7979
use crate::offers::static_invoice::StaticInvoice;
8080
use crate::rgb_utils::{
8181
color_closing, color_commitment, color_htlc, get_rgb_channel_info_path,
82-
get_rgb_channel_info_pending, parse_rgb_channel_info, rename_rgb_files,
83-
update_rgb_channel_amount_pending,
82+
get_rgb_channel_info_pending, parse_rgb_channel_info,
83+
read_rgb_channel_info_kv, rename_rgb_files, update_rgb_channel_amount_pending,
8484
};
8585
use crate::routing::gossip::NodeId;
8686
use crate::sign::ecdsa::EcdsaChannelSigner;
@@ -104,6 +104,8 @@ use crate::prelude::*;
104104
use crate::sign::type_resolver::ChannelSignerType;
105105
#[cfg(any(test, fuzzing, debug_assertions))]
106106
use crate::sync::Mutex;
107+
use crate::sync::Arc;
108+
use crate::util::persist::KVStoreSync;
107109
use core::ops::Deref;
108110
use core::time::Duration;
109111
use core::{cmp, fmt, mem};
@@ -3132,6 +3134,9 @@ where
31323134
pub(super) consignment_endpoint: Option<RgbTransport>,
31333135

31343136
pub(crate) ldk_data_dir: PathBuf,
3137+
3138+
/// Optional KVStore for RGB data persistence
3139+
pub(crate) rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
31353140
}
31363141

31373142
/// A channel struct implementing this trait can receive an initial counterparty commitment
@@ -3232,7 +3237,7 @@ where
32323237
let temporary_channel_id = context.channel_id;
32333238
context.channel_id = channel_id;
32343239
if context.is_colored() {
3235-
rename_rgb_files(&context.channel_id, &temporary_channel_id, &context.ldk_data_dir);
3240+
rename_rgb_files(&context.channel_id, &temporary_channel_id, &context.ldk_data_dir, context.rgb_kv_store.as_ref());
32363241
}
32373242

32383243
assert!(!context.channel_state.is_monitor_update_in_progress()); // We have not had any monitor(s) yet to fail update!
@@ -3401,6 +3406,7 @@ where
34013406
msg_push_msat: u64,
34023407
open_channel_fields: msgs::CommonOpenChannelFields,
34033408
ldk_data_dir: PathBuf,
3409+
rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
34043410
) -> Result<(FundingScope, ChannelContext<SP>), ChannelError>
34053411
where
34063412
ES::Target: EntropySource,
@@ -3723,6 +3729,7 @@ where
37233729

37243730
consignment_endpoint: open_channel_fields.consignment_endpoint,
37253731
ldk_data_dir,
3732+
rgb_kv_store,
37263733
};
37273734

37283735
Ok((funding, channel_context))
@@ -3748,6 +3755,7 @@ where
37483755
_logger: L,
37493756
consignment_endpoint: Option<RgbTransport>,
37503757
ldk_data_dir: PathBuf,
3758+
rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
37513759
) -> Result<(FundingScope, ChannelContext<SP>), APIError>
37523760
where
37533761
ES::Target: EntropySource,
@@ -3966,6 +3974,7 @@ where
39663974

39673975
consignment_endpoint,
39683976
ldk_data_dir,
3977+
rgb_kv_store,
39693978
};
39703979

39713980
Ok((funding, channel_context))
@@ -4344,11 +4353,15 @@ where
43444353

43454354
/// Get the channel local RGB amount
43464355
pub fn get_local_rgb_amount(&self) -> u64 {
4347-
let info_file_path = get_rgb_channel_info_path(
4348-
&self.channel_id.0.as_hex().to_string(),
4349-
&self.ldk_data_dir,
4350-
false,
4351-
);
4356+
let channel_id_str = self.channel_id.0.as_hex().to_string();
4357+
// Try KVStore first (using injected store)
4358+
if let Some(ref kv_store) = self.rgb_kv_store {
4359+
if let Ok(rgb_info) = read_rgb_channel_info_kv(kv_store.as_ref(), &channel_id_str, false) {
4360+
return rgb_info.local_rgb_amount;
4361+
}
4362+
}
4363+
// Fallback to filesystem
4364+
let info_file_path = get_rgb_channel_info_path(&channel_id_str, &self.ldk_data_dir, false);
43524365
if info_file_path.exists() {
43534366
let rgb_info = parse_rgb_channel_info(&info_file_path);
43544367
rgb_info.local_rgb_amount
@@ -4359,11 +4372,15 @@ where
43594372

43604373
/// Get the channel remote RGB amount
43614374
pub fn get_remote_rgb_amount(&self) -> u64 {
4362-
let info_file_path = get_rgb_channel_info_path(
4363-
&self.channel_id.0.as_hex().to_string(),
4364-
&self.ldk_data_dir,
4365-
false,
4366-
);
4375+
let channel_id_str = self.channel_id.0.as_hex().to_string();
4376+
// Try KVStore first (using injected store)
4377+
if let Some(ref kv_store) = self.rgb_kv_store {
4378+
if let Ok(rgb_info) = read_rgb_channel_info_kv(kv_store.as_ref(), &channel_id_str, false) {
4379+
return rgb_info.remote_rgb_amount;
4380+
}
4381+
}
4382+
// Fallback to filesystem
4383+
let info_file_path = get_rgb_channel_info_path(&channel_id_str, &self.ldk_data_dir, false);
43674384
if info_file_path.exists() {
43684385
let rgb_info = parse_rgb_channel_info(&info_file_path);
43694386
rgb_info.remote_rgb_amount
@@ -5080,7 +5097,7 @@ where
50805097
&holder_keys.revocation_key,
50815098
);
50825099
if self.is_colored() {
5083-
color_htlc(&mut htlc_tx, htlc, &self.ldk_data_dir)
5100+
color_htlc(&mut htlc_tx, htlc, &self.ldk_data_dir, self.rgb_kv_store.as_ref())
50845101
.expect("successful htlc coloring");
50855102
}
50865103

@@ -7324,6 +7341,7 @@ where
73247341
&self.context.channel_id,
73257342
&mut closing_transaction,
73267343
&self.context.ldk_data_dir,
7344+
self.context.rgb_kv_store.as_ref(),
73277345
)
73287346
.expect("successful closing TX coloring");
73297347
}
@@ -8915,6 +8933,7 @@ where
89158933
rgb_offered_htlc,
89168934
rgb_received_htlc,
89178935
&self.context.ldk_data_dir,
8936+
self.context.rgb_kv_store.as_ref(),
89188937
);
89198938
}
89208939

@@ -11729,7 +11748,7 @@ where
1172911748
let were_node_one = node_id.as_slice() < counterparty_node_id.as_slice();
1173011749

1173111750
let contract_id = if self.context.is_colored() {
11732-
let (rgb_info, _) = get_rgb_channel_info_pending(&self.context.channel_id, &self.context.ldk_data_dir);
11751+
let (rgb_info, _) = get_rgb_channel_info_pending(&self.context.channel_id, &self.context.ldk_data_dir, self.context.rgb_kv_store.as_ref());
1173311752
Some(rgb_info.contract_id)
1173411753
} else {
1173511754
None
@@ -12883,7 +12902,7 @@ where
1288312902
}
1288412903
}
1288512904
if self.context.is_colored() && rgb_received_htlc > 0 {
12886-
update_rgb_channel_amount_pending(&self.context.channel_id, 0, rgb_received_htlc, &self.context.ldk_data_dir);
12905+
update_rgb_channel_amount_pending(&self.context.channel_id, 0, rgb_received_htlc, &self.context.ldk_data_dir, self.context.rgb_kv_store.as_ref());
1288712906
}
1288812907
if let Some((feerate, update_state)) = self.context.pending_update_fee {
1288912908
if update_state == FeeUpdateState::AwaitingRemoteRevokeToAnnounce {
@@ -13550,6 +13569,7 @@ where
1355013569
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP, counterparty_node_id: PublicKey, their_features: &InitFeatures,
1355113570
channel_value_satoshis: u64, push_msat: u64, user_id: u128, config: &UserConfig, current_chain_height: u32,
1355213571
outbound_scid_alias: u64, temporary_channel_id: Option<ChannelId>, logger: L, consignment_endpoint: Option<RgbTransport>, ldk_data_dir: PathBuf,
13572+
rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
1355313573
) -> Result<OutboundV1Channel<SP>, APIError>
1355413574
where ES::Target: EntropySource,
1355513575
F::Target: FeeEstimator,
@@ -13589,6 +13609,7 @@ where
1358913609
logger,
1359013610
consignment_endpoint,
1359113611
ldk_data_dir,
13612+
rgb_kv_store,
1359213613
)?;
1359313614
let unfunded_context = UnfundedChannelContext {
1359413615
unfunded_channel_age_ticks: 0,
@@ -13672,7 +13693,7 @@ where
1367213693
let temporary_channel_id = self.context.channel_id;
1367313694
self.context.channel_id = ChannelId::v1_from_funding_outpoint(funding_txo);
1367413695
if self.context.is_colored() {
13675-
rename_rgb_files(&self.context.channel_id, &temporary_channel_id, &self.context.ldk_data_dir);
13696+
rename_rgb_files(&self.context.channel_id, &temporary_channel_id, &self.context.ldk_data_dir, self.context.rgb_kv_store.as_ref());
1367613697
}
1367713698

1367813699
// If the funding transaction is a coinbase transaction, we need to set the minimum depth to 100.
@@ -13925,7 +13946,8 @@ where
1392513946
fee_estimator: &LowerBoundedFeeEstimator<F>, entropy_source: &ES, signer_provider: &SP,
1392613947
counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
1392713948
their_features: &InitFeatures, msg: &msgs::OpenChannel, user_id: u128, config: &UserConfig,
13928-
current_chain_height: u32, logger: &L, is_0conf: bool, ldk_data_dir: PathBuf
13949+
current_chain_height: u32, logger: &L, is_0conf: bool, ldk_data_dir: PathBuf,
13950+
rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
1392913951
) -> Result<InboundV1Channel<SP>, ChannelError>
1393013952
where ES::Target: EntropySource,
1393113953
F::Target: FeeEstimator,
@@ -13966,6 +13988,7 @@ where
1396613988
msg.push_msat,
1396713989
msg.common_fields.clone(),
1396813990
ldk_data_dir,
13991+
rgb_kv_store,
1396913992
)?;
1397013993
let unfunded_context = UnfundedChannelContext {
1397113994
unfunded_channel_age_ticks: 0,
@@ -14166,7 +14189,7 @@ where
1416614189
counterparty_node_id: PublicKey, their_features: &InitFeatures, funding_satoshis: u64,
1416714190
funding_inputs: Vec<FundingTxInput>, user_id: u128, config: &UserConfig,
1416814191
current_chain_height: u32, outbound_scid_alias: u64, funding_confirmation_target: ConfirmationTarget,
14169-
logger: L, ldk_data_dir: PathBuf,
14192+
logger: L, ldk_data_dir: PathBuf, rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
1417014193
) -> Result<Self, APIError>
1417114194
where ES::Target: EntropySource,
1417214195
F::Target: FeeEstimator,
@@ -14209,6 +14232,7 @@ where
1420914232
// ok to pass consignment_endpoint as None since this method is unused
1421014233
None,
1421114234
ldk_data_dir,
14235+
rgb_kv_store,
1421214236
)?;
1421314237
let unfunded_context = UnfundedChannelContext {
1421414238
unfunded_channel_age_ticks: 0,
@@ -14319,7 +14343,7 @@ where
1431914343
holder_node_id: PublicKey, counterparty_node_id: PublicKey, our_supported_features: &ChannelTypeFeatures,
1432014344
their_features: &InitFeatures, msg: &msgs::OpenChannelV2,
1432114345
user_id: u128, config: &UserConfig, current_chain_height: u32, logger: &L,
14322-
ldk_data_dir: PathBuf,
14346+
ldk_data_dir: PathBuf, rgb_kv_store: Option<Arc<dyn KVStoreSync + Send + Sync>>,
1432314347
) -> Result<Self, ChannelError>
1432414348
where ES::Target: EntropySource,
1432514349
F::Target: FeeEstimator,
@@ -14365,6 +14389,7 @@ where
1436514389
0 /* push_msat not used in dual-funding */,
1436614390
msg.common_fields.clone(),
1436714391
ldk_data_dir,
14392+
rgb_kv_store,
1436814393
)?;
1436914394
let channel_id = ChannelId::v2_from_revocation_basepoints(
1437014395
&funding.get_holder_pubkeys().revocation_basepoint,
@@ -15054,16 +15079,16 @@ where
1505415079
}
1505515080
}
1505615081

15057-
impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c ChannelTypeFeatures, PathBuf)>
15082+
impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c ChannelTypeFeatures, PathBuf, Option<Arc<dyn KVStoreSync + Send + Sync>>)>
1505815083
for FundedChannel<SP>
1505915084
where
1506015085
ES::Target: EntropySource,
1506115086
SP::Target: SignerProvider,
1506215087
{
1506315088
fn read<R: io::Read>(
15064-
reader: &mut R, args: (&'a ES, &'b SP, &'c ChannelTypeFeatures, PathBuf),
15089+
reader: &mut R, args: (&'a ES, &'b SP, &'c ChannelTypeFeatures, PathBuf, Option<Arc<dyn KVStoreSync + Send + Sync>>),
1506515090
) -> Result<Self, DecodeError> {
15066-
let (entropy_source, signer_provider, our_supported_features, ldk_data_dir) = args;
15091+
let (entropy_source, signer_provider, our_supported_features, ldk_data_dir, rgb_kv_store) = args;
1506715092
let ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
1506815093
if ver <= 2 {
1506915094
return Err(DecodeError::UnknownVersion);
@@ -15859,6 +15884,7 @@ where
1585915884

1586015885
consignment_endpoint,
1586115886
ldk_data_dir,
15887+
rgb_kv_store,
1586215888
},
1586315889
holder_commitment_point,
1586415890
pending_splice,
@@ -16770,7 +16796,9 @@ mod tests {
1677016796
// These aren't set in the test vectors:
1677116797
[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
1677216798
[0; 32],
16799+
std::path::PathBuf::new(),
1677316800
[0; 32],
16801+
None,
1677416802
);
1677516803

1677616804
let holder_pubkeys = signer.pubkeys(&secp_ctx);

0 commit comments

Comments
 (0)