From: Matt Corallo <649246+TheBlueMatt@users.noreply.github.com> Date: Tue, 10 Aug 2021 00:56:25 +0000 (+0000) Subject: Merge pull request #1038 from valentinewallace/2021-08-keysend-docs X-Git-Tag: v0.0.100~6 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=6a94ff9daeb6f5f38cbb16b7f46c8480924592cd;hp=552a24419107d46ac8066b0462709f55094daaca;p=rust-lightning Merge pull request #1038 from valentinewallace/2021-08-keysend-docs --- diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 70ddac5d..ef9ce82d 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -39,6 +39,7 @@ use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::ln::channelmanager::{ChainParameters, ChannelManager, PaymentSendFailure, ChannelManagerReadArgs}; use lightning::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use lightning::ln::msgs::{CommitmentUpdate, ChannelMessageHandler, DecodeError, UpdateAddHTLC, Init}; +use lightning::ln::script::ShutdownScript; use lightning::util::enforcing_trait_impls::{EnforcingSigner, INITIAL_REVOKED_COMMITMENT_NUMBER}; use lightning::util::errors::APIError; use lightning::util::events; @@ -164,9 +165,11 @@ impl KeysInterface for KeyProvider { Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() } - fn get_shutdown_pubkey(&self) -> PublicKey { + fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { let secp_ctx = Secp256k1::signing_only(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap()) + let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, self.node_id]).unwrap(); + let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize()); + ShutdownScript::new_p2wpkh(&pubkey_hash) } fn get_channel_signer(&self, _inbound: bool, channel_value_satoshis: u64) -> EnforcingSigner { @@ -250,6 +253,7 @@ fn check_api_err(api_err: APIError) { APIError::MonitorUpdateFailed => { // We can (obviously) temp-fail a monitor update }, + APIError::IncompatibleShutdownScript { .. } => panic!("Cannot send an incompatible shutdown script"), } } #[inline] @@ -393,6 +397,9 @@ pub fn do_test(data: &[u8], out: Out) { let mut channel_txn = Vec::new(); macro_rules! make_channel { ($source: expr, $dest: expr, $chan_id: expr) => { { + $source.peer_connected(&$dest.get_our_node_id(), &Init { features: InitFeatures::known() }); + $dest.peer_connected(&$source.get_our_node_id(), &Init { features: InitFeatures::known() }); + $source.create_channel($dest.get_our_node_id(), 100_000, 42, 0, None).unwrap(); let open_channel = { let events = $source.get_and_clear_pending_msg_events(); diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index d1adf06e..4f474bd3 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -36,6 +36,7 @@ use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::ln::channelmanager::{ChainParameters, ChannelManager}; use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor}; use lightning::ln::msgs::DecodeError; +use lightning::ln::script::ShutdownScript; use lightning::routing::router::get_route; use lightning::routing::network_graph::NetGraphMsgHandler; use lightning::util::config::UserConfig; @@ -271,9 +272,11 @@ impl KeysInterface for KeyProvider { Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script() } - fn get_shutdown_pubkey(&self) -> PublicKey { + fn get_shutdown_scriptpubkey(&self) -> ShutdownScript { let secp_ctx = Secp256k1::signing_only(); - PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap()) + let secret_key = SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]).unwrap(); + let pubkey_hash = WPubkeyHash::hash(&PublicKey::from_secret_key(&secp_ctx, &secret_key).serialize()); + ShutdownScript::new_p2wpkh(&pubkey_hash) } fn get_channel_signer(&self, inbound: bool, channel_value_satoshis: u64) -> EnforcingSigner { diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index afa3633b..e73ddeb7 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -50,6 +50,8 @@ const FRESHNESS_TIMER: u64 = 60; #[cfg(test)] const FRESHNESS_TIMER: u64 = 1; +const PING_TIMER: u64 = 5; + /// Trait which handles persisting a [`ChannelManager`] to disk. /// /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager @@ -138,7 +140,8 @@ impl BackgroundProcessor { let stop_thread = Arc::new(AtomicBool::new(false)); let stop_thread_clone = stop_thread.clone(); let handle = thread::spawn(move || -> Result<(), std::io::Error> { - let mut current_time = Instant::now(); + let mut last_freshness_call = Instant::now(); + let mut last_ping_call = Instant::now(); loop { peer_manager.process_events(); channel_manager.process_pending_events(&event_handler); @@ -153,11 +156,27 @@ impl BackgroundProcessor { log_trace!(logger, "Terminating background processor."); return Ok(()); } - if current_time.elapsed().as_secs() > FRESHNESS_TIMER { - log_trace!(logger, "Calling ChannelManager's and PeerManager's timer_tick_occurred"); + if last_freshness_call.elapsed().as_secs() > FRESHNESS_TIMER { + log_trace!(logger, "Calling ChannelManager's timer_tick_occurred"); channel_manager.timer_tick_occurred(); + last_freshness_call = Instant::now(); + } + if last_ping_call.elapsed().as_secs() > PING_TIMER * 2 { + // On various platforms, we may be starved of CPU cycles for several reasons. + // E.g. on iOS, if we've been in the background, we will be entirely paused. + // Similarly, if we're on a desktop platform and the device has been asleep, we + // may not get any cycles. + // In any case, if we've been entirely paused for more than double our ping + // timer, we should have disconnected all sockets by now (and they're probably + // dead anyway), so disconnect them by calling `timer_tick_occurred()` twice. + log_trace!(logger, "Awoke after more than double our ping timer, disconnecting peers."); + peer_manager.timer_tick_occurred(); peer_manager.timer_tick_occurred(); - current_time = Instant::now(); + last_ping_call = Instant::now(); + } else if last_ping_call.elapsed().as_secs() > PING_TIMER { + log_trace!(logger, "Calling PeerManager's timer_tick_occurred"); + peer_manager.timer_tick_occurred(); + last_ping_call = Instant::now(); } } }); @@ -224,7 +243,7 @@ mod tests { use lightning::get_event_msg; use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager}; use lightning::ln::features::InitFeatures; - use lightning::ln::msgs::ChannelMessageHandler; + use lightning::ln::msgs::{ChannelMessageHandler, Init}; use lightning::ln::peer_handler::{PeerManager, MessageHandler, SocketDescriptor}; use lightning::util::config::UserConfig; use lightning::util::events::{Event, MessageSendEventsProvider, MessageSendEvent}; @@ -298,6 +317,14 @@ mod tests { let node = Node { node: manager, peer_manager, chain_monitor, persister, tx_broadcaster, logger, best_block }; nodes.push(node); } + + for i in 0..num_nodes { + for j in (i+1)..num_nodes { + nodes[i].node.peer_connected(&nodes[j].node.get_our_node_id(), &Init { features: InitFeatures::known() }); + nodes[j].node.peer_connected(&nodes[i].node.get_our_node_id(), &Init { features: InitFeatures::known() }); + } + } + nodes } @@ -441,8 +468,10 @@ mod tests { let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone()); loop { let log_entries = nodes[0].logger.lines.lock().unwrap(); - let desired_log = "Calling ChannelManager's and PeerManager's timer_tick_occurred".to_string(); - if log_entries.get(&("lightning_background_processor".to_string(), desired_log)).is_some() { + let desired_log = "Calling ChannelManager's timer_tick_occurred".to_string(); + let second_desired_log = "Calling PeerManager's timer_tick_occurred".to_string(); + if log_entries.get(&("lightning_background_processor".to_string(), desired_log)).is_some() && + log_entries.get(&("lightning_background_processor".to_string(), second_desired_log)).is_some() { break } } diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 7904d9bd..6c11703d 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -438,6 +438,9 @@ pub(crate) enum ChannelMonitorUpdateStep { /// think we've fallen behind! should_broadcast: bool, }, + ShutdownScript { + scriptpubkey: Script, + }, } impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep, @@ -461,6 +464,9 @@ impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep, (4, ChannelForceClosed) => { (0, should_broadcast, required), }, + (5, ShutdownScript) => { + (0, scriptpubkey, required), + }, ;); /// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates @@ -493,7 +499,7 @@ pub(crate) struct ChannelMonitorImpl { destination_script: Script, broadcasted_holder_revokable_script: Option<(Script, PublicKey, PublicKey)>, counterparty_payment_script: Script, - shutdown_script: Script, + shutdown_script: Option