Skip to content

Commit 4010a2f

Browse files
authored
Merge pull request #265 from elnafateh/expose-splice-events
Expose splice negotiation events over gRPC
2 parents eb3be3a + 4dc5ac7 commit 4010a2f

5 files changed

Lines changed: 118 additions & 2 deletions

File tree

docs/api-guide.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ See [Pagination](#pagination) below for how to page through results.
212212
| `PaymentClaimable` | A hodl invoice payment arrived and is waiting to be claimed or failed |
213213
| `PaymentForwarded` | A payment was routed through this node |
214214
| `ChannelStateChanged` | A channel changed state (pending, ready, open failed, closed) |
215+
| `SpliceNegotiated` | A channel splice was negotiated and the funding transaction is pending confirmation |
216+
| `SpliceNegotiationFailed` | A channel splice negotiation round failed |
215217

216218
Events are broadcast to all connected subscribers. The server uses a bounded broadcast channel
217219
(capacity 1024). A slow subscriber that falls behind will miss events.

e2e-tests/tests/e2e.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,11 +1200,24 @@ async fn splice_in_via_cli(splice_amount: &str) {
12001200
let server_b = LdkServerHandle::start(&bitcoind).await;
12011201
let user_channel_id = setup_funded_channel(&bitcoind, &server_a, &server_b, 100_000).await;
12021202

1203+
let mut events_a = server_a.client().subscribe_events().await.unwrap();
1204+
12031205
let output = run_cli(
12041206
&server_a,
12051207
&["splice-in", &user_channel_id, server_b.node_id(), splice_amount],
12061208
);
12071209
assert!(output.is_object());
1210+
1211+
let event_a =
1212+
wait_for_event(&mut events_a, |e| matches!(e, Event::SpliceNegotiated(_))).await;
1213+
match &event_a.event {
1214+
Some(Event::SpliceNegotiated(splice_negotiated)) => {
1215+
assert_eq!(splice_negotiated.user_channel_id, user_channel_id);
1216+
assert_eq!(splice_negotiated.counterparty_node_id, server_b.node_id());
1217+
assert!(!splice_negotiated.new_funding_txo.is_empty());
1218+
},
1219+
other => panic!("expected SpliceNegotiated event, got {other:?}"),
1220+
}
12081221
}
12091222

12101223
#[tokio::test]

ldk-server-grpc/src/events.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#[allow(clippy::derive_partial_eq_without_eq)]
1515
#[derive(Clone, PartialEq, ::prost::Message)]
1616
pub struct EventEnvelope {
17-
#[prost(oneof = "event_envelope::Event", tags = "2, 3, 4, 6, 7, 8")]
17+
#[prost(oneof = "event_envelope::Event", tags = "2, 3, 4, 6, 7, 8, 9, 10")]
1818
pub event: ::core::option::Option<event_envelope::Event>,
1919
}
2020
/// Nested message and enum types in `EventEnvelope`.
@@ -36,6 +36,10 @@ pub mod event_envelope {
3636
PaymentClaimable(super::PaymentClaimable),
3737
#[prost(message, tag = "8")]
3838
ChannelStateChanged(super::ChannelStateChanged),
39+
#[prost(message, tag = "9")]
40+
SpliceNegotiated(super::SpliceNegotiated),
41+
#[prost(message, tag = "10")]
42+
SpliceNegotiationFailed(super::SpliceNegotiationFailed),
3943
}
4044
}
4145
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@@ -140,6 +144,38 @@ pub struct ChannelStateChanged {
140144
#[prost(enumeration = "ChannelClosureInitiator", tag = "7")]
141145
pub closure_initiator: i32,
142146
}
147+
/// SpliceNegotiated indicates a channel splice has been negotiated and the funding
148+
/// transaction is pending confirmation on-chain.
149+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
151+
#[cfg_attr(feature = "serde", serde(default))]
152+
#[allow(clippy::derive_partial_eq_without_eq)]
153+
#[derive(Clone, PartialEq, ::prost::Message)]
154+
pub struct SpliceNegotiated {
155+
#[prost(string, tag = "1")]
156+
pub channel_id: ::prost::alloc::string::String,
157+
#[prost(string, tag = "2")]
158+
pub user_channel_id: ::prost::alloc::string::String,
159+
#[prost(string, tag = "3")]
160+
pub counterparty_node_id: ::prost::alloc::string::String,
161+
/// The outpoint of the channel's splice funding transaction.
162+
#[prost(string, tag = "4")]
163+
pub new_funding_txo: ::prost::alloc::string::String,
164+
}
165+
/// SpliceNegotiationFailed indicates a channel splice negotiation round has failed.
166+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
167+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
168+
#[cfg_attr(feature = "serde", serde(default))]
169+
#[allow(clippy::derive_partial_eq_without_eq)]
170+
#[derive(Clone, PartialEq, ::prost::Message)]
171+
pub struct SpliceNegotiationFailed {
172+
#[prost(string, tag = "1")]
173+
pub channel_id: ::prost::alloc::string::String,
174+
#[prost(string, tag = "2")]
175+
pub user_channel_id: ::prost::alloc::string::String,
176+
#[prost(string, tag = "3")]
177+
pub counterparty_node_id: ::prost::alloc::string::String,
178+
}
143179
/// PaymentReceived indicates a payment has been received.
144180
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
145181
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]

ldk-server-grpc/src/proto/events.proto

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ message EventEnvelope {
1111
PaymentForwarded payment_forwarded = 6;
1212
PaymentClaimable payment_claimable = 7;
1313
ChannelStateChanged channel_state_changed = 8;
14+
SpliceNegotiated splice_negotiated = 9;
15+
SpliceNegotiationFailed splice_negotiation_failed = 10;
1416
}
1517
}
1618

@@ -120,6 +122,23 @@ message ChannelStateChanged {
120122
ChannelClosureInitiator closure_initiator = 7;
121123
}
122124

125+
// SpliceNegotiated indicates a channel splice has been negotiated and the funding
126+
// transaction is pending confirmation on-chain.
127+
message SpliceNegotiated {
128+
string channel_id = 1;
129+
string user_channel_id = 2;
130+
string counterparty_node_id = 3;
131+
// The outpoint of the channel's splice funding transaction.
132+
string new_funding_txo = 4;
133+
}
134+
135+
// SpliceNegotiationFailed indicates a channel splice negotiation round has failed.
136+
message SpliceNegotiationFailed {
137+
string channel_id = 1;
138+
string user_channel_id = 2;
139+
string counterparty_node_id = 3;
140+
}
141+
123142
// PaymentReceived indicates a payment has been received.
124143
message PaymentReceived {
125144
// The payment details for the payment in event.

ldk-server/src/main.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,11 +634,57 @@ fn main() {
634634
}
635635
}
636636
},
637-
_ => {
637+
Event::SpliceNegotiated {
638+
channel_id,
639+
user_channel_id,
640+
counterparty_node_id,
641+
new_funding_txo,
642+
} => {
643+
info!(
644+
"SPLICE_NEGOTIATED: {} from counterparty {}",
645+
channel_id, counterparty_node_id
646+
);
647+
648+
send_channel_state_event(
649+
event_envelope::Event::SpliceNegotiated(events::SpliceNegotiated {
650+
channel_id: channel_id.0.to_lower_hex_string(),
651+
user_channel_id: user_channel_id.0.to_string(),
652+
counterparty_node_id: counterparty_node_id.to_string(),
653+
new_funding_txo: new_funding_txo.to_string(),
654+
}),
655+
&event_sender,
656+
);
657+
638658
if let Err(e) = event_node.event_handled() {
639659
error!("Failed to mark event as handled: {e}");
640660
}
641661
},
662+
Event::SpliceNegotiationFailed {
663+
channel_id,
664+
user_channel_id,
665+
counterparty_node_id,
666+
} => {
667+
info!(
668+
"SPLICE_NEGOTIATION_FAILED: {} from counterparty {}",
669+
channel_id, counterparty_node_id
670+
);
671+
672+
send_channel_state_event(
673+
event_envelope::Event::SpliceNegotiationFailed(
674+
events::SpliceNegotiationFailed {
675+
channel_id: channel_id.0.to_lower_hex_string(),
676+
user_channel_id: user_channel_id.0.to_string(),
677+
counterparty_node_id: counterparty_node_id.to_string(),
678+
},
679+
),
680+
&event_sender,
681+
);
682+
683+
if let Err(e) = event_node.event_handled() {
684+
error!("Failed to mark event as handled: {e}");
685+
}
686+
},
687+
642688
}
643689
},
644690
res = grpc_listener.accept() => {

0 commit comments

Comments
 (0)