Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 480
Add a simple send-funds benchmark in channelmanager#860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ccbff84592792078062568a9f0b8File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -434,6 +434,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, | ||
| #[cfg(not(any(test, feature = "_test_utils")))] | ||
| channel_state: Mutex<ChannelHolder<Signer>>, | ||
| our_network_key: SecretKey, | ||
| our_network_pubkey: PublicKey, | ||
| /// Used to track the last value sent in a node_announcement "timestamp" field. We ensure this | ||
| /// 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 | ||
| latest_block_height: AtomicUsize::new(params.latest_height), | ||
| last_block_hash: RwLock::new(params.latest_hash), | ||
| secp_ctx, | ||
| channel_state: Mutex::new(ChannelHolder{ | ||
| by_id: HashMap::new(), | ||
| @@ -832,6 +832,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | ||
| pending_msg_events: Vec::new(), | ||
| }), | ||
| our_network_key: keys_manager.get_node_secret(), | ||
| our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &keys_manager.get_node_secret()), | ||
| secp_ctx, | ||
| last_node_announcement_serial: AtomicUsize::new(0), | ||
| @@ -2315,7 +2317,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana | ||
| /// Gets the node_id held by this ChannelManager | ||
| pub fn get_our_node_id(&self) -> PublicKey { | ||
| PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key) | ||
| self.our_network_pubkey.clone() | ||
| } | ||
| /// 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> | ||
| latest_block_height: AtomicUsize::new(latest_block_height as usize), | ||
| last_block_hash: RwLock::new(last_block_hash), | ||
| secp_ctx, | ||
| channel_state: Mutex::new(ChannelHolder { | ||
| by_id, | ||
| @@ -4328,6 +4329,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> | ||
| pending_msg_events: Vec::new(), | ||
| }), | ||
| our_network_key: args.keys_manager.get_node_secret(), | ||
| our_network_pubkey: PublicKey::from_secret_key(&secp_ctx, &args.keys_manager.get_node_secret()), | ||
| secp_ctx, | ||
| last_node_announcement_serial: AtomicUsize::new(last_node_announcement_serial as usize), | ||
| @@ -4404,3 +4407,154 @@ mod tests { | ||
| } | ||
| } | ||
| } | ||
| #[cfg(all(any(test, feature = "_test_utils"), feature = "unstable"))] | ||
| pub mod bench { | ||
| use chain::Listen; | ||
| use chain::chainmonitor::ChainMonitor; | ||
| use chain::channelmonitor::Persist; | ||
| use chain::keysinterface::{KeysManager, InMemorySigner}; | ||
| use chain::transaction::OutPoint; | ||
| use ln::channelmanager::{ChainParameters, ChannelManager, PaymentHash, PaymentPreimage}; | ||
| use ln::features::InitFeatures; | ||
| use ln::functional_test_utils::*; | ||
| use ln::msgs::ChannelMessageHandler; | ||
| use routing::network_graph::NetworkGraph; | ||
| use routing::router::get_route; | ||
| use util::test_utils; | ||
| use util::config::UserConfig; | ||
| use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; | ||
| use bitcoin::hashes::Hash; | ||
| use bitcoin::hashes::sha256::Hash as Sha256; | ||
| use bitcoin::{Block, BlockHeader, Transaction, TxOut}; | ||
| use std::sync::Mutex; | ||
| use test::Bencher; | ||
| struct NodeHolder<'a, P: Persist<InMemorySigner>> { | ||
| node: &'a ChannelManager<InMemorySigner, | ||
Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd be curious to compare this to an CollaboratorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd be astounded if it made a difference - we aren't actually cloning the | ||
| &'a ChainMonitor<InMemorySigner, &'a test_utils::TestChainSource, | ||
| &'a test_utils::TestBroadcaster, &'a test_utils::TestFeeEstimator, | ||
| &'a test_utils::TestLogger, &'a P>, | ||
| &'a test_utils::TestBroadcaster, &'a KeysManager, | ||
| &'a test_utils::TestFeeEstimator, &'a test_utils::TestLogger> | ||
| } | ||
| #[cfg(test)] | ||
| #[bench] | ||
| fn bench_sends(bench: &mut Bencher) { | ||
valentinewallace marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| bench_two_sends(bench, test_utils::TestPersister::new(), test_utils::TestPersister::new()); | ||
| } | ||
| pub fn bench_two_sends<P: Persist<InMemorySigner>>(bench: &mut Bencher, persister_a: P, persister_b: P) { | ||
| // Do a simple benchmark of sending a payment back and forth between two nodes. | ||
| // Note that this is unrealistic as each payment send will require at least two fsync | ||
| // calls per node. | ||
| let network = bitcoin::Network::Testnet; | ||
| let genesis_hash = bitcoin::blockdata::constants::genesis_block(network).header.block_hash(); | ||
| let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}; | ||
| let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; | ||
| let mut config: UserConfig = Default::default(); | ||
| config.own_channel_config.minimum_depth = 1; | ||
| let logger_a = test_utils::TestLogger::with_id("node a".to_owned()); | ||
| let chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a); | ||
| let seed_a = [1u8; 32]; | ||
| let keys_manager_a = KeysManager::new(&seed_a, 42, 42); | ||
| let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &logger_a, &keys_manager_a, config.clone(), ChainParameters { | ||
| network, | ||
| latest_hash: genesis_hash, | ||
| latest_height: 0, | ||
| }); | ||
| let node_a_holder = NodeHolder { node: &node_a }; | ||
| let logger_b = test_utils::TestLogger::with_id("node a".to_owned()); | ||
| let chain_monitor_b = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b); | ||
| let seed_b = [2u8; 32]; | ||
| let keys_manager_b = KeysManager::new(&seed_b, 42, 42); | ||
| let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &logger_b, &keys_manager_b, config.clone(), ChainParameters { | ||
| network, | ||
| latest_hash: genesis_hash, | ||
| latest_height: 0, | ||
| }); | ||
| let node_b_holder = NodeHolder { node: &node_b }; | ||
| node_a.create_channel(node_b.get_our_node_id(), 8_000_000, 100_000_000, 42, None).unwrap(); | ||
| 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())); | ||
| 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())); | ||
| let tx; | ||
| if let Event::FundingGenerationReady { temporary_channel_id, output_script, .. } = get_event!(node_a_holder, Event::FundingGenerationReady) { | ||
| tx = Transaction { version: 2, lock_time: 0, input: Vec::new(), output: vec![TxOut { | ||
| value: 8_000_000, script_pubkey: output_script, | ||
| }]}; | ||
| let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 }; | ||
| node_a.funding_transaction_generated(&temporary_channel_id, funding_outpoint); | ||
| } else { panic!(); } | ||
| 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())); | ||
| 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())); | ||
| get_event!(node_a_holder, Event::FundingBroadcastSafe); | ||
| let block = Block { | ||
| header: BlockHeader { version: 0x20000000, prev_blockhash: genesis_hash, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }, | ||
| txdata: vec![tx], | ||
| }; | ||
| Listen::block_connected(&node_a, &block, 1); | ||
| Listen::block_connected(&node_b, &block, 1); | ||
| 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())); | ||
| 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())); | ||
| let dummy_graph = NetworkGraph::new(genesis_hash); | ||
| macro_rules! send_payment { | ||
| ($node_a: expr, $node_b: expr) => { | ||
| let usable_channels = $node_a.list_usable_channels(); | ||
| 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(); | ||
| let payment_preimage = PaymentPreimage([0; 32]); | ||
| let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()); | ||
| $node_a.send_payment(&route, payment_hash, &None).unwrap(); | ||
| let payment_event = SendEvent::from_event($node_a.get_and_clear_pending_msg_events().pop().unwrap()); | ||
| $node_b.handle_update_add_htlc(&$node_a.get_our_node_id(), &payment_event.msgs[0]); | ||
| $node_b.handle_commitment_signed(&$node_a.get_our_node_id(), &payment_event.commitment_msg); | ||
| let (raa, cs) = get_revoke_commit_msgs!(NodeHolder { node: &$node_b }, $node_a.get_our_node_id()); | ||
| $node_a.handle_revoke_and_ack(&$node_b.get_our_node_id(), &raa); | ||
| $node_a.handle_commitment_signed(&$node_b.get_our_node_id(), &cs); | ||
| $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())); | ||
| expect_pending_htlcs_forwardable!(NodeHolder { node: &$node_b }); | ||
| expect_payment_received!(NodeHolder { node: &$node_b }, payment_hash, 10_000); | ||
| assert!($node_b.claim_funds(payment_preimage, &None, 10_000)); | ||
| match $node_b.get_and_clear_pending_msg_events().pop().unwrap() { | ||
| MessageSendEvent::UpdateHTLCs { node_id, updates } => { | ||
| assert_eq!(node_id, $node_a.get_our_node_id()); | ||
| $node_a.handle_update_fulfill_htlc(&$node_b.get_our_node_id(), &updates.update_fulfill_htlcs[0]); | ||
| $node_a.handle_commitment_signed(&$node_b.get_our_node_id(), &updates.commitment_signed); | ||
| }, | ||
| _ => panic!("Failed to generate claim event"), | ||
| } | ||
| let (raa, cs) = get_revoke_commit_msgs!(NodeHolder { node: &$node_a }, $node_b.get_our_node_id()); | ||
| $node_b.handle_revoke_and_ack(&$node_a.get_our_node_id(), &raa); | ||
| $node_b.handle_commitment_signed(&$node_a.get_our_node_id(), &cs); | ||
| $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())); | ||
| expect_payment_sent!(NodeHolder { node: &$node_a }, payment_preimage); | ||
| } | ||
| } | ||
| bench.iter(|| { | ||
| send_payment!(node_a, node_b); | ||
| send_payment!(node_b, node_a); | ||
| }); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -313,6 +313,24 @@ macro_rules! get_event_msg { | ||
| } | ||
| } | ||
| /// Get a specific event from the pending events queue. | ||
| #[macro_export] | ||
| macro_rules! get_event { | ||
| ($node: expr, $event_type: path) => { | ||
| { | ||
| let mut events = $node.node.get_and_clear_pending_events(); | ||
| assert_eq!(events.len(), 1); | ||
| let ev = events.pop().unwrap(); | ||
| match ev { | ||
| $event_type { .. } => { | ||
| ev | ||
| }, | ||
| _ => panic!("Unexpected event"), | ||
| } | ||
| } | ||
| } | ||
| } | ||
| #[cfg(test)] | ||
| macro_rules! get_htlc_update_msgs { | ||
| ($node: expr, $node_id: expr) => { | ||
| @@ -848,7 +866,7 @@ macro_rules! expect_pending_htlcs_forwardable { | ||
| }} | ||
| } | ||
| #[cfg(test)] | ||
| #[cfg(any(test, feature = "unstable"))] | ||
| macro_rules! expect_payment_received { | ||
TheBlueMatt marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| ($node: expr, $expected_payment_hash: expr, $expected_recv_value: expr) => { | ||
| let events = $node.node.get_and_clear_pending_events(); | ||
Uh oh!
There was an error while loading. Please reload this page.