Skip to content

Commit 2ceb197

Browse files
committed
Allow pushing some msats on channel open
1 parent b124eca commit 2ceb197

File tree

3 files changed

+64
-37
lines changed

3 files changed

+64
-37
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ fn main() {
2626

2727
node.sync_wallets().unwrap();
2828

29-
node.connect_open_channel("NODE_ID@PEER_ADDR:PORT", 10000, false).unwrap();
29+
node.connect_open_channel("NODE_ID@PEER_ADDR:PORT", 10000, None, false).unwrap();
3030

3131
let invoice = Invoice::from_str("INVOICE_STR").unwrap();
3232
node.send_payment(invoice).unwrap();

src/lib.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
//!
4545
//! node.sync_wallets().unwrap();
4646
//!
47-
//! node.connect_open_channel("NODE_ID@PEER_ADDR:PORT", 10000, false).unwrap();
47+
//! node.connect_open_channel("NODE_ID@PEER_ADDR:PORT", 10000, None, false).unwrap();
4848
//!
4949
//! let invoice = Invoice::from_str("INVOICE_STR").unwrap();
5050
//! node.send_payment(invoice).unwrap();
@@ -841,11 +841,18 @@ impl Node {
841841
self.channel_manager.list_channels()
842842
}
843843

844-
/// Connect to a node and open a new channel. Disconnects and re-connects are handled automatically
844+
/// Connect to a node and opens a new channel.
845845
///
846-
/// Returns a temporary channel id
846+
/// Disconnects and reconnects are handled automatically.
847+
///
848+
/// If `push_to_counterparty_msat` is set, the given value will be pushed (read: sent) to the
849+
/// channel counterparty on channel open. This can be useful to start out with the balance not
850+
/// entirely shifted to one side, therefore allowing to receive payments from the getgo.
851+
///
852+
/// Returns a temporary channel id.
847853
pub fn connect_open_channel(
848-
&self, node_pubkey_and_address: &str, channel_amount_sats: u64, announce_channel: bool,
854+
&self, node_pubkey_and_address: &str, channel_amount_sats: u64,
855+
push_to_counterparty_msat: Option<u64>, announce_channel: bool,
849856
) -> Result<(), Error> {
850857
let runtime_lock = self.running.read().unwrap();
851858
if runtime_lock.is_none() {
@@ -895,12 +902,13 @@ impl Node {
895902
..Default::default()
896903
};
897904

905+
let push_msat = push_to_counterparty_msat.unwrap_or(0);
898906
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
899907

900908
match self.channel_manager.create_channel(
901909
peer_info.pubkey,
902910
channel_amount_sats,
903-
0,
911+
push_msat,
904912
user_channel_id,
905913
Some(user_config),
906914
) {

src/test/functional_tests.rs

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,24 @@ fn channel_full_cycle() {
2020
node_b.start().unwrap();
2121
let addr_b = node_b.new_funding_address().unwrap();
2222

23+
let premine_amount_sat = 100_000;
24+
2325
premine_and_distribute_funds(
2426
&bitcoind,
2527
&electrsd,
2628
vec![addr_a, addr_b],
27-
Amount::from_sat(100000),
29+
Amount::from_sat(premine_amount_sat),
2830
);
2931
node_a.sync_wallets().unwrap();
3032
node_b.sync_wallets().unwrap();
31-
assert_eq!(node_a.on_chain_balance().unwrap().get_spendable(), 100000);
32-
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), 100000);
33+
assert_eq!(node_a.on_chain_balance().unwrap().get_spendable(), premine_amount_sat);
34+
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), premine_amount_sat);
3335

3436
println!("\nA -- connect_open_channel -> B");
37+
let funding_amount_sat = 80_000;
38+
let push_msat = (funding_amount_sat / 2) * 1000; // balance the channel
3539
let node_b_addr = format!("{}@{}", node_b.node_id(), node_b.listening_address().unwrap());
36-
node_a.connect_open_channel(&node_b_addr, 50000, true).unwrap();
40+
node_a.connect_open_channel(&node_b_addr, funding_amount_sat, Some(push_msat), true).unwrap();
3741

3842
expect_event!(node_a, ChannelPending);
3943

@@ -55,10 +59,13 @@ fn channel_full_cycle() {
5559
node_a.sync_wallets().unwrap();
5660
node_b.sync_wallets().unwrap();
5761

62+
let onchain_fee_buffer_sat = 1500;
5863
let node_a_balance = node_a.on_chain_balance().unwrap();
59-
assert!(node_a_balance.get_spendable() < 50000);
60-
assert!(node_a_balance.get_spendable() > 40000);
61-
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), 100000);
64+
let node_a_upper_bound_sat = premine_amount_sat - funding_amount_sat;
65+
let node_a_lower_bound_sat = premine_amount_sat - funding_amount_sat - onchain_fee_buffer_sat;
66+
assert!(node_a_balance.get_spendable() < node_a_upper_bound_sat);
67+
assert!(node_a_balance.get_spendable() > node_a_lower_bound_sat);
68+
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), premine_amount_sat);
6269

6370
expect_event!(node_a, ChannelReady);
6471

@@ -74,8 +81,8 @@ fn channel_full_cycle() {
7481
};
7582

7683
println!("\nB receive_payment");
77-
let invoice_amount = 1000000;
78-
let invoice = node_b.receive_payment(invoice_amount, &"asdf", 9217).unwrap();
84+
let invoice_amount_1_msat = 1000000;
85+
let invoice = node_b.receive_payment(invoice_amount_1_msat, &"asdf", 9217).unwrap();
7986

8087
println!("\nA send_payment");
8188
let payment_hash = node_a.send_payment(invoice.clone()).unwrap();
@@ -100,27 +107,27 @@ fn channel_full_cycle() {
100107
expect_event!(node_b, PaymentReceived);
101108
assert_eq!(node_a.payment(&payment_hash).unwrap().status, PaymentStatus::Succeeded);
102109
assert_eq!(node_a.payment(&payment_hash).unwrap().direction, PaymentDirection::Outbound);
103-
assert_eq!(node_a.payment(&payment_hash).unwrap().amount_msat, Some(invoice_amount));
110+
assert_eq!(node_a.payment(&payment_hash).unwrap().amount_msat, Some(invoice_amount_1_msat));
104111
assert_eq!(node_b.payment(&payment_hash).unwrap().status, PaymentStatus::Succeeded);
105112
assert_eq!(node_b.payment(&payment_hash).unwrap().direction, PaymentDirection::Inbound);
106-
assert_eq!(node_b.payment(&payment_hash).unwrap().amount_msat, Some(invoice_amount));
113+
assert_eq!(node_b.payment(&payment_hash).unwrap().amount_msat, Some(invoice_amount_1_msat));
107114

108115
// Assert we fail duplicate outbound payments.
109116
assert_eq!(Err(Error::NonUniquePaymentHash), node_a.send_payment(invoice));
110117

111118
// Test under-/overpayment
112-
let invoice_amount = 1000000;
113-
let invoice = node_b.receive_payment(invoice_amount, &"asdf", 9217).unwrap();
119+
let invoice_amount_2_msat = 1000_000;
120+
let invoice = node_b.receive_payment(invoice_amount_2_msat, &"asdf", 9217).unwrap();
114121

115-
let underpaid_amount = invoice_amount - 1;
122+
let underpaid_amount = invoice_amount_2_msat - 1;
116123
assert_eq!(
117124
Err(Error::InvalidAmount),
118125
node_a.send_payment_using_amount(invoice, underpaid_amount)
119126
);
120127

121-
let invoice = node_b.receive_payment(invoice_amount, &"asdf", 9217).unwrap();
122-
let overpaid_amount = invoice_amount + 100;
123-
let payment_hash = node_a.send_payment_using_amount(invoice, overpaid_amount).unwrap();
128+
let invoice = node_b.receive_payment(invoice_amount_2_msat, &"asdf", 9217).unwrap();
129+
let overpaid_amount_msat = invoice_amount_2_msat + 100;
130+
let payment_hash = node_a.send_payment_using_amount(invoice, overpaid_amount_msat).unwrap();
124131
expect_event!(node_a, PaymentSuccessful);
125132
let received_amount = match node_b.next_event() {
126133
ref e @ Event::PaymentReceived { amount_msat, .. } => {
@@ -132,20 +139,20 @@ fn channel_full_cycle() {
132139
panic!("{} got unexpected event!: {:?}", std::stringify!(node_b), e);
133140
}
134141
};
135-
assert_eq!(received_amount, overpaid_amount);
142+
assert_eq!(received_amount, overpaid_amount_msat);
136143
assert_eq!(node_a.payment(&payment_hash).unwrap().status, PaymentStatus::Succeeded);
137144
assert_eq!(node_a.payment(&payment_hash).unwrap().direction, PaymentDirection::Outbound);
138-
assert_eq!(node_a.payment(&payment_hash).unwrap().amount_msat, Some(overpaid_amount));
145+
assert_eq!(node_a.payment(&payment_hash).unwrap().amount_msat, Some(overpaid_amount_msat));
139146
assert_eq!(node_b.payment(&payment_hash).unwrap().status, PaymentStatus::Succeeded);
140147
assert_eq!(node_b.payment(&payment_hash).unwrap().direction, PaymentDirection::Inbound);
141-
assert_eq!(node_b.payment(&payment_hash).unwrap().amount_msat, Some(overpaid_amount));
148+
assert_eq!(node_b.payment(&payment_hash).unwrap().amount_msat, Some(overpaid_amount_msat));
142149

143150
// Test "zero-amount" invoice payment
144151
let variable_amount_invoice = node_b.receive_variable_amount_payment(&"asdf", 9217).unwrap();
145-
let determined_amount = 1234567;
152+
let determined_amount_msat = 1234_567;
146153
assert_eq!(Err(Error::InvalidInvoice), node_a.send_payment(variable_amount_invoice.clone()));
147154
let payment_hash =
148-
node_a.send_payment_using_amount(variable_amount_invoice, determined_amount).unwrap();
155+
node_a.send_payment_using_amount(variable_amount_invoice, determined_amount_msat).unwrap();
149156

150157
expect_event!(node_a, PaymentSuccessful);
151158
let received_amount = match node_b.next_event() {
@@ -158,13 +165,13 @@ fn channel_full_cycle() {
158165
panic!("{} got unexpected event!: {:?}", std::stringify!(node_b), e);
159166
}
160167
};
161-
assert_eq!(received_amount, determined_amount);
168+
assert_eq!(received_amount, determined_amount_msat);
162169
assert_eq!(node_a.payment(&payment_hash).unwrap().status, PaymentStatus::Succeeded);
163170
assert_eq!(node_a.payment(&payment_hash).unwrap().direction, PaymentDirection::Outbound);
164-
assert_eq!(node_a.payment(&payment_hash).unwrap().amount_msat, Some(determined_amount));
171+
assert_eq!(node_a.payment(&payment_hash).unwrap().amount_msat, Some(determined_amount_msat));
165172
assert_eq!(node_b.payment(&payment_hash).unwrap().status, PaymentStatus::Succeeded);
166173
assert_eq!(node_b.payment(&payment_hash).unwrap().direction, PaymentDirection::Inbound);
167-
assert_eq!(node_b.payment(&payment_hash).unwrap().amount_msat, Some(determined_amount));
174+
assert_eq!(node_b.payment(&payment_hash).unwrap().amount_msat, Some(determined_amount_msat));
168175

169176
node_b.close_channel(&channel_id, &node_a.node_id()).unwrap();
170177
expect_event!(node_a, ChannelClosed);
@@ -176,8 +183,18 @@ fn channel_full_cycle() {
176183
node_a.sync_wallets().unwrap();
177184
node_b.sync_wallets().unwrap();
178185

179-
assert!(node_a.on_chain_balance().unwrap().get_spendable() > 90000);
180-
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), 103234);
186+
let sum_of_all_payments_sat =
187+
(push_msat + invoice_amount_1_msat + overpaid_amount_msat + determined_amount_msat) / 1000;
188+
let node_a_upper_bound_sat =
189+
(premine_amount_sat - funding_amount_sat) + (funding_amount_sat - sum_of_all_payments_sat);
190+
let node_a_lower_bound_sat = node_a_upper_bound_sat - onchain_fee_buffer_sat;
191+
assert!(node_a.on_chain_balance().unwrap().get_spendable() > node_a_lower_bound_sat);
192+
assert!(node_a.on_chain_balance().unwrap().get_spendable() < node_a_upper_bound_sat);
193+
let expected_final_amount_node_b_sat = premine_amount_sat + sum_of_all_payments_sat;
194+
assert_eq!(
195+
node_b.on_chain_balance().unwrap().get_spendable(),
196+
expected_final_amount_node_b_sat
197+
);
181198

182199
node_a.stop().unwrap();
183200
println!("\nA stopped");
@@ -201,22 +218,24 @@ fn channel_open_fails_when_funds_insufficient() {
201218
node_b.start().unwrap();
202219
let addr_b = node_b.new_funding_address().unwrap();
203220

221+
let premine_amount_sat = 100_000;
222+
204223
premine_and_distribute_funds(
205224
&bitcoind,
206225
&electrsd,
207226
vec![addr_a, addr_b],
208-
Amount::from_sat(100000),
227+
Amount::from_sat(premine_amount_sat),
209228
);
210229
node_a.sync_wallets().unwrap();
211230
node_b.sync_wallets().unwrap();
212-
assert_eq!(node_a.on_chain_balance().unwrap().get_spendable(), 100000);
213-
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), 100000);
231+
assert_eq!(node_a.on_chain_balance().unwrap().get_spendable(), premine_amount_sat);
232+
assert_eq!(node_b.on_chain_balance().unwrap().get_spendable(), premine_amount_sat);
214233

215234
println!("\nA -- connect_open_channel -> B");
216235
let node_b_addr = format!("{}@{}", node_b.node_id(), node_b.listening_address().unwrap());
217236
assert_eq!(
218237
Err(Error::InsufficientFunds),
219-
node_a.connect_open_channel(&node_b_addr, 120000, true)
238+
node_a.connect_open_channel(&node_b_addr, 120000, None, true)
220239
);
221240
}
222241

0 commit comments

Comments
 (0)