Skip to content

Commit 8b40a56

Browse files
committed
Allow for trusted inbound 0conf channels
1 parent bc7a4ba commit 8b40a56

File tree

5 files changed

+109
-12
lines changed

5 files changed

+109
-12
lines changed

bindings/ldk_node.udl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ interface Node {
3636
[Throws=NodeError]
3737
u64 total_onchain_balance_sats();
3838
[Throws=NodeError]
39-
void connect(PublicKey node_id, SocketAddr address, boolean permanently);
39+
void connect(PublicKey node_id, SocketAddr address, boolean permanently, boolean trusted_0conf);
4040
[Throws=NodeError]
4141
void disconnect([ByRef]PublicKey node_id);
4242
[Throws=NodeError]
43-
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel);
43+
void connect_open_channel(PublicKey node_id, SocketAddr address, u64 channel_amount_sats, u64? push_to_counterparty_msat, boolean announce_channel, boolean trusted_0conf);
4444
[Throws=NodeError]
4545
void close_channel([ByRef]ChannelId channel_id, [ByRef]PublicKey counterparty_node_id);
4646
[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;
@@ -250,6 +251,7 @@ where
250251
network_graph: Arc<NetworkGraph>,
251252
keys_manager: Arc<KeysManager>,
252253
payment_store: Arc<PaymentStore<K, L>>,
254+
peer_store: Arc<PeerStore<K, L>>,
253255
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>,
254256
logger: L,
255257
_config: Arc<Config>,
@@ -264,7 +266,8 @@ where
264266
wallet: Arc<Wallet<bdk::database::SqliteDatabase>>, event_queue: Arc<EventQueue<K, L>>,
265267
channel_manager: Arc<ChannelManager>, network_graph: Arc<NetworkGraph>,
266268
keys_manager: Arc<KeysManager>, payment_store: Arc<PaymentStore<K, L>>,
267-
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>, logger: L, _config: Arc<Config>,
269+
peer_store: Arc<PeerStore<K, L>>, runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>,
270+
logger: L, _config: Arc<Config>,
268271
) -> Self {
269272
Self {
270273
event_queue,
@@ -273,6 +276,7 @@ where
273276
network_graph,
274277
keys_manager,
275278
payment_store,
279+
peer_store,
276280
logger,
277281
runtime,
278282
_config,
@@ -566,7 +570,85 @@ where
566570
}
567571
}
568572
}
569-
LdkEvent::OpenChannelRequest { .. } => {}
573+
LdkEvent::OpenChannelRequest {
574+
temporary_channel_id,
575+
counterparty_node_id,
576+
funding_satoshis,
577+
channel_type,
578+
push_msat: _,
579+
} => {
580+
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
581+
if channel_type.requires_zero_conf() {
582+
if let Some(peer_info) = self.peer_store.get_peer(&counterparty_node_id) {
583+
if peer_info.trusted_0conf {
584+
match self
585+
.channel_manager
586+
.accept_inbound_channel_from_trusted_peer_0conf(
587+
&temporary_channel_id,
588+
&counterparty_node_id,
589+
user_channel_id,
590+
) {
591+
Ok(()) => {
592+
log_info!(
593+
self.logger,
594+
"Accepting inbound 0conf channel of {}sats from {}",
595+
funding_satoshis,
596+
counterparty_node_id,
597+
);
598+
}
599+
Err(e) => {
600+
log_error!(
601+
self.logger,
602+
"Error while accepting inbound 0conf channel: {:?}",
603+
e
604+
);
605+
}
606+
}
607+
}
608+
} else {
609+
log_error!(
610+
self.logger,
611+
"Rejecting request for inbound 0conf channel from untrusted peer {}",
612+
counterparty_node_id,
613+
);
614+
match self.channel_manager.force_close_without_broadcasting_txn(
615+
&temporary_channel_id,
616+
&counterparty_node_id,
617+
) {
618+
Ok(()) => {}
619+
Err(e) => {
620+
log_error!(
621+
self.logger,
622+
"Error while rejecting untrusted inbound 0conf channel: {:?}",
623+
e
624+
);
625+
}
626+
}
627+
}
628+
} else {
629+
match self.channel_manager.accept_inbound_channel(
630+
&temporary_channel_id,
631+
&counterparty_node_id,
632+
user_channel_id,
633+
) {
634+
Ok(()) => {
635+
log_info!(
636+
self.logger,
637+
"Accepting inbound channel of {}sats from {}",
638+
funding_satoshis,
639+
counterparty_node_id,
640+
);
641+
}
642+
Err(e) => {
643+
log_error!(
644+
self.logger,
645+
"Error while accepting inbound channel: {:?}",
646+
e
647+
);
648+
}
649+
}
650+
}
651+
}
570652
LdkEvent::PaymentForwarded {
571653
prev_channel_id,
572654
next_channel_id,

src/lib.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ impl Builder {
442442
// Initialize the ChannelManager
443443
let mut user_config = UserConfig::default();
444444
user_config.channel_handshake_limits.force_announced_channel_preference = false;
445+
user_config.manually_accept_inbound_channels = true;
445446
let channel_manager = {
446447
if let Ok(mut reader) = kv_store
447448
.read(CHANNEL_MANAGER_PERSISTENCE_NAMESPACE, CHANNEL_MANAGER_PERSISTENCE_KEY)
@@ -638,6 +639,7 @@ impl Node {
638639
Arc::clone(&self.network_graph),
639640
Arc::clone(&self.keys_manager),
640641
Arc::clone(&self.payment_store),
642+
Arc::clone(&self.peer_store),
641643
Arc::clone(&self.runtime),
642644
Arc::clone(&self.logger),
643645
Arc::clone(&self.config),
@@ -909,16 +911,18 @@ impl Node {
909911
/// Connect to a node on the peer-to-peer network.
910912
///
911913
/// If `permanently` is set to `true`, we'll remember the peer and reconnect to it on restart.
914+
///
915+
/// If `trusted_0conf` is set to `true`, we will trust incoming 0conf channels from this peer.
912916
pub fn connect(
913-
&self, node_id: PublicKey, address: SocketAddr, permanently: bool,
917+
&self, node_id: PublicKey, address: SocketAddr, permanently: bool, trusted_0conf: bool,
914918
) -> Result<(), Error> {
915919
let rt_lock = self.runtime.read().unwrap();
916920
if rt_lock.is_none() {
917921
return Err(Error::NotRunning);
918922
}
919923
let runtime = rt_lock.as_ref().unwrap();
920924

921-
let peer_info = PeerInfo { pubkey: node_id, address };
925+
let peer_info = PeerInfo { pubkey: node_id, address, trusted_0conf };
922926

923927
let con_peer_pubkey = peer_info.pubkey;
924928
let con_peer_addr = peer_info.address;
@@ -980,10 +984,12 @@ impl Node {
980984
/// channel counterparty on channel open. This can be useful to start out with the balance not
981985
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
982986
///
987+
/// If `trusted_0conf` is set to `true`, we will trust incoming 0conf channels from this peer.
988+
///
983989
/// Returns a temporary channel id.
984990
pub fn connect_open_channel(
985991
&self, node_id: PublicKey, address: SocketAddr, channel_amount_sats: u64,
986-
push_to_counterparty_msat: Option<u64>, announce_channel: bool,
992+
push_to_counterparty_msat: Option<u64>, announce_channel: bool, trusted_0conf: bool,
987993
) -> Result<(), Error> {
988994
let rt_lock = self.runtime.read().unwrap();
989995
if rt_lock.is_none() {
@@ -997,7 +1003,7 @@ impl Node {
9971003
return Err(Error::InsufficientFunds);
9981004
}
9991005

1000-
let peer_info = PeerInfo { pubkey: node_id, address };
1006+
let peer_info = PeerInfo { pubkey: node_id, address, trusted_0conf };
10011007

10021008
let con_peer_pubkey = peer_info.pubkey;
10031009
let con_peer_addr = peer_info.address;

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

@@ -244,7 +245,8 @@ fn channel_open_fails_when_funds_insufficient() {
244245
node_b.listening_address().unwrap(),
245246
120000,
246247
None,
247-
true
248+
true,
249+
false,
248250
)
249251
);
250252
}

0 commit comments

Comments
 (0)