Skip to content

Commit df732f4

Browse files
authored
Merge pull request #860 from TheBlueMatt/2021-03-bench-sends
Add a simple send-funds benchmark in channelmanager
2 parents 7665b14 + 8a9f0b8 commit df732f4

File tree

7 files changed

+203
-12
lines changed

7 files changed

+203
-12
lines changed

lightning-persister/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ description = """
88
Utilities to manage Rust-Lightning channel data persistence and retrieval.
99
"""
1010

11+
[features]
12+
unstable = ["lightning/unstable"]
13+
1114
[dependencies]
1215
bitcoin = "0.26"
1316
lightning = { version = "0.0.13", path = "../lightning" }

lightning-persister/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
#![deny(broken_intra_doc_links)]
44
#![deny(missing_docs)]
55

6+
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
7+
#[cfg(all(test, feature = "unstable"))] extern crate test;
8+
69
mod util;
710

811
extern crate lightning;
@@ -330,3 +333,15 @@ mod tests {
330333
added_monitors.clear();
331334
}
332335
}
336+
337+
#[cfg(all(test, feature = "unstable"))]
338+
pub mod bench {
339+
use test::Bencher;
340+
341+
#[bench]
342+
fn bench_sends(bench: &mut Bencher) {
343+
let persister_a = super::FilesystemPersister::new("bench_filesystem_persister_a".to_string());
344+
let persister_b = super::FilesystemPersister::new("bench_filesystem_persister_b".to_string());
345+
lightning::ln::channelmanager::bench::bench_two_sends(bench, persister_a, persister_b);
346+
}
347+
}

lightning/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
#![allow(bare_trait_objects)]
2929
#![allow(ellipsis_inclusive_range_patterns)]
3030

31-
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
32-
#[cfg(all(test, feature = "unstable"))] extern crate test;
31+
#![cfg_attr(all(any(test, feature = "_test_utils"), feature = "unstable"), feature(test))]
32+
#[cfg(all(any(test, feature = "_test_utils"), feature = "unstable"))] extern crate test;
3333

3434
extern crate bitcoin;
3535
#[cfg(any(test, feature = "_test_utils"))] extern crate hex;

lightning/src/ln/channelmanager.rs

Lines changed: 157 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
434434
#[cfg(not(any(test, feature = "_test_utils")))]
435435
channel_state: Mutex<ChannelHolder<Signer>>,
436436
our_network_key: SecretKey,
437+
our_network_pubkey: PublicKey,
437438

438439
/// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this
439440
/// value increases strictly since we don't assume access to a time source.
@@ -822,7 +823,6 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
822823

823824
latest_block_height: AtomicUsize::new(params.latest_height),
824825
last_block_hash: RwLock::new(params.latest_hash),
825-
secp_ctx,
826826

827827
channel_state: Mutex::new(ChannelHolder{
828828
by_id: HashMap::new(),
@@ -832,6 +832,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
832832
pending_msg_events: Vec::new(),
833833
}),
834834
our_network_key: keys_manager.get_node_secret(),
835+
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()),
836+
secp_ctx,
835837

836838
last_node_announcement_serial: AtomicUsize::new(0),
837839

@@ -2315,7 +2317,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
23152317

23162318
/// Gets the node_id held by this ChannelManager
23172319
pub fn get_our_node_id(&self) -> PublicKey {
2318-
PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key)
2320+
self.our_network_pubkey.clone()
23192321
}
23202322

23212323
/// Restores a single, given channel to normal operation after a
@@ -4318,7 +4320,6 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
43184320

43194321
latest_block_height: AtomicUsize::new(latest_block_height as usize),
43204322
last_block_hash: RwLock::new(last_block_hash),
4321-
secp_ctx,
43224323

43234324
channel_state: Mutex::new(ChannelHolder {
43244325
by_id,
@@ -4328,6 +4329,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
43284329
pending_msg_events: Vec::new(),
43294330
}),
43304331
our_network_key: args.keys_manager.get_node_secret(),
4332+
our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &args.keys_manager.get_node_secret()),
4333+
secp_ctx,
43314334

43324335
last_node_announcement_serial: AtomicUsize::new(last_node_announcement_serial as usize),
43334336

@@ -4404,3 +4407,154 @@ mod tests {
44044407
}
44054408
}
44064409
}
4410+
4411+
#[cfg(all(any(test, feature = "_test_utils"), feature = "unstable"))]
4412+
pub mod bench {
4413+
use chain::Listen;
4414+
use chain::chainmonitor::ChainMonitor;
4415+
use chain::channelmonitor::Persist;
4416+
use chain::keysinterface::{KeysManager, InMemorySigner};
4417+
use chain::transaction::OutPoint;
4418+
use ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
4419+
use ln::features::InitFeatures;
4420+
use ln::functional_test_utils::*;
4421+
use ln::msgs::ChannelMessageHandler;
4422+
use routing::network_graph::NetworkGraph;
4423+
use routing::router::get_route;
4424+
use util::test_utils;
4425+
use util::config::UserConfig;
4426+
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
4427+
4428+
use bitcoin::hashes::Hash;
4429+
use bitcoin::hashes::sha256::Hash as Sha256;
4430+
use bitcoin::{Block, BlockHeader, Transaction, TxOut};
4431+
4432+
use std::sync::Mutex;
4433+
4434+
use test::Bencher;
4435+
4436+
struct NodeHolder<'a, P: Persist<InMemorySigner>> {
4437+
node: &'a ChannelManager<InMemorySigner,
4438+
&'a ChainMonitor<InMemorySigner, &'a test_utils::TestChainSource,
4439+
&'a test_utils::TestBroadcaster, &'a test_utils::TestFeeEstimator,
4440+
&'a test_utils::TestLogger, &'a P>,
4441+
&'a test_utils::TestBroadcaster, &'a KeysManager,
4442+
&'a test_utils::TestFeeEstimator, &'a test_utils::TestLogger>
4443+
}
4444+
4445+
#[cfg(test)]
4446+
#[bench]
4447+
fn bench_sends(bench: &mut Bencher) {
4448+
bench_two_sends(bench, test_utils::TestPersister::new(), test_utils::TestPersister::new());
4449+
}
4450+
4451+
pub fn bench_two_sends<P: Persist<InMemorySigner>>(bench: &mut Bencher, persister_a: P, persister_b: P) {
4452+
// Do a simple benchmark of sending a payment back and forth between two nodes.
4453+
// Note that this is unrealistic as each payment send will require at least two fsync
4454+
// calls per node.
4455+
let network = bitcoin::Network::Testnet;
4456+
let genesis_hash = bitcoin::blockdata::constants::genesis_block(network).header.block_hash();
4457+
4458+
let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())};
4459+
let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
4460+
4461+
let mut config: UserConfig = Default::default();
4462+
config.own_channel_config.minimum_depth = 1;
4463+
4464+
let logger_a = test_utils::TestLogger::with_id("node a".to_owned());
4465+
let chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a);
4466+
let seed_a = [1u8; 32];
4467+
let keys_manager_a = KeysManager::new(&seed_a, 42, 42);
4468+
let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &logger_a, &keys_manager_a, config.clone(), ChainParameters {
4469+
network,
4470+
latest_hash: genesis_hash,
4471+
latest_height: 0,
4472+
});
4473+
let node_a_holder = NodeHolder { node: &node_a };
4474+
4475+
let logger_b = test_utils::TestLogger::with_id("node a".to_owned());
4476+
let chain_monitor_b = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b);
4477+
let seed_b = [2u8; 32];
4478+
let keys_manager_b = KeysManager::new(&seed_b, 42, 42);
4479+
let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &logger_b, &keys_manager_b, config.clone(), ChainParameters {
4480+
network,
4481+
latest_hash: genesis_hash,
4482+
latest_height: 0,
4483+
});
4484+
let node_b_holder = NodeHolder { node: &node_b };
4485+
4486+
node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None).unwrap();
4487+
node_b.handle_open_channel(&node_a.get_our_node_id(), InitFeatures::known(), &get_event_msg!(node_a_holder, MessageSendEvent::SendOpenChannel, node_b.get_our_node_id()));
4488+
node_a.handle_accept_channel(&node_b.get_our_node_id(), InitFeatures::known(), &get_event_msg!(node_b_holder, MessageSendEvent::SendAcceptChannel, node_a.get_our_node_id()));
4489+
4490+
let tx;
4491+
if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = get_event!(node_a_holder, Event::FundingGenerationReady) {
4492+
tx = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: vec![TxOut {
4493+
value: 8_000_000, script_pubkey: output_script,
4494+
}]};
4495+
let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 };
4496+
node_a.funding_transaction_generated(&temporary_channel_id, funding_outpoint);
4497+
} else { panic!(); }
4498+
4499+
node_b.handle_funding_created(&node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendFundingCreated, node_b.get_our_node_id()));
4500+
node_a.handle_funding_signed(&node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendFundingSigned, node_a.get_our_node_id()));
4501+
4502+
get_event!(node_a_holder, Event::FundingBroadcastSafe);
4503+
4504+
let block = Block {
4505+
header: BlockHeader { version: 0x20000000, prev_blockhash: genesis_hash, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 },
4506+
txdata: vec![tx],
4507+
};
4508+
Listen::block_connected(&node_a, &block, 1);
4509+
Listen::block_connected(&node_b, &block, 1);
4510+
4511+
node_a.handle_funding_locked(&node_b.get_our_node_id(), &get_event_msg!(node_b_holder, MessageSendEvent::SendFundingLocked, node_a.get_our_node_id()));
4512+
node_b.handle_funding_locked(&node_a.get_our_node_id(), &get_event_msg!(node_a_holder, MessageSendEvent::SendFundingLocked, node_b.get_our_node_id()));
4513+
4514+
let dummy_graph = NetworkGraph::new(genesis_hash);
4515+
4516+
macro_rules! send_payment {
4517+
($node_a: expr, $node_b: expr) => {
4518+
let usable_channels = $node_a.list_usable_channels();
4519+
let route = get_route(&$node_a.get_our_node_id(), &dummy_graph, &$node_b.get_our_node_id(), None, Some(&usable_channels.iter().map(|r| r).collect::<Vec<_>>()), &[], 10_000, TEST_FINAL_CLTV, &logger_a).unwrap();
4520+
4521+
let payment_preimage = PaymentPreimage([0; 32]);
4522+
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
4523+
4524+
$node_a.send_payment(&route, payment_hash, &None).unwrap();
4525+
let payment_event = SendEvent::from_event($node_a.get_and_clear_pending_msg_events().pop().unwrap());
4526+
$node_b.handle_update_add_htlc(&$node_a.get_our_node_id(), &payment_event.msgs[0]);
4527+
$node_b.handle_commitment_signed(&$node_a.get_our_node_id(), &payment_event.commitment_msg);
4528+
let (raa, cs) = get_revoke_commit_msgs!(NodeHolder { node: &$node_b }, $node_a.get_our_node_id());
4529+
$node_a.handle_revoke_and_ack(&$node_b.get_our_node_id(), &raa);
4530+
$node_a.handle_commitment_signed(&$node_b.get_our_node_id(), &cs);
4531+
$node_b.handle_revoke_and_ack(&$node_a.get_our_node_id(), &get_event_msg!(NodeHolder { node: &$node_a }, MessageSendEvent::SendRevokeAndACK, $node_b.get_our_node_id()));
4532+
4533+
expect_pending_htlcs_forwardable!(NodeHolder { node: &$node_b });
4534+
expect_payment_received!(NodeHolder { node: &$node_b }, payment_hash, 10_000);
4535+
assert!($node_b.claim_funds(payment_preimage, &None, 10_000));
4536+
4537+
match $node_b.get_and_clear_pending_msg_events().pop().unwrap() {
4538+
MessageSendEvent::UpdateHTLCs { node_id, updates } => {
4539+
assert_eq!(node_id, $node_a.get_our_node_id());
4540+
$node_a.handle_update_fulfill_htlc(&$node_b.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
4541+
$node_a.handle_commitment_signed(&$node_b.get_our_node_id(), &updates.commitment_signed);
4542+
},
4543+
_ => panic!("Failed to generate claim event"),
4544+
}
4545+
4546+
let (raa, cs) = get_revoke_commit_msgs!(NodeHolder { node: &$node_a }, $node_b.get_our_node_id());
4547+
$node_b.handle_revoke_and_ack(&$node_a.get_our_node_id(), &raa);
4548+
$node_b.handle_commitment_signed(&$node_a.get_our_node_id(), &cs);
4549+
$node_a.handle_revoke_and_ack(&$node_b.get_our_node_id(), &get_event_msg!(NodeHolder { node: &$node_b }, MessageSendEvent::SendRevokeAndACK, $node_a.get_our_node_id()));
4550+
4551+
expect_payment_sent!(NodeHolder { node: &$node_a }, payment_preimage);
4552+
}
4553+
}
4554+
4555+
bench.iter(|| {
4556+
send_payment!(node_a, node_b);
4557+
send_payment!(node_b, node_a);
4558+
});
4559+
}
4560+
}

lightning/src/ln/functional_test_utils.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,24 @@ macro_rules! get_event_msg {
313313
}
314314
}
315315

316+
/// Get a specific event from the pending events queue.
317+
#[macro_export]
318+
macro_rules! get_event {
319+
($node: expr, $event_type: path) => {
320+
{
321+
let mut events = $node.node.get_and_clear_pending_events();
322+
assert_eq!(events.len(), 1);
323+
let ev = events.pop().unwrap();
324+
match ev {
325+
$event_type { .. } => {
326+
ev
327+
},
328+
_ => panic!("Unexpected event"),
329+
}
330+
}
331+
}
332+
}
333+
316334
#[cfg(test)]
317335
macro_rules! get_htlc_update_msgs {
318336
($node: expr, $node_id: expr) => {
@@ -848,7 +866,7 @@ macro_rules! expect_pending_htlcs_forwardable {
848866
}}
849867
}
850868

851-
#[cfg(test)]
869+
#[cfg(any(test, feature = "unstable"))]
852870
macro_rules! expect_payment_received {
853871
($node: expr, $expected_payment_hash: expr, $expected_recv_value: expr) => {
854872
let events = $node.node.get_and_clear_pending_events();

lightning/src/ln/mod.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
//! you want to learn things about the network topology (eg get a route for sending a payment),
1919
//! call into your NetGraphMsgHandler.
2020
21+
#[cfg(any(test, feature = "_test_utils"))]
22+
#[macro_use]
23+
pub mod functional_test_utils;
24+
2125
pub mod channelmanager;
2226
pub mod msgs;
2327
pub mod peer_handler;
@@ -38,9 +42,6 @@ mod wire;
3842
// without the node parameter being mut. This is incorrect, and thus newer rustcs will complain
3943
// about an unnecessary mut. Thus, we silence the unused_mut warning in two test modules below.
4044

41-
#[cfg(any(test, feature = "_test_utils"))]
42-
#[macro_use]
43-
pub mod functional_test_utils;
4445
#[cfg(test)]
4546
#[allow(unused_mut)]
4647
mod functional_tests;

lightning/src/util/test_utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,12 +186,12 @@ impl TestPersister {
186186
*self.update_ret.lock().unwrap() = ret;
187187
}
188188
}
189-
impl channelmonitor::Persist<EnforcingSigner> for TestPersister {
190-
fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
189+
impl<Signer: keysinterface::Sign> channelmonitor::Persist<Signer> for TestPersister {
190+
fn persist_new_channel(&self, _funding_txo: OutPoint, _data: &channelmonitor::ChannelMonitor<Signer>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
191191
self.update_ret.lock().unwrap().clone()
192192
}
193193

194-
fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &channelmonitor::ChannelMonitorUpdate, _data: &channelmonitor::ChannelMonitor<EnforcingSigner>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
194+
fn update_persisted_channel(&self, _funding_txo: OutPoint, _update: &channelmonitor::ChannelMonitorUpdate, _data: &channelmonitor::ChannelMonitor<Signer>) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
195195
self.update_ret.lock().unwrap().clone()
196196
}
197197
}

0 commit comments

Comments
 (0)