Skip to content

Commit 9610723

Browse files
committed
Allow for trusted inbound 0conf channels
1 parent dfad7f1 commit 9610723

5 files changed

Lines changed: 109 additions & 12 deletions

File tree

bindings/ldk_node.udl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ interface Node {
3333
[Throws=NodeError]
3434
u64 total_onchain_balance_sats();
3535
[Throws=NodeError]
36-
void connect(PublicKey node_id, SocketAddr address, boolean permanently);
36+
void connect(PublicKey node_id, SocketAddr address, boolean permanently, boolean trusted_0conf);
3737
[Throws=NodeError]
3838
void disconnect([ByRef]PublicKey node_id);
3939
[Throws=NodeError]
40-
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel);
40+
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel, boolean trusted_0conf);
4141
[Throws=NodeError]
4242
void close_channel([ByRef]ChannelId channel_id, [ByRef]PublicKey counterparty_node_id);
4343
[Throws=NodeError]

src/event.rs

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::io::{
1111
KVStore, TransactionalWrite, EVENT_QUEUE_PERSISTENCE_KEY, EVENT_QUEUE_PERSISTENCE_NAMESPACE,
1212
};
1313
use crate::logger::{log_error, log_info, Logger};
14+
use crate::peer_store::PeerStore;
1415

1516
use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator};
1617
use lightning::events::Event as LdkEvent;
@@ -251,6 +252,7 @@ where
251252
network_graph: Arc<NetworkGraph>,
252253
keys_manager: Arc<KeysManager>,
253254
payment_store: Arc<PaymentStore<K, L>>,
255+
peer_store: Arc<PeerStore<K, L>>,
254256
tokio_runtime: Arc<tokio::runtime::Runtime>,
255257
logger: L,
256258
_config: Arc<Config>,
@@ -265,7 +267,8 @@ where
265267
wallet: Arc<Wallet<bdk::database::SqliteDatabase>>, event_queue: Arc<EventQueue<K, L>>,
266268
channel_manager: Arc<ChannelManager>, network_graph: Arc<NetworkGraph>,
267269
keys_manager: Arc<KeysManager>, payment_store: Arc<PaymentStore<K, L>>,
268-
tokio_runtime: Arc<tokio::runtime::Runtime>, logger: L, _config: Arc<Config>,
270+
peer_store: Arc<PeerStore<K, L>>, tokio_runtime: Arc<tokio::runtime::Runtime>, logger: L,
271+
_config: Arc<Config>,
269272
) -> Self {
270273
Self {
271274
event_queue,
@@ -274,6 +277,7 @@ where
274277
network_graph,
275278
keys_manager,
276279
payment_store,
280+
peer_store,
277281
logger,
278282
tokio_runtime,
279283
_config,
@@ -567,7 +571,85 @@ where
567571
}
568572
}
569573
}
570-
LdkEvent::OpenChannelRequest { .. } => {}
574+
LdkEvent::OpenChannelRequest {
575+
temporary_channel_id,
576+
counterparty_node_id,
577+
funding_satoshis,
578+
channel_type,
579+
push_msat: _,
580+
} => {
581+
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
582+
if channel_type.requires_zero_conf() {
583+
if let Some(peer_info) = self.peer_store.get_peer(&counterparty_node_id) {
584+
if peer_info.trusted_0conf {
585+
match self
586+
.channel_manager
587+
.accept_inbound_channel_from_trusted_peer_0conf(
588+
&temporary_channel_id,
589+
&counterparty_node_id,
590+
user_channel_id,
591+
) {
592+
Ok(()) => {
593+
log_info!(
594+
self.logger,
595+
"Accepting inbound 0conf channel of {}sats from {}",
596+
funding_satoshis,
597+
counterparty_node_id,
598+
);
599+
}
600+
Err(e) => {
601+
log_error!(
602+
self.logger,
603+
"Error while accepting inbound 0conf channel: {:?}",
604+
e
605+
);
606+
}
607+
}
608+
}
609+
} else {
610+
log_error!(
611+
self.logger,
612+
"Rejecting request for inbound 0conf channel from untrusted peer {}",
613+
counterparty_node_id,
614+
);
615+
match self.channel_manager.force_close_without_broadcasting_txn(
616+
&temporary_channel_id,
617+
&counterparty_node_id,
618+
) {
619+
Ok(()) => {}
620+
Err(e) => {
621+
log_error!(
622+
self.logger,
623+
"Error while rejecting untrusted inbound 0conf channel: {:?}",
624+
e
625+
);
626+
}
627+
}
628+
}
629+
} else {
630+
match self.channel_manager.accept_inbound_channel(
631+
&temporary_channel_id,
632+
&counterparty_node_id,
633+
user_channel_id,
634+
) {
635+
Ok(()) => {
636+
log_info!(
637+
self.logger,
638+
"Accepting inbound channel of {}sats from {}",
639+
funding_satoshis,
640+
counterparty_node_id,
641+
);
642+
}
643+
Err(e) => {
644+
log_error!(
645+
self.logger,
646+
"Error while accepting inbound channel: {:?}",
647+
e
648+
);
649+
}
650+
}
651+
}
652+
}
571653
LdkEvent::PaymentForwarded {
572654
prev_channel_id,
573655
next_channel_id,

src/lib.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,7 @@ impl Builder {
418418
// Initialize the ChannelManager
419419
let mut user_config = UserConfig::default();
420420
user_config.channel_handshake_limits.force_announced_channel_preference = false;
421+
user_config.manually_accept_inbound_channels = true;
421422
let channel_manager = {
422423
if let Ok(mut reader) = kv_store
423424
.read(CHANNEL_MANAGER_PERSISTENCE_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_KEY)
@@ -654,6 +655,7 @@ impl Node {
654655
Arc::clone(&self.network_graph),
655656
Arc::clone(&self.keys_manager),
656657
Arc::clone(&self.payment_store),
658+
Arc::clone(&self.peer_store),
657659
Arc::clone(&tokio_runtime),
658660
Arc::clone(&self.logger),
659661
Arc::clone(&self.config),
@@ -858,8 +860,10 @@ impl Node {
858860
/// Connect to a node on the peer-to-peer network.
859861
///
860862
/// If `permanently` is set to `true`, we'll remember the peer and reconnect to it on restart.
863+
///
864+
/// If `trusted_0conf` is set to `true`, we will trust incoming 0conf channels from this peer.
861865
pub fn connect(
862-
&self, node_id: PublicKey, address: SocketAddr, permanently: bool,
866+
&self, node_id: PublicKey, address: SocketAddr, permanently: bool, trusted_0conf: bool,
863867
) -> Result<(), Error> {
864868
let runtime_lock = self.running.read().unwrap();
865869
if runtime_lock.is_none() {
@@ -868,7 +872,7 @@ impl Node {
868872

869873
let runtime = runtime_lock.as_ref().unwrap();
870874

871-
let peer_info = PeerInfo { pubkey: node_id, address };
875+
let peer_info = PeerInfo { pubkey: node_id, address, trusted_0conf };
872876

873877
let con_peer_pubkey = peer_info.pubkey.clone();
874878
let con_peer_addr = peer_info.address.clone();
@@ -930,10 +934,12 @@ impl Node {
930934
/// channel counterparty on channel open. This can be useful to start out with the balance not
931935
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
932936
///
937+
/// If `trusted_0conf` is set to `true`, we will trust incoming 0conf channels from this peer.
938+
///
933939
/// Returns a temporary channel id.
934940
pub fn connect_open_channel(
935941
&self, node_id: PublicKey, address: SocketAddr, channel_amount_sats: u64,
936-
push_to_counterparty_msat: Option<u64>, announce_channel: bool,
942+
push_to_counterparty_msat: Option<u64>, announce_channel: bool, trusted_0conf: bool,
937943
) -> Result<(), Error> {
938944
let runtime_lock = self.running.read().unwrap();
939945
if runtime_lock.is_none() {
@@ -948,7 +954,7 @@ impl Node {
948954
return Err(Error::InsufficientFunds);
949955
}
950956

951-
let peer_info = PeerInfo { pubkey: node_id, address };
957+
let peer_info = PeerInfo { pubkey: node_id, address, trusted_0conf };
952958

953959
let con_peer_pubkey = peer_info.pubkey.clone();
954960
let con_peer_addr = peer_info.address.clone();

src/peer_store.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ where
3636
pub(crate) fn add_peer(&self, peer_info: PeerInfo) -> Result<(), Error> {
3737
let mut locked_peers = self.peers.write().unwrap();
3838

39+
if locked_peers.contains_key(&peer_info.pubkey) {
40+
return Ok(());
41+
}
42+
3943
locked_peers.insert(peer_info.pubkey, peer_info);
4044
self.write_peers_and_commit(&*locked_peers)
4145
}
@@ -145,6 +149,7 @@ impl Writeable for PeerStoreSerWrapper<'_> {
145149
pub(crate) struct PeerInfo {
146150
pub pubkey: PublicKey,
147151
pub address: SocketAddr,
152+
pub trusted_0conf: bool,
148153
}
149154

150155
impl Readable for PeerInfo {
@@ -166,10 +171,10 @@ impl Readable for PeerInfo {
166171
};
167172

168173
let port: u16 = Readable::read(reader)?;
169-
170174
let address = SocketAddr::new(ip_addr, port);
175+
let trusted_0conf = Readable::read(reader)?;
171176

172-
Ok(PeerInfo { pubkey, address })
177+
Ok(PeerInfo { pubkey, address, trusted_0conf })
173178
}
174179
}
175180

@@ -189,6 +194,7 @@ impl Writeable for PeerInfo {
189194
}
190195

191196
self.address.port().write(writer)?;
197+
self.trusted_0conf.write(writer)?;
192198

193199
Ok(())
194200
}
@@ -212,7 +218,8 @@ mod tests {
212218
)
213219
.unwrap();
214220
let address: SocketAddr = "127.0.0.1:9738".parse().unwrap();
215-
let expected_peer_info = PeerInfo { pubkey, address };
221+
let trusted_0conf = true;
222+
let expected_peer_info = PeerInfo { pubkey, address, trusted_0conf };
216223
peer_store.add_peer(expected_peer_info.clone()).unwrap();
217224
assert!(store.get_and_clear_did_persist());
218225

src/test/functional_tests.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ fn channel_full_cycle() {
4343
funding_amount_sat,
4444
Some(push_msat),
4545
true,
46+
false,
4647
)
4748
.unwrap();
4849

@@ -243,7 +244,8 @@ fn channel_open_fails_when_funds_insufficient() {
243244
*node_b.listening_address().unwrap(),
244245
120000,
245246
None,
246-
true
247+
true,
248+
false,
247249
)
248250
);
249251
}

0 commit comments

Comments
 (0)