diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 7c3700f85f5..59612636a9e 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -62,7 +62,9 @@ use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessa use lightning::routing::router::{ InFlightHtlcs, Path, PaymentParameters, Route, RouteHop, RouteParameters, Router, }; -use lightning::sign::{EntropySource, InMemorySigner, NodeSigner, Recipient, SignerProvider}; +use lightning::sign::{ + EntropySource, InMemorySigner, NodeSigner, PeerStorageKey, Recipient, SignerProvider, +}; use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::util::config::UserConfig; use lightning::util::hash_tables::*; @@ -189,6 +191,7 @@ struct TestChainMonitor { Arc, Arc, Arc, + Arc, >, >, pub latest_monitors: Mutex>, @@ -205,6 +208,8 @@ impl TestChainMonitor { logger.clone(), feeest, Arc::clone(&persister), + Arc::clone(&keys), + keys.get_peer_storage_key(), )), logger, keys, @@ -338,6 +343,10 @@ impl NodeSigner for KeyProvider { unreachable!() } + fn get_peer_storage_key(&self) -> PeerStorageKey { + PeerStorageKey { inner: [42; 32] } + } + fn sign_bolt12_invoice( &self, _invoice: &UnsignedBolt12Invoice, ) -> Result { diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 90755ae94f1..f6fa07199fa 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -56,7 +56,9 @@ use lightning::routing::router::{ InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router, }; use lightning::routing::utxo::UtxoLookup; -use lightning::sign::{EntropySource, InMemorySigner, NodeSigner, Recipient, SignerProvider}; +use lightning::sign::{ + EntropySource, InMemorySigner, NodeSigner, PeerStorageKey, Recipient, SignerProvider, +}; use lightning::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::util::config::{ChannelConfig, UserConfig}; use lightning::util::errors::APIError; @@ -223,6 +225,7 @@ type ChannelMan<'a> = ChannelManager< Arc, Arc, Arc, + Arc, >, >, Arc, @@ -242,6 +245,7 @@ type PeerMan<'a> = PeerManager< Arc, IgnoringMessageHandler, Arc, + IgnoringMessageHandler, >; struct MoneyLossDetector<'a> { @@ -254,6 +258,7 @@ struct MoneyLossDetector<'a> { Arc, Arc, Arc, + Arc, >, >, handler: PeerMan<'a>, @@ -278,6 +283,7 @@ impl<'a> MoneyLossDetector<'a> { Arc, Arc, Arc, + Arc, >, >, handler: PeerMan<'a>, @@ -428,6 +434,10 @@ impl NodeSigner for KeyProvider { let secp_ctx = Secp256k1::signing_only(); Ok(secp_ctx.sign_ecdsa(&msg_hash, &self.node_secret)) } + + fn get_peer_storage_key(&self) -> PeerStorageKey { + PeerStorageKey { inner: [42; 32] } + } } impl SignerProvider for KeyProvider { @@ -560,20 +570,24 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { ]; let broadcast = Arc::new(TestBroadcaster { txn_broadcasted: Mutex::new(Vec::new()) }); + + let keys_manager = Arc::new(KeyProvider { + node_secret: our_network_key.clone(), + inbound_payment_key: ExpandedKey::new(inbound_payment_key), + counter: AtomicU64::new(0), + signer_state: RefCell::new(new_hash_map()), + }); + let monitor = Arc::new(chainmonitor::ChainMonitor::new( None, broadcast.clone(), Arc::clone(&logger), fee_est.clone(), Arc::new(TestPersister { update_ret: Mutex::new(ChannelMonitorUpdateStatus::Completed) }), + Arc::clone(&keys_manager), + keys_manager.get_peer_storage_key(), )); - let keys_manager = Arc::new(KeyProvider { - node_secret: our_network_key.clone(), - inbound_payment_key: ExpandedKey::new(inbound_payment_key), - counter: AtomicU64::new(0), - signer_state: RefCell::new(new_hash_map()), - }); let network = Network::Bitcoin; let best_block_timestamp = genesis_block(network).header.time; let params = ChainParameters { network, best_block: BestBlock::from_network(network) }; @@ -605,6 +619,7 @@ pub fn do_test(mut data: &[u8], logger: &Arc) { route_handler: gossip_sync.clone(), onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: IgnoringMessageHandler {}, + send_only_message_handler: IgnoringMessageHandler {}, }; let random_data = [ 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, @@ -1170,7 +1185,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 255 ext_from_hex("0301ff", &mut test); // beginning of accept_channel - ext_from_hex("0021 0000000000000000000000000000000000000000000000000000000000000e05 0000000000000162 00000000004c4b40 00000000000003e8 00000000000003e8 00000002 03f0 0005 030000000000000000000000000000000000000000000000000000000000000100 030000000000000000000000000000000000000000000000000000000000000200 030000000000000000000000000000000000000000000000000000000000000300 030000000000000000000000000000000000000000000000000000000000000400 030000000000000000000000000000000000000000000000000000000000000500 02660000000000000000000000000000", &mut test); + ext_from_hex("0021 0000000000000000000000000000000000000000000000000000000000000e12 0000000000000162 00000000004c4b40 00000000000003e8 00000000000003e8 00000002 03f0 0005 030000000000000000000000000000000000000000000000000000000000000100 030000000000000000000000000000000000000000000000000000000000000200 030000000000000000000000000000000000000000000000000000000000000300 030000000000000000000000000000000000000000000000000000000000000400 030000000000000000000000000000000000000000000000000000000000000500 02660000000000000000000000000000", &mut test); // inbound read from peer id 1 of len 35 ext_from_hex("030123", &mut test); // rest of accept_channel and mac @@ -1191,11 +1206,11 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 114 ext_from_hex("030172", &mut test); // funding_signed message and mac - ext_from_hex("0023 3a00000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000007c0001000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); + ext_from_hex("0023 2900000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000b90001000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); // broadcast funding transaction ext_from_hex("0b", &mut test); - // by now client should have sent a channel_ready (CHECK 4: SendChannelReady to 03020000 for chan 3f000000) + // by now client should have sent a channel_ready (CHECK 4: SendChannelReady to 03020000 for chan 2f000000) // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1204,7 +1219,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 83 ext_from_hex("030153", &mut test); // channel_ready and mac - ext_from_hex("0024 3a00000000000000000000000000000000000000000000000000000000000000 026700000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); + ext_from_hex("0024 2900000000000000000000000000000000000000000000000000000000000000 026700000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); // inbound read from peer id 0 of len 18 ext_from_hex("030012", &mut test); @@ -1257,7 +1272,7 @@ fn two_peer_forwarding_seed() -> Vec { ext_from_hex("07", &mut test); // Four feerate requests to check dust exposure while forwarding the HTLC ext_from_hex("00fd00fd00fd00fd", &mut test); - // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7: UpdateHTLCs event for node 03020000 with 1 HTLCs for channel 3f000000) + // client now sends id 1 update_add_htlc and commitment_signed (CHECK 7: UpdateHTLCs event for node 03020000 with 1 HTLCs for channel 2f000000) // we respond with commitment_signed then revoke_and_ack (a weird, but valid, order) // inbound read from peer id 1 of len 18 @@ -1267,7 +1282,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 116 ext_from_hex("030174", &mut test); // commitment_signed and mac - ext_from_hex("0084 3a00000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000006a0001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); + ext_from_hex("0084 2900000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000e40001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); // // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1276,7 +1291,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 115 ext_from_hex("030173", &mut test); // revoke_and_ack and mac - ext_from_hex("0085 3a00000000000000000000000000000000000000000000000000000000000000 6600000000000000000000000000000000000000000000000000000000000000 026400000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); + ext_from_hex("0085 2900000000000000000000000000000000000000000000000000000000000000 6600000000000000000000000000000000000000000000000000000000000000 026400000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); // // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1285,7 +1300,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 90 ext_from_hex("03015a", &mut test); // update_fulfill_htlc and mac - ext_from_hex("0082 3a00000000000000000000000000000000000000000000000000000000000000 0000000000000000 ff00888888888888888888888888888888888888888888888888888888888888 01000000000000000000000000000000", &mut test); + ext_from_hex("0082 2900000000000000000000000000000000000000000000000000000000000000 0000000000000000 ff00888888888888888888888888888888888888888888888888888888888888 01000000000000000000000000000000", &mut test); // client should immediately claim the pending HTLC from peer 0 (CHECK 8: SendFulfillHTLCs for node 03000000 with preimage ff00888888 for channel 3d000000) // inbound read from peer id 1 of len 18 @@ -1295,7 +1310,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 116 ext_from_hex("030174", &mut test); // commitment_signed and mac - ext_from_hex("0084 3a00000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000100001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); + ext_from_hex("0084 2900000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000330001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1304,7 +1319,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 115 ext_from_hex("030173", &mut test); // revoke_and_ack and mac - ext_from_hex("0085 3a00000000000000000000000000000000000000000000000000000000000000 6700000000000000000000000000000000000000000000000000000000000000 026500000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); + ext_from_hex("0085 2900000000000000000000000000000000000000000000000000000000000000 6700000000000000000000000000000000000000000000000000000000000000 026500000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); // before responding to the commitment_signed generated above, send a new HTLC // inbound read from peer id 0 of len 18 @@ -1380,7 +1395,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 116 ext_from_hex("030174", &mut test); // commitment_signed and mac - ext_from_hex("0084 3a00000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000390001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); + ext_from_hex("0084 2900000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000009c0001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1389,7 +1404,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 115 ext_from_hex("030173", &mut test); // revoke_and_ack and mac - ext_from_hex("0085 3a00000000000000000000000000000000000000000000000000000000000000 6400000000000000000000000000000000000000000000000000000000000000 027000000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); + ext_from_hex("0085 2900000000000000000000000000000000000000000000000000000000000000 6400000000000000000000000000000000000000000000000000000000000000 027000000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1398,7 +1413,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 60 ext_from_hex("03013c", &mut test); // update_fail_htlc and mac - ext_from_hex("0083 3a00000000000000000000000000000000000000000000000000000000000000 0000000000000001 0000 01000000000000000000000000000000", &mut test); + ext_from_hex("0083 2900000000000000000000000000000000000000000000000000000000000000 0000000000000001 0000 01000000000000000000000000000000", &mut test); // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1407,7 +1422,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 116 ext_from_hex("030174", &mut test); // commitment_signed and mac - ext_from_hex("0084 3a00000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000390001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); + ext_from_hex("0084 2900000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000e20001000000000000000000000000000000000000000000000000000000000000 0000 01000000000000000000000000000000", &mut test); // inbound read from peer id 1 of len 18 ext_from_hex("030112", &mut test); @@ -1416,7 +1431,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 1 of len 115 ext_from_hex("030173", &mut test); // revoke_and_ack and mac - ext_from_hex("0085 3a00000000000000000000000000000000000000000000000000000000000000 6500000000000000000000000000000000000000000000000000000000000000 027100000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); + ext_from_hex("0085 2900000000000000000000000000000000000000000000000000000000000000 6500000000000000000000000000000000000000000000000000000000000000 027100000000000000000000000000000000000000000000000000000000000000 01000000000000000000000000000000", &mut test); // process the now-pending HTLC forward ext_from_hex("07", &mut test); @@ -1449,7 +1464,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 0 of len 255 ext_from_hex("0300ff", &mut test); // beginning of update_add_htlc from 0 to 1 via client - ext_from_hex("0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000002 00000000000b0838 ff00000000000000000000000000000000000000000000000000000000000000 000003f0 00 030000000000000000000000000000000000000000000000000000000000000555 12 02030927c0 0401a0 060800000e0000010000 0a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", &mut test); + ext_from_hex("0080 3d00000000000000000000000000000000000000000000000000000000000000 0000000000000002 00000000000b0838 ff00000000000000000000000000000000000000000000000000000000000000 000003f0 00 030000000000000000000000000000000000000000000000000000000000000555 12 02030927c1 0401a0 060800000e0000010000 0a00000000000000000000000000000000000000000000000000000000000000 ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", &mut test); // inbound read from peer id 0 of len 255 ext_from_hex("0300ff", &mut test); ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", &mut test); @@ -1465,7 +1480,7 @@ fn two_peer_forwarding_seed() -> Vec { // inbound read from peer id 0 of len 193 ext_from_hex("0300c1", &mut test); // end of update_add_htlc from 0 to 1 via client and mac - ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 5300000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test); + ext_from_hex("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 5200000000000000000000000000000000000000000000000000000000000000 03000000000000000000000000000000", &mut test); // One feerate request to check dust exposure ext_from_hex("00fd", &mut test); @@ -1497,15 +1512,15 @@ fn two_peer_forwarding_seed() -> Vec { // connect a block with one transaction of len 125 ext_from_hex("0c007d", &mut test); - // the commitment transaction for channel 3f00000000000000000000000000000000000000000000000000000000000000 - ext_from_hex("02000000013a000000000000000000000000000000000000000000000000000000000000000000000000000000800258020000000000002200204b0000000000000000000000000000000000000000000000000000000000000014c0000000000000160014280000000000000000000000000000000000000005000020", &mut test); + // the commitment transaction for channel 2900000000000000000000000000000000000000000000000000000000000000 + ext_from_hex("020000000129000000000000000000000000000000000000000000000000000000000000000000000000000000800258020000000000002200201f0000000000000000000000000000000000000000000000000000000000000013c00000000000001600143b0000000000000000000000000000000000000005000020", &mut test); // Two feerate requests during block connection ext_from_hex("00fd00fd", &mut test); // // connect a block with one transaction of len 94 ext_from_hex("0c005e", &mut test); // the HTLC timeout transaction - ext_from_hex("0200000001730000000000000000000000000000000000000000000000000000000000000000000000000000000001a701000000000000220020b20000000000000000000000000000000000000000000000000000000000000000000000", &mut test); + ext_from_hex("0200000001200000000000000000000000000000000000000000000000000000000000000000000000000000000001a701000000000000220020e60000000000000000000000000000000000000000000000000000000000000000000000", &mut test); // Two feerate requests during block connection ext_from_hex("00fd00fd", &mut test); // connect a block with no transactions @@ -1687,19 +1702,19 @@ mod tests { // 3 assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendChannelReady event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000002 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 4 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendChannelReady event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 3a00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendChannelReady event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 for channel 2900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 5 assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling SendRevokeAndACK event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000002 for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&4)); // 6 assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000002 with 0 adds, 0 fulfills, 0 fails, 1 commits for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 7 - assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails, 1 commits for channel 3a00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); + assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030200000000000000000000000000000000000000000000000000000000000000 with 1 adds, 0 fulfills, 0 fails, 1 commits for channel 2900000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&3)); // 8 assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000002 with 0 adds, 1 fulfills, 0 fails, 1 commits for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&1)); // 9 assert_eq!(log_entries.get(&("lightning::ln::peer_handler".to_string(), "Handling UpdateHTLCs event in peer_handler for node 030000000000000000000000000000000000000000000000000000000000000002 with 0 adds, 0 fulfills, 1 fails, 1 commits for channel 3d00000000000000000000000000000000000000000000000000000000000000".to_string())), Some(&2)); // 10 - assert_eq!(log_entries.get(&("lightning::chain::channelmonitor".to_string(), "Input spending counterparty commitment tx (0000000000000000000000000000000000000000000000000000000000000073:0) in 0000000000000000000000000000000000000000000000000000000000000067 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); + assert_eq!(log_entries.get(&("lightning::chain::channelmonitor".to_string(), "Input spending counterparty commitment tx (0000000000000000000000000000000000000000000000000000000000000020:0) in 0000000000000000000000000000000000000000000000000000000000000060 resolves outbound HTLC with payment hash ff00000000000000000000000000000000000000000000000000000000000000 with timeout".to_string())), Some(&1)); } #[test] diff --git a/fuzz/src/onion_message.rs b/fuzz/src/onion_message.rs index a5782dacd42..f2da1a316fc 100644 --- a/fuzz/src/onion_message.rs +++ b/fuzz/src/onion_message.rs @@ -23,7 +23,7 @@ use lightning::onion_message::messenger::{ }; use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler}; use lightning::onion_message::packet::OnionMessageContents; -use lightning::sign::{EntropySource, NodeSigner, Recipient, SignerProvider}; +use lightning::sign::{EntropySource, NodeSigner, PeerStorageKey, Recipient, SignerProvider}; use lightning::types::features::InitFeatures; use lightning::util::logger::Logger; use lightning::util::ser::{LengthReadable, Writeable, Writer}; @@ -249,6 +249,10 @@ impl NodeSigner for KeyProvider { ) -> Result { unreachable!() } + + fn get_peer_storage_key(&self) -> PeerStorageKey { + unreachable!() + } } impl SignerProvider for KeyProvider { diff --git a/lightning-background-processor/src/lib.rs b/lightning-background-processor/src/lib.rs index 239ff3f0c98..dda54362e35 100644 --- a/lightning-background-processor/src/lib.rs +++ b/lightning-background-processor/src/lib.rs @@ -37,6 +37,7 @@ use lightning::routing::utxo::UtxoLookup; use lightning::sign::ChangeDestinationSource; #[cfg(feature = "std")] use lightning::sign::ChangeDestinationSourceSync; +use lightning::sign::EntropySource; use lightning::sign::OutputSpender; use lightning::util::logger::Logger; use lightning::util::persist::{KVStore, Persister}; @@ -668,14 +669,14 @@ use futures_util::{dummy_waker, OptionalSelector, Selector, SelectorOutput}; /// # fn send_data(&mut self, _data: &[u8], _resume_read: bool) -> usize { 0 } /// # fn disconnect_socket(&mut self) {} /// # } -/// # type ChainMonitor = lightning::chain::chainmonitor::ChainMonitor, Arc, Arc, Arc, Arc>; +/// # type ChainMonitor = lightning::chain::chainmonitor::ChainMonitor, Arc, Arc, Arc, Arc, Arc>; /// # type NetworkGraph = lightning::routing::gossip::NetworkGraph>; /// # type P2PGossipSync
    = lightning::routing::gossip::P2PGossipSync, Arc
      , Arc>; /// # type ChannelManager = lightning::ln::channelmanager::SimpleArcChannelManager, B, FE, Logger>; /// # type OnionMessenger = lightning::onion_message::messenger::OnionMessenger, Arc, Arc, Arc>, Arc, Arc, Arc>>, Arc>, lightning::ln::peer_handler::IgnoringMessageHandler, lightning::ln::peer_handler::IgnoringMessageHandler, lightning::ln::peer_handler::IgnoringMessageHandler>; /// # type LiquidityManager = lightning_liquidity::LiquidityManager, Arc>, Arc>; /// # type Scorer = RwLock, Arc>>; -/// # type PeerManager = lightning::ln::peer_handler::SimpleArcPeerManager, B, FE, Arc
        , Logger>; +/// # type PeerManager = lightning::ln::peer_handler::SimpleArcPeerManager, B, FE, Arc
          , Logger, F, Store>; /// # /// # struct Node< /// # B: lightning::chain::chaininterface::BroadcasterInterface + Send + Sync + 'static, @@ -780,8 +781,9 @@ pub async fn process_events_async< EventHandlerFuture: core::future::Future>, EventHandler: Fn(Event) -> EventHandlerFuture, PS: 'static + Deref + Send, + ES: 'static + Deref + Send, M: 'static - + Deref::Signer, CF, T, F, L, P>> + + Deref::Signer, CF, T, F, L, P, ES>> + Send + Sync, CM: 'static + Deref, @@ -813,6 +815,7 @@ where L::Target: 'static + Logger, P::Target: 'static + Persist<::Signer>, PS::Target: 'static + Persister<'a, CM, L, S>, + ES::Target: 'static + EntropySource, CM::Target: AChannelManager, OM::Target: AOnionMessenger, PM::Target: APeerManager, @@ -976,8 +979,11 @@ impl BackgroundProcessor { P: 'static + Deref, EH: 'static + EventHandler + Send, PS: 'static + Deref + Send, + ES: 'static + Deref + Send, M: 'static - + Deref::Signer, CF, T, F, L, P>> + + Deref< + Target = ChainMonitor<::Signer, CF, T, F, L, P, ES>, + > + Send + Sync, CM: 'static + Deref + Send, @@ -1005,6 +1011,7 @@ impl BackgroundProcessor { L::Target: 'static + Logger, P::Target: 'static + Persist<::Signer>, PS::Target: 'static + Persister<'a, CM, L, S>, + ES::Target: 'static + EntropySource, CM::Target: AChannelManager, OM::Target: AOnionMessenger, PM::Target: APeerManager, @@ -1174,7 +1181,7 @@ mod tests { use lightning::routing::gossip::{NetworkGraph, P2PGossipSync}; use lightning::routing::router::{CandidateRouteHop, DefaultRouter, Path, RouteHop}; use lightning::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp, ScoreUpdate}; - use lightning::sign::{ChangeDestinationSourceSync, InMemorySigner, KeysManager}; + use lightning::sign::{ChangeDestinationSourceSync, InMemorySigner, KeysManager, NodeSigner}; use lightning::types::features::{ChannelFeatures, NodeFeatures}; use lightning::types::payment::PaymentHash; use lightning::util::config::UserConfig; @@ -1250,6 +1257,7 @@ mod tests { Arc, Arc, Arc, + Arc, >; type PGS = Arc< @@ -1301,6 +1309,7 @@ mod tests { Arc, IgnoringMessageHandler, Arc, + IgnoringMessageHandler, >, >, liquidity_manager: Arc, @@ -1662,6 +1671,8 @@ mod tests { logger.clone(), fee_estimator.clone(), kv_store.clone(), + keys_manager.clone(), + keys_manager.get_peer_storage_key(), )); let best_block = BestBlock::from_network(network); let params = ChainParameters { network, best_block }; @@ -1715,6 +1726,7 @@ mod tests { route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), onion_message_handler: messenger.clone(), custom_message_handler: IgnoringMessageHandler {}, + send_only_message_handler: IgnoringMessageHandler {}, }; let peer_manager = Arc::new(PeerManager::new( msg_handler, diff --git a/lightning-block-sync/src/init.rs b/lightning-block-sync/src/init.rs index 7697adacf2a..f71a72456dc 100644 --- a/lightning-block-sync/src/init.rs +++ b/lightning-block-sync/src/init.rs @@ -76,7 +76,7 @@ where /// P: chainmonitor::Persist, /// >( /// block_source: &B, -/// chain_monitor: &ChainMonitor, +/// chain_monitor: &ChainMonitor, /// config: UserConfig, /// entropy_source: &ES, /// node_signer: &NS, @@ -109,7 +109,7 @@ where /// config, /// vec![&mut monitor], /// ); -/// <(BlockHash, ChannelManager<&ChainMonitor, &T, &ES, &NS, &SP, &F, &R, &MR, &L>)>::read( +/// <(BlockHash, ChannelManager<&ChainMonitor, &T, &ES, &NS, &SP, &F, &R, &MR, &L>)>::read( /// &mut Cursor::new(&serialized_manager), read_args).unwrap() /// }; /// diff --git a/lightning-liquidity/tests/common/mod.rs b/lightning-liquidity/tests/common/mod.rs index 2259d1eae06..7d5ff0280e0 100644 --- a/lightning-liquidity/tests/common/mod.rs +++ b/lightning-liquidity/tests/common/mod.rs @@ -5,7 +5,7 @@ #![allow(unused_macros)] use lightning::chain::Filter; -use lightning::sign::EntropySource; +use lightning::sign::{EntropySource, NodeSigner}; use bitcoin::blockdata::constants::{genesis_block, ChainHash}; use bitcoin::blockdata::transaction::Transaction; @@ -101,6 +101,7 @@ type ChainMonitor = chainmonitor::ChainMonitor< Arc, Arc, Arc, + Arc, >; type PGS = Arc< @@ -130,6 +131,7 @@ pub(crate) struct Node { >, >, Arc, + Arc, >, >, pub(crate) liquidity_manager: @@ -429,6 +431,8 @@ pub(crate) fn create_liquidity_node( logger.clone(), fee_estimator.clone(), kv_store.clone(), + keys_manager.clone(), + keys_manager.get_peer_storage_key(), )); let best_block = BestBlock::from_network(network); let chain_params = ChainParameters { network, best_block }; @@ -467,6 +471,7 @@ pub(crate) fn create_liquidity_node( route_handler: Arc::new(test_utils::TestRoutingMessageHandler::new()), onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: Arc::clone(&liquidity_manager), + send_only_message_handler: Arc::clone(&chain_monitor), }; let peer_manager = Arc::new(PeerManager::new(msg_handler, 0, &seed, logger.clone(), keys_manager.clone())); diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index 888915f43e2..ea23e5a0115 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -837,6 +837,7 @@ mod tests { route_handler: Arc::clone(&a_handler), onion_message_handler: Arc::new(IgnoringMessageHandler {}), custom_message_handler: Arc::new(IgnoringMessageHandler {}), + send_only_message_handler: Arc::new(IgnoringMessageHandler {}), }; let a_manager = Arc::new(PeerManager::new( a_msg_handler, @@ -860,6 +861,7 @@ mod tests { route_handler: Arc::clone(&b_handler), onion_message_handler: Arc::new(IgnoringMessageHandler {}), custom_message_handler: Arc::new(IgnoringMessageHandler {}), + send_only_message_handler: Arc::new(IgnoringMessageHandler {}), }; let b_manager = Arc::new(PeerManager::new( b_msg_handler, @@ -922,6 +924,7 @@ mod tests { onion_message_handler: Arc::new(IgnoringMessageHandler {}), route_handler: Arc::new(lightning::ln::peer_handler::IgnoringMessageHandler {}), custom_message_handler: Arc::new(IgnoringMessageHandler {}), + send_only_message_handler: Arc::new(IgnoringMessageHandler {}), }; let a_manager = Arc::new(PeerManager::new( a_msg_handler, diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 09d87b775be..53784a84163 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -34,16 +34,19 @@ use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use crate::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, Balance, MonitorEvent, TransactionOutputs, WithChannelMonitor}; use crate::chain::transaction::{OutPoint, TransactionData}; use crate::ln::types::ChannelId; +use crate::ln::msgs::{self, BaseMessageHandler, Init, MessageSendEvent}; +use crate::ln::our_peer_storage::DecryptedOurPeerStorage; use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::{EntropySource, PeerStorageKey}; use crate::events::{self, Event, EventHandler, ReplayEvent}; use crate::util::logger::{Logger, WithContext}; use crate::util::errors::APIError; use crate::util::persist::MonitorName; use crate::util::wakers::{Future, Notifier}; use crate::ln::channel_state::ChannelDetails; - use crate::prelude::*; use crate::sync::{RwLock, RwLockReadGuard, Mutex, MutexGuard}; +use crate::types::features::{InitFeatures, NodeFeatures}; use core::ops::Deref; use core::sync::atomic::{AtomicUsize, Ordering}; use bitcoin::secp256k1::PublicKey; @@ -233,12 +236,13 @@ impl Deref for LockedChannelMonitor<'_, Chann /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [module-level documentation]: crate::chain::chainmonitor /// [`rebroadcast_pending_claims`]: Self::rebroadcast_pending_claims -pub struct ChainMonitor +pub struct ChainMonitor where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, + ES::Target: EntropySource, { monitors: RwLock>>, chain_source: Option, @@ -246,6 +250,7 @@ pub struct ChainMonitor, PublicKey)>>, @@ -255,14 +260,20 @@ pub struct ChainMonitor>, + + our_peerstorage_encryption_key: PeerStorageKey, } -impl ChainMonitor +impl ChainMonitor where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, + ES::Target: EntropySource, { /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view /// of a channel and reacting accordingly based on transactions in the given chain data. See @@ -388,7 +399,19 @@ where C::Target: chain::Filter, /// pre-filter blocks or only fetch blocks matching a compact filter. Otherwise, clients may /// always need to fetch full blocks absent another means for determining which blocks contain /// transactions relevant to the watched channels. - pub fn new(chain_source: Option, broadcaster: T, logger: L, feeest: F, persister: P) -> Self { + /// + /// # Note + /// `our_peerstorage_encryption_key` must be obtained from [`NodeSigner::get_peer_storage_key`]. + /// This key is used to encrypt peer storage backups. + /// + /// **Important**: This key should not be set arbitrarily or changed after initialization. The same key + /// is obtained by the [`ChannelManager`] through [`NodeSigner`] to decrypt peer backups. + /// Using an inconsistent or incorrect key will result in the inability to decrypt previously encrypted backups. + /// + /// [`NodeSigner`]: crate::sign::NodeSigner + /// [`NodeSigner::get_peer_storage_key`]: crate::sign::NodeSigner::get_peer_storage_key + /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager + pub fn new(chain_source: Option, broadcaster: T, logger: L, feeest: F, persister: P, entropy_source: ES, our_peerstorage_encryption_key: PeerStorageKey) -> Self { Self { monitors: RwLock::new(new_hash_map()), chain_source, @@ -396,9 +419,12 @@ where C::Target: chain::Filter, logger, fee_estimator: feeest, persister, + entropy_source, pending_monitor_events: Mutex::new(Vec::new()), highest_chain_height: AtomicUsize::new(0), event_notifier: Notifier::new(), + pending_send_only_events: Mutex::new(Vec::new()), + our_peerstorage_encryption_key } } @@ -667,16 +693,69 @@ where C::Target: chain::Filter, }); } } + + /// This function collects the counterparty node IDs from all monitors into a `HashSet`, + /// ensuring unique IDs are returned. + fn all_counterparty_node_ids(&self) -> HashSet { + let mon = self.monitors.read().unwrap(); + mon + .values() + .map(|monitor| monitor.monitor.get_counterparty_node_id()) + .collect() + } + + fn send_peer_storage(&self, their_node_id: PublicKey) { + // TODO: Serialize `ChannelMonitor`s inside `our_peer_storage`. + + let random_bytes = self.entropy_source.get_secure_random_bytes(); + let serialised_channels = Vec::new(); + let our_peer_storage = DecryptedOurPeerStorage::new(serialised_channels); + let cipher = our_peer_storage.encrypt(&self.our_peerstorage_encryption_key, &random_bytes); + + log_debug!(self.logger, "Sending Peer Storage to {}", log_pubkey!(their_node_id)); + let send_peer_storage_event = MessageSendEvent::SendPeerStorage { + node_id: their_node_id, msg: msgs::PeerStorage { data: cipher.into_vec() } + }; + + self.pending_send_only_events.lock().unwrap().push(send_peer_storage_event) + } +} + +impl BaseMessageHandler for ChainMonitor +where C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, + ES::Target: EntropySource, +{ + fn get_and_clear_pending_msg_events(&self) -> Vec { + let mut pending_events = self.pending_send_only_events.lock().unwrap(); + core::mem::take(&mut *pending_events) + } + + fn peer_disconnected(&self, _their_node_id: PublicKey) {} + + fn provided_node_features(&self) -> NodeFeatures { + NodeFeatures::empty() + } + + fn provided_init_features(&self, _their_node_id: PublicKey) -> InitFeatures { + InitFeatures::empty() + } + + fn peer_connected(&self, _their_node_id: PublicKey, _msg: &Init, _inbound: bool) -> Result<(), ()> { Ok(()) } } -impl -chain::Listen for ChainMonitor +impl +chain::Listen for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, P::Target: Persist, + ES::Target: EntropySource, { fn filtered_block_connected(&self, header: &Header, txdata: &TransactionData, height: u32) { log_debug!(self.logger, "New best block {} at height {} provided via block_connected", header.block_hash(), height); @@ -684,6 +763,12 @@ where monitor.block_connected( header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &self.logger) }); + + // Send peer storage everytime a new block arrives. + for node_id in self.all_counterparty_node_ids() { + self.send_peer_storage(node_id); + } + // Assume we may have some new events and wake the event processor self.event_notifier.notify(); } @@ -698,14 +783,15 @@ where } } -impl -chain::Confirm for ChainMonitor +impl +chain::Confirm for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, P::Target: Persist, + ES::Target: EntropySource, { fn transactions_confirmed(&self, header: &Header, txdata: &TransactionData, height: u32) { log_debug!(self.logger, "{} provided transactions confirmed at height {} in block {}", txdata.len(), height, header.block_hash()); @@ -735,6 +821,12 @@ where header, height, &*self.broadcaster, &*self.fee_estimator, &self.logger ) }); + + // Send peer storage everytime a new block arrives. + for node_id in self.all_counterparty_node_ids() { + self.send_peer_storage(node_id); + } + // Assume we may have some new events and wake the event processor self.event_notifier.notify(); } @@ -752,13 +844,14 @@ where } } -impl -chain::Watch for ChainMonitor +impl +chain::Watch for ChainMonitor where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, + ES::Target: EntropySource, { fn watch_channel(&self, channel_id: ChannelId, monitor: ChannelMonitor) -> Result { let logger = WithChannelMonitor::from(&self.logger, &monitor, None); @@ -891,12 +984,13 @@ where C::Target: chain::Filter, } } -impl events::EventsProvider for ChainMonitor - where C::Target: chain::Filter, - T::Target: BroadcasterInterface, - F::Target: FeeEstimator, - L::Target: Logger, - P::Target: Persist, +impl events::EventsProvider for ChainMonitor +where C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: Persist, + ES::Target: EntropySource, { /// Processes [`SpendableOutputs`] events produced from each [`ChannelMonitor`] upon maturity. /// diff --git a/lightning/src/ln/blinded_payment_tests.rs b/lightning/src/ln/blinded_payment_tests.rs index f43d672a164..b714f76616f 100644 --- a/lightning/src/ln/blinded_payment_tests.rs +++ b/lightning/src/ln/blinded_payment_tests.rs @@ -36,7 +36,7 @@ use crate::offers::invoice::UnsignedBolt12Invoice; use crate::offers::nonce::Nonce; use crate::prelude::*; use crate::routing::router::{BlindedTail, Path, Payee, PaymentParameters, RouteHop, RouteParameters, TrampolineHop}; -use crate::sign::{NodeSigner, Recipient}; +use crate::sign::{NodeSigner, PeerStorageKey, Recipient}; use crate::util::config::UserConfig; use crate::util::ser::{WithoutLength, Writeable}; use crate::util::test_utils; @@ -1631,6 +1631,7 @@ fn route_blinding_spec_test_vector() { fn sign_invoice( &self, _invoice: &RawBolt11Invoice, _recipient: Recipient, ) -> Result { unreachable!() } + fn get_peer_storage_key(&self) -> PeerStorageKey { unreachable!() } fn sign_bolt12_invoice( &self, _invoice: &UnsignedBolt12Invoice, ) -> Result { unreachable!() } @@ -1940,6 +1941,7 @@ fn test_trampoline_inbound_payment_decoding() { fn sign_invoice( &self, _invoice: &RawBolt11Invoice, _recipient: Recipient, ) -> Result { unreachable!() } + fn get_peer_storage_key(&self) -> PeerStorageKey { unreachable!() } fn sign_bolt12_invoice( &self, _invoice: &UnsignedBolt12Invoice, ) -> Result { unreachable!() } diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 6a3c066ce14..649c71d8fb3 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -78,6 +78,7 @@ use crate::ln::onion_payment::{ }; use crate::ln::onion_utils::{self}; use crate::ln::onion_utils::{HTLCFailReason, LocalHTLCFailureReason}; +use crate::ln::our_peer_storage::EncryptedOurPeerStorage; #[cfg(test)] use crate::ln::outbound_payment; use crate::ln::outbound_payment::{ @@ -8546,15 +8547,38 @@ This indicates a bug inside LDK. Please report this error at https://github.com/ } #[rustfmt::skip] - fn internal_peer_storage_retrieval(&self, counterparty_node_id: PublicKey, _msg: msgs::PeerStorageRetrieval) -> Result<(), MsgHandleErrInternal> { - // TODO: Decrypt and check if have any stale or missing ChannelMonitor. + fn internal_peer_storage_retrieval(&self, counterparty_node_id: PublicKey, msg: msgs::PeerStorageRetrieval) -> Result<(), MsgHandleErrInternal> { + // TODO: Check if have any stale or missing ChannelMonitor. let logger = WithContext::from(&self.logger, Some(counterparty_node_id), None, None); + let err = MsgHandleErrInternal::from_chan_no_close( + ChannelError::Ignore("Invalid PeerStorageRetrieval message received.".into()), + ChannelId([0; 32]), + ); + let err_str = || { + format!("Invalid PeerStorage received from {}", counterparty_node_id) + }; - log_debug!(logger, "Received unexpected peer_storage_retrieval from {}. This is unusual since we do not yet distribute peer storage. Sending a warning.", log_pubkey!(counterparty_node_id)); + let encrypted_ops = match EncryptedOurPeerStorage::new(msg.data) { + Ok(encrypted_ops) => encrypted_ops, + Err(_) => { + log_debug!(logger, "{}", err_str()); + return Err(err); + } + }; + + let decrypted_data = match encrypted_ops.decrypt(&self.node_signer.get_peer_storage_key()) { + Ok(decrypted_ops) => decrypted_ops.into_vec(), + Err(_) => { + log_debug!(logger, "{}", err_str()); + return Err(err); + } + }; - Err(MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn( - "Invalid peer_storage_retrieval message received.".into(), - ), ChannelId([0; 32]))) + if decrypted_data.is_empty() { + log_debug!(logger, "Received a peer storage from peer {} with 0 channels.", log_pubkey!(counterparty_node_id)); + } + + Ok(()) } #[rustfmt::skip] @@ -15439,9 +15463,26 @@ mod tests { create_announced_chan_between_nodes(&nodes, 0, 1); - // Since we do not send peer storage, we manually simulate receiving a dummy - // `PeerStorage` from the channel partner. - nodes[0].node.handle_peer_storage(nodes[1].node.get_our_node_id(), msgs::PeerStorage{data: vec![0; 100]}); + let peer_storage_msg_events_node0 = nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_msg_events(); + let peer_storage_msg_events_node1 = nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_msg_events(); + assert_ne!(peer_storage_msg_events_node0.len(), 0); + assert_ne!(peer_storage_msg_events_node1.len(), 0); + + match peer_storage_msg_events_node0[0] { + MessageSendEvent::SendPeerStorage { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + nodes[1].node.handle_peer_storage(nodes[0].node.get_our_node_id(), msg.clone()); + } + _ => panic!("Unexpected event"), + } + + match peer_storage_msg_events_node1[0] { + MessageSendEvent::SendPeerStorage { ref node_id, ref msg } => { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + nodes[0].node.handle_peer_storage(nodes[1].node.get_our_node_id(), msg.clone()); + } + _ => panic!("Unexpected event"), + } nodes[0].node.peer_disconnected(nodes[1].node.get_our_node_id()); nodes[1].node.peer_disconnected(nodes[0].node.get_our_node_id()); @@ -15453,9 +15494,24 @@ mod tests { features: nodes[0].node.init_features(), networks: None, remote_network_address: None }, false).unwrap(); + let node_1_events = nodes[1].node.get_and_clear_pending_msg_events(); + assert_eq!(node_1_events.len(), 2); + let node_0_events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(node_0_events.len(), 2); + for msg in node_1_events{ + if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg { + nodes[0].node.handle_channel_reestablish(nodes[1].node.get_our_node_id(), msg); + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + } else if let MessageSendEvent::SendPeerStorageRetrieval { ref node_id, ref msg } = msg { + nodes[0].node.handle_peer_storage_retrieval(nodes[1].node.get_our_node_id(), msg.clone()); + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + } else { + panic!("Unexpected event") + } + } + for msg in node_0_events{ if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg { nodes[1].node.handle_channel_reestablish(nodes[0].node.get_our_node_id(), msg); @@ -15468,29 +15524,34 @@ mod tests { } } - let msg_events_after_peer_storage_retrieval = nodes[1].node.get_and_clear_pending_msg_events(); + let node_1_msg_events = nodes[1].node.get_and_clear_pending_msg_events(); + let node_0_msg_events = nodes[0].node.get_and_clear_pending_msg_events(); - // Check if we receive a warning message. - let peer_storage_warning: Vec<&MessageSendEvent> = msg_events_after_peer_storage_retrieval - .iter() - .filter(|event| match event { - MessageSendEvent::HandleError { .. } => true, - _ => false, - }) - .collect(); + assert_eq!(node_1_msg_events.len(), 3); + assert_eq!(node_0_msg_events.len(), 3); - assert_eq!(peer_storage_warning.len(), 1); - - match peer_storage_warning[0] { - MessageSendEvent::HandleError { node_id, action } => { + for msg in node_1_msg_events { + if let MessageSendEvent::SendChannelReady { ref node_id, .. } = msg { assert_eq!(*node_id, nodes[0].node.get_our_node_id()); - match action { - ErrorAction::SendWarningMessage { msg, .. } => - assert_eq!(msg.data, "Invalid peer_storage_retrieval message received.".to_owned()), - _ => panic!("Unexpected error action"), - } + } else if let MessageSendEvent::SendAnnouncementSignatures { ref node_id, .. } = msg { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + } else if let MessageSendEvent::SendChannelUpdate { ref node_id, .. } = msg { + assert_eq!(*node_id, nodes[0].node.get_our_node_id()); + } else { + panic!("Unexpected event") + } + } + + for msg in node_0_msg_events { + if let MessageSendEvent::SendChannelReady { ref node_id, .. } = msg { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + } else if let MessageSendEvent::SendAnnouncementSignatures { ref node_id, .. } = msg { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + } else if let MessageSendEvent::SendChannelUpdate { ref node_id, .. } = msg { + assert_eq!(*node_id, nodes[1].node.get_our_node_id()); + } else { + panic!("Unexpected event") } - _ => panic!("Unexpected event"), } } @@ -16755,7 +16816,7 @@ pub mod bench { use crate::ln::msgs::{BaseMessageHandler, ChannelMessageHandler, Init, MessageSendEvent}; use crate::routing::gossip::NetworkGraph; use crate::routing::router::{PaymentParameters, RouteParameters}; - use crate::sign::{InMemorySigner, KeysManager}; + use crate::sign::{InMemorySigner, KeysManager, NodeSigner}; use crate::util::config::{MaxDustHTLCExposure, UserConfig}; use crate::util::test_utils; @@ -16778,6 +16839,7 @@ pub mod bench { &'a test_utils::TestFeeEstimator, &'a test_utils::TestLogger, &'a P, + &'a KeysManager, >, &'a test_utils::TestBroadcaster, &'a KeysManager, @@ -16829,9 +16891,9 @@ pub mod bench { config.channel_config.max_dust_htlc_exposure = MaxDustHTLCExposure::FeeRateMultiplier(5_000_000 / 253); config.channel_handshake_config.minimum_depth = 1; - 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 chain_monitor_a = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_a, &keys_manager_a, keys_manager_a.get_peer_storage_key()); let node_a = ChannelManager::new(&fee_estimator, &chain_monitor_a, &tx_broadcaster, &router, &message_router, &logger_a, &keys_manager_a, &keys_manager_a, &keys_manager_a, config.clone(), ChainParameters { network, best_block: BestBlock::from_network(network), @@ -16839,9 +16901,9 @@ pub mod bench { let node_a_holder = ANodeHolder { 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 chain_monitor_b = ChainMonitor::new(None, &tx_broadcaster, &logger_a, &fee_estimator, &persister_b, &keys_manager_b, keys_manager_b.get_peer_storage_key()); let node_b = ChannelManager::new(&fee_estimator, &chain_monitor_b, &tx_broadcaster, &router, &message_router, &logger_b, &keys_manager_b, &keys_manager_b, &keys_manager_b, config.clone(), ChainParameters { network, best_block: BestBlock::from_network(network), diff --git a/lightning/src/ln/mod.rs b/lightning/src/ln/mod.rs index 8d741f2954d..d95c9fc1275 100644 --- a/lightning/src/ln/mod.rs +++ b/lightning/src/ln/mod.rs @@ -21,6 +21,7 @@ mod features; pub mod inbound_payment; pub mod msgs; pub mod onion_payment; +pub mod our_peer_storage; pub mod peer_handler; pub mod script; pub mod types; diff --git a/lightning/src/ln/our_peer_storage.rs b/lightning/src/ln/our_peer_storage.rs new file mode 100644 index 00000000000..430c9f559f9 --- /dev/null +++ b/lightning/src/ln/our_peer_storage.rs @@ -0,0 +1,186 @@ +// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +//! `DecryptedOurPeerStorage` enables storage of encrypted serialized channel data. +//! It provides encryption of data to maintain data integrity and +//! security during transmission. + +use bitcoin::hashes::sha256::Hash as Sha256; +use bitcoin::hashes::{Hash, HashEngine, Hmac, HmacEngine}; + +use crate::sign::PeerStorageKey; + +use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC; +use crate::prelude::*; + +/// [`DecryptedOurPeerStorage`] is used to store serialised channel information that allows for the creation of a +/// `peer_storage` backup. +/// +/// This structure is designed to serialize channel data for backup and supports encryption +/// using `ChaCha20Poly1305RFC` for transmission. +/// +/// # Key Methods +/// - [`DecryptedOurPeerStorage::new`]: Returns [`DecryptedOurPeerStorage`] with the given data. +/// - [`DecryptedOurPeerStorage::encrypt`]: Returns [`EncryptedOurPeerStorage`] created from encrypting the provided data. +/// - [`DecryptedOurPeerStorage::into_vec`]: Returns the data in [`Vec`] format. +/// +/// ## Example +/// ``` +/// use lightning::ln::our_peer_storage::DecryptedOurPeerStorage; +/// use lightning::sign::{KeysManager, NodeSigner}; +/// let seed = [1u8; 32]; +/// let keys_mgr = KeysManager::new(&seed, 42, 42); +/// let key = keys_mgr.get_peer_storage_key(); +/// let decrypted_ops = DecryptedOurPeerStorage::new(vec![1, 2, 3]); +/// let our_peer_storage = decrypted_ops.encrypt(&key, &[0u8; 32]); +/// let decrypted_data = our_peer_storage.decrypt(&key).unwrap(); +/// assert_eq!(decrypted_data.into_vec(), vec![1, 2, 3]); +/// ``` +pub struct DecryptedOurPeerStorage { + data: Vec, +} + +impl DecryptedOurPeerStorage { + /// Returns [`DecryptedOurPeerStorage`] with the given data. + pub fn new(data: Vec) -> Self { + Self { data } + } + + /// Returns data stored in [`Vec`] format. + pub fn into_vec(self) -> Vec { + self.data + } + + /// Encrypts the data inside [`DecryptedOurPeerStorage`] using [`PeerStorageKey`] and `random_bytes` + /// and returns [`EncryptedOurPeerStorage`]. + pub fn encrypt(self, key: &PeerStorageKey, random_bytes: &[u8; 32]) -> EncryptedOurPeerStorage { + let mut data = self.data; + let plaintext_len = data.len(); + let nonce = derive_nonce(key, random_bytes); + + let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b""); + let mut tag = [0; 16]; + chacha.encrypt_full_message_in_place(&mut data[0..plaintext_len], &mut tag); + + data.extend_from_slice(&tag); + + // Append `random_bytes` in front of the encrypted_blob. + data.extend_from_slice(random_bytes); + + EncryptedOurPeerStorage { cipher: data } + } +} + +/// [`EncryptedOurPeerStorage`] represents encrypted state of the corresponding [`DecryptedOurPeerStorage`]. +/// +/// # Key Methods +/// - [`EncryptedOurPeerStorage::new`]: Returns [`EncryptedOurPeerStorage`] with the given encrypted cipher. +/// - [`EncryptedOurPeerStorage::decrypt`]: Returns [`DecryptedOurPeerStorage`] created from decrypting the cipher. +/// - [`EncryptedOurPeerStorage::into_vec`]: Returns the cipher in [`Vec`] format. +pub struct EncryptedOurPeerStorage { + cipher: Vec, +} + +impl EncryptedOurPeerStorage { + // Ciphertext is of the form: random_bytes(32 bytes) + encrypted_data + tag(16 bytes). + const MIN_CIPHERTEXT_LEN: usize = 32 + 16; + + /// Returns [`EncryptedOurPeerStorage`] if cipher is of appropriate length, else returns error. + pub fn new(cipher: Vec) -> Result { + if cipher.len() < Self::MIN_CIPHERTEXT_LEN { + return Err(()); + } + return Ok(Self { cipher }); + } + + /// Returns cipher in the format [`Vec`]. + pub fn into_vec(self) -> Vec { + self.cipher + } + + /// Returns [`DecryptedOurPeerStorage`] if it successfully decrypts the ciphertext with the `key`, + /// else returns error. + pub fn decrypt(self, key: &PeerStorageKey) -> Result { + let mut cipher = self.cipher; + let cyphertext_len = cipher.len(); + + if cipher.len() < Self::MIN_CIPHERTEXT_LEN { + return Err(()); + } + + // Ciphertext is of the form: encrypted_data + tag(16 bytes) + random_bytes(32 bytes). + let (data_mut, random_bytes) = cipher.split_at_mut(cyphertext_len - 32); + let (encrypted_data, tag) = data_mut.split_at_mut(data_mut.len() - 16); + + let nonce = derive_nonce(key, random_bytes); + + let mut chacha = ChaCha20Poly1305RFC::new(&key.inner, &nonce, b""); + + if chacha.check_decrypt_in_place(encrypted_data, tag).is_err() { + return Err(()); + } + + // Remove tag(16 bytes) + random_bytes(32 bytes). + cipher.truncate(cyphertext_len - 16 - 32); + + Ok(DecryptedOurPeerStorage { data: cipher }) + } +} + +/// Nonce for encryption and decryption: Hmac(Sha256(key) + random_bytes). +fn derive_nonce(key: &PeerStorageKey, random_bytes: &[u8]) -> [u8; 12] { + let key_hash = Sha256::hash(&key.inner); + + let mut hmac = HmacEngine::::new(key_hash.as_byte_array()); + hmac.input(&random_bytes); + let mut nonce = [0u8; 12]; + // First 4 bytes of the nonce should be 0. + nonce[4..].copy_from_slice(&Hmac::from_engine(hmac).to_byte_array()[0..8]); + + nonce +} + +#[cfg(test)] +mod tests { + use crate::ln::our_peer_storage::{derive_nonce, DecryptedOurPeerStorage}; + use crate::sign::PeerStorageKey; + + #[test] + fn test_peer_storage_encryption_decryption() { + let key1 = PeerStorageKey { inner: [0u8; 32] }; + let key2 = PeerStorageKey { inner: [1u8; 32] }; + let random_bytes1 = [200; 32]; + let random_bytes2 = [201; 32]; + + // Happy Path + let decrypted_ops = DecryptedOurPeerStorage::new(vec![42u8; 32]); + let decrypted_ops_res: DecryptedOurPeerStorage = + decrypted_ops.encrypt(&key1, &random_bytes1).decrypt(&key1).unwrap(); + assert_eq!(decrypted_ops_res.into_vec(), vec![42u8; 32]); + + // Changing Key + let decrypted_ops_wrong_key = DecryptedOurPeerStorage::new(vec![42u8; 32]); + let decrypted_ops_wrong_key_res = + decrypted_ops_wrong_key.encrypt(&key2, &random_bytes2).decrypt(&key1); + assert!(decrypted_ops_wrong_key_res.is_err()); + + // Nonce derivation happy path + let nonce = derive_nonce(&key1, &random_bytes1); + let nonce_happy_path = derive_nonce(&key1, &random_bytes1); + assert_eq!(nonce, nonce_happy_path); + + // Nonce derivation with different `random_bytes` & `key` + let nonce_diff_random_bytes = derive_nonce(&key1, &random_bytes2); + let nonce_diff_key = derive_nonce(&key2, &random_bytes1); + let nonce_diff_key_random_bytes = derive_nonce(&key2, &random_bytes2); + assert_ne!(nonce, nonce_diff_random_bytes); + assert_ne!(nonce, nonce_diff_key); + assert_ne!(nonce, nonce_diff_key_random_bytes); + } +} diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 92fc73d64f9..a989d172687 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -51,10 +51,11 @@ use core::ops::Deref; use core::convert::Infallible; #[cfg(not(c_bindings))] use { + crate::chain::chainmonitor::ChainMonitor, crate::ln::channelmanager::{SimpleArcChannelManager, SimpleRefChannelManager}, crate::onion_message::messenger::{SimpleArcOnionMessenger, SimpleRefOnionMessenger}, crate::routing::gossip::{NetworkGraph, P2PGossipSync}, - crate::sign::KeysManager, + crate::sign::{KeysManager, InMemorySigner}, crate::sync::Arc, }; @@ -418,11 +419,12 @@ impl Deref for ErroringMessageHandler { } /// Provides references to trait impls which handle different types of messages. -pub struct MessageHandler where +pub struct MessageHandler where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, CustomM::Target: CustomMessageHandler, + SM::Target: BaseMessageHandler, { /// A message handler which handles messages specific to channels. Usually this is just a /// [`ChannelManager`] object or an [`ErroringMessageHandler`]. @@ -444,6 +446,12 @@ pub struct MessageHandler where /// A message handler which handles custom messages. The only LDK-provided implementation is /// [`IgnoringMessageHandler`]. pub custom_message_handler: CustomM, + + /// A message handler which only allows sending messages. This should generally be a + /// [`ChainMonitor`]. + /// + /// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor + pub send_only_message_handler: SM, } /// Provides an object which can be used to send data to and which uniquely identifies a connection @@ -732,14 +740,15 @@ impl Peer { /// /// This is not exported to bindings users as type aliases aren't supported in most languages. #[cfg(not(c_bindings))] -pub type SimpleArcPeerManager = PeerManager< +pub type SimpleArcPeerManager = PeerManager< SD, Arc>, Arc>>, C, Arc>>, Arc>, Arc, IgnoringMessageHandler, - Arc + Arc, + Arc, Arc, Arc, Arc, Arc, Arc>>, >; /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference @@ -760,7 +769,8 @@ pub type SimpleRefPeerManager< &'h SimpleRefOnionMessenger<'a, 'b, 'c, 'd, 'e, 'graph, 'logger, 'i, 'j, 'k, M, T, F, L>, &'logger L, IgnoringMessageHandler, - &'c KeysManager + &'c KeysManager, + &'j ChainMonitor<&'a M, C, &'b T, &'c F, &'logger L, &'c KeysManager, &'c KeysManager>, >; @@ -785,18 +795,21 @@ pub trait APeerManager { type CMH: Deref; type NST: NodeSigner + ?Sized; type NS: Deref; + type SMT: BaseMessageHandler + ?Sized; + type SM: Deref; /// Gets a reference to the underlying [`PeerManager`]. - fn as_ref(&self) -> &PeerManager; + fn as_ref(&self) -> &PeerManager; } -impl -APeerManager for PeerManager where +impl +APeerManager for PeerManager where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, L::Target: Logger, CMH::Target: CustomMessageHandler, NS::Target: NodeSigner, + SM::Target: BaseMessageHandler, { type Descriptor = Descriptor; type CMT = ::Target; @@ -811,7 +824,9 @@ APeerManager for PeerManager where type CMH = CMH; type NST = ::Target; type NS = NS; - fn as_ref(&self) -> &PeerManager { self } + type SMT = ::Target; + type SM = SM; + fn as_ref(&self) -> &PeerManager { self } } /// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls @@ -833,14 +848,16 @@ APeerManager for PeerManager where /// you're using lightning-net-tokio. /// /// [`read_event`]: PeerManager::read_event -pub struct PeerManager where +pub struct PeerManager where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, L::Target: Logger, CMH::Target: CustomMessageHandler, - NS::Target: NodeSigner { - message_handler: MessageHandler, + NS::Target: NodeSigner, + SM::Target: BaseMessageHandler, +{ + message_handler: MessageHandler, /// Connection state for each connected peer - we have an outer read-write lock which is taken /// as read while we're doing processing for a peer and taken write when a peer is being added /// or removed. @@ -915,11 +932,13 @@ macro_rules! encode_msg { }} } -impl PeerManager where +impl PeerManager where CM::Target: ChannelMessageHandler, OM::Target: OnionMessageHandler, L::Target: Logger, - NS::Target: NodeSigner { + NS::Target: NodeSigner, + SM::Target: BaseMessageHandler, +{ /// Constructs a new `PeerManager` with the given `ChannelMessageHandler` and /// `OnionMessageHandler`. No routing message handler is used and network graph messages are /// ignored. @@ -933,17 +952,18 @@ impl Pe /// minute should suffice. /// /// This is not exported to bindings users as we can't export a PeerManager with a dummy route handler - pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { + pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS, send_only_message_handler: SM) -> Self { Self::new(MessageHandler { chan_handler: channel_message_handler, route_handler: IgnoringMessageHandler{}, onion_message_handler, custom_message_handler: IgnoringMessageHandler{}, + send_only_message_handler, }, current_time, ephemeral_random_data, logger, node_signer) } } -impl PeerManager where +impl PeerManager where RM::Target: RoutingMessageHandler, L::Target: Logger, NS::Target: NodeSigner { @@ -967,6 +987,7 @@ impl PeerManager) -> Option } } -impl PeerManager where +impl PeerManager where CM::Target: ChannelMessageHandler, RM::Target: RoutingMessageHandler, OM::Target: OnionMessageHandler, L::Target: Logger, CMH::Target: CustomMessageHandler, - NS::Target: NodeSigner + NS::Target: NodeSigner, + SM::Target: BaseMessageHandler, { /// Constructs a new `PeerManager` with the given message handlers. /// @@ -1029,7 +1051,7 @@ impl, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { + pub fn new(message_handler: MessageHandler, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, node_signer: NS) -> Self { let mut ephemeral_key_midstate = Sha256::engine(); ephemeral_key_midstate.input(ephemeral_random_data); @@ -2671,6 +2693,11 @@ impl(peer_count: usize, cfgs: &'a Vec) -> Vec> { + fn create_network<'a>(peer_count: usize, cfgs: &'a Vec) -> Vec> { let mut peers = Vec::new(); for i in 0..peer_count { let ephemeral_bytes = [i as u8; 32]; let msg_handler = MessageHandler { chan_handler: &cfgs[i].chan_handler, route_handler: &cfgs[i].routing_handler, - onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: &cfgs[i].custom_handler + onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: &cfgs[i].custom_handler, send_only_message_handler: IgnoringMessageHandler {}, }; let peer = PeerManager::new(msg_handler, 0, &ephemeral_bytes, &cfgs[i].logger, &cfgs[i].node_signer); peers.push(peer); @@ -3183,7 +3210,7 @@ mod tests { peers } - fn try_establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor, Result, Result) { + fn try_establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor, Result, Result) { let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; @@ -3214,7 +3241,7 @@ mod tests { } - fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { + fn establish_connection<'a>(peer_a: &PeerManager, peer_b: &PeerManager) -> (FileDescriptor, FileDescriptor) { let addr_a = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1000}; let addr_b = SocketAddress::TcpIpV4{addr: [127, 0, 0, 1], port: 1001}; @@ -3616,12 +3643,14 @@ mod tests { route_handler: IgnoringMessageHandler {}, onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: IgnoringMessageHandler {}, + send_only_message_handler: IgnoringMessageHandler {}, }, 0, &[0; 32], &logger, &node_signer_a); let peer_b = PeerManager::new(MessageHandler { chan_handler: ErroringMessageHandler::new(), route_handler: IgnoringMessageHandler {}, onion_message_handler: IgnoringMessageHandler {}, custom_message_handler: IgnoringMessageHandler {}, + send_only_message_handler: IgnoringMessageHandler {}, }, 0, &[1; 32], &logger, &node_signer_b); let a_id = node_signer_a.get_node_id(Recipient::Node).unwrap(); diff --git a/lightning/src/sign/mod.rs b/lightning/src/sign/mod.rs index f35a407634a..a623858ae56 100644 --- a/lightning/src/sign/mod.rs +++ b/lightning/src/sign/mod.rs @@ -796,6 +796,13 @@ pub trait ChannelSigner { fn channel_keys_id(&self) -> [u8; 32]; } +/// Represents the secret key material used for encrypting Peer Storage. +#[derive(Clone, Copy, PartialEq, Eq)] +pub struct PeerStorageKey { + /// Represents the key used to encrypt and decrypt Peer Storage. + pub inner: [u8; 32], +} + /// Specifies the recipient of an invoice. /// /// This indicates to [`NodeSigner::sign_invoice`] what node secret key should be used to sign @@ -834,6 +841,15 @@ pub trait NodeSigner { /// [phantom node payments]: PhantomKeysManager fn get_inbound_payment_key(&self) -> ExpandedKey; + /// Defines a method to derive a 32-byte encryption key for peer storage. + /// + /// Implementations of this method must derive a secure encryption key. + /// The key is used to encrypt or decrypt backups of our state stored with our peers. + /// + /// Thus, if you wish to rely on recovery using this method, you should use a key which + /// can be re-derived from data which would be available after state loss (eg the wallet seed). + fn get_peer_storage_key(&self) -> PeerStorageKey; + /// Get node id based on the provided [`Recipient`]. /// /// This method must return the same value each time it is called with a given [`Recipient`] @@ -1809,6 +1825,7 @@ pub struct KeysManager { shutdown_pubkey: PublicKey, channel_master_key: Xpriv, channel_child_index: AtomicUsize, + peer_storage_key: PeerStorageKey, #[cfg(test)] pub(crate) entropy_source: RandomBytes, @@ -1839,44 +1856,54 @@ impl KeysManager { /// /// [`ChannelMonitor`]: crate::chain::channelmonitor::ChannelMonitor pub fn new(seed: &[u8; 32], starting_time_secs: u64, starting_time_nanos: u32) -> Self { + // Constants for key derivation path indices used in this function. + const NODE_SECRET_INDEX: ChildNumber = ChildNumber::Hardened { index: 0 }; + const DESTINATION_SCRIPT_INDEX: ChildNumber = ChildNumber::Hardened { index: (1) }; + const SHUTDOWN_PUBKEY_INDEX: ChildNumber = ChildNumber::Hardened { index: (2) }; + const CHANNEL_MASTER_KEY_INDEX: ChildNumber = ChildNumber::Hardened { index: (3) }; + const INBOUND_PAYMENT_KEY_INDEX: ChildNumber = ChildNumber::Hardened { index: (5) }; + const PEER_STORAGE_KEY_INDEX: ChildNumber = ChildNumber::Hardened { index: (6) }; + let secp_ctx = Secp256k1::new(); // Note that when we aren't serializing the key, network doesn't matter match Xpriv::new_master(Network::Testnet, seed) { Ok(master_key) => { let node_secret = master_key - .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(0).unwrap()) + .derive_priv(&secp_ctx, &NODE_SECRET_INDEX) .expect("Your RNG is busted") .private_key; let node_id = PublicKey::from_secret_key(&secp_ctx, &node_secret); - let destination_script = match master_key - .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(1).unwrap()) - { - Ok(destination_key) => { - let wpubkey_hash = WPubkeyHash::hash( - &Xpub::from_priv(&secp_ctx, &destination_key).to_pub().to_bytes(), - ); - Builder::new() - .push_opcode(opcodes::all::OP_PUSHBYTES_0) - .push_slice(&wpubkey_hash.to_byte_array()) - .into_script() - }, - Err(_) => panic!("Your RNG is busted"), - }; - let shutdown_pubkey = match master_key - .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(2).unwrap()) - { - Ok(shutdown_key) => Xpub::from_priv(&secp_ctx, &shutdown_key).public_key, - Err(_) => panic!("Your RNG is busted"), - }; + let destination_script = + match master_key.derive_priv(&secp_ctx, &DESTINATION_SCRIPT_INDEX) { + Ok(destination_key) => { + let wpubkey_hash = WPubkeyHash::hash( + &Xpub::from_priv(&secp_ctx, &destination_key).to_pub().to_bytes(), + ); + Builder::new() + .push_opcode(opcodes::all::OP_PUSHBYTES_0) + .push_slice(&wpubkey_hash.to_byte_array()) + .into_script() + }, + Err(_) => panic!("Your RNG is busted"), + }; + let shutdown_pubkey = + match master_key.derive_priv(&secp_ctx, &SHUTDOWN_PUBKEY_INDEX) { + Ok(shutdown_key) => Xpub::from_priv(&secp_ctx, &shutdown_key).public_key, + Err(_) => panic!("Your RNG is busted"), + }; let channel_master_key = master_key - .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(3).unwrap()) + .derive_priv(&secp_ctx, &CHANNEL_MASTER_KEY_INDEX) .expect("Your RNG is busted"); let inbound_payment_key: SecretKey = master_key - .derive_priv(&secp_ctx, &ChildNumber::from_hardened_idx(5).unwrap()) + .derive_priv(&secp_ctx, &INBOUND_PAYMENT_KEY_INDEX) .expect("Your RNG is busted") .private_key; let mut inbound_pmt_key_bytes = [0; 32]; inbound_pmt_key_bytes.copy_from_slice(&inbound_payment_key[..]); + let peer_storage_key = master_key + .derive_priv(&secp_ctx, &PEER_STORAGE_KEY_INDEX) + .expect("Your RNG is busted") + .private_key; let mut rand_bytes_engine = Sha256::engine(); rand_bytes_engine.input(&starting_time_secs.to_be_bytes()); @@ -1892,6 +1919,8 @@ impl KeysManager { node_id, inbound_payment_key: ExpandedKey::new(inbound_pmt_key_bytes), + peer_storage_key: PeerStorageKey { inner: peer_storage_key.secret_bytes() }, + destination_script, shutdown_pubkey, @@ -2117,6 +2146,10 @@ impl NodeSigner for KeysManager { self.inbound_payment_key.clone() } + fn get_peer_storage_key(&self) -> PeerStorageKey { + self.peer_storage_key.clone() + } + fn sign_invoice( &self, invoice: &RawBolt11Invoice, recipient: Recipient, ) -> Result { @@ -2278,6 +2311,10 @@ impl NodeSigner for PhantomKeysManager { self.inbound_payment_key.clone() } + fn get_peer_storage_key(&self) -> PeerStorageKey { + self.inner.peer_storage_key.clone() + } + fn sign_invoice( &self, invoice: &RawBolt11Invoice, recipient: Recipient, ) -> Result { diff --git a/lightning/src/util/anchor_channel_reserves.rs b/lightning/src/util/anchor_channel_reserves.rs index 968a60ada0b..ebae770fb8a 100644 --- a/lightning/src/util/anchor_channel_reserves.rs +++ b/lightning/src/util/anchor_channel_reserves.rs @@ -29,6 +29,7 @@ use crate::ln::chan_utils::max_htlcs; use crate::ln::channelmanager::AChannelManager; use crate::prelude::new_hash_set; use crate::sign::ecdsa::EcdsaChannelSigner; +use crate::sign::EntropySource; use crate::types::features::ChannelTypeFeatures; use crate::util::logger::Logger; use bitcoin::constants::WITNESS_SCALE_FACTOR; @@ -276,6 +277,7 @@ pub fn can_support_additional_anchor_channel< EstimatorRef: Deref, LoggerRef: Deref, PersistRef: Deref, + EntropySourceRef: Deref, ChainMonitorRef: Deref< Target = ChainMonitor< ChannelSigner, @@ -284,6 +286,7 @@ pub fn can_support_additional_anchor_channel< EstimatorRef, LoggerRef, PersistRef, + EntropySourceRef, >, >, >( @@ -297,6 +300,7 @@ where EstimatorRef::Target: FeeEstimator, LoggerRef::Target: Logger, PersistRef::Target: Persist, + EntropySourceRef::Target: EntropySource, { let mut anchor_channels = new_hash_set(); // Calculate the number of in-progress anchor channels by inspecting ChannelMonitors with balance. diff --git a/lightning/src/util/dyn_signer.rs b/lightning/src/util/dyn_signer.rs index 939e40cf7c4..7e9844e2ac0 100644 --- a/lightning/src/util/dyn_signer.rs +++ b/lightning/src/util/dyn_signer.rs @@ -17,7 +17,9 @@ use crate::sign::taproot::TaprootChannelSigner; use crate::sign::ChannelSigner; use crate::sign::InMemorySigner; use crate::sign::{EntropySource, HTLCDescriptor, OutputSpender, PhantomKeysManager}; -use crate::sign::{NodeSigner, Recipient, SignerProvider, SpendableOutputDescriptor}; +use crate::sign::{ + NodeSigner, PeerStorageKey, Recipient, SignerProvider, SpendableOutputDescriptor, +}; use bitcoin; use bitcoin::absolute::LockTime; use bitcoin::secp256k1::All; @@ -214,7 +216,8 @@ inner, fn sign_bolt12_invoice(, invoice: &crate::offers::invoice::UnsignedBolt12Invoice ) -> Result, - fn get_inbound_payment_key(,) -> ExpandedKey + fn get_inbound_payment_key(,) -> ExpandedKey, + fn get_peer_storage_key(,) -> PeerStorageKey ); delegate!(DynKeysInterface, SignerProvider, @@ -278,7 +281,8 @@ delegate!(DynPhantomKeysInterface, NodeSigner, fn sign_invoice(, invoice: &RawBolt11Invoice, recipient: Recipient) -> Result, fn sign_bolt12_invoice(, invoice: &crate::offers::invoice::UnsignedBolt12Invoice ) -> Result, - fn get_inbound_payment_key(,) -> ExpandedKey + fn get_inbound_payment_key(,) -> ExpandedKey, + fn get_peer_storage_key(,) -> PeerStorageKey ); impl SignerProvider for DynPhantomKeysInterface { diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index a6f0b38a4fb..db8457a55a3 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -46,7 +46,7 @@ use crate::routing::router::{ use crate::routing::scoring::{ChannelUsage, ScoreLookUp, ScoreUpdate}; use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult}; use crate::sign; -use crate::sign::ChannelSigner; +use crate::sign::{ChannelSigner, PeerStorageKey}; use crate::sync::RwLock; use crate::types::features::{ChannelFeatures, InitFeatures, NodeFeatures}; use crate::util::config::UserConfig; @@ -407,6 +407,7 @@ pub struct TestChainMonitor<'a> { &'a TestFeeEstimator, &'a TestLogger, &'a dyn SyncPersist, + &'a TestKeysInterface, >, pub keys_manager: &'a TestKeysInterface, /// If this is set to Some(), the next update_channel call (not watch_channel) must be a @@ -435,6 +436,8 @@ impl<'a> TestChainMonitor<'a> { logger, fee_estimator, persister, + keys_manager, + keys_manager.get_peer_storage_key(), ), keys_manager, expect_channel_force_closed: Mutex::new(None), @@ -1488,6 +1491,10 @@ impl NodeSigner for TestNodeSigner { unreachable!() } + fn get_peer_storage_key(&self) -> PeerStorageKey { + unreachable!() + } + fn get_node_id(&self, recipient: Recipient) -> Result { let node_secret = match recipient { Recipient::Node => Ok(&self.node_secret), @@ -1568,6 +1575,10 @@ impl NodeSigner for TestKeysInterface { self.backing.sign_invoice(invoice, recipient) } + fn get_peer_storage_key(&self) -> PeerStorageKey { + self.backing.get_peer_storage_key() + } + fn sign_bolt12_invoice( &self, invoice: &UnsignedBolt12Invoice, ) -> Result {