Merge pull request #2818 from valentinewallace/2024-01-blinded-path-retries
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Wed, 17 Jan 2024 21:21:36 +0000 (21:21 +0000)
committerGitHub <noreply@github.com>
Wed, 17 Jan 2024 21:21:36 +0000 (21:21 +0000)
Avoid retrying over previously failed blinded paths

48 files changed:
CONTRIBUTING.md
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
fuzz/src/onion_message.rs
lightning-block-sync/src/gossip.rs
lightning-invoice/src/ser.rs
lightning-net-tokio/src/lib.rs
lightning/src/blinded_path/message.rs
lightning/src/blinded_path/payment.rs
lightning/src/blinded_path/utils.rs
lightning/src/chain/channelmonitor.rs
lightning/src/crypto/chacha20.rs [new file with mode: 0644]
lightning/src/crypto/chacha20poly1305rfc.rs [new file with mode: 0644]
lightning/src/crypto/mod.rs [new file with mode: 0644]
lightning/src/crypto/poly1305.rs [new file with mode: 0644]
lightning/src/crypto/streams.rs [new file with mode: 0644]
lightning/src/crypto/utils.rs [new file with mode: 0644]
lightning/src/events/mod.rs
lightning/src/lib.rs
lightning/src/ln/blinded_payment_tests.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/channel.rs
lightning/src/ln/channel_keys.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/inbound_payment.rs
lightning/src/ln/monitor_tests.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_payment.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/peer_channel_encryptor.rs
lightning/src/ln/peer_handler.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/onion_message/mod.rs
lightning/src/onion_message/offers.rs
lightning/src/onion_message/packet.rs
lightning/src/routing/router.rs
lightning/src/sign/mod.rs
lightning/src/util/chacha20.rs [deleted file]
lightning/src/util/chacha20poly1305rfc.rs [deleted file]
lightning/src/util/crypto.rs [deleted file]
lightning/src/util/mod.rs
lightning/src/util/poly1305.rs [deleted file]
lightning/src/util/scid_utils.rs
lightning/src/util/test_utils.rs
lightning/src/util/wakers.rs

index 78c515007d03a75ba2b0261d25ebc74f46531244..b57217165e6b79c239351ebeef85647bafdab18a 100644 (file)
@@ -148,7 +148,7 @@ Security
 --------
 
 Security is the primary focus of `rust-lightning`; disclosure of security
-vulnerabilites helps prevent user loss of funds. If you believe a vulnerability
+vulnerabilities helps prevent user loss of funds. If you believe a vulnerability
 may affect other Lightning implementations, please inform them.
 
 You can find further information on submitting (possible) vulnerabilities in the
index 7a32434b86fff16dfcd58e76e9495095c6c4098f..89ff07fe698268a9f8fff51f1b298c124b46e73b 100644 (file)
@@ -48,7 +48,7 @@ use lightning::ln::script::ShutdownScript;
 use lightning::ln::functional_test_utils::*;
 use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
 use lightning::offers::invoice_request::UnsignedInvoiceRequest;
-use lightning::onion_message::{Destination, MessageRouter, OnionMessagePath};
+use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath};
 use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState};
 use lightning::util::errors::APIError;
 use lightning::util::logger::Logger;
@@ -1289,6 +1289,94 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
                        },
                        0x89 => { fee_est_c.ret_val.store(253, atomic::Ordering::Release); nodes[2].maybe_update_chan_fees(); },
 
+                       0xf0 => {
+                               let pending_updates = monitor_a.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+                               if let Some(id) = pending_updates.get(0) {
+                                       monitor_a.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+                               }
+                               nodes[0].process_monitor_events();
+                       }
+                       0xf1 => {
+                               let pending_updates = monitor_a.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+                               if let Some(id) = pending_updates.get(1) {
+                                       monitor_a.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+                               }
+                               nodes[0].process_monitor_events();
+                       }
+                       0xf2 => {
+                               let pending_updates = monitor_a.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+                               if let Some(id) = pending_updates.last() {
+                                       monitor_a.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+                               }
+                               nodes[0].process_monitor_events();
+                       }
+
+                       0xf4 => {
+                               let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+                               if let Some(id) = pending_updates.get(0) {
+                                       monitor_b.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+                               }
+                               nodes[1].process_monitor_events();
+                       }
+                       0xf5 => {
+                               let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+                               if let Some(id) = pending_updates.get(1) {
+                                       monitor_b.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+                               }
+                               nodes[1].process_monitor_events();
+                       }
+                       0xf6 => {
+                               let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_1_funding).unwrap();
+                               if let Some(id) = pending_updates.last() {
+                                       monitor_b.chain_monitor.channel_monitor_updated(chan_1_funding, *id).unwrap();
+                               }
+                               nodes[1].process_monitor_events();
+                       }
+
+                       0xf8 => {
+                               let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+                               if let Some(id) = pending_updates.get(0) {
+                                       monitor_b.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+                               }
+                               nodes[1].process_monitor_events();
+                       }
+                       0xf9 => {
+                               let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+                               if let Some(id) = pending_updates.get(1) {
+                                       monitor_b.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+                               }
+                               nodes[1].process_monitor_events();
+                       }
+                       0xfa => {
+                               let pending_updates = monitor_b.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+                               if let Some(id) = pending_updates.last() {
+                                       monitor_b.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+                               }
+                               nodes[1].process_monitor_events();
+                       }
+
+                       0xfc => {
+                               let pending_updates = monitor_c.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+                               if let Some(id) = pending_updates.get(0) {
+                                       monitor_c.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+                               }
+                               nodes[2].process_monitor_events();
+                       }
+                       0xfd => {
+                               let pending_updates = monitor_c.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+                               if let Some(id) = pending_updates.get(1) {
+                                       monitor_c.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+                               }
+                               nodes[2].process_monitor_events();
+                       }
+                       0xfe => {
+                               let pending_updates = monitor_c.chain_monitor.list_pending_monitor_updates().remove(&chan_2_funding).unwrap();
+                               if let Some(id) = pending_updates.last() {
+                                       monitor_c.chain_monitor.channel_monitor_updated(chan_2_funding, *id).unwrap();
+                               }
+                               nodes[2].process_monitor_events();
+                       }
+
                        0xff => {
                                // Test that no channel is in a stuck state where neither party can send funds even
                                // after we resolve all pending events.
index a2ce98cf4d22c9bebaf40ff895b98f88d7b8da2e..1f5ceb2123517a5b14559ee5e82adc085fe576b7 100644 (file)
@@ -45,7 +45,7 @@ use lightning::ln::script::ShutdownScript;
 use lightning::ln::functional_test_utils::*;
 use lightning::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
 use lightning::offers::invoice_request::UnsignedInvoiceRequest;
-use lightning::onion_message::{Destination, MessageRouter, OnionMessagePath};
+use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath};
 use lightning::routing::gossip::{P2PGossipSync, NetworkGraph};
 use lightning::routing::utxo::UtxoLookup;
 use lightning::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteParameters, Router};
index d2d60cfcf640593e2e38d264eac6eeb0c2abafad..4ad770fc20c8baa4e2a7a2cd1da8df3ff814a818 100644 (file)
@@ -16,7 +16,9 @@ use lightning::sign::{Recipient, KeyMaterial, EntropySource, NodeSigner, SignerP
 use lightning::util::test_channel_signer::TestChannelSigner;
 use lightning::util::logger::Logger;
 use lightning::util::ser::{Readable, Writeable, Writer};
-use lightning::onion_message::{CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, PendingOnionMessage};
+use lightning::onion_message::messenger::{CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger, PendingOnionMessage};
+use lightning::onion_message::offers::{OffersMessage, OffersMessageHandler};
+use lightning::onion_message::packet::OnionMessageContents;
 
 use crate::utils::test_logger;
 
index 591b0298793ffb3baadb1d0ee0009b1199a95941..9cd4049679c30fd5d7ddd2f86562d6df81758447 100644 (file)
@@ -132,14 +132,12 @@ impl<
 pub struct GossipVerifier<S: FutureSpawner,
        Blocks: Deref + Send + Sync + 'static + Clone,
        L: Deref + Send + Sync + 'static,
-       APM: Deref + Send + Sync + 'static + Clone,
 > where
        Blocks::Target: UtxoSource,
        L::Target: Logger,
-       APM::Target: APeerManager,
 {
        source: Blocks,
-       peer_manager: APM,
+       peer_manager_wake: Arc<dyn Fn() + Send + Sync>,
        gossiper: Arc<P2PGossipSync<Arc<NetworkGraph<L>>, Self, L>>,
        spawn: S,
        block_cache: Arc<Mutex<VecDeque<(u32, Block)>>>,
@@ -150,19 +148,20 @@ const BLOCK_CACHE_SIZE: usize = 5;
 impl<S: FutureSpawner,
        Blocks: Deref + Send + Sync + Clone,
        L: Deref + Send + Sync,
-       APM: Deref + Send + Sync + Clone,
-> GossipVerifier<S, Blocks, L, APM> where
+> GossipVerifier<S, Blocks, L> where
        Blocks::Target: UtxoSource,
        L::Target: Logger,
-       APM::Target: APeerManager,
 {
        /// Constructs a new [`GossipVerifier`].
        ///
        /// This is expected to be given to a [`P2PGossipSync`] (initially constructed with `None` for
        /// the UTXO lookup) via [`P2PGossipSync::add_utxo_lookup`].
-       pub fn new(source: Blocks, spawn: S, gossiper: Arc<P2PGossipSync<Arc<NetworkGraph<L>>, Self, L>>, peer_manager: APM) -> Self {
+       pub fn new<APM: Deref + Send + Sync + Clone + 'static>(
+               source: Blocks, spawn: S, gossiper: Arc<P2PGossipSync<Arc<NetworkGraph<L>>, Self, L>>, peer_manager: APM
+       ) -> Self where APM::Target: APeerManager {
+               let peer_manager_wake = Arc::new(move || peer_manager.as_ref().process_events());
                Self {
-                       source, spawn, gossiper, peer_manager,
+                       source, spawn, gossiper, peer_manager_wake,
                        block_cache: Arc::new(Mutex::new(VecDeque::with_capacity(BLOCK_CACHE_SIZE))),
                }
        }
@@ -252,11 +251,9 @@ impl<S: FutureSpawner,
 impl<S: FutureSpawner,
        Blocks: Deref + Send + Sync + Clone,
        L: Deref + Send + Sync,
-       APM: Deref + Send + Sync + Clone,
-> Deref for GossipVerifier<S, Blocks, L, APM> where
+> Deref for GossipVerifier<S, Blocks, L> where
        Blocks::Target: UtxoSource,
        L::Target: Logger,
-       APM::Target: APeerManager,
 {
        type Target = Self;
        fn deref(&self) -> &Self { self }
@@ -266,11 +263,9 @@ impl<S: FutureSpawner,
 impl<S: FutureSpawner,
        Blocks: Deref + Send + Sync + Clone,
        L: Deref + Send + Sync,
-       APM: Deref + Send + Sync + Clone,
-> UtxoLookup for GossipVerifier<S, Blocks, L, APM> where
+> UtxoLookup for GossipVerifier<S, Blocks, L> where
        Blocks::Target: UtxoSource,
        L::Target: Logger,
-       APM::Target: APeerManager,
 {
        fn get_utxo(&self, _chain_hash: &ChainHash, short_channel_id: u64) -> UtxoResult {
                let res = UtxoFuture::new();
@@ -278,11 +273,11 @@ impl<S: FutureSpawner,
                let source = self.source.clone();
                let gossiper = Arc::clone(&self.gossiper);
                let block_cache = Arc::clone(&self.block_cache);
-               let pm = self.peer_manager.clone();
+               let pmw = Arc::clone(&self.peer_manager_wake);
                self.spawn.spawn(async move {
                        let res = Self::retrieve_utxo(source, block_cache, short_channel_id).await;
                        fut.resolve(gossiper.network_graph(), &*gossiper, res);
-                       pm.as_ref().process_events();
+                       (pmw)();
                });
                UtxoResult::Async(res)
        }
index fe42f72b6532f593083049832a07f31272cd43a5..dc63783bfa388fc35f7394d8cc243471683df99e 100644 (file)
@@ -52,7 +52,7 @@ impl<'a, W: WriteBase32> BytesToBase32<'a, W> {
                }
 
                // Combine all bits from buffer with enough bits from this rounds byte so that they fill
-               // a u5. Save reamining bits from byte to buffer.
+               // a u5. Save remaining bits from byte to buffer.
                let from_buffer = self.buffer >> 3;
                let from_byte = byte >> (3 + self.buffer_bits); // buffer_bits <= 4
 
index 1aa2cc25a13cc0772ee2e958da66aca602ce0eb4..be41a2401244f0bff743e44b9e7ec26482d95227 100644 (file)
@@ -502,6 +502,9 @@ impl peer_handler::SocketDescriptor for SocketDescriptor {
                                                        written_len += res;
                                                        if written_len == data.len() { return written_len; }
                                                },
+                                               Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
+                                                       continue;
+                                               }
                                                Err(_) => return written_len,
                                        }
                                },
index d2e81444ef6307a2cac41082c444f18568af7a85..3a5541fa1468272f3859972bca2cdfb4f8053ee8 100644 (file)
@@ -5,10 +5,10 @@ use crate::blinded_path::utils;
 use crate::io;
 use crate::io::Cursor;
 use crate::ln::onion_utils;
-use crate::onion_message::ControlTlvs;
+use crate::onion_message::packet::ControlTlvs;
 use crate::prelude::*;
 use crate::sign::{NodeSigner, Recipient};
-use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter;
+use crate::crypto::streams::ChaChaPolyReadAdapter;
 use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Writeable, Writer};
 
 use core::mem;
index f4df1e379d931b3ac65cbcdae65441c629554c6c..5d332a76faf57fed3b2fe844b91d5c5d04ed8a81 100644 (file)
@@ -97,12 +97,24 @@ pub struct PaymentConstraints {
        pub htlc_minimum_msat: u64,
 }
 
-impl From<CounterpartyForwardingInfo> for PaymentRelay {
-       fn from(info: CounterpartyForwardingInfo) -> Self {
+impl TryFrom<CounterpartyForwardingInfo> for PaymentRelay {
+       type Error = ();
+
+       fn try_from(info: CounterpartyForwardingInfo) -> Result<Self, ()> {
                let CounterpartyForwardingInfo {
                        fee_base_msat, fee_proportional_millionths, cltv_expiry_delta
                } = info;
-               Self { cltv_expiry_delta, fee_proportional_millionths, fee_base_msat }
+
+               // Avoid exposing esoteric CLTV expiry deltas
+               let cltv_expiry_delta = match cltv_expiry_delta {
+                       0..=40 => 40,
+                       41..=80 => 80,
+                       81..=144 => 144,
+                       145..=216 => 216,
+                       _ => return Err(()),
+               };
+
+               Ok(Self { cltv_expiry_delta, fee_proportional_millionths, fee_base_msat })
        }
 }
 
index 2e691898dc26cc187504fee5e774d4f8ce9a4af7..d4894a86aa1a9069abdc9b2e073cd0a31c789048 100644 (file)
@@ -18,8 +18,8 @@ use bitcoin::secp256k1::ecdh::SharedSecret;
 use super::{BlindedHop, BlindedPath};
 use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils;
-use crate::onion_message::Destination;
-use crate::util::chacha20poly1305rfc::ChaChaPolyWriteAdapter;
+use crate::onion_message::messenger::Destination;
+use crate::crypto::streams::ChaChaPolyWriteAdapter;
 use crate::util::ser::{Readable, Writeable};
 
 use crate::io;
index bcc324a5582af9d0f6c399034d7cf4e0b2327161..c81a48b78ac8b4aa6fba1facae191f7190e27d51 100644 (file)
@@ -4808,7 +4808,7 @@ mod tests {
                                preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|(htlc, _)| (htlc, None)).collect()
                        }
                }
-               let dummy_sig = crate::util::crypto::sign(&secp_ctx,
+               let dummy_sig = crate::crypto::utils::sign(&secp_ctx,
                        &bitcoin::secp256k1::Message::from_slice(&[42; 32]).unwrap(),
                        &SecretKey::from_slice(&[42; 32]).unwrap());
 
diff --git a/lightning/src/crypto/chacha20.rs b/lightning/src/crypto/chacha20.rs
new file mode 100644 (file)
index 0000000..d6fd3a7
--- /dev/null
@@ -0,0 +1,686 @@
+// This file was stolen from rust-crypto.
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+#[cfg(not(fuzzing))]
+mod real_chacha {
+       use core::cmp;
+       use core::convert::TryInto;
+
+       #[derive(Clone, Copy, PartialEq, Eq)]
+       #[allow(non_camel_case_types)]
+       struct u32x4(pub u32, pub u32, pub u32, pub u32);
+       impl ::core::ops::Add for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn add(self, rhs: u32x4) -> u32x4 {
+                       u32x4(self.0.wrapping_add(rhs.0),
+                             self.1.wrapping_add(rhs.1),
+                             self.2.wrapping_add(rhs.2),
+                             self.3.wrapping_add(rhs.3))
+               }
+       }
+       impl ::core::ops::Sub for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn sub(self, rhs: u32x4) -> u32x4 {
+                       u32x4(self.0.wrapping_sub(rhs.0),
+                             self.1.wrapping_sub(rhs.1),
+                             self.2.wrapping_sub(rhs.2),
+                             self.3.wrapping_sub(rhs.3))
+               }
+       }
+       impl ::core::ops::BitXor for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn bitxor(self, rhs: u32x4) -> u32x4 {
+                       u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
+               }
+       }
+       impl ::core::ops::Shr<u8> for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn shr(self, shr: u8) -> u32x4 {
+                       u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
+               }
+       }
+       impl ::core::ops::Shl<u8> for u32x4 {
+               type Output = u32x4;
+               #[inline]
+               fn shl(self, shl: u8) -> u32x4 {
+                       u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
+               }
+       }
+       impl u32x4 {
+               #[inline]
+               fn from_bytes(bytes: &[u8]) -> Self {
+                       assert_eq!(bytes.len(), 4*4);
+                       Self (
+                               u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
+                               u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
+                               u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
+                               u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
+                       )
+               }
+       }
+
+       const BLOCK_SIZE: usize = 64;
+
+       #[derive(Clone,Copy)]
+       struct ChaChaState {
+               a: u32x4,
+               b: u32x4,
+               c: u32x4,
+               d: u32x4
+       }
+
+       #[derive(Copy)]
+       pub struct ChaCha20 {
+               state  : ChaChaState,
+               output : [u8; BLOCK_SIZE],
+               offset : usize,
+       }
+
+       impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
+
+       macro_rules! swizzle {
+               ($b: expr, $c: expr, $d: expr) => {{
+                       let u32x4(b10, b11, b12, b13) = $b;
+                       $b = u32x4(b11, b12, b13, b10);
+                       let u32x4(c10, c11, c12, c13) = $c;
+                       $c = u32x4(c12, c13,c10, c11);
+                       let u32x4(d10, d11, d12, d13) = $d;
+                       $d = u32x4(d13, d10, d11, d12);
+               }}
+       }
+
+       macro_rules! state_to_buffer {
+               ($state: expr, $output: expr) => {{
+                       let u32x4(a1, a2, a3, a4) = $state.a;
+                       let u32x4(b1, b2, b3, b4) = $state.b;
+                       let u32x4(c1, c2, c3, c4) = $state.c;
+                       let u32x4(d1, d2, d3, d4) = $state.d;
+                       let lens = [
+                               a1,a2,a3,a4,
+                               b1,b2,b3,b4,
+                               c1,c2,c3,c4,
+                               d1,d2,d3,d4
+                       ];
+                       for i in 0..lens.len() {
+                               $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
+                       }
+               }}
+       }
+
+       macro_rules! round{
+               ($state: expr) => {{
+                       $state.a = $state.a + $state.b;
+                       rotate!($state.d, $state.a, 16);
+                       $state.c = $state.c + $state.d;
+                       rotate!($state.b, $state.c, 12);
+                       $state.a = $state.a + $state.b;
+                       rotate!($state.d, $state.a, 8);
+                       $state.c = $state.c + $state.d;
+                       rotate!($state.b, $state.c, 7);
+               }}
+       }
+
+       macro_rules! rotate {
+               ($a: expr, $b: expr, $rot: expr) => {{
+                       let v = $a ^ $b;
+                       let r = 32 - $rot;
+                       let right = v >> r;
+                       $a = (v << $rot) ^ right
+               }}
+       }
+
+       impl ChaCha20 {
+               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
+                       assert!(key.len() == 16 || key.len() == 32);
+                       assert!(nonce.len() == 8 || nonce.len() == 12);
+
+                       ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
+               }
+
+               /// Get one block from a ChaCha stream.
+               pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
+                       let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
+                       let mut chacha_bytes = [0; 32];
+                       chacha.process_in_place(&mut chacha_bytes);
+                       chacha_bytes
+               }
+
+               /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
+               /// `src` in a second call will decrypt it.
+               pub fn encrypt_single_block(
+                       key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
+               ) {
+                       debug_assert_eq!(dest.len(), src.len());
+                       debug_assert!(dest.len() <= 32);
+
+                       let block = ChaCha20::get_single_block(key, nonce);
+                       for i in 0..dest.len() {
+                               dest[i] = block[i] ^ src[i];
+                       }
+               }
+
+               /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
+               pub fn encrypt_single_block_in_place(
+                       key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
+               ) {
+                       let block = ChaCha20::get_single_block(key, nonce);
+                       for i in 0..bytes.len() {
+                               bytes[i] = block[i] ^ bytes[i];
+                       }
+               }
+
+               fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
+                       let constant = match key.len() {
+                               16 => b"expand 16-byte k",
+                               32 => b"expand 32-byte k",
+                               _  => unreachable!(),
+                       };
+                       ChaChaState {
+                               a: u32x4::from_bytes(&constant[0..16]),
+                               b: u32x4::from_bytes(&key[0..16]),
+                               c: if key.len() == 16 {
+                                       u32x4::from_bytes(&key[0..16])
+                               } else {
+                                       u32x4::from_bytes(&key[16..32])
+                               },
+                               d: if nonce.len() == 16 {
+                                       u32x4::from_bytes(&nonce[0..16])
+                               } else if nonce.len() == 12 {
+                                       let mut nonce4 = [0; 4*4];
+                                       nonce4[4..].copy_from_slice(nonce);
+                                       u32x4::from_bytes(&nonce4)
+                               } else {
+                                       let mut nonce4 = [0; 4*4];
+                                       nonce4[8..].copy_from_slice(nonce);
+                                       u32x4::from_bytes(&nonce4)
+                               }
+                       }
+               }
+
+               // put the the next BLOCK_SIZE keystream bytes into self.output
+               fn update(&mut self) {
+                       let mut state = self.state;
+
+                       for _ in 0..10 {
+                               round!(state);
+                               swizzle!(state.b, state.c, state.d);
+                               round!(state);
+                               swizzle!(state.d, state.c, state.b);
+                       }
+                       state.a = state.a + self.state.a;
+                       state.b = state.b + self.state.b;
+                       state.c = state.c + self.state.c;
+                       state.d = state.d + self.state.d;
+
+                       state_to_buffer!(state, self.output);
+
+                       self.state.d = self.state.d + u32x4(1, 0, 0, 0);
+                       let u32x4(c12, _, _, _) = self.state.d;
+                       if c12 == 0 {
+                               // we could increment the other counter word with an 8 byte nonce
+                               // but other implementations like boringssl have this same
+                               // limitation
+                               panic!("counter is exhausted");
+                       }
+
+                       self.offset = 0;
+               }
+
+               #[inline] // Useful cause input may be 0s on stack that should be optimized out
+               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
+                       assert!(input.len() == output.len());
+                       let len = input.len();
+                       let mut i = 0;
+                       while i < len {
+                               // If there is no keystream available in the output buffer,
+                               // generate the next block.
+                               if self.offset == BLOCK_SIZE {
+                                       self.update();
+                               }
+
+                               // Process the min(available keystream, remaining input length).
+                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
+                               // explicitly assert lengths to avoid bounds checks:
+                               assert!(output.len() >= i + count);
+                               assert!(input.len() >= i + count);
+                               assert!(self.output.len() >= self.offset + count);
+                               for j in 0..count {
+                                       output[i + j] = input[i + j] ^ self.output[self.offset + j];
+                               }
+                               i += count;
+                               self.offset += count;
+                       }
+               }
+
+               pub fn process_in_place(&mut self, input_output: &mut [u8]) {
+                       let len = input_output.len();
+                       let mut i = 0;
+                       while i < len {
+                               // If there is no keystream available in the output buffer,
+                               // generate the next block.
+                               if self.offset == BLOCK_SIZE {
+                                       self.update();
+                               }
+
+                               // Process the min(available keystream, remaining input length).
+                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
+                               // explicitly assert lengths to avoid bounds checks:
+                               assert!(input_output.len() >= i + count);
+                               assert!(self.output.len() >= self.offset + count);
+                               for j in 0..count {
+                                       input_output[i + j] ^= self.output[self.offset + j];
+                               }
+                               i += count;
+                               self.offset += count;
+                       }
+               }
+
+               #[cfg(test)]
+               pub fn seek_to_block(&mut self, block_offset: u32) {
+                       self.state.d.0 = block_offset;
+                       self.update();
+               }
+       }
+}
+#[cfg(not(fuzzing))]
+pub use self::real_chacha::ChaCha20;
+
+#[cfg(fuzzing)]
+mod fuzzy_chacha {
+       pub struct ChaCha20 {}
+
+       impl ChaCha20 {
+               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
+                       assert!(key.len() == 16 || key.len() == 32);
+                       assert!(nonce.len() == 8 || nonce.len() == 12);
+                       Self {}
+               }
+
+               pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
+                       [0; 32]
+               }
+
+               pub fn encrypt_single_block(
+                       _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
+               ) {
+                       debug_assert_eq!(dest.len(), src.len());
+                       debug_assert!(dest.len() <= 32);
+               }
+
+               pub fn encrypt_single_block_in_place(
+                       _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
+               ) {}
+
+               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
+                       output.copy_from_slice(input);
+               }
+
+               pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
+       }
+}
+#[cfg(fuzzing)]
+pub use self::fuzzy_chacha::ChaCha20;
+
+#[cfg(test)]
+mod test {
+       use alloc::vec;
+       use alloc::vec::{Vec};
+       use core::convert::TryInto;
+       use core::iter::repeat;
+
+       use super::ChaCha20;
+
+       #[test]
+       fn test_chacha20_256_tls_vectors() {
+               struct TestVector {
+                       key:   [u8; 32],
+                       nonce: [u8; 8],
+                       keystream: Vec<u8>,
+               }
+               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
+               let test_vectors = vec!(
+                       TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
+                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
+                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
+                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
+                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
+                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
+                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
+                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
+                               keystream: vec!(
+                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
+                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
+                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
+                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
+                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
+                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
+                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
+                                       0x44, 0x5f, 0x41, 0xe3,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
+                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
+                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
+                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
+                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
+                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
+                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
+                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                               ],
+                               nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
+                               keystream: vec!(
+                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
+                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
+                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
+                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
+                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
+                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
+                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
+                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
+                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
+                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
+                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
+                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
+                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
+                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
+                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
+                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
+                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
+                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
+                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
+                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
+                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
+                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
+                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
+                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
+                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
+                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
+                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
+                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
+                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
+                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
+                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
+                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
+                               ),
+                       },
+               );
+
+               for tv in test_vectors.iter() {
+                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
+                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
+                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
+                       c.process(&input[..], &mut output[..]);
+                       assert_eq!(output, tv.keystream);
+               }
+       }
+
+       #[test]
+       fn test_chacha20_256_tls_vectors_96_nonce() {
+               struct TestVector {
+                       key:   [u8; 32],
+                       nonce: [u8; 12],
+                       keystream: Vec<u8>,
+               }
+               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
+               let test_vectors = vec!(
+                       TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
+                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
+                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
+                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
+                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
+                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
+                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
+                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
+                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
+                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
+                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
+                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
+                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
+                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
+                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
+                               keystream: vec!(
+                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
+                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
+                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
+                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
+                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
+                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
+                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
+                                       0x44, 0x5f, 0x41, 0xe3,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                               ],
+                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
+                               keystream: vec!(
+                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
+                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
+                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
+                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
+                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
+                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
+                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
+                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
+                               ),
+                       }, TestVector{
+                               key: [
+                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                               ],
+                               nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
+                               keystream: vec!(
+                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
+                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
+                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
+                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
+                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
+                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
+                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
+                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
+                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
+                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
+                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
+                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
+                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
+                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
+                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
+                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
+                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
+                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
+                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
+                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
+                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
+                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
+                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
+                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
+                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
+                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
+                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
+                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
+                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
+                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
+                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
+                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
+                               ),
+                       },
+               );
+
+               for tv in test_vectors.iter() {
+                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
+                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
+                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
+                       c.process(&input[..], &mut output[..]);
+                       assert_eq!(output, tv.keystream);
+               }
+       }
+
+       #[test]
+       fn get_single_block() {
+               // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
+               // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
+               // bytes.
+               let key = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               ];
+               let nonce_16bytes = [
+                       0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
+               ];
+               let counter_pos = &nonce_16bytes[..4];
+               let nonce_12bytes = &nonce_16bytes[4..];
+
+               // Initialize a ChaCha20 instance with its counter starting at 0.
+               let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
+               // Seek its counter to the block at counter_pos.
+               chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
+               let mut block_bytes = [0; 32];
+               chacha20.process_in_place(&mut block_bytes);
+
+               assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
+       }
+
+       #[test]
+       fn encrypt_single_block() {
+               let key = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               ];
+               let nonce = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+               ];
+               let bytes = [1; 32];
+
+               let mut encrypted_bytes = [0; 32];
+               ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
+
+               let mut decrypted_bytes = [0; 32];
+               ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
+
+               assert_eq!(bytes, decrypted_bytes);
+       }
+
+       #[test]
+       fn encrypt_single_block_in_place() {
+               let key = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+               ];
+               let nonce = [
+                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+               ];
+               let unencrypted_bytes = [1; 32];
+               let mut bytes = unencrypted_bytes;
+
+               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
+               assert_ne!(bytes, unencrypted_bytes);
+
+               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
+               assert_eq!(bytes, unencrypted_bytes);
+       }
+}
diff --git a/lightning/src/crypto/chacha20poly1305rfc.rs b/lightning/src/crypto/chacha20poly1305rfc.rs
new file mode 100644 (file)
index 0000000..4ca9744
--- /dev/null
@@ -0,0 +1,237 @@
+// ring has a garbage API so its use is avoided, but rust-crypto doesn't have RFC-variant poly1305
+// Instead, we steal rust-crypto's implementation and tweak it to match the RFC.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+//
+// This is a port of Andrew Moons poly1305-donna
+// https://github.com/floodyberry/poly1305-donna
+
+#[cfg(not(fuzzing))]
+mod real_chachapoly {
+       use super::super::chacha20::ChaCha20;
+       use super::super::poly1305::Poly1305;
+       use super::super::fixed_time_eq;
+
+       #[derive(Clone, Copy)]
+       pub struct ChaCha20Poly1305RFC {
+               cipher: ChaCha20,
+               mac: Poly1305,
+               finished: bool,
+               data_len: usize,
+               aad_len: u64,
+       }
+
+       impl ChaCha20Poly1305RFC {
+               #[inline]
+               fn pad_mac_16(mac: &mut Poly1305, len: usize) {
+                       if len % 16 != 0 {
+                               mac.input(&[0; 16][0..16 - (len % 16)]);
+                       }
+               }
+               pub fn new(key: &[u8], nonce: &[u8], aad: &[u8]) -> ChaCha20Poly1305RFC {
+                       assert!(key.len() == 16 || key.len() == 32);
+                       assert!(nonce.len() == 12);
+
+                       // Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
+                       assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
+
+                       let mut cipher = ChaCha20::new(key, &nonce[4..]);
+                       let mut mac_key = [0u8; 64];
+                       let zero_key = [0u8; 64];
+                       cipher.process(&zero_key, &mut mac_key);
+
+                       let mut mac = Poly1305::new(&mac_key[..32]);
+                       mac.input(aad);
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut mac, aad.len());
+
+                       ChaCha20Poly1305RFC {
+                               cipher,
+                               mac,
+                               finished: false,
+                               data_len: 0,
+                               aad_len: aad.len() as u64,
+                       }
+               }
+
+               pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
+                       assert!(input.len() == output.len());
+                       assert!(self.finished == false);
+                       self.cipher.process(input, output);
+                       self.data_len += input.len();
+                       self.mac.input(output);
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+                       self.finished = true;
+                       self.mac.input(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+                       self.mac.raw_result(out_tag);
+               }
+
+               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
+                       self.encrypt_in_place(input_output);
+                       self.finish_and_get_tag(out_tag);
+               }
+
+               // Encrypt `input_output` in-place. To finish and calculate the tag, use `finish_and_get_tag`
+               // below.
+               pub(in super::super) fn encrypt_in_place(&mut self, input_output: &mut [u8]) {
+                       debug_assert!(self.finished == false);
+                       self.cipher.process_in_place(input_output);
+                       self.data_len += input_output.len();
+                       self.mac.input(input_output);
+               }
+
+               // If we were previously encrypting with `encrypt_in_place`, this method can be used to finish
+               // encrypting and calculate the tag.
+               pub(in super::super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
+                       debug_assert!(self.finished == false);
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+                       self.finished = true;
+                       self.mac.input(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+                       self.mac.raw_result(out_tag);
+               }
+
+               /// Decrypt the `input`, checking the given `tag` prior to writing the decrypted contents
+               /// into `output`. Note that, because `output` is not touched until the `tag` is checked,
+               /// this decryption is *variable time*.
+               pub fn variable_time_decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       assert!(input.len() == output.len());
+                       assert!(self.finished == false);
+
+                       self.finished = true;
+
+                       self.mac.input(input);
+
+                       self.data_len += input.len();
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+                       self.mac.input(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+
+                       let mut calc_tag =  [0u8; 16];
+                       self.mac.raw_result(&mut calc_tag);
+                       if fixed_time_eq(&calc_tag, tag) {
+                               self.cipher.process(input, output);
+                               Ok(())
+                       } else {
+                               Err(())
+                       }
+               }
+
+               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       self.decrypt_in_place(input_output);
+                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
+               }
+
+               /// Decrypt in place, without checking the tag. Use `finish_and_check_tag` to check it
+               /// later when decryption finishes.
+               ///
+               /// Should never be `pub` because the public API should always enforce tag checking.
+               pub(in super::super) fn decrypt_in_place(&mut self, input_output: &mut [u8]) {
+                       debug_assert!(self.finished == false);
+                       self.mac.input(input_output);
+                       self.data_len += input_output.len();
+                       self.cipher.process_in_place(input_output);
+               }
+
+               /// If we were previously decrypting with `just_decrypt_in_place`, this method must be used
+               /// to check the tag. Returns whether or not the tag is valid.
+               pub(in super::super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
+                       debug_assert!(self.finished == false);
+                       self.finished = true;
+                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
+                       self.mac.input(&self.aad_len.to_le_bytes());
+                       self.mac.input(&(self.data_len as u64).to_le_bytes());
+
+                       let mut calc_tag =  [0u8; 16];
+                       self.mac.raw_result(&mut calc_tag);
+                       if fixed_time_eq(&calc_tag, tag) {
+                               true
+                       } else {
+                               false
+                       }
+               }
+       }
+}
+#[cfg(not(fuzzing))]
+pub use self::real_chachapoly::ChaCha20Poly1305RFC;
+
+#[cfg(fuzzing)]
+mod fuzzy_chachapoly {
+       #[derive(Clone, Copy)]
+       pub struct ChaCha20Poly1305RFC {
+               tag: [u8; 16],
+               finished: bool,
+       }
+       impl ChaCha20Poly1305RFC {
+               pub fn new(key: &[u8], nonce: &[u8], _aad: &[u8]) -> ChaCha20Poly1305RFC {
+                       assert!(key.len() == 16 || key.len() == 32);
+                       assert!(nonce.len() == 12);
+
+                       // Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
+                       assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
+
+                       let mut tag = [0; 16];
+                       tag.copy_from_slice(&key[0..16]);
+
+                       ChaCha20Poly1305RFC {
+                               tag,
+                               finished: false,
+                       }
+               }
+
+               pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
+                       assert!(input.len() == output.len());
+                       assert!(self.finished == false);
+
+                       output.copy_from_slice(&input);
+                       out_tag.copy_from_slice(&self.tag);
+                       self.finished = true;
+               }
+
+               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
+                       self.encrypt_in_place(input_output);
+                       self.finish_and_get_tag(out_tag);
+               }
+
+               pub(in super::super) fn encrypt_in_place(&mut self, _input_output: &mut [u8]) {
+                       assert!(self.finished == false);
+               }
+
+               pub(in super::super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
+                       assert!(self.finished == false);
+                       out_tag.copy_from_slice(&self.tag);
+                       self.finished = true;
+               }
+
+               pub fn variable_time_decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       assert!(input.len() == output.len());
+                       assert!(self.finished == false);
+
+                       if tag[..] != self.tag[..] { return Err(()); }
+                       output.copy_from_slice(input);
+                       self.finished = true;
+                       Ok(())
+               }
+
+               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
+                       self.decrypt_in_place(input_output);
+                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
+               }
+
+               pub(in super::super) fn decrypt_in_place(&mut self, _input: &mut [u8]) {
+                       assert!(self.finished == false);
+               }
+
+               pub(in super::super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
+                       if tag[..] != self.tag[..] { return false; }
+                       self.finished = true;
+                       true
+               }
+       }
+}
+#[cfg(fuzzing)]
+pub use self::fuzzy_chachapoly::ChaCha20Poly1305RFC;
diff --git a/lightning/src/crypto/mod.rs b/lightning/src/crypto/mod.rs
new file mode 100644 (file)
index 0000000..6efd120
--- /dev/null
@@ -0,0 +1,8 @@
+use bitcoin::hashes::cmp::fixed_time_eq;
+
+pub(crate) mod chacha20;
+#[cfg(not(fuzzing))]
+pub(crate) mod poly1305;
+pub(crate) mod chacha20poly1305rfc;
+pub(crate) mod streams;
+pub(crate) mod utils;
diff --git a/lightning/src/crypto/poly1305.rs b/lightning/src/crypto/poly1305.rs
new file mode 100644 (file)
index 0000000..a1b9fba
--- /dev/null
@@ -0,0 +1,341 @@
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// This is a port of Andrew Moons poly1305-donna
+// https://github.com/floodyberry/poly1305-donna
+
+use core::cmp::min;
+use core::convert::TryInto;
+
+#[derive(Clone, Copy)]
+pub struct Poly1305 {
+       r         : [u32; 5],
+       h         : [u32; 5],
+       pad       : [u32; 4],
+       leftover  : usize,
+       buffer    : [u8; 16],
+       finalized : bool,
+}
+
+impl Poly1305 {
+       pub fn new(key: &[u8]) -> Poly1305 {
+               assert!(key.len() == 32);
+               let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false };
+
+               // r &= 0xffffffc0ffffffc0ffffffc0fffffff
+               poly.r[0] = (u32::from_le_bytes(key[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
+               poly.r[1] = (u32::from_le_bytes(key[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffff03;
+               poly.r[2] = (u32::from_le_bytes(key[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffc0ff;
+               poly.r[3] = (u32::from_le_bytes(key[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3f03fff;
+               poly.r[4] = (u32::from_le_bytes(key[12..16].try_into().expect("len is 4")) >> 8) & 0x00fffff;
+
+               poly.pad[0] = u32::from_le_bytes(key[16..20].try_into().expect("len is 4"));
+               poly.pad[1] = u32::from_le_bytes(key[20..24].try_into().expect("len is 4"));
+               poly.pad[2] = u32::from_le_bytes(key[24..28].try_into().expect("len is 4"));
+               poly.pad[3] = u32::from_le_bytes(key[28..32].try_into().expect("len is 4"));
+
+               poly
+       }
+
+       fn block(&mut self, m: &[u8]) {
+               let hibit : u32 = if self.finalized { 0 } else { 1 << 24 };
+
+               let r0 = self.r[0];
+               let r1 = self.r[1];
+               let r2 = self.r[2];
+               let r3 = self.r[3];
+               let r4 = self.r[4];
+
+               let s1 = r1 * 5;
+               let s2 = r2 * 5;
+               let s3 = r3 * 5;
+               let s4 = r4 * 5;
+
+               let mut h0 = self.h[0];
+               let mut h1 = self.h[1];
+               let mut h2 = self.h[2];
+               let mut h3 = self.h[3];
+               let mut h4 = self.h[4];
+
+               // h += m
+               h0 += (u32::from_le_bytes(m[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
+               h1 += (u32::from_le_bytes(m[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffffff;
+               h2 += (u32::from_le_bytes(m[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffffff;
+               h3 += (u32::from_le_bytes(m[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3ffffff;
+               h4 += (u32::from_le_bytes(m[12..16].try_into().expect("len is 4")) >> 8) | hibit;
+
+               // h *= r
+               let     d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64);
+               let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64);
+               let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64);
+               let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64);
+               let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64);
+
+               // (partial) h %= p
+               let mut c : u32;
+                               c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff;
+               d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff;
+               d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff;
+               d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff;
+               d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff;
+               h0 += c * 5;    c = h0 >> 26; h0 = h0 & 0x3ffffff;
+               h1 += c;
+
+               self.h[0] = h0;
+               self.h[1] = h1;
+               self.h[2] = h2;
+               self.h[3] = h3;
+               self.h[4] = h4;
+       }
+
+       pub fn finish(&mut self) {
+               if self.leftover > 0 {
+                       self.buffer[self.leftover] = 1;
+                       for i in self.leftover+1..16 {
+                               self.buffer[i] = 0;
+                       }
+                       self.finalized = true;
+                       let tmp = self.buffer;
+                       self.block(&tmp);
+               }
+
+               // fully carry h
+               let mut h0 = self.h[0];
+               let mut h1 = self.h[1];
+               let mut h2 = self.h[2];
+               let mut h3 = self.h[3];
+               let mut h4 = self.h[4];
+
+               let mut c : u32;
+                            c = h1 >> 26; h1 = h1 & 0x3ffffff;
+               h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
+               h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
+               h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
+               h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
+               h1 +=     c;
+
+               // compute h + -p
+               let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff;
+               let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff;
+               let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff;
+               let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff;
+               let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
+
+               // select h if h < p, or h + -p if h >= p
+               let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
+               g0 &= mask;
+               g1 &= mask;
+               g2 &= mask;
+               g3 &= mask;
+               g4 &= mask;
+               mask = !mask;
+               h0 = (h0 & mask) | g0;
+               h1 = (h1 & mask) | g1;
+               h2 = (h2 & mask) | g2;
+               h3 = (h3 & mask) | g3;
+               h4 = (h4 & mask) | g4;
+
+               // h = h % (2^128)
+               h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
+               h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
+               h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
+               h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
+
+               // h = mac = (h + pad) % (2^128)
+               let mut f : u64;
+               f = h0 as u64 + self.pad[0] as u64            ; h0 = f as u32;
+               f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32;
+               f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32;
+               f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32;
+
+               self.h[0] = h0;
+               self.h[1] = h1;
+               self.h[2] = h2;
+               self.h[3] = h3;
+       }
+
+       pub fn input(&mut self, data: &[u8]) {
+               assert!(!self.finalized);
+               let mut m = data;
+
+               if self.leftover > 0 {
+                       let want = min(16 - self.leftover, m.len());
+                       for i in 0..want {
+                               self.buffer[self.leftover+i] = m[i];
+                       }
+                       m = &m[want..];
+                       self.leftover += want;
+
+                       if self.leftover < 16 {
+                               return;
+                       }
+
+                       // self.block(self.buffer[..]);
+                       let tmp = self.buffer;
+                       self.block(&tmp);
+
+                       self.leftover = 0;
+               }
+
+               while m.len() >= 16 {
+                       self.block(&m[0..16]);
+                       m = &m[16..];
+               }
+
+               for i in 0..m.len() {
+                       self.buffer[i] = m[i];
+               }
+               self.leftover = m.len();
+       }
+
+       pub fn raw_result(&mut self, output: &mut [u8]) {
+               assert!(output.len() >= 16);
+               if !self.finalized{
+                       self.finish();
+               }
+               output[0..4].copy_from_slice(&self.h[0].to_le_bytes());
+               output[4..8].copy_from_slice(&self.h[1].to_le_bytes());
+               output[8..12].copy_from_slice(&self.h[2].to_le_bytes());
+               output[12..16].copy_from_slice(&self.h[3].to_le_bytes());
+       }
+}
+
+#[cfg(test)]
+mod test {
+       use core::iter::repeat;
+       use alloc::vec::Vec;
+
+       use super::Poly1305;
+
+       fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) {
+               let mut poly = Poly1305::new(key);
+               poly.input(msg);
+               poly.raw_result(mac);
+       }
+
+       #[test]
+       fn test_nacl_vector() {
+               let key = [
+                       0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91,
+                       0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25,
+                       0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65,
+                       0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80,
+               ];
+
+               let msg = [
+                       0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
+                       0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
+                       0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
+                       0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
+                       0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
+                       0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
+                       0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
+                       0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
+                       0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
+                       0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
+                       0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
+                       0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
+                       0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
+                       0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
+                       0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
+                       0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
+                       0xe3,0x55,0xa5,
+               ];
+
+               let expected = [
+                       0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
+                       0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
+               ];
+
+               let mut mac = [0u8; 16];
+               poly1305(&key, &msg, &mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+
+               let mut poly = Poly1305::new(&key);
+               poly.input(&msg[0..32]);
+               poly.input(&msg[32..96]);
+               poly.input(&msg[96..112]);
+               poly.input(&msg[112..120]);
+               poly.input(&msg[120..124]);
+               poly.input(&msg[124..126]);
+               poly.input(&msg[126..127]);
+               poly.input(&msg[127..128]);
+               poly.input(&msg[128..129]);
+               poly.input(&msg[129..130]);
+               poly.input(&msg[130..131]);
+               poly.raw_result(&mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+       }
+
+       #[test]
+       fn donna_self_test() {
+               let wrap_key = [
+                       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               ];
+
+               let wrap_msg = [
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+               ];
+
+               let wrap_mac = [
+                       0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               ];
+
+               let mut mac = [0u8; 16];
+               poly1305(&wrap_key, &wrap_msg, &mut mac);
+               assert_eq!(&mac[..], &wrap_mac[..]);
+
+               let total_key = [
+                       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff,
+                       0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+               ];
+
+               let total_mac = [
+                       0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
+                       0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39,
+               ];
+
+               let mut tpoly = Poly1305::new(&total_key);
+               for i in 0..256 {
+                       let key: Vec<u8> = repeat(i as u8).take(32).collect();
+                       let msg: Vec<u8> = repeat(i as u8).take(256).collect();
+                       let mut mac = [0u8; 16];
+                       poly1305(&key[..], &msg[0..i], &mut mac);
+                       tpoly.input(&mac);
+               }
+               tpoly.raw_result(&mut mac);
+               assert_eq!(&mac[..], &total_mac[..]);
+       }
+
+       #[test]
+       fn test_tls_vectors() {
+               // from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
+               let key = b"this is 32-byte key for Poly1305";
+               let msg = [0u8; 32];
+               let expected = [
+                       0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6,
+                       0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
+               ];
+               let mut mac = [0u8; 16];
+               poly1305(key, &msg, &mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+
+               let msg = b"Hello world!";
+               let expected= [
+                       0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16,
+                       0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
+               ];
+               poly1305(key, msg, &mut mac);
+               assert_eq!(&mac[..], &expected[..]);
+       }
+}
diff --git a/lightning/src/crypto/streams.rs b/lightning/src/crypto/streams.rs
new file mode 100644 (file)
index 0000000..14921a3
--- /dev/null
@@ -0,0 +1,211 @@
+use crate::crypto::chacha20::ChaCha20;
+use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
+
+use crate::ln::msgs::DecodeError;
+use crate::util::ser::{FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer};
+use crate::io::{self, Read, Write};
+
+pub(crate) struct ChaChaReader<'a, R: io::Read> {
+       pub chacha: &'a mut ChaCha20,
+       pub read: R,
+}
+impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
+       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
+               let res = self.read.read(dest)?;
+               if res > 0 {
+                       self.chacha.process_in_place(&mut dest[0..res]);
+               }
+               Ok(res)
+       }
+}
+
+/// Enables the use of the serialization macros for objects that need to be simultaneously encrypted and
+/// serialized. This allows us to avoid an intermediate Vec allocation.
+pub(crate) struct ChaChaPolyWriteAdapter<'a, W: Writeable> {
+       pub rho: [u8; 32],
+       pub writeable: &'a W,
+}
+
+impl<'a, W: Writeable> ChaChaPolyWriteAdapter<'a, W> {
+       #[allow(unused)] // This will be used for onion messages soon
+       pub fn new(rho: [u8; 32], writeable: &'a W) -> ChaChaPolyWriteAdapter<'a, W> {
+               Self { rho, writeable }
+       }
+}
+
+impl<'a, T: Writeable> Writeable for ChaChaPolyWriteAdapter<'a, T> {
+       // Simultaneously write and encrypt Self::writeable.
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+               let mut chacha = ChaCha20Poly1305RFC::new(&self.rho, &[0; 12], &[]);
+               let mut chacha_stream = ChaChaPolyWriter { chacha: &mut chacha, write: w };
+               self.writeable.write(&mut chacha_stream)?;
+               let mut tag = [0 as u8; 16];
+               chacha.finish_and_get_tag(&mut tag);
+               tag.write(w)?;
+
+               Ok(())
+       }
+}
+
+/// Enables the use of the serialization macros for objects that need to be simultaneously decrypted and
+/// deserialized. This allows us to avoid an intermediate Vec allocation.
+pub(crate) struct ChaChaPolyReadAdapter<R: Readable> {
+       pub readable: R,
+}
+
+impl<T: Readable> LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter<T> {
+       // Simultaneously read and decrypt an object from a LengthRead, storing it in Self::readable.
+       // LengthRead must be used instead of std::io::Read because we need the total length to separate
+       // out the tag at the end.
+       fn read<R: LengthRead>(mut r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
+               if r.total_bytes() < 16 { return Err(DecodeError::InvalidValue) }
+
+               let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]);
+               let decrypted_len = r.total_bytes() - 16;
+               let s = FixedLengthReader::new(&mut r, decrypted_len);
+               let mut chacha_stream = ChaChaPolyReader { chacha: &mut chacha, read: s };
+               let readable: T = Readable::read(&mut chacha_stream)?;
+               chacha_stream.read.eat_remaining()?;
+
+               let mut tag = [0 as u8; 16];
+               r.read_exact(&mut tag)?;
+               if !chacha.finish_and_check_tag(&tag) {
+                       return Err(DecodeError::InvalidValue)
+               }
+
+               Ok(Self { readable })
+       }
+}
+
+
+/// Enables simultaneously reading and decrypting a ChaCha20Poly1305RFC stream from a std::io::Read.
+struct ChaChaPolyReader<'a, R: Read> {
+       pub chacha: &'a mut ChaCha20Poly1305RFC,
+       pub read: R,
+}
+
+impl<'a, R: Read> Read for ChaChaPolyReader<'a, R> {
+       // Decrypt bytes from Self::read into `dest`.
+       // `ChaCha20Poly1305RFC::finish_and_check_tag` must be called to check the tag after all reads
+       // complete.
+       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
+               let res = self.read.read(dest)?;
+               if res > 0 {
+                       self.chacha.decrypt_in_place(&mut dest[0..res]);
+               }
+               Ok(res)
+       }
+}
+
+/// Enables simultaneously writing and encrypting a byte stream into a Writer.
+struct ChaChaPolyWriter<'a, W: Writer> {
+       pub chacha: &'a mut ChaCha20Poly1305RFC,
+       pub write: &'a mut W,
+}
+
+impl<'a, W: Writer> Writer for ChaChaPolyWriter<'a, W> {
+       // Encrypt then write bytes from `src` into Self::write.
+       // `ChaCha20Poly1305RFC::finish_and_get_tag` can be called to retrieve the tag after all writes
+       // complete.
+       fn write_all(&mut self, src: &[u8]) -> Result<(), io::Error> {
+               let mut src_idx = 0;
+               while src_idx < src.len() {
+                       let mut write_buffer = [0; 8192];
+                       let bytes_written = (&mut write_buffer[..]).write(&src[src_idx..]).expect("In-memory writes can't fail");
+                       self.chacha.encrypt_in_place(&mut write_buffer[..bytes_written]);
+                       self.write.write_all(&write_buffer[..bytes_written])?;
+                       src_idx += bytes_written;
+               }
+               Ok(())
+       }
+}
+
+
+#[cfg(test)]
+mod tests {
+       use crate::ln::msgs::DecodeError;
+       use super::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
+       use crate::util::ser::{self, FixedLengthReader, LengthReadableArgs, Writeable};
+
+       // Used for for testing various lengths of serialization.
+       #[derive(Debug, PartialEq, Eq)]
+       struct TestWriteable {
+               field1: Vec<u8>,
+               field2: Vec<u8>,
+               field3: Vec<u8>,
+       }
+       impl_writeable_tlv_based!(TestWriteable, {
+               (1, field1, required_vec),
+               (2, field2, required_vec),
+               (3, field3, required_vec),
+       });
+
+       #[test]
+       fn test_chacha_stream_adapters() {
+               // Check that ChaChaPolyReadAdapter and ChaChaPolyWriteAdapter correctly encode and decode an
+               // encrypted object.
+               macro_rules! check_object_read_write {
+                       ($obj: expr) => {
+                               // First, serialize the object, encrypted with ChaCha20Poly1305.
+                               let rho = [42; 32];
+                               let writeable_len = $obj.serialized_length() as u64 + 16;
+                               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &$obj);
+                               let encrypted_writeable_bytes = write_adapter.encode();
+                               let encrypted_writeable = &encrypted_writeable_bytes[..];
+
+                               // Now deserialize the object back and make sure it matches the original.
+                               let mut rd = FixedLengthReader::new(encrypted_writeable, writeable_len);
+                               let read_adapter = <ChaChaPolyReadAdapter<TestWriteable>>::read(&mut rd, rho).unwrap();
+                               assert_eq!($obj, read_adapter.readable);
+                       };
+               }
+
+               // Try a big object that will require multiple write buffers.
+               let big_writeable = TestWriteable {
+                       field1: vec![43],
+                       field2: vec![44; 4192],
+                       field3: vec![45; 4192 + 1],
+               };
+               check_object_read_write!(big_writeable);
+
+               // Try a small object that fits into one write buffer.
+               let small_writeable = TestWriteable {
+                       field1: vec![43],
+                       field2: vec![44],
+                       field3: vec![45],
+               };
+               check_object_read_write!(small_writeable);
+       }
+
+       fn do_chacha_stream_adapters_ser_macros() -> Result<(), DecodeError> {
+               let writeable = TestWriteable {
+                       field1: vec![43],
+                       field2: vec![44; 4192],
+                       field3: vec![45; 4192 + 1],
+               };
+
+               // First, serialize the object into a TLV stream, encrypted with ChaCha20Poly1305.
+               let rho = [42; 32];
+               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &writeable);
+               let mut writer = ser::VecWriter(Vec::new());
+               encode_tlv_stream!(&mut writer, {
+                       (1, write_adapter, required),
+               });
+
+               // Now deserialize the object back and make sure it matches the original.
+               let mut read_adapter: Option<ChaChaPolyReadAdapter<TestWriteable>> = None;
+               decode_tlv_stream!(&writer.0[..], {
+                       (1, read_adapter, (option: LengthReadableArgs, rho)),
+               });
+               assert_eq!(writeable, read_adapter.unwrap().readable);
+
+               Ok(())
+       }
+
+       #[test]
+       fn chacha_stream_adapters_ser_macros() {
+               // Test that our stream adapters work as expected with the TLV macros.
+               // This also serves to test the `option: $trait` variant of the `_decode_tlv` ser macro.
+               do_chacha_stream_adapters_ser_macros().unwrap()
+       }
+}
diff --git a/lightning/src/crypto/utils.rs b/lightning/src/crypto/utils.rs
new file mode 100644 (file)
index 0000000..98963c7
--- /dev/null
@@ -0,0 +1,83 @@
+use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::hmac::{Hmac, HmacEngine};
+use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing};
+
+use crate::sign::EntropySource;
+
+use core::ops::Deref;
+
+macro_rules! hkdf_extract_expand {
+       ($salt: expr, $ikm: expr) => {{
+               let mut hmac = HmacEngine::<Sha256>::new($salt);
+               hmac.input($ikm);
+               let prk = Hmac::from_engine(hmac).to_byte_array();
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&[1; 1]);
+               let t1 = Hmac::from_engine(hmac).to_byte_array();
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&t1);
+               hmac.input(&[2; 1]);
+               (t1, Hmac::from_engine(hmac).to_byte_array(), prk)
+       }};
+       ($salt: expr, $ikm: expr, 2) => {{
+               let (k1, k2, _) = hkdf_extract_expand!($salt, $ikm);
+               (k1, k2)
+       }};
+       ($salt: expr, $ikm: expr, 5) => {{
+               let (k1, k2, prk) = hkdf_extract_expand!($salt, $ikm);
+
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&k2);
+               hmac.input(&[3; 1]);
+               let k3 = Hmac::from_engine(hmac).to_byte_array();
+
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&k3);
+               hmac.input(&[4; 1]);
+               let k4 = Hmac::from_engine(hmac).to_byte_array();
+
+               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
+               hmac.input(&k4);
+               hmac.input(&[5; 1]);
+               let k5 = Hmac::from_engine(hmac).to_byte_array();
+
+               (k1, k2, k3, k4, k5)
+       }}
+}
+
+pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
+       hkdf_extract_expand!(salt, ikm, 2)
+}
+
+pub fn hkdf_extract_expand_5x(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
+       hkdf_extract_expand!(salt, ikm, 5)
+}
+
+#[inline]
+pub fn sign<C: Signing>(ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey) -> Signature {
+       #[cfg(feature = "grind_signatures")]
+       let sig = ctx.sign_ecdsa_low_r(msg, sk);
+       #[cfg(not(feature = "grind_signatures"))]
+       let sig = ctx.sign_ecdsa(msg, sk);
+       sig
+}
+
+#[inline]
+#[allow(unused_variables)]
+pub fn sign_with_aux_rand<C: Signing, ES: Deref>(
+       ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey, entropy_source: &ES
+) -> Signature where ES::Target: EntropySource {
+       #[cfg(feature = "grind_signatures")]
+       let sig = loop {
+               let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
+               if sig.serialize_compact()[0] < 0x80 {
+                       break sig;
+               }
+       };
+       #[cfg(all(not(feature = "grind_signatures"), not(feature = "_test_vectors")))]
+       let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
+       #[cfg(all(not(feature = "grind_signatures"), feature = "_test_vectors"))]
+       let sig = sign(ctx, msg, sk);
+       sig
+}
index 76e5f25c0e5f6eef87b2ff48102dd19acc239231..77f6937c54558aae85d10a3c1c8cc9c05bc5d424 100644 (file)
@@ -24,6 +24,7 @@ use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS;
 use crate::ln::features::ChannelTypeFeatures;
 use crate::ln::msgs;
 use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
+use crate::chain::transaction;
 use crate::routing::gossip::NetworkUpdate;
 use crate::util::errors::APIError;
 use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, WithoutLength};
@@ -540,8 +541,8 @@ pub enum Event {
        /// replies. Handlers should connect to the node otherwise any buffered messages may be lost.
        ///
        /// [`OnionMessage`]: msgs::OnionMessage
-       /// [`MessageRouter`]: crate::onion_message::MessageRouter
-       /// [`Destination`]: crate::onion_message::Destination
+       /// [`MessageRouter`]: crate::onion_message::messenger::MessageRouter
+       /// [`Destination`]: crate::onion_message::messenger::Destination
        /// [`OnionMessageHandler`]: crate::ln::msgs::OnionMessageHandler
        ConnectionNeeded {
                /// The node id for the node needing a connection.
@@ -861,7 +862,7 @@ pub enum Event {
        ///
        /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel
        /// [`UserConfig::manually_accept_inbound_channels`]: crate::util::config::UserConfig::manually_accept_inbound_channels
-       ChannelClosed  {
+       ChannelClosed {
                /// The `channel_id` of the channel which has been closed. Note that on-chain transactions
                /// resolving the channel are likely still awaiting confirmation.
                channel_id: ChannelId,
@@ -886,6 +887,10 @@ pub enum Event {
                ///
                /// This field will be `None` for objects serialized prior to LDK 0.0.117.
                channel_capacity_sats: Option<u64>,
+               /// The original channel funding TXO; this helps checking for the existence and confirmation
+               /// status of the closing tx.
+               /// Note that for instances serialized in v0.0.119 or prior this will be missing (None).
+               channel_funding_txo: Option<transaction::OutPoint>,
        },
        /// Used to indicate to the user that they can abandon the funding transaction and recycle the
        /// inputs for another purpose.
@@ -1091,7 +1096,7 @@ impl Writeable for Event {
                                });
                        },
                        &Event::ChannelClosed { ref channel_id, ref user_channel_id, ref reason,
-                               ref counterparty_node_id, ref channel_capacity_sats
+                               ref counterparty_node_id, ref channel_capacity_sats, ref channel_funding_txo
                        } => {
                                9u8.write(writer)?;
                                // `user_channel_id` used to be a single u64 value. In order to remain backwards
@@ -1106,6 +1111,7 @@ impl Writeable for Event {
                                        (3, user_channel_id_high, required),
                                        (5, counterparty_node_id, option),
                                        (7, channel_capacity_sats, option),
+                                       (9, channel_funding_txo, option),
                                });
                        },
                        &Event::DiscardFunding { ref channel_id, ref transaction } => {
@@ -1405,6 +1411,7 @@ impl MaybeReadable for Event {
                                        let mut user_channel_id_high_opt: Option<u64> = None;
                                        let mut counterparty_node_id = None;
                                        let mut channel_capacity_sats = None;
+                                       let mut channel_funding_txo = None;
                                        read_tlv_fields!(reader, {
                                                (0, channel_id, required),
                                                (1, user_channel_id_low_opt, option),
@@ -1412,6 +1419,7 @@ impl MaybeReadable for Event {
                                                (3, user_channel_id_high_opt, option),
                                                (5, counterparty_node_id, option),
                                                (7, channel_capacity_sats, option),
+                                               (9, channel_funding_txo, option),
                                        });
 
                                        // `user_channel_id` used to be a single u64 value. In order to remain
@@ -1421,7 +1429,7 @@ impl MaybeReadable for Event {
                                                ((user_channel_id_high_opt.unwrap_or(0) as u128) << 64);
 
                                        Ok(Some(Event::ChannelClosed { channel_id, user_channel_id, reason: _init_tlv_based_struct_field!(reason, upgradable_required),
-                                               counterparty_node_id, channel_capacity_sats }))
+                                               counterparty_node_id, channel_capacity_sats, channel_funding_txo }))
                                };
                                f()
                        },
index 6eefb3983cca95f1bb0351a43bfddf39d2be58db..160f632415b472238b18f728e43c990fdf002f45 100644 (file)
@@ -84,6 +84,8 @@ pub mod onion_message;
 pub mod blinded_path;
 pub mod events;
 
+pub(crate) mod crypto;
+
 #[cfg(feature = "std")]
 /// Re-export of either `core2::io` or `std::io`, depending on the `std` feature flag.
 pub use std::io;
index 69b0e74a02c6a0f60c72c5efe82451c79cdbd93e..3232cd0d33e2381a44dc0afa98ea87dd1be39086 100644 (file)
@@ -498,6 +498,29 @@ fn two_hop_blinded_path_success() {
        claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage);
 }
 
+#[test]
+fn three_hop_blinded_path_success() {
+       let chanmon_cfgs = create_chanmon_cfgs(5);
+       let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, None]);
+       let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs);
+       create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
+       create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 1_000_000, 0);
+       let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents;
+       let chan_upd_3_4 = create_announced_chan_between_nodes_with_value(&nodes, 3, 4, 1_000_000, 0).0.contents;
+
+       let amt_msat = 5000;
+       let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[4], Some(amt_msat), None);
+       let route_params = get_blinded_route_parameters(amt_msat, payment_secret,
+               nodes.iter().skip(2).map(|n| n.node.get_our_node_id()).collect(),
+               &[&chan_upd_2_3, &chan_upd_3_4], &chanmon_cfgs[4].keys_manager);
+
+       nodes[0].node.send_payment(payment_hash, RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
+       check_added_monitors(&nodes[0], 1);
+       pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2], &nodes[3], &nodes[4]]], amt_msat, payment_hash, payment_secret);
+       claim_payment(&nodes[0], &[&nodes[1], &nodes[2], &nodes[3], &nodes[4]], payment_preimage);
+}
+
 #[derive(PartialEq)]
 enum ReceiveCheckFail {
        // The recipient fails the payment upon `PaymentClaimable`.
@@ -545,11 +568,11 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
        };
 
        let amt_msat = 5000;
-       let final_cltv_delta = if check == ReceiveCheckFail::ProcessPendingHTLCsCheck {
+       let excess_final_cltv_delta_opt = if check == ReceiveCheckFail::ProcessPendingHTLCsCheck {
                // Set the final CLTV expiry too low to trigger the failure in process_pending_htlc_forwards.
                Some(TEST_FINAL_CLTV as u16 - 2)
        } else { None };
-       let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), final_cltv_delta);
+       let (_, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[2], Some(amt_msat), excess_final_cltv_delta_opt);
        let mut route_params = get_blinded_route_parameters(amt_msat, payment_secret,
                nodes.iter().skip(1).map(|n| n.node.get_our_node_id()).collect(), &[&chan_upd_1_2],
                &chanmon_cfgs[2].keys_manager);
@@ -557,7 +580,8 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
        let route = if check == ReceiveCheckFail::ProcessPendingHTLCsCheck {
                let mut route = get_route(&nodes[0], &route_params).unwrap();
                // Set the final CLTV expiry too low to trigger the failure in process_pending_htlc_forwards.
-               route.paths[0].blinded_tail.as_mut().map(|bt| bt.excess_final_cltv_expiry_delta = TEST_FINAL_CLTV - 2);
+               route.paths[0].hops.last_mut().map(|h| h.cltv_expiry_delta += excess_final_cltv_delta_opt.unwrap() as u32);
+               route.paths[0].blinded_tail.as_mut().map(|bt| bt.excess_final_cltv_expiry_delta = excess_final_cltv_delta_opt.unwrap() as u32);
                route
        } else if check == ReceiveCheckFail::PaymentConstraints {
                // Create a blinded path where the receiver's encrypted payload has an htlc_minimum_msat that is
@@ -665,6 +689,7 @@ fn do_multi_hop_receiver_fail(check: ReceiveCheckFail) {
                        commitment_signed_dance!(nodes[2], nodes[1], (), false, true, false, false);
                },
                ReceiveCheckFail::ProcessPendingHTLCsCheck => {
+                       assert_eq!(payment_event_1_2.msgs[0].cltv_expiry, nodes[0].best_block_info().1 + 1 + excess_final_cltv_delta_opt.unwrap() as u32);
                        nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event_1_2.msgs[0]);
                        check_added_monitors!(nodes[2], 0);
                        do_commitment_signed_dance(&nodes[2], &nodes[1], &payment_event_1_2.commitment_msg, true, true);
index 672e3aa862e460e94f26451ebff4ff39293eb4e9..18c4d83406c1bdbcdb673b0461062de62f400b0a 100644 (file)
@@ -45,7 +45,7 @@ use crate::ln::channel::{INITIAL_COMMITMENT_NUMBER, ANCHOR_OUTPUT_VALUE_SATOSHI}
 use core::ops::Deref;
 use crate::chain;
 use crate::ln::features::ChannelTypeFeatures;
-use crate::util::crypto::{sign, sign_with_aux_rand};
+use crate::crypto::utils::{sign, sign_with_aux_rand};
 use super::channel_keys::{DelayedPaymentBasepoint, DelayedPaymentKey, HtlcKey, HtlcBasepoint, RevocationKey, RevocationBasepoint};
 
 /// Maximum number of one-way in-flight HTLC (protocol-level value).
index 1dfc6dc552fea205a01b27ee573c2de4315e803e..ec4f26664a76b053bf7313695e686bdfe7b37c22 100644 (file)
@@ -814,6 +814,7 @@ pub(super) struct ReestablishResponses {
 /// The result of a shutdown that should be handled.
 #[must_use]
 pub(crate) struct ShutdownResult {
+       pub(crate) closure_reason: ClosureReason,
        /// A channel monitor update to apply.
        pub(crate) monitor_update: Option<(PublicKey, OutPoint, ChannelMonitorUpdate)>,
        /// A list of dropped outbound HTLCs that can safely be failed backwards immediately.
@@ -822,7 +823,11 @@ pub(crate) struct ShutdownResult {
        /// propagated to the remainder of the batch.
        pub(crate) unbroadcasted_batch_funding_txid: Option<Txid>,
        pub(crate) channel_id: ChannelId,
+       pub(crate) user_channel_id: u128,
+       pub(crate) channel_capacity_satoshis: u64,
        pub(crate) counterparty_node_id: PublicKey,
+       pub(crate) unbroadcasted_funding_tx: Option<Transaction>,
+       pub(crate) channel_funding_txo: Option<OutPoint>,
 }
 
 /// If the majority of the channels funds are to the fundee and the initiator holds only just
@@ -1833,8 +1838,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
        /// will sign and send to our counterparty.
        /// If an Err is returned, it is a ChannelError::Close (for get_funding_created)
        fn build_remote_transaction_keys(&self) -> TxCreationKeys {
-               //TODO: Ensure that the payment_key derived here ends up in the library users' wallet as we
-               //may see payments to it!
                let revocation_basepoint = &self.get_holder_pubkeys().revocation_basepoint;
                let htlc_basepoint = &self.get_holder_pubkeys().htlc_basepoint;
                let counterparty_pubkeys = self.get_counterparty_pubkeys();
@@ -2313,15 +2316,17 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                res
        }
 
-       fn if_unbroadcasted_funding<F, O>(&self, f: F) -> Option<O>
-               where F: Fn() -> Option<O> {
+       fn if_unbroadcasted_funding<F, O>(&self, f: F) -> Option<O> where F: Fn() -> Option<O> {
                match self.channel_state {
                        ChannelState::FundingNegotiated => f(),
-                       ChannelState::AwaitingChannelReady(flags) => if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) {
-                               f()
-                       } else {
-                               None
-                       },
+                       ChannelState::AwaitingChannelReady(flags) =>
+                               if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH) ||
+                                       flags.is_set(FundedStateFlags::MONITOR_UPDATE_IN_PROGRESS.into())
+                               {
+                                       f()
+                               } else {
+                                       None
+                               },
                        _ => None,
                }
        }
@@ -2356,7 +2361,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
        /// those explicitly stated to be allowed after shutdown completes, eg some simple getters).
        /// Also returns the list of payment_hashes for channels which we can safely fail backwards
        /// immediately (others we will have to allow to time out).
-       pub fn force_shutdown(&mut self, should_broadcast: bool) -> ShutdownResult {
+       pub fn force_shutdown(&mut self, should_broadcast: bool, closure_reason: ClosureReason) -> ShutdownResult {
                // Note that we MUST only generate a monitor update that indicates force-closure - we're
                // called during initialization prior to the chain_monitor in the encompassing ChannelManager
                // being fully configured in some cases. Thus, its likely any monitor events we generate will
@@ -2397,15 +2402,21 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider  {
                        } else { None }
                } else { None };
                let unbroadcasted_batch_funding_txid = self.unbroadcasted_batch_funding_txid();
+               let unbroadcasted_funding_tx = self.unbroadcasted_funding();
 
                self.channel_state = ChannelState::ShutdownComplete;
                self.update_time_counter += 1;
                ShutdownResult {
+                       closure_reason,
                        monitor_update,
                        dropped_outbound_htlcs,
                        unbroadcasted_batch_funding_txid,
                        channel_id: self.channel_id,
+                       user_channel_id: self.user_id,
+                       channel_capacity_satoshis: self.channel_value_satoshis,
                        counterparty_node_id: self.counterparty_node_id,
+                       unbroadcasted_funding_tx,
+                       channel_funding_txo: self.get_funding_txo(),
                }
        }
 
@@ -2546,26 +2557,24 @@ impl FailHTLCContents for msgs::OnionErrorPacket {
                HTLCUpdateAwaitingACK::FailHTLC { htlc_id, err_packet: self }
        }
 }
-impl FailHTLCContents for (u16, [u8; 32]) {
-       type Message = msgs::UpdateFailMalformedHTLC; // (failure_code, sha256_of_onion)
+impl FailHTLCContents for ([u8; 32], u16) {
+       type Message = msgs::UpdateFailMalformedHTLC;
        fn to_message(self, htlc_id: u64, channel_id: ChannelId) -> Self::Message {
                msgs::UpdateFailMalformedHTLC {
                        htlc_id,
                        channel_id,
-                       failure_code: self.0,
-                       sha256_of_onion: self.1
+                       sha256_of_onion: self.0,
+                       failure_code: self.1
                }
        }
        fn to_inbound_htlc_state(self) -> InboundHTLCState {
-               InboundHTLCState::LocalRemoved(
-                       InboundHTLCRemovalReason::FailMalformed((self.1, self.0))
-               )
+               InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailMalformed(self))
        }
        fn to_htlc_update_awaiting_ack(self, htlc_id: u64) -> HTLCUpdateAwaitingACK {
                HTLCUpdateAwaitingACK::FailMalformedHTLC {
                        htlc_id,
-                       failure_code: self.0,
-                       sha256_of_onion: self.1
+                       sha256_of_onion: self.0,
+                       failure_code: self.1
                }
        }
 }
@@ -2892,7 +2901,7 @@ impl<SP: Deref> Channel<SP> where
        pub fn queue_fail_malformed_htlc<L: Deref>(
                &mut self, htlc_id_arg: u64, failure_code: u16, sha256_of_onion: [u8; 32], logger: &L
        ) -> Result<(), ChannelError> where L::Target: Logger {
-               self.fail_htlc(htlc_id_arg, (failure_code, sha256_of_onion), true, logger)
+               self.fail_htlc(htlc_id_arg, (sha256_of_onion, failure_code), true, logger)
                        .map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
        }
 
@@ -2905,7 +2914,7 @@ impl<SP: Deref> Channel<SP> where
        /// return `Ok(_)` if preconditions are met. In any case, `Err`s will only be
        /// [`ChannelError::Ignore`].
        fn fail_htlc<L: Deref, E: FailHTLCContents + Clone>(
-               &mut self, htlc_id_arg: u64, err_packet: E, mut force_holding_cell: bool,
+               &mut self, htlc_id_arg: u64, err_contents: E, mut force_holding_cell: bool,
                logger: &L
        ) -> Result<Option<E::Message>, ChannelError> where L::Target: Logger {
                if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
@@ -2972,7 +2981,7 @@ impl<SP: Deref> Channel<SP> where
                                }
                        }
                        log_trace!(logger, "Placing failure for HTLC ID {} in holding cell in channel {}.", htlc_id_arg, &self.context.channel_id());
-                       self.context.holding_cell_htlc_updates.push(err_packet.to_htlc_update_awaiting_ack(htlc_id_arg));
+                       self.context.holding_cell_htlc_updates.push(err_contents.to_htlc_update_awaiting_ack(htlc_id_arg));
                        return Ok(None);
                }
 
@@ -2980,10 +2989,10 @@ impl<SP: Deref> Channel<SP> where
                        E::Message::name(), &self.context.channel_id());
                {
                        let htlc = &mut self.context.pending_inbound_htlcs[pending_idx];
-                       htlc.state = err_packet.clone().to_inbound_htlc_state();
+                       htlc.state = err_contents.clone().to_inbound_htlc_state();
                }
 
-               Ok(Some(err_packet.to_message(htlc_id_arg, self.context.channel_id())))
+               Ok(Some(err_contents.to_message(htlc_id_arg, self.context.channel_id())))
        }
 
        // Message handlers:
@@ -3596,7 +3605,7 @@ impl<SP: Deref> Channel<SP> where
                                // the limit. In case it's less rare than I anticipate, we may want to revisit
                                // handling this case better and maybe fulfilling some of the HTLCs while attempting
                                // to rebalance channels.
-                               match &htlc_update {
+                               let fail_htlc_res = match &htlc_update {
                                        &HTLCUpdateAwaitingACK::AddHTLC {
                                                amount_msat, cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet,
                                                skimmed_fee_msat, blinding_point, ..
@@ -3624,6 +3633,7 @@ impl<SP: Deref> Channel<SP> where
                                                                }
                                                        }
                                                }
+                                               None
                                        },
                                        &HTLCUpdateAwaitingACK::ClaimHTLC { ref payment_preimage, htlc_id, .. } => {
                                                // If an HTLC claim was previously added to the holding cell (via
@@ -3637,40 +3647,33 @@ impl<SP: Deref> Channel<SP> where
                                                        { monitor_update } else { unreachable!() };
                                                update_fulfill_count += 1;
                                                monitor_update.updates.append(&mut additional_monitor_update.updates);
+                                               None
                                        },
                                        &HTLCUpdateAwaitingACK::FailHTLC { htlc_id, ref err_packet } => {
-                                               match self.fail_htlc(htlc_id, err_packet.clone(), false, logger) {
-                                                       Ok(update_fail_msg_option) => {
-                                                               // If an HTLC failure was previously added to the holding cell (via
-                                                               // `queue_fail_htlc`) then generating the fail message itself must
-                                                               // not fail - we should never end up in a state where we double-fail
-                                                               // an HTLC or fail-then-claim an HTLC as it indicates we didn't wait
-                                                               // for a full revocation before failing.
-                                                               debug_assert!(update_fail_msg_option.is_some());
-                                                               update_fail_count += 1;
-                                                       },
-                                                       Err(e) => {
-                                                               if let ChannelError::Ignore(_) = e {}
-                                                               else {
-                                                                       panic!("Got a non-IgnoreError action trying to fail holding cell HTLC");
-                                                               }
-                                                       }
-                                               }
+                                               Some(self.fail_htlc(htlc_id, err_packet.clone(), false, logger)
+                                                .map(|fail_msg_opt| fail_msg_opt.map(|_| ())))
                                        },
                                        &HTLCUpdateAwaitingACK::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => {
-                                               match self.fail_htlc(htlc_id, (failure_code, sha256_of_onion), false, logger) {
-                                                       Ok(update_fail_malformed_opt) => {
-                                                               debug_assert!(update_fail_malformed_opt.is_some()); // See above comment
-                                                               update_fail_count += 1;
-                                                       },
-                                                       Err(e) => {
-                                                               if let ChannelError::Ignore(_) = e {}
-                                                               else {
-                                                                       panic!("Got a non-IgnoreError action trying to fail holding cell HTLC");
-                                                               }
-                                                       }
-                                               }
-                                       },
+                                               Some(self.fail_htlc(htlc_id, (sha256_of_onion, failure_code), false, logger)
+                                                .map(|fail_msg_opt| fail_msg_opt.map(|_| ())))
+                                       }
+                               };
+                               if let Some(res) = fail_htlc_res {
+                                       match res {
+                                               Ok(fail_msg_opt) => {
+                                                       // If an HTLC failure was previously added to the holding cell (via
+                                                       // `queue_fail_{malformed_}htlc`) then generating the fail message itself must
+                                                       // not fail - we should never end up in a state where we double-fail
+                                                       // an HTLC or fail-then-claim an HTLC as it indicates we didn't wait
+                                                       // for a full revocation before failing.
+                                                       debug_assert!(fail_msg_opt.is_some());
+                                                       update_fail_count += 1;
+                                               },
+                                               Err(ChannelError::Ignore(_)) => {},
+                                               Err(_) => {
+                                                       panic!("Got a non-IgnoreError action trying to fail holding cell HTLC");
+                                               },
+                                       }
                                }
                        }
                        if update_add_count == 0 && update_fulfill_count == 0 && update_fail_count == 0 && self.context.holding_cell_update_fee.is_none() {
@@ -4933,11 +4936,16 @@ impl<SP: Deref> Channel<SP> where
                if let Some((last_fee, sig)) = self.context.last_sent_closing_fee {
                        if last_fee == msg.fee_satoshis {
                                let shutdown_result = ShutdownResult {
+                                       closure_reason: ClosureReason::CooperativeClosure,
                                        monitor_update: None,
                                        dropped_outbound_htlcs: Vec::new(),
                                        unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(),
                                        channel_id: self.context.channel_id,
+                                       user_channel_id: self.context.user_id,
+                                       channel_capacity_satoshis: self.context.channel_value_satoshis,
                                        counterparty_node_id: self.context.counterparty_node_id,
+                                       unbroadcasted_funding_tx: self.context.unbroadcasted_funding(),
+                                       channel_funding_txo: self.context.get_funding_txo(),
                                };
                                let tx = self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &sig);
                                self.context.channel_state = ChannelState::ShutdownComplete;
@@ -4963,11 +4971,16 @@ impl<SP: Deref> Channel<SP> where
                                                        .map_err(|_| ChannelError::Close("External signer refused to sign closing transaction".to_owned()))?;
                                                let (signed_tx, shutdown_result) = if $new_fee == msg.fee_satoshis {
                                                        let shutdown_result = ShutdownResult {
+                                                               closure_reason: ClosureReason::CooperativeClosure,
                                                                monitor_update: None,
                                                                dropped_outbound_htlcs: Vec::new(),
                                                                unbroadcasted_batch_funding_txid: self.context.unbroadcasted_batch_funding_txid(),
                                                                channel_id: self.context.channel_id,
+                                                               user_channel_id: self.context.user_id,
+                                                               channel_capacity_satoshis: self.context.channel_value_satoshis,
                                                                counterparty_node_id: self.context.counterparty_node_id,
+                                                               unbroadcasted_funding_tx: self.context.unbroadcasted_funding(),
+                                                               channel_funding_txo: self.context.get_funding_txo(),
                                                        };
                                                        self.context.channel_state = ChannelState::ShutdownComplete;
                                                        self.context.update_time_counter += 1;
index f737dd23407727786d669b5ca1cbc50776cc1251..b577dc60008583537c4d9c1cebc8b2f6e5f48e77 100644 (file)
@@ -25,126 +25,125 @@ use bitcoin::secp256k1::PublicKey;
 use bitcoin::hashes::sha256::Hash as Sha256;
 
 macro_rules! doc_comment {
-    ($x:expr, $($tt:tt)*) => {
-        #[doc = $x]
-        $($tt)*
-    };
+       ($x:expr, $($tt:tt)*) => {
+               #[doc = $x]
+               $($tt)*
+       };
 }
 macro_rules! basepoint_impl {
-    ($BasepointT:ty) => {
-        impl $BasepointT {
-            /// Get inner Public Key
-            pub fn to_public_key(&self) -> PublicKey {
-                self.0
-            }
-        }
-        
-        impl From<PublicKey> for $BasepointT {
-            fn from(value: PublicKey) -> Self {
-                Self(value)
-            }
-        }
-        
-    }
+       ($BasepointT:ty) => {
+               impl $BasepointT {
+                       /// Get inner Public Key
+                       pub fn to_public_key(&self) -> PublicKey {
+                               self.0
+                       }
+               }
+
+               impl From<PublicKey> for $BasepointT {
+                       fn from(value: PublicKey) -> Self {
+                               Self(value)
+                       }
+               }
+
+       }
 }
 macro_rules! key_impl {
-    ($BasepointT:ty, $KeyName:expr) => {
-        doc_comment! {
-            concat!("Generate ", $KeyName, " using per_commitment_point"),
-            pub fn from_basepoint<T: secp256k1::Signing>(
-                secp_ctx: &Secp256k1<T>,
-                basepoint: &$BasepointT,
-                per_commitment_point: &PublicKey,
-            ) -> Self {
-                Self(derive_public_key(secp_ctx, per_commitment_point, &basepoint.0))
-            }
-        }
-        
-        doc_comment! {
-            concat!("Generate ", $KeyName, " from privkey"),
-            pub fn from_secret_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, sk: &SecretKey) -> Self {
-                Self(PublicKey::from_secret_key(&secp_ctx, &sk))
-            }
-        }
-        
-        /// Get inner Public Key
-        pub fn to_public_key(&self) -> PublicKey {
-            self.0
-        }
-    }
+       ($BasepointT:ty, $KeyName:expr) => {
+               doc_comment! {
+                       concat!("Derive a public ", $KeyName, " using one node's `per_commitment_point` and its countersignatory's `basepoint`"),
+                       pub fn from_basepoint<T: secp256k1::Signing>(
+                               secp_ctx: &Secp256k1<T>,
+                               countersignatory_basepoint: &$BasepointT,
+                               per_commitment_point: &PublicKey,
+                       ) -> Self {
+                               Self(derive_public_key(secp_ctx, per_commitment_point, &countersignatory_basepoint.0))
+                       }
+               }
+
+               doc_comment! {
+                       concat!("Build a ", $KeyName, " directly from an already-derived private key"),
+                       pub fn from_secret_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, sk: &SecretKey) -> Self {
+                               Self(PublicKey::from_secret_key(&secp_ctx, &sk))
+                       }
+               }
+
+               /// Get inner Public Key
+               pub fn to_public_key(&self) -> PublicKey {
+                       self.0
+               }
+       }
 }
 macro_rules! key_read_write {
-    ($SelfT:ty) => {
-        impl Writeable for $SelfT {
-            fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
-                self.0.serialize().write(w)
-            }
-        }
-        
-        impl Readable for $SelfT {
-            fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
-                let key: PublicKey = Readable::read(r)?;
-                Ok(Self(key))
-            }
-        }
-    }
+       ($SelfT:ty) => {
+               impl Writeable for $SelfT {
+                       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+                               self.0.serialize().write(w)
+                       }
+               }
+
+               impl Readable for $SelfT {
+                       fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+                               let key: PublicKey = Readable::read(r)?;
+                               Ok(Self(key))
+                       }
+               }
+       }
 }
 
 
 
-/// Master key used in conjunction with per_commitment_point to generate [`local_delayedpubkey`](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
-/// A watcher can be given a [DelayedPaymentBasepoint] to generate per commitment [DelayedPaymentKey] to create justice transactions.
+/// Base key used in conjunction with a `per_commitment_point` to generate a [`DelayedPaymentKey`].
+///
+/// The delayed payment key is used to pay the commitment state broadcaster their
+/// non-HTLC-encumbered funds after a delay to give their counterparty a chance to punish if the
+/// state broadcasted was previously revoked.
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub struct DelayedPaymentBasepoint(pub PublicKey);
 basepoint_impl!(DelayedPaymentBasepoint);
 key_read_write!(DelayedPaymentBasepoint);
 
-/// [delayedpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
-/// To allow a counterparty to contest a channel state published by a node, Lightning protocol sets delays for some of the outputs, before can be spend.
-/// For example a commitment transaction has to_local output encumbered by a delay, negotiated at the channel establishment flow.
-/// To spend from such output a node has to generate a script using, among others, a local delayed payment key.
+
+/// A derived key built from a [`DelayedPaymentBasepoint`] and `per_commitment_point`.
+///
+/// The delayed payment key is used to pay the commitment state broadcaster their
+/// non-HTLC-encumbered funds after a delay. This delay gives their counterparty a chance to
+/// punish and claim all the channel funds if the state broadcasted was previously revoked.
+///
+/// [See the BOLT specs]
+/// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
+/// for more information on key derivation details.
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub struct DelayedPaymentKey(pub PublicKey);
 
 impl DelayedPaymentKey {
-    key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
+       key_impl!(DelayedPaymentBasepoint, "delayedpubkey");
 }
 key_read_write!(DelayedPaymentKey);
 
-/// Master key used in conjunction with per_commitment_point to generate a [localpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
-/// Also used to generate a commitment number in a commitment transaction or as a Payment Key for a remote node (not us) in an anchor output if `option_static_remotekey` is enabled.
-/// Shared by both nodes in a channel establishment message flow.
-#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
-pub struct PaymentBasepoint(pub PublicKey);
-basepoint_impl!(PaymentBasepoint);
-key_read_write!(PaymentBasepoint);
-
-
-/// [localpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of a payment basepoint,
-/// that enables a secure hash-lock for off-chain payments without risk of funds getting stuck or stolen. A payment key is normally shared with a counterparty so that it can generate 
-/// a commitment transaction's to_remote ouput, which our node can claim in case the counterparty force closes the channel.
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct PaymentKey(pub PublicKey);
-
-impl PaymentKey {
-    key_impl!(PaymentBasepoint, "localpubkey");
-}
-key_read_write!(PaymentKey);
-
-/// Master key used in conjunction with per_commitment_point to generate [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#key-derivation) for the latest state of a channel.
+/// Base key used in conjunction with a `per_commitment_point` to generate an [`HtlcKey`].
+///
+/// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
+/// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
+/// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub struct HtlcBasepoint(pub PublicKey);
 basepoint_impl!(HtlcBasepoint);
 key_read_write!(HtlcBasepoint);
 
-
-/// [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of an htlc basepoint,
-/// that enables secure routing of payments in onion scheme without a risk of them getting stuck or diverted. It is used to claim the funds in successful or timed out htlc outputs.
+/// A derived key built from a [`HtlcBasepoint`] and `per_commitment_point`.
+///
+/// HTLC keys are used to ensure only the recipient of an HTLC can claim it on-chain with the HTLC
+/// preimage and that only the sender of an HTLC can claim it on-chain after it has timed out.
+/// Thus, both channel counterparties' HTLC keys will appears in each HTLC output's script.
+///
+/// [See the BOLT specs]
+/// (https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation)
+/// for more information on key derivation details.
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub struct HtlcKey(pub PublicKey);
 
 impl HtlcKey {
-    key_impl!(HtlcBasepoint, "htlcpubkey");
+       key_impl!(HtlcBasepoint, "htlcpubkey");
 }
 key_read_write!(HtlcKey);
 
@@ -156,7 +155,6 @@ fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitm
        sha.input(&per_commitment_point.serialize());
        sha.input(&base_point.serialize());
        let res = Sha256::from_engine(sha).to_byte_array();
-    
 
        let hashkey = PublicKey::from_secret_key(&secp_ctx,
                &SecretKey::from_slice(&res).expect("Hashes should always be valid keys unless SHA-256 is broken"));
@@ -172,68 +170,71 @@ basepoint_impl!(RevocationBasepoint);
 key_read_write!(RevocationBasepoint);
 
 
-/// [htlcpubkey](https://github.com/lightning/bolts/blob/master/03-transactions.md#localpubkey-local_htlcpubkey-remote_htlcpubkey-local_delayedpubkey-and-remote_delayedpubkey-derivation) is a child key of a revocation basepoint,
-/// that enables a node to create a justice transaction punishing a counterparty for an attempt to steal funds. Used to in generation of commitment and htlc outputs.
+/// The revocation key is used to allow a channel party to revoke their state - giving their
+/// counterparty the required material to claim all of their funds if they broadcast that state.
+///
+/// Each commitment transaction has a revocation key based on the basepoint and
+/// per_commitment_point which is used in both commitment and HTLC transactions.
+///
+/// See [the BOLT spec for derivation details]
+/// (https://github.com/lightning/bolts/blob/master/03-transactions.md#revocationpubkey-derivation)
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub struct RevocationKey(pub PublicKey);
 
 impl RevocationKey {
-    /// Derives a per-commitment-transaction revocation public key from its constituent parts. This is
-    /// the public equivalend of derive_private_revocation_key - using only public keys to derive a
-    /// public key instead of private keys.
-    ///
-    /// Only the cheating participant owns a valid witness to propagate a revoked
-    /// commitment transaction, thus per_commitment_point always come from cheater
-    /// and revocation_base_point always come from punisher, which is the broadcaster
-    /// of the transaction spending with this key knowledge.
-    ///
-    /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
-    /// generated (ie our own).
-    pub fn from_basepoint<T: secp256k1::Verification>(
-        secp_ctx: &Secp256k1<T>,
-        basepoint: &RevocationBasepoint,
-        per_commitment_point: &PublicKey,
-    ) -> Self {
-        let rev_append_commit_hash_key = {
-            let mut sha = Sha256::engine();
-            sha.input(&basepoint.to_public_key().serialize());
-            sha.input(&per_commitment_point.serialize());
-    
-            Sha256::from_engine(sha).to_byte_array()
-        };
-        let commit_append_rev_hash_key = {
-            let mut sha = Sha256::engine();
-            sha.input(&per_commitment_point.serialize());
-            sha.input(&basepoint.to_public_key().serialize());
-    
-            Sha256::from_engine(sha).to_byte_array()
-        };
-    
-        let countersignatory_contrib = basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
-            .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
-        let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
-            .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
-        let pk = countersignatory_contrib.combine(&broadcaster_contrib)
-            .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
-        Self(pk)
-    }
-
-    /// Get inner Public Key
-    pub fn to_public_key(&self) -> PublicKey {
-        self.0
-    }
+       /// Derives a per-commitment-transaction revocation public key from one party's per-commitment
+       /// point and the other party's [`RevocationBasepoint`]. This is the public equivalent of
+       /// [`chan_utils::derive_private_revocation_key`] - using only public keys to derive a public
+       /// key instead of private keys.
+       ///
+       /// Note that this is infallible iff we trust that at least one of the two input keys are randomly
+       /// generated (ie our own).
+       ///
+       /// [`chan_utils::derive_private_revocation_key`]: crate::ln::chan_utils::derive_private_revocation_key
+       pub fn from_basepoint<T: secp256k1::Verification>(
+               secp_ctx: &Secp256k1<T>,
+               countersignatory_basepoint: &RevocationBasepoint,
+               per_commitment_point: &PublicKey,
+       ) -> Self {
+               let rev_append_commit_hash_key = {
+                       let mut sha = Sha256::engine();
+                       sha.input(&countersignatory_basepoint.to_public_key().serialize());
+                       sha.input(&per_commitment_point.serialize());
+
+                       Sha256::from_engine(sha).to_byte_array()
+               };
+               let commit_append_rev_hash_key = {
+                       let mut sha = Sha256::engine();
+                       sha.input(&per_commitment_point.serialize());
+                       sha.input(&countersignatory_basepoint.to_public_key().serialize());
+
+                       Sha256::from_engine(sha).to_byte_array()
+               };
+
+               let countersignatory_contrib = countersignatory_basepoint.to_public_key().mul_tweak(&secp_ctx, &Scalar::from_be_bytes(rev_append_commit_hash_key).unwrap())
+                       .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
+               let broadcaster_contrib = (&per_commitment_point).mul_tweak(&secp_ctx, &Scalar::from_be_bytes(commit_append_rev_hash_key).unwrap())
+                       .expect("Multiplying a valid public key by a hash is expected to never fail per secp256k1 docs");
+               let pk = countersignatory_contrib.combine(&broadcaster_contrib)
+                       .expect("Addition only fails if the tweak is the inverse of the key. This is not possible when the tweak commits to the key.");
+               Self(pk)
+       }
+
+       /// Get inner Public Key
+       pub fn to_public_key(&self) -> PublicKey {
+               self.0
+       }
 }
 key_read_write!(RevocationKey);
 
 
-
 #[cfg(test)]
 mod test {
-    use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
-    use bitcoin::hashes::hex::FromHex;
-    use super::derive_public_key;
+       use bitcoin::secp256k1::{Secp256k1, SecretKey, PublicKey};
+       use bitcoin::hashes::hex::FromHex;
+       use super::derive_public_key;
 
-    #[test]
+       #[test]
        fn test_key_derivation() {
                // Test vectors from BOLT 3 Appendix E:
                let secp_ctx = Secp256k1::new();
@@ -248,6 +249,6 @@ mod test {
                assert_eq!(per_commitment_point.serialize()[..], <Vec<u8>>::from_hex("025f7117a78150fe2ef97db7cfc83bd57b2e2c0d0dd25eaf467a4a1c2a45ce1486").unwrap()[..]);
 
                assert_eq!(derive_public_key(&secp_ctx, &per_commitment_point, &base_point).serialize()[..],
-                               <Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
+                       <Vec<u8>>::from_hex("0235f2dbfaa89b57ec7b055afe29849ef7ddfeb1cefdb9ebdc43f5494984db29e5").unwrap()[..]);
        }
 }
index 80d129bbe6fc045bc5300a973359be64e0cc4eb6..87197dd45493ff6ba689179cbe721cd905d834ea 100644 (file)
@@ -48,7 +48,7 @@ use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFea
 #[cfg(any(feature = "_test_utils", test))]
 use crate::ln::features::Bolt11InvoiceFeatures;
 use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, Payee, PaymentParameters, Route, RouteParameters, Router};
-use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundOnionErr, NextPacketDetails};
+use crate::ln::onion_payment::{check_incoming_htlc_cltv, create_recv_pending_htlc_info, create_fwd_pending_htlc_info, decode_incoming_update_add_htlc_onion, InboundHTLCErr, NextPacketDetails};
 use crate::ln::msgs;
 use crate::ln::onion_utils;
 use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING};
@@ -63,7 +63,8 @@ use crate::offers::merkle::SignError;
 use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder};
 use crate::offers::parse::Bolt12SemanticError;
 use crate::offers::refund::{Refund, RefundBuilder};
-use crate::onion_message::{Destination, MessageRouter, OffersMessage, OffersMessageHandler, PendingOnionMessage, new_pending_onion_message};
+use crate::onion_message::messenger::{Destination, MessageRouter, PendingOnionMessage, new_pending_onion_message};
+use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
 use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
 use crate::sign::ecdsa::WriteableEcdsaChannelSigner;
 use crate::util::config::{UserConfig, ChannelConfig, ChannelConfigUpdate};
@@ -201,15 +202,16 @@ pub struct BlindedForward {
        /// onion payload if we're the introduction node. Useful for calculating the next hop's
        /// [`msgs::UpdateAddHTLC::blinding_point`].
        pub inbound_blinding_point: PublicKey,
-       // Another field will be added here when we support forwarding as a non-intro node.
+       /// If needed, this determines how this HTLC should be failed backwards, based on whether we are
+       /// the introduction node.
+       pub failure: BlindedFailure,
 }
 
 impl PendingHTLCRouting {
        // Used to override the onion failure code and data if the HTLC is blinded.
        fn blinded_failure(&self) -> Option<BlindedFailure> {
-               // TODO: needs update when we support forwarding blinded HTLCs as non-intro node
                match self {
-                       Self::Forward { blinded: Some(_), .. } => Some(BlindedFailure::FromIntroductionNode),
+                       Self::Forward { blinded: Some(BlindedForward { failure, .. }), .. } => Some(*failure),
                        Self::Receive { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode),
                        _ => None,
                }
@@ -304,10 +306,15 @@ pub(super) enum HTLCForwardInfo {
        },
 }
 
-// Used for failing blinded HTLCs backwards correctly.
+/// Whether this blinded HTLC is being failed backwards by the introduction node or a blinded node,
+/// which determines the failure message that should be used.
 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
-enum BlindedFailure {
+pub enum BlindedFailure {
+       /// This HTLC is being failed backwards by the introduction node, and thus should be failed with
+       /// [`msgs::UpdateFailHTLC`] and error code `0x8000|0x4000|24`.
        FromIntroductionNode,
+       /// This HTLC is being failed backwards by a blinded node within the path, and thus should be
+       /// failed with [`msgs::UpdateFailMalformedHTLC`] and error code `0x8000|0x4000|24`.
        FromBlindedNode,
 }
 
@@ -550,9 +557,8 @@ impl Into<u16> for FailureCode {
 
 struct MsgHandleErrInternal {
        err: msgs::LightningError,
-       chan_id: Option<(ChannelId, u128)>, // If Some a channel of ours has been closed
+       closes_channel: bool,
        shutdown_finish: Option<(ShutdownResult, Option<msgs::ChannelUpdate>)>,
-       channel_capacity: Option<u64>,
 }
 impl MsgHandleErrInternal {
        #[inline]
@@ -567,17 +573,16 @@ impl MsgHandleErrInternal {
                                        },
                                },
                        },
-                       chan_id: None,
+                       closes_channel: false,
                        shutdown_finish: None,
-                       channel_capacity: None,
                }
        }
        #[inline]
        fn from_no_close(err: msgs::LightningError) -> Self {
-               Self { err, chan_id: None, shutdown_finish: None, channel_capacity: None }
+               Self { err, closes_channel: false, shutdown_finish: None }
        }
        #[inline]
-       fn from_finish_shutdown(err: String, channel_id: ChannelId, user_channel_id: u128, shutdown_res: ShutdownResult, channel_update: Option<msgs::ChannelUpdate>, channel_capacity: u64) -> Self {
+       fn from_finish_shutdown(err: String, channel_id: ChannelId, shutdown_res: ShutdownResult, channel_update: Option<msgs::ChannelUpdate>) -> Self {
                let err_msg = msgs::ErrorMessage { channel_id, data: err.clone() };
                let action = if shutdown_res.monitor_update.is_some() {
                        // We have a closing `ChannelMonitorUpdate`, which means the channel was funded and we
@@ -589,9 +594,8 @@ impl MsgHandleErrInternal {
                };
                Self {
                        err: LightningError { err, action },
-                       chan_id: Some((channel_id, user_channel_id)),
+                       closes_channel: true,
                        shutdown_finish: Some((shutdown_res, channel_update)),
-                       channel_capacity: Some(channel_capacity)
                }
        }
        #[inline]
@@ -622,14 +626,13 @@ impl MsgHandleErrInternal {
                                        },
                                },
                        },
-                       chan_id: None,
+                       closes_channel: false,
                        shutdown_finish: None,
-                       channel_capacity: None,
                }
        }
 
        fn closes_channel(&self) -> bool {
-               self.chan_id.is_some()
+               self.closes_channel
        }
 }
 
@@ -1961,30 +1964,27 @@ macro_rules! handle_error {
 
                match $internal {
                        Ok(msg) => Ok(msg),
-                       Err(MsgHandleErrInternal { err, chan_id, shutdown_finish, channel_capacity }) => {
+                       Err(MsgHandleErrInternal { err, shutdown_finish, .. }) => {
                                let mut msg_events = Vec::with_capacity(2);
 
                                if let Some((shutdown_res, update_option)) = shutdown_finish {
+                                       let counterparty_node_id = shutdown_res.counterparty_node_id;
+                                       let channel_id = shutdown_res.channel_id;
+                                       let logger = WithContext::from(
+                                               &$self.logger, Some(counterparty_node_id), Some(channel_id),
+                                       );
+                                       log_error!(logger, "Force-closing channel: {}", err.err);
+
                                        $self.finish_close_channel(shutdown_res);
                                        if let Some(update) = update_option {
                                                msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                                        msg: update
                                                });
                                        }
-                                       if let Some((channel_id, user_channel_id)) = chan_id {
-                                               $self.pending_events.lock().unwrap().push_back((events::Event::ChannelClosed {
-                                                       channel_id, user_channel_id,
-                                                       reason: ClosureReason::ProcessingError { err: err.err.clone() },
-                                                       counterparty_node_id: Some($counterparty_node_id),
-                                                       channel_capacity_sats: channel_capacity,
-                                               }, None));
-                                       }
+                               } else {
+                                       log_error!($self.logger, "Got non-closing error: {}", err.err);
                                }
 
-                               let logger = WithContext::from(
-                                       &$self.logger, Some($counterparty_node_id), chan_id.map(|(chan_id, _)| chan_id)
-                               );
-                               log_error!(logger, "{}", err.err);
                                if let msgs::ErrorAction::IgnoreError = err.action {
                                } else {
                                        msg_events.push(events::MessageSendEvent::HandleError {
@@ -2044,12 +2044,11 @@ macro_rules! convert_chan_phase_err {
                                let logger = WithChannelContext::from(&$self.logger, &$channel.context);
                                log_error!(logger, "Closing channel {} due to close-required error: {}", $channel_id, msg);
                                update_maps_on_chan_removal!($self, $channel.context);
-                               let shutdown_res = $channel.context.force_shutdown(true);
-                               let user_id = $channel.context.get_user_id();
-                               let channel_capacity_satoshis = $channel.context.get_value_satoshis();
-
-                               (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, user_id,
-                                       shutdown_res, $channel_update, channel_capacity_satoshis))
+                               let reason = ClosureReason::ProcessingError { err: msg.clone() };
+                               let shutdown_res = $channel.context.force_shutdown(true, reason);
+                               let err =
+                                       MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, shutdown_res, $channel_update);
+                               (true, err)
                        },
                }
        };
@@ -2706,26 +2705,6 @@ where
                        .collect()
        }
 
-       /// Helper function that issues the channel close events
-       fn issue_channel_close_events(&self, context: &ChannelContext<SP>, closure_reason: ClosureReason) {
-               let mut pending_events_lock = self.pending_events.lock().unwrap();
-               match context.unbroadcasted_funding() {
-                       Some(transaction) => {
-                               pending_events_lock.push_back((events::Event::DiscardFunding {
-                                       channel_id: context.channel_id(), transaction
-                               }, None));
-                       },
-                       None => {},
-               }
-               pending_events_lock.push_back((events::Event::ChannelClosed {
-                       channel_id: context.channel_id(),
-                       user_channel_id: context.get_user_id(),
-                       reason: closure_reason,
-                       counterparty_node_id: Some(context.get_counterparty_node_id()),
-                       channel_capacity_sats: Some(context.get_value_satoshis()),
-               }, None));
-       }
-
        fn close_channel_internal(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, target_feerate_sats_per_1000_weight: Option<u32>, override_shutdown_script: Option<ShutdownScript>) -> Result<(), APIError> {
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
 
@@ -2767,9 +2746,8 @@ where
                                                                peer_state_lock, peer_state, per_peer_state, chan);
                                                }
                                        } else {
-                                               self.issue_channel_close_events(chan_phase_entry.get().context(), ClosureReason::HolderForceClosed);
                                                let mut chan_phase = remove_channel_phase!(self, chan_phase_entry);
-                                               shutdown_result = Some(chan_phase.context_mut().force_shutdown(false));
+                                               shutdown_result = Some(chan_phase.context_mut().force_shutdown(false, ClosureReason::HolderForceClosed));
                                        }
                                },
                                hash_map::Entry::Vacant(_) => {
@@ -2866,7 +2844,9 @@ where
                let logger = WithContext::from(
                        &self.logger, Some(shutdown_res.counterparty_node_id), Some(shutdown_res.channel_id),
                );
-               log_debug!(logger, "Finishing closure of channel with {} HTLCs to fail", shutdown_res.dropped_outbound_htlcs.len());
+
+               log_debug!(logger, "Finishing closure of channel due to {} with {} HTLCs to fail",
+                       shutdown_res.closure_reason, shutdown_res.dropped_outbound_htlcs.len());
                for htlc_source in shutdown_res.dropped_outbound_htlcs.drain(..) {
                        let (source, payment_hash, counterparty_node_id, channel_id) = htlc_source;
                        let reason = HTLCFailReason::from_failure_code(0x4000 | 8);
@@ -2891,8 +2871,7 @@ where
                                        let mut peer_state = peer_state_mutex.lock().unwrap();
                                        if let Some(mut chan) = peer_state.channel_by_id.remove(&channel_id) {
                                                update_maps_on_chan_removal!(self, &chan.context());
-                                               self.issue_channel_close_events(&chan.context(), ClosureReason::FundingBatchClosure);
-                                               shutdown_results.push(chan.context_mut().force_shutdown(false));
+                                               shutdown_results.push(chan.context_mut().force_shutdown(false, ClosureReason::FundingBatchClosure));
                                        }
                                }
                                has_uncompleted_channel = Some(has_uncompleted_channel.map_or(!state, |v| v || !state));
@@ -2902,6 +2881,24 @@ where
                                "Closing a batch where all channels have completed initial monitor update",
                        );
                }
+
+               {
+                       let mut pending_events = self.pending_events.lock().unwrap();
+                       pending_events.push_back((events::Event::ChannelClosed {
+                               channel_id: shutdown_res.channel_id,
+                               user_channel_id: shutdown_res.user_channel_id,
+                               reason: shutdown_res.closure_reason,
+                               counterparty_node_id: Some(shutdown_res.counterparty_node_id),
+                               channel_capacity_sats: Some(shutdown_res.channel_capacity_satoshis),
+                               channel_funding_txo: shutdown_res.channel_funding_txo,
+                       }, None));
+
+                       if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx {
+                               pending_events.push_back((events::Event::DiscardFunding {
+                                       channel_id: shutdown_res.channel_id, transaction
+                               }, None));
+                       }
+               }
                for shutdown_result in shutdown_results.drain(..) {
                        self.finish_close_channel(shutdown_result);
                }
@@ -2924,17 +2921,16 @@ where
                        let logger = WithContext::from(&self.logger, Some(*peer_node_id), Some(*channel_id));
                        if let hash_map::Entry::Occupied(chan_phase_entry) = peer_state.channel_by_id.entry(channel_id.clone()) {
                                log_error!(logger, "Force-closing channel {}", channel_id);
-                               self.issue_channel_close_events(&chan_phase_entry.get().context(), closure_reason);
                                let mut chan_phase = remove_channel_phase!(self, chan_phase_entry);
                                mem::drop(peer_state);
                                mem::drop(per_peer_state);
                                match chan_phase {
                                        ChannelPhase::Funded(mut chan) => {
-                                               self.finish_close_channel(chan.context.force_shutdown(broadcast));
+                                               self.finish_close_channel(chan.context.force_shutdown(broadcast, closure_reason));
                                                (self.get_channel_update_for_broadcast(&chan).ok(), chan.context.get_counterparty_node_id())
                                        },
                                        ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {
-                                               self.finish_close_channel(chan_phase.context_mut().force_shutdown(false));
+                                               self.finish_close_channel(chan_phase.context_mut().force_shutdown(false, closure_reason));
                                                // Unfunded channel has no update
                                                (None, chan_phase.context().get_counterparty_node_id())
                                        },
@@ -3035,8 +3031,9 @@ where
 
                let is_intro_node_forward = match next_hop {
                        onion_utils::Hop::Forward {
-                               // TODO: update this when we support blinded forwarding as non-intro node
-                               next_hop_data: msgs::InboundOnionPayload::BlindedForward { .. }, ..
+                               next_hop_data: msgs::InboundOnionPayload::BlindedForward {
+                                       intro_node_blinding_point: Some(_), ..
+                               }, ..
                        } => true,
                        _ => false,
                };
@@ -3245,14 +3242,14 @@ where
                                                // delay) once they've send us a commitment_signed!
                                                PendingHTLCStatus::Forward(info)
                                        },
-                                       Err(InboundOnionErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
+                                       Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
                                }
                        },
                        onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
                                match create_fwd_pending_htlc_info(msg, next_hop_data, next_hop_hmac,
                                        new_packet_bytes, shared_secret, next_packet_pubkey_opt) {
                                        Ok(info) => PendingHTLCStatus::Forward(info),
-                                       Err(InboundOnionErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
+                                       Err(InboundHTLCErr { err_code, err_data, msg }) => return_err!(msg, err_code, &err_data)
                                }
                        }
                }
@@ -3755,7 +3752,7 @@ where
                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                let funding_txo;
-               let (chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
+               let (mut chan, msg_opt) = match peer_state.channel_by_id.remove(temporary_channel_id) {
                        Some(ChannelPhase::UnfundedOutboundV1(mut chan)) => {
                                funding_txo = find_funding_output(&chan, &funding_transaction)?;
 
@@ -3763,10 +3760,9 @@ where
                                let funding_res = chan.get_funding_created(funding_transaction, funding_txo, is_batch_funding, &&logger)
                                        .map_err(|(mut chan, e)| if let ChannelError::Close(msg) = e {
                                                let channel_id = chan.context.channel_id();
-                                               let user_id = chan.context.get_user_id();
-                                               let shutdown_res = chan.context.force_shutdown(false);
-                                               let channel_capacity = chan.context.get_value_satoshis();
-                                               (chan, MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, user_id, shutdown_res, None, channel_capacity))
+                                               let reason = ClosureReason::ProcessingError { err: msg.clone() };
+                                               let shutdown_res = chan.context.force_shutdown(false, reason);
+                                               (chan, MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, shutdown_res, None))
                                        } else { unreachable!(); });
                                match funding_res {
                                        Ok(funding_msg) => (chan, funding_msg),
@@ -3806,8 +3802,20 @@ where
                        },
                        hash_map::Entry::Vacant(e) => {
                                let mut outpoint_to_peer = self.outpoint_to_peer.lock().unwrap();
-                               if outpoint_to_peer.insert(funding_txo, chan.context.get_counterparty_node_id()).is_some() {
-                                       panic!("outpoint_to_peer map already contained funding outpoint, which shouldn't be possible");
+                               match outpoint_to_peer.entry(funding_txo) {
+                                       hash_map::Entry::Vacant(e) => { e.insert(chan.context.get_counterparty_node_id()); },
+                                       hash_map::Entry::Occupied(o) => {
+                                               let err = format!(
+                                                       "An existing channel using outpoint {} is open with peer {}",
+                                                       funding_txo, o.get()
+                                               );
+                                               mem::drop(outpoint_to_peer);
+                                               mem::drop(peer_state_lock);
+                                               mem::drop(per_peer_state);
+                                               let reason = ClosureReason::ProcessingError { err: err.clone() };
+                                               self.finish_close_channel(chan.context.force_shutdown(true, reason));
+                                               return Err(APIError::ChannelUnavailable { err });
+                                       }
                                }
                                e.insert(ChannelPhase::UnfundedOutboundV1(chan));
                        }
@@ -3971,8 +3979,8 @@ where
                                                .and_then(|mut peer_state| peer_state.channel_by_id.remove(&channel_id))
                                                .map(|mut chan| {
                                                        update_maps_on_chan_removal!(self, &chan.context());
-                                                       self.issue_channel_close_events(&chan.context(), ClosureReason::ProcessingError { err: e.clone() });
-                                                       shutdown_results.push(chan.context_mut().force_shutdown(false));
+                                                       let closure_reason = ClosureReason::ProcessingError { err: e.clone() };
+                                                       shutdown_results.push(chan.context_mut().force_shutdown(false, closure_reason));
                                                });
                                }
                        }
@@ -4309,7 +4317,7 @@ where
                                                                                                                        current_height, self.default_configuration.accept_mpp_keysend)
                                                                                                                {
                                                                                                                        Ok(info) => phantom_receives.push((prev_short_channel_id, prev_funding_outpoint, prev_user_channel_id, vec![(info, prev_htlc_id)])),
-                                                                                                                       Err(InboundOnionErr { err_code, err_data, msg }) => failed_payment!(msg, err_code, err_data, Some(phantom_shared_secret))
+                                                                                                                       Err(InboundHTLCErr { err_code, err_data, msg }) => failed_payment!(msg, err_code, err_data, Some(phantom_shared_secret))
                                                                                                                }
                                                                                                        },
                                                                                                        _ => panic!(),
@@ -4351,7 +4359,7 @@ where
                                        if let Some(ChannelPhase::Funded(ref mut chan)) = peer_state.channel_by_id.get_mut(&forward_chan_id) {
                                                let logger = WithChannelContext::from(&self.logger, &chan.context);
                                                for forward_info in pending_forwards.drain(..) {
-                                                       match forward_info {
+                                                       let queue_fail_htlc_res = match forward_info {
                                                                HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
                                                                        prev_short_channel_id, prev_htlc_id, prev_funding_outpoint, prev_user_channel_id,
                                                                        forward_info: PendingHTLCInfo {
@@ -4370,7 +4378,7 @@ where
                                                                                incoming_packet_shared_secret: incoming_shared_secret,
                                                                                // Phantom payments are only PendingHTLCRouting::Receive.
                                                                                phantom_shared_secret: None,
-                                                                               blinded_failure: blinded.map(|_| BlindedFailure::FromIntroductionNode),
+                                                                               blinded_failure: blinded.map(|b| b.failure),
                                                                        });
                                                                        let next_blinding_point = blinded.and_then(|b| {
                                                                                let encrypted_tlvs_ss = self.node_signer.ecdh(
@@ -4397,40 +4405,35 @@ where
                                                                                ));
                                                                                continue;
                                                                        }
+                                                                       None
                                                                },
                                                                HTLCForwardInfo::AddHTLC { .. } => {
                                                                        panic!("short_channel_id != 0 should imply any pending_forward entries are of type Forward");
                                                                },
                                                                HTLCForwardInfo::FailHTLC { htlc_id, err_packet } => {
                                                                        log_trace!(logger, "Failing HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id);
-                                                                       if let Err(e) = chan.queue_fail_htlc(
-                                                                               htlc_id, err_packet, &&logger
-                                                                       ) {
-                                                                               if let ChannelError::Ignore(msg) = e {
-                                                                                       log_trace!(logger, "Failed to fail HTLC with ID {} backwards to short_id {}: {}", htlc_id, short_chan_id, msg);
-                                                                               } else {
-                                                                                       panic!("Stated return value requirements in queue_fail_htlc() were not met");
-                                                                               }
-                                                                               // fail-backs are best-effort, we probably already have one
-                                                                               // pending, and if not that's OK, if not, the channel is on
-                                                                               // the chain and sending the HTLC-Timeout is their problem.
-                                                                               continue;
-                                                                       }
+                                                                       Some((chan.queue_fail_htlc(htlc_id, err_packet, &&logger), htlc_id))
                                                                },
                                                                HTLCForwardInfo::FailMalformedHTLC { htlc_id, failure_code, sha256_of_onion } => {
-                                                                       log_trace!(self.logger, "Failing malformed HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id);
-                                                                       if let Err(e) = chan.queue_fail_malformed_htlc(htlc_id, failure_code, sha256_of_onion, &self.logger) {
-                                                                               if let ChannelError::Ignore(msg) = e {
-                                                                                       log_trace!(self.logger, "Failed to fail HTLC with ID {} backwards to short_id {}: {}", htlc_id, short_chan_id, msg);
-                                                                               } else {
-                                                                                       panic!("Stated return value requirements in queue_fail_malformed_htlc() were not met");
-                                                                               }
-                                                                               // fail-backs are best-effort, we probably already have one
-                                                                               // pending, and if not that's OK, if not, the channel is on
-                                                                               // the chain and sending the HTLC-Timeout is their problem.
-                                                                               continue;
-                                                                       }
+                                                                       log_trace!(logger, "Failing malformed HTLC back to channel with short id {} (backward HTLC ID {}) after delay", short_chan_id, htlc_id);
+                                                                       let res = chan.queue_fail_malformed_htlc(
+                                                                               htlc_id, failure_code, sha256_of_onion, &&logger
+                                                                       );
+                                                                       Some((res, htlc_id))
                                                                },
+                                                       };
+                                                       if let Some((queue_fail_htlc_res, htlc_id)) = queue_fail_htlc_res {
+                                                               if let Err(e) = queue_fail_htlc_res {
+                                                                       if let ChannelError::Ignore(msg) = e {
+                                                                               log_trace!(logger, "Failed to fail HTLC with ID {} backwards to short_id {}: {}", htlc_id, short_chan_id, msg);
+                                                                       } else {
+                                                                               panic!("Stated return value requirements in queue_fail_{{malformed_}}htlc() were not met");
+                                                                       }
+                                                                       // fail-backs are best-effort, we probably already have one
+                                                                       // pending, and if not that's OK, if not, the channel is on
+                                                                       // the chain and sending the HTLC-Timeout is their problem.
+                                                                       continue;
+                                                               }
                                                        }
                                                }
                                        } else {
@@ -4894,8 +4897,7 @@ where
                                        log_error!(logger,
                                                "Force-closing pending channel with ID {} for not establishing in a timely manner", chan_id);
                                        update_maps_on_chan_removal!(self, &context);
-                                       self.issue_channel_close_events(&context, ClosureReason::HolderForceClosed);
-                                       shutdown_channels.push(context.force_shutdown(false));
+                                       shutdown_channels.push(context.force_shutdown(false, ClosureReason::HolderForceClosed));
                                        pending_msg_events.push(MessageSendEvent::HandleError {
                                                node_id: counterparty_node_id,
                                                action: msgs::ErrorAction::SendErrorMessage {
@@ -6002,13 +6004,20 @@ where
        }
 
        fn do_accept_inbound_channel(&self, temporary_channel_id: &ChannelId, counterparty_node_id: &PublicKey, accept_0conf: bool, user_channel_id: u128) -> Result<(), APIError> {
+
+               let logger = WithContext::from(&self.logger, Some(*counterparty_node_id), Some(*temporary_channel_id));
                let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
 
                let peers_without_funded_channels =
                        self.peers_without_funded_channels(|peer| { peer.total_channel_count() > 0 });
                let per_peer_state = self.per_peer_state.read().unwrap();
                let peer_state_mutex = per_peer_state.get(counterparty_node_id)
-                       .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) })?;
+               .ok_or_else(|| {
+                       let err_str = format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id);
+                       log_error!(logger, "{}", err_str);
+
+                       APIError::ChannelUnavailable { err: err_str }
+               })?;
                let mut peer_state_lock = peer_state_mutex.lock().unwrap();
                let peer_state = &mut *peer_state_lock;
                let is_only_peer_channel = peer_state.total_channel_count() == 1;
@@ -6023,9 +6032,19 @@ where
                                InboundV1Channel::new(&self.fee_estimator, &self.entropy_source, &self.signer_provider,
                                        counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features,
                                        &unaccepted_channel.open_channel_msg, user_channel_id, &self.default_configuration, best_block_height,
-                                       &self.logger, accept_0conf).map_err(|e| APIError::ChannelUnavailable { err: e.to_string() })
+                                       &self.logger, accept_0conf).map_err(|e| {
+                                               let err_str = e.to_string();
+                                               log_error!(logger, "{}", err_str);
+
+                                               APIError::ChannelUnavailable { err: err_str }
+                                       })
+                               }
+                       _ => {
+                               let err_str = "No such channel awaiting to be accepted.".to_owned();
+                               log_error!(logger, "{}", err_str);
+
+                               Err(APIError::APIMisuseError { err: err_str })
                        }
-                       _ => Err(APIError::APIMisuseError { err: "No such channel awaiting to be accepted.".to_owned() })
                }?;
 
                if accept_0conf {
@@ -6039,7 +6058,10 @@ where
                                }
                        };
                        peer_state.pending_msg_events.push(send_msg_err_event);
-                       return Err(APIError::APIMisuseError { err: "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned() });
+                       let err_str = "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned();
+                       log_error!(logger, "{}", err_str);
+
+                       return Err(APIError::APIMisuseError { err: err_str });
                } else {
                        // If this peer already has some channels, a new channel won't increase our number of peers
                        // with unfunded channels, so as long as we aren't over the maximum number of unfunded
@@ -6052,7 +6074,10 @@ where
                                        }
                                };
                                peer_state.pending_msg_events.push(send_msg_err_event);
-                               return Err(APIError::APIMisuseError { err: "Too many peers with unfunded channels, refusing to accept new ones".to_owned() });
+                               let err_str = "Too many peers with unfunded channels, refusing to accept new ones".to_owned();
+                               log_error!(logger, "{}", err_str);
+
+                               return Err(APIError::APIMisuseError { err: err_str });
                        }
                }
 
@@ -6386,7 +6411,7 @@ where
                                        let res =
                                                chan.funding_signed(&msg, best_block, &self.signer_provider, &&logger);
                                        match res {
-                                               Ok((chan, monitor)) => {
+                                               Ok((mut chan, monitor)) => {
                                                        if let Ok(persist_status) = self.chain_monitor.watch_channel(chan.context.get_funding_txo().unwrap(), monitor) {
                                                                // We really should be able to insert here without doing a second
                                                                // lookup, but sadly rust stdlib doesn't currently allow keeping
@@ -6398,6 +6423,11 @@ where
                                                                Ok(())
                                                        } else {
                                                                let e = ChannelError::Close("Channel funding outpoint was a duplicate".to_owned());
+                                                               // We weren't able to watch the channel to begin with, so no
+                                                               // updates should be made on it. Previously, full_stack_target
+                                                               // found an (unreachable) panic when the monitor update contained
+                                                               // within `shutdown_finish` was applied.
+                                                               chan.unset_funding_info(msg.channel_id);
                                                                return Err(convert_chan_phase_err!(self, e, &mut ChannelPhase::Funded(chan), &msg.channel_id).1);
                                                        }
                                                },
@@ -6520,9 +6550,8 @@ where
                                                let context = phase.context_mut();
                                                let logger = WithChannelContext::from(&self.logger, context);
                                                log_error!(logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id);
-                                               self.issue_channel_close_events(&context, ClosureReason::CounterpartyCoopClosedUnfundedChannel);
                                                let mut chan = remove_channel_phase!(self, chan_phase_entry);
-                                               finish_shutdown = Some(chan.context_mut().force_shutdown(false));
+                                               finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel));
                                        },
                                }
                        } else {
@@ -6591,7 +6620,6 @@ where
                                        msg: update
                                });
                        }
-                       self.issue_channel_close_events(&chan.context, ClosureReason::CooperativeClosure);
                }
                mem::drop(per_peer_state);
                if let Some(shutdown_result) = shutdown_result {
@@ -7243,13 +7271,12 @@ where
                                                                let pending_msg_events = &mut peer_state.pending_msg_events;
                                                                if let hash_map::Entry::Occupied(chan_phase_entry) = peer_state.channel_by_id.entry(funding_outpoint.to_channel_id()) {
                                                                        if let ChannelPhase::Funded(mut chan) = remove_channel_phase!(self, chan_phase_entry) {
-                                                                               failed_channels.push(chan.context.force_shutdown(false));
+                                                                               failed_channels.push(chan.context.force_shutdown(false, ClosureReason::HolderForceClosed));
                                                                                if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
                                                                                        pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                                                                                msg: update
                                                                                        });
                                                                                }
-                                                                               self.issue_channel_close_events(&chan.context, ClosureReason::HolderForceClosed);
                                                                                pending_msg_events.push(events::MessageSendEvent::HandleError {
                                                                                        node_id: chan.context.get_counterparty_node_id(),
                                                                                        action: msgs::ErrorAction::DisconnectPeer {
@@ -7436,8 +7463,6 @@ where
                                                                                        });
                                                                                }
 
-                                                                               self.issue_channel_close_events(&chan.context, ClosureReason::CooperativeClosure);
-
                                                                                log_info!(logger, "Broadcasting {}", log_tx!(tx));
                                                                                self.tx_broadcaster.broadcast_transactions(&[&tx]);
                                                                                update_maps_on_chan_removal!(self, &chan.context);
@@ -8450,14 +8475,13 @@ where
                                                                update_maps_on_chan_removal!(self, &channel.context);
                                                                // It looks like our counterparty went on-chain or funding transaction was
                                                                // reorged out of the main chain. Close the channel.
-                                                               failed_channels.push(channel.context.force_shutdown(true));
+                                                               let reason_message = format!("{}", reason);
+                                                               failed_channels.push(channel.context.force_shutdown(true, reason));
                                                                if let Ok(update) = self.get_channel_update_for_broadcast(&channel) {
                                                                        pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                                                                msg: update
                                                                        });
                                                                }
-                                                               let reason_message = format!("{}", reason);
-                                                               self.issue_channel_close_events(&channel.context, reason);
                                                                pending_msg_events.push(events::MessageSendEvent::HandleError {
                                                                        node_id: channel.context.get_counterparty_node_id(),
                                                                        action: msgs::ErrorAction::DisconnectPeer {
@@ -8855,8 +8879,7 @@ where
                                        };
                                        // Clean up for removal.
                                        update_maps_on_chan_removal!(self, &context);
-                                       self.issue_channel_close_events(&context, ClosureReason::DisconnectedPeer);
-                                       failed_channels.push(context.force_shutdown(false));
+                                       failed_channels.push(context.force_shutdown(false, ClosureReason::DisconnectedPeer));
                                        false
                                });
                                // Note that we don't bother generating any events for pre-accept channels -
@@ -9335,6 +9358,7 @@ pub fn provided_init_features(config: &UserConfig) -> InitFeatures {
        features.set_channel_type_optional();
        features.set_scid_privacy_optional();
        features.set_zero_conf_optional();
+       features.set_route_blinding_optional();
        if config.channel_handshake_config.negotiate_anchors_zero_fee_htlc_tx {
                features.set_anchors_zero_fee_htlc_tx_optional();
        }
@@ -9480,6 +9504,7 @@ impl_writeable_tlv_based!(PhantomRouteHints, {
 
 impl_writeable_tlv_based!(BlindedForward, {
        (0, inbound_blinding_point, required),
+       (1, failure, (default_value, BlindedFailure::FromIntroductionNode)),
 });
 
 impl_writeable_tlv_based_enum!(PendingHTLCRouting,
@@ -10296,7 +10321,7 @@ where
                                                log_error!(logger, " The ChannelMonitor for channel {} is at counterparty commitment transaction number {} but the ChannelManager is at counterparty commitment transaction number {}.",
                                                        &channel.context.channel_id(), monitor.get_cur_counterparty_commitment_number(), channel.get_cur_counterparty_commitment_transaction_number());
                                        }
-                                       let mut shutdown_result = channel.context.force_shutdown(true);
+                                       let mut shutdown_result = channel.context.force_shutdown(true, ClosureReason::OutdatedChannelManager);
                                        if shutdown_result.unbroadcasted_batch_funding_txid.is_some() {
                                                return Err(DecodeError::InvalidValue);
                                        }
@@ -10312,6 +10337,7 @@ where
                                                reason: ClosureReason::OutdatedChannelManager,
                                                counterparty_node_id: Some(channel.context.get_counterparty_node_id()),
                                                channel_capacity_sats: Some(channel.context.get_value_satoshis()),
+                                               channel_funding_txo: channel.context.get_funding_txo(),
                                        }, None));
                                        for (channel_htlc_source, payment_hash) in channel.inflight_htlc_sources() {
                                                let mut found_htlc = false;
@@ -10358,13 +10384,14 @@ where
                                // If we were persisted and shut down while the initial ChannelMonitor persistence
                                // was in-progress, we never broadcasted the funding transaction and can still
                                // safely discard the channel.
-                               let _ = channel.context.force_shutdown(false);
+                               let _ = channel.context.force_shutdown(false, ClosureReason::DisconnectedPeer);
                                channel_closures.push_back((events::Event::ChannelClosed {
                                        channel_id: channel.context.channel_id(),
                                        user_channel_id: channel.context.get_user_id(),
                                        reason: ClosureReason::DisconnectedPeer,
                                        counterparty_node_id: Some(channel.context.get_counterparty_node_id()),
                                        channel_capacity_sats: Some(channel.context.get_value_satoshis()),
+                                       channel_funding_txo: channel.context.get_funding_txo(),
                                }, None));
                        } else {
                                log_error!(logger, "Missing ChannelMonitor for channel {} needed by ChannelManager.", &channel.context.channel_id());
@@ -12104,8 +12131,8 @@ mod tests {
                let sender_intended_amt_msat = 100;
                let extra_fee_msat = 10;
                let hop_data = msgs::InboundOnionPayload::Receive {
-                       amt_msat: 100,
-                       outgoing_cltv_value: 42,
+                       sender_intended_htlc_amt_msat: 100,
+                       cltv_expiry_height: 42,
                        payment_metadata: None,
                        keysend_preimage: None,
                        payment_data: Some(msgs::FinalOnionHopData {
@@ -12116,7 +12143,7 @@ mod tests {
                // Check that if the amount we received + the penultimate hop extra fee is less than the sender
                // intended amount, we fail the payment.
                let current_height: u32 = node[0].node.best_block.read().unwrap().height();
-               if let Err(crate::ln::channelmanager::InboundOnionErr { err_code, .. }) =
+               if let Err(crate::ln::channelmanager::InboundHTLCErr { err_code, .. }) =
                        create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]),
                                sender_intended_amt_msat - extra_fee_msat - 1, 42, None, true, Some(extra_fee_msat),
                                current_height, node[0].node.default_configuration.accept_mpp_keysend)
@@ -12126,8 +12153,8 @@ mod tests {
 
                // If amt_received + extra_fee is equal to the sender intended amount, we're fine.
                let hop_data = msgs::InboundOnionPayload::Receive { // This is the same payload as above, InboundOnionPayload doesn't implement Clone
-                       amt_msat: 100,
-                       outgoing_cltv_value: 42,
+                       sender_intended_htlc_amt_msat: 100,
+                       cltv_expiry_height: 42,
                        payment_metadata: None,
                        keysend_preimage: None,
                        payment_data: Some(msgs::FinalOnionHopData {
@@ -12150,8 +12177,8 @@ mod tests {
 
                let current_height: u32 = node[0].node.best_block.read().unwrap().height();
                let result = create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive {
-                       amt_msat: 100,
-                       outgoing_cltv_value: 22,
+                       sender_intended_htlc_amt_msat: 100,
+                       cltv_expiry_height: 22,
                        payment_metadata: None,
                        keysend_preimage: None,
                        payment_data: Some(msgs::FinalOnionHopData {
index a2d9631716c4c23098135a8f95ee37a1fc5a6949..d153a0a4c2d7b964f6c4d4f6656e7959a7de6c88 100644 (file)
@@ -1218,7 +1218,7 @@ pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, r
        (tx, as_channel_ready.channel_id)
 }
 
-pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> Transaction {
+pub fn exchange_open_accept_chan<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> ChannelId {
        let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None, None).unwrap();
        let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id());
        assert_eq!(open_channel_msg.temporary_channel_id, create_chan_id);
@@ -1238,6 +1238,11 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
        node_a.node.handle_accept_channel(&node_b.node.get_our_node_id(), &accept_channel_msg);
        assert_ne!(node_b.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 0);
 
+       create_chan_id
+}
+
+pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64) -> Transaction {
+       let create_chan_id = exchange_open_accept_chan(node_a, node_b, channel_value, push_msat);
        sign_funding_transaction(node_a, node_b, channel_value, create_chan_id)
 }
 
@@ -1534,6 +1539,8 @@ pub struct ExpectedCloseEvent {
        pub counterparty_node_id: Option<PublicKey>,
        pub discard_funding: bool,
        pub reason: Option<ClosureReason>,
+       pub channel_funding_txo: Option<OutPoint>,
+       pub user_channel_id: Option<u128>,
 }
 
 impl ExpectedCloseEvent {
@@ -1544,6 +1551,8 @@ impl ExpectedCloseEvent {
                        counterparty_node_id: None,
                        discard_funding,
                        reason: Some(reason),
+                       channel_funding_txo: None,
+                       user_channel_id: None,
                }
        }
 }
@@ -1562,12 +1571,20 @@ pub fn check_closed_events(node: &Node, expected_close_events: &[ExpectedCloseEv
                                reason,
                                counterparty_node_id,
                                channel_capacity_sats,
+                               channel_funding_txo,
+                               user_channel_id,
                                ..
                        } if (
                                expected_event.channel_id.map(|expected| *channel_id == expected).unwrap_or(true) &&
                                expected_event.reason.as_ref().map(|expected| reason == expected).unwrap_or(true) &&
-                               expected_event.counterparty_node_id.map(|expected| *counterparty_node_id == Some(expected)).unwrap_or(true) &&
-                               expected_event.channel_capacity_sats.map(|expected| *channel_capacity_sats == Some(expected)).unwrap_or(true)
+                               expected_event.
+                                       counterparty_node_id.map(|expected| *counterparty_node_id == Some(expected)).unwrap_or(true) &&
+                               expected_event.channel_capacity_sats
+                                       .map(|expected| *channel_capacity_sats == Some(expected)).unwrap_or(true) &&
+                               expected_event.channel_funding_txo
+                                       .map(|expected| *channel_funding_txo == Some(expected)).unwrap_or(true) &&
+                               expected_event.user_channel_id
+                                       .map(|expected| *user_channel_id == expected).unwrap_or(true)
                        )
                )));
        }
@@ -1592,6 +1609,8 @@ pub fn check_closed_event(node: &Node, events_count: usize, expected_reason: Clo
                counterparty_node_id: Some(*node_id),
                discard_funding: is_check_discard_funding,
                reason: Some(expected_reason.clone()),
+               channel_funding_txo: None,
+               user_channel_id: None,
        }).collect::<Vec<_>>();
        check_closed_events(node, expected_close_events.as_slice());
 }
index 2ad53faa8b2e129874cbec1391156ab58aabc6e5..5711f238aa0c519a8ccf58aae91bb80694dcf70f 100644 (file)
@@ -768,7 +768,7 @@ fn test_update_fee_that_funder_cannot_afford() {
        //check to see if the funder, who sent the update_fee request, can afford the new fee (funder_balance >= fee+channel_reserve)
        //Should produce and error.
        nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &commit_signed_msg);
-       nodes[1].logger.assert_log("lightning::ln::channelmanager", "Funding remote cannot afford proposed new fee".to_string(), 1);
+       nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Funding remote cannot afford proposed new fee", 3);
        check_added_monitors!(nodes[1], 1);
        check_closed_broadcast!(nodes[1], true);
        check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: String::from("Funding remote cannot afford proposed new fee") },
@@ -1617,7 +1617,7 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() {
 
        nodes[0].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &msg);
        // Check that the payment failed and the channel is closed in response to the malicious UpdateAdd.
-       nodes[0].logger.assert_log("lightning::ln::channelmanager", "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_string(), 1);
+       nodes[0].logger.assert_log_contains("lightning::ln::channelmanager", "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value", 3);
        assert_eq!(nodes[0].node.list_channels().len(), 0);
        let err_msg = check_closed_broadcast!(nodes[0], true).unwrap();
        assert_eq!(err_msg.data, "Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value");
@@ -1796,7 +1796,7 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() {
 
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &msg);
        // Check that the payment failed and the channel is closed in response to the malicious UpdateAdd.
-       nodes[1].logger.assert_log("lightning::ln::channelmanager", "Remote HTLC add would put them under remote reserve value".to_string(), 1);
+       nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Remote HTLC add would put them under remote reserve value", 3);
        assert_eq!(nodes[1].node.list_channels().len(), 1);
        let err_msg = check_closed_broadcast!(nodes[1], true).unwrap();
        assert_eq!(err_msg.data, "Remote HTLC add would put them under remote reserve value");
@@ -3328,22 +3328,18 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
 
        let events = nodes[1].node.get_and_clear_pending_events();
        assert_eq!(events.len(), if deliver_bs_raa { 3 + nodes.len() - 1 } else { 4 + nodes.len() });
-       match events[0] {
-               Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => { },
-               _ => panic!("Unexepected event"),
-       }
-       match events[1] {
-               Event::PaymentPathFailed { ref payment_hash, .. } => {
-                       assert_eq!(*payment_hash, fourth_payment_hash);
-               },
-               _ => panic!("Unexpected event"),
-       }
-       match events[2] {
-               Event::PaymentFailed { ref payment_hash, .. } => {
-                       assert_eq!(*payment_hash, fourth_payment_hash);
-               },
-               _ => panic!("Unexpected event"),
-       }
+       assert!(events.iter().any(|ev| matches!(
+               ev,
+               Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. }
+       )));
+       assert!(events.iter().any(|ev| matches!(
+               ev,
+               Event::PaymentPathFailed { ref payment_hash, .. } if *payment_hash == fourth_payment_hash
+       )));
+       assert!(events.iter().any(|ev| matches!(
+               ev,
+               Event::PaymentFailed { ref payment_hash, .. } if *payment_hash == fourth_payment_hash
+       )));
 
        nodes[1].node.process_pending_htlc_forwards();
        check_added_monitors!(nodes[1], 1);
@@ -6299,7 +6295,7 @@ fn test_update_add_htlc_bolt2_receiver_zero_value_msat() {
        updates.update_add_htlcs[0].amount_msat = 0;
 
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
-       nodes[1].logger.assert_log("lightning::ln::channelmanager", "Remote side tried to send a 0-msat HTLC".to_string(), 1);
+       nodes[1].logger.assert_log_contains("lightning::ln::channelmanager", "Remote side tried to send a 0-msat HTLC", 3);
        check_closed_broadcast!(nodes[1], true).unwrap();
        check_added_monitors!(nodes[1], 1);
        check_closed_event!(nodes[1], 1, ClosureReason::ProcessingError { err: "Remote side tried to send a 0-msat HTLC".to_string() },
@@ -8216,8 +8212,10 @@ fn test_onion_value_mpp_set_calculation() {
                                RecipientOnionFields::secret_only(our_payment_secret), height + 1, &None).unwrap();
                        // Edit amt_to_forward to simulate the sender having set
                        // the final amount and the routing node taking less fee
-                       if let msgs::OutboundOnionPayload::Receive { ref mut amt_msat, .. } = onion_payloads[1] {
-                               *amt_msat = 99_000;
+                       if let msgs::OutboundOnionPayload::Receive {
+                               ref mut sender_intended_htlc_amt_msat, ..
+                       } = onion_payloads[1] {
+                               *sender_intended_htlc_amt_msat = 99_000;
                        } else { panic!() }
                        let new_onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash).unwrap();
                        payment_event.msgs[0].onion_routing_packet = new_onion_packet;
@@ -8981,6 +8979,101 @@ fn test_duplicate_temporary_channel_id_from_different_peers() {
        }
 }
 
+#[test]
+fn test_peer_funding_sidechannel() {
+       // Test that if a peer somehow learns which txid we'll use for our channel funding before we
+       // receive `funding_transaction_generated` the peer cannot cause us to crash. We'd previously
+       // assumed that LDK would receive `funding_transaction_generated` prior to our peer learning
+       // the txid and panicked if the peer tried to open a redundant channel to us with the same
+       // funding outpoint.
+       //
+       // While this assumption is generally safe, some users may have out-of-band protocols where
+       // they notify their LSP about a funding outpoint first, or this may be violated in the future
+       // with collaborative transaction construction protocols, i.e. dual-funding.
+       let chanmon_cfgs = create_chanmon_cfgs(3);
+       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+       let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+       let temp_chan_id_ab = exchange_open_accept_chan(&nodes[0], &nodes[1], 1_000_000, 0);
+       let temp_chan_id_ca = exchange_open_accept_chan(&nodes[2], &nodes[0], 1_000_000, 0);
+
+       let (_, tx, funding_output) =
+               create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
+
+       let cs_funding_events = nodes[2].node.get_and_clear_pending_events();
+       assert_eq!(cs_funding_events.len(), 1);
+       match cs_funding_events[0] {
+               Event::FundingGenerationReady { .. } => {}
+               _ => panic!("Unexpected event {:?}", cs_funding_events),
+       }
+
+       nodes[2].node.funding_transaction_generated_unchecked(&temp_chan_id_ca, &nodes[0].node.get_our_node_id(), tx.clone(), funding_output.index).unwrap();
+       let funding_created_msg = get_event_msg!(nodes[2], MessageSendEvent::SendFundingCreated, nodes[0].node.get_our_node_id());
+       nodes[0].node.handle_funding_created(&nodes[2].node.get_our_node_id(), &funding_created_msg);
+       get_event_msg!(nodes[0], MessageSendEvent::SendFundingSigned, nodes[2].node.get_our_node_id());
+       expect_channel_pending_event(&nodes[0], &nodes[2].node.get_our_node_id());
+       check_added_monitors!(nodes[0], 1);
+
+       let res = nodes[0].node.funding_transaction_generated(&temp_chan_id_ab, &nodes[1].node.get_our_node_id(), tx.clone());
+       let err_msg = format!("{:?}", res.unwrap_err());
+       assert!(err_msg.contains("An existing channel using outpoint "));
+       assert!(err_msg.contains(" is open with peer"));
+       // Even though the last funding_transaction_generated errored, it still generated a
+       // SendFundingCreated. However, when the peer responds with a funding_signed it will send the
+       // appropriate error message.
+       let as_funding_created = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
+       nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &as_funding_created);
+       check_added_monitors!(nodes[1], 1);
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
+       let reason = ClosureReason::ProcessingError { err: format!("An existing channel using outpoint {} is open with peer {}", funding_output, nodes[2].node.get_our_node_id()), };
+       check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(funding_output.to_channel_id(), true, reason)]);
+
+       let funding_signed = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
+       nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed);
+       get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id());
+}
+
+#[test]
+fn test_duplicate_conflicting_funding_from_second_peer() {
+       // Test that if a user tries to fund a channel with a funding outpoint they'd previously used
+       // we don't try to remove the previous ChannelMonitor. This is largely a test to ensure we
+       // don't regress in the fuzzer, as such funding getting passed our outpoint-matches checks
+       // implies the user (and our counterparty) has reused cryptographic keys across channels, which
+       // we require the user not do.
+       let chanmon_cfgs = create_chanmon_cfgs(4);
+       let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+       let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+
+       let temp_chan_id = exchange_open_accept_chan(&nodes[0], &nodes[1], 1_000_000, 0);
+
+       let (_, tx, funding_output) =
+               create_funding_transaction(&nodes[0], &nodes[1].node.get_our_node_id(), 1_000_000, 42);
+
+       // Now that we have a funding outpoint, create a dummy `ChannelMonitor` and insert it into
+       // nodes[0]'s ChainMonitor so that the initial `ChannelMonitor` write fails.
+       let dummy_chan_id = create_chan_between_nodes(&nodes[2], &nodes[3]).3;
+       let dummy_monitor = get_monitor!(nodes[2], dummy_chan_id).clone();
+       nodes[0].chain_monitor.chain_monitor.watch_channel(funding_output, dummy_monitor).unwrap();
+
+       nodes[0].node.funding_transaction_generated(&temp_chan_id, &nodes[1].node.get_our_node_id(), tx.clone()).unwrap();
+
+       let mut funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id());
+       nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg);
+       let funding_signed_msg = get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id());
+       check_added_monitors!(nodes[1], 1);
+       expect_channel_pending_event(&nodes[1], &nodes[0].node.get_our_node_id());
+
+       nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &funding_signed_msg);
+       // At this point, the channel should be closed, after having generated one monitor write (the
+       // watch_channel call which failed), but zero monitor updates.
+       check_added_monitors!(nodes[0], 1);
+       get_err_msg(&nodes[0], &nodes[1].node.get_our_node_id());
+       let err_reason = ClosureReason::ProcessingError { err: "Channel funding outpoint was a duplicate".to_owned() };
+       check_closed_events(&nodes[0], &[ExpectedCloseEvent::from_id_reason(funding_signed_msg.channel_id, true, err_reason)]);
+}
+
 #[test]
 fn test_duplicate_funding_err_in_funding() {
        // Test that if we have a live channel with one peer, then another peer comes along and tries
@@ -9131,16 +9224,16 @@ fn test_duplicate_chan_id() {
                                chan.get_funding_created(tx.clone(), funding_outpoint, false, &&logger).map_err(|_| ()).unwrap()
                        },
                        _ => panic!("Unexpected ChannelPhase variant"),
-               }
+               }.unwrap()
        };
        check_added_monitors!(nodes[0], 0);
-       nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created.unwrap());
+       nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created);
        // At this point we'll look up if the channel_id is present and immediately fail the channel
        // without trying to persist the `ChannelMonitor`.
        check_added_monitors!(nodes[1], 0);
 
        check_closed_events(&nodes[1], &[
-               ExpectedCloseEvent::from_id_reason(channel_id, false, ClosureReason::ProcessingError {
+               ExpectedCloseEvent::from_id_reason(funding_created.temporary_channel_id, false, ClosureReason::ProcessingError {
                        err: "Already had channel with the new channel_id".to_owned()
                })
        ]);
@@ -10596,17 +10689,23 @@ fn test_disconnect_in_funding_batch() {
        nodes[0].node.peer_disconnected(&nodes[2].node.get_our_node_id());
 
        // The channels in the batch will close immediately.
-       let channel_id_1 = OutPoint { txid: tx.txid(), index: 0 }.to_channel_id();
-       let channel_id_2 = OutPoint { txid: tx.txid(), index: 1 }.to_channel_id();
+       let funding_txo_1 = OutPoint { txid: tx.txid(), index: 0 };
+       let funding_txo_2 = OutPoint { txid: tx.txid(), index: 1 };
+       let channel_id_1 = funding_txo_1.to_channel_id();
+       let channel_id_2 = funding_txo_2.to_channel_id();
        check_closed_events(&nodes[0], &[
                ExpectedCloseEvent {
                        channel_id: Some(channel_id_1),
                        discard_funding: true,
+                       channel_funding_txo: Some(funding_txo_1),
+                       user_channel_id: Some(42),
                        ..Default::default()
                },
                ExpectedCloseEvent {
                        channel_id: Some(channel_id_2),
                        discard_funding: true,
+                       channel_funding_txo: Some(funding_txo_2),
+                       user_channel_id: Some(43),
                        ..Default::default()
                },
        ]);
@@ -10664,8 +10763,10 @@ fn test_batch_funding_close_after_funding_signed() {
        assert_eq!(nodes[0].tx_broadcaster.txn_broadcast().len(), 0);
 
        // Force-close the channel for which we've completed the initial monitor.
-       let channel_id_1 = OutPoint { txid: tx.txid(), index: 0 }.to_channel_id();
-       let channel_id_2 = OutPoint { txid: tx.txid(), index: 1 }.to_channel_id();
+       let funding_txo_1 = OutPoint { txid: tx.txid(), index: 0 };
+       let funding_txo_2 = OutPoint { txid: tx.txid(), index: 1 };
+       let channel_id_1 = funding_txo_1.to_channel_id();
+       let channel_id_2 = funding_txo_2.to_channel_id();
        nodes[0].node.force_close_broadcasting_latest_txn(&channel_id_1, &nodes[1].node.get_our_node_id()).unwrap();
        check_added_monitors(&nodes[0], 2);
        {
@@ -10697,11 +10798,15 @@ fn test_batch_funding_close_after_funding_signed() {
                ExpectedCloseEvent {
                        channel_id: Some(channel_id_1),
                        discard_funding: true,
+                       channel_funding_txo: Some(funding_txo_1),
+                       user_channel_id: Some(42),
                        ..Default::default()
                },
                ExpectedCloseEvent {
                        channel_id: Some(channel_id_2),
                        discard_funding: true,
+                       channel_funding_txo: Some(funding_txo_2),
+                       user_channel_id: Some(43),
                        ..Default::default()
                },
        ]);
index 2ee93a6c46efca8ef2c1d6904f7c7d6553205ca1..eeae514fdf3ce4097f79487ed09ceace231cadd4 100644 (file)
@@ -18,8 +18,8 @@ use crate::sign::{KeyMaterial, EntropySource};
 use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use crate::ln::msgs;
 use crate::ln::msgs::MAX_VALUE_MSAT;
-use crate::util::chacha20::ChaCha20;
-use crate::util::crypto::hkdf_extract_expand_5x;
+use crate::crypto::chacha20::ChaCha20;
+use crate::crypto::utils::hkdf_extract_expand_5x;
 use crate::util::errors::APIError;
 use crate::util::logger::Logger;
 
index 74740a6f2279d6549ba57b443b473410e26fbef6..b62701814399d99240354d1200908b61732e99ae 100644 (file)
@@ -19,7 +19,7 @@ use crate::ln::channel;
 use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, PaymentId, RecipientOnionFields};
 use crate::ln::msgs::ChannelMessageHandler;
 use crate::util::config::UserConfig;
-use crate::util::crypto::sign;
+use crate::crypto::utils::sign;
 use crate::util::ser::Writeable;
 use crate::util::scid_utils::block_from_scid;
 use crate::util::test_utils;
index 2e56e2fc2c0c95d2e3cb3380d1f8b50138404ead..d39f1a6084274762331b456d28494b725999d69e 100644 (file)
@@ -53,7 +53,7 @@ use crate::io::{self, Cursor, Read};
 use crate::io_extras::read_to_end;
 
 use crate::events::{EventsProvider, MessageSendEventsProvider};
-use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter;
+use crate::crypto::streams::ChaChaPolyReadAdapter;
 use crate::util::logger;
 use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
 use crate::util::base32;
@@ -695,7 +695,7 @@ pub struct OnionMessage {
        /// Used in decrypting the onion packet's payload.
        pub blinding_point: PublicKey,
        /// The full onion packet including hop data, pubkey, and hmac
-       pub onion_routing_packet: onion_message::Packet,
+       pub onion_routing_packet: onion_message::packet::Packet,
 }
 
 /// An [`update_fulfill_htlc`] message to be sent to or received from a peer.
@@ -1706,20 +1706,20 @@ mod fuzzy_internal_msgs {
                        payment_metadata: Option<Vec<u8>>,
                        keysend_preimage: Option<PaymentPreimage>,
                        custom_tlvs: Vec<(u64, Vec<u8>)>,
-                       amt_msat: u64,
-                       outgoing_cltv_value: u32,
+                       sender_intended_htlc_amt_msat: u64,
+                       cltv_expiry_height: u32,
                },
                BlindedForward {
                        short_channel_id: u64,
                        payment_relay: PaymentRelay,
                        payment_constraints: PaymentConstraints,
                        features: BlindedHopFeatures,
-                       intro_node_blinding_point: PublicKey,
+                       intro_node_blinding_point: Option<PublicKey>,
                },
                BlindedReceive {
-                       amt_msat: u64,
+                       sender_intended_htlc_amt_msat: u64,
                        total_msat: u64,
-                       outgoing_cltv_value: u32,
+                       cltv_expiry_height: u32,
                        payment_secret: PaymentSecret,
                        payment_constraints: PaymentConstraints,
                        intro_node_blinding_point: Option<PublicKey>,
@@ -1738,17 +1738,17 @@ mod fuzzy_internal_msgs {
                        payment_metadata: Option<Vec<u8>>,
                        keysend_preimage: Option<PaymentPreimage>,
                        custom_tlvs: Vec<(u64, Vec<u8>)>,
-                       amt_msat: u64,
-                       outgoing_cltv_value: u32,
+                       sender_intended_htlc_amt_msat: u64,
+                       cltv_expiry_height: u32,
                },
                BlindedForward {
                        encrypted_tlvs: Vec<u8>,
                        intro_node_blinding_point: Option<PublicKey>,
                },
                BlindedReceive {
-                       amt_msat: u64,
+                       sender_intended_htlc_amt_msat: u64,
                        total_msat: u64,
-                       outgoing_cltv_value: u32,
+                       cltv_expiry_height: u32,
                        encrypted_tlvs: Vec<u8>,
                        intro_node_blinding_point: Option<PublicKey>, // Set if the introduction node of the blinded path is the final node
                }
@@ -2245,7 +2245,8 @@ impl Readable for OnionMessage {
                let blinding_point: PublicKey = Readable::read(r)?;
                let len: u16 = Readable::read(r)?;
                let mut packet_reader = FixedLengthReader::new(r, len as u64);
-               let onion_routing_packet: onion_message::Packet = <onion_message::Packet as LengthReadable>::read(&mut packet_reader)?;
+               let onion_routing_packet: onion_message::packet::Packet =
+                       <onion_message::packet::Packet as LengthReadable>::read(&mut packet_reader)?;
                Ok(Self {
                        blinding_point,
                        onion_routing_packet,
@@ -2289,8 +2290,8 @@ impl Writeable for OutboundOnionPayload {
                                });
                        },
                        Self::Receive {
-                               ref payment_data, ref payment_metadata, ref keysend_preimage, amt_msat,
-                               outgoing_cltv_value, ref custom_tlvs,
+                               ref payment_data, ref payment_metadata, ref keysend_preimage, sender_intended_htlc_amt_msat,
+                               cltv_expiry_height, ref custom_tlvs,
                        } => {
                                // We need to update [`ln::outbound_payment::RecipientOnionFields::with_custom_tlvs`]
                                // to reject any reserved types in the experimental range if new ones are ever
@@ -2299,8 +2300,8 @@ impl Writeable for OutboundOnionPayload {
                                let mut custom_tlvs: Vec<&(u64, Vec<u8>)> = custom_tlvs.iter().chain(keysend_tlv.iter()).collect();
                                custom_tlvs.sort_unstable_by_key(|(typ, _)| *typ);
                                _encode_varint_length_prefixed_tlv!(w, {
-                                       (2, HighZeroBytesDroppedBigSize(*amt_msat), required),
-                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+                                       (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
+                                       (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
                                        (8, payment_data, option),
                                        (16, payment_metadata.as_ref().map(|m| WithoutLength(m)), option)
                                }, custom_tlvs.iter());
@@ -2312,12 +2313,12 @@ impl Writeable for OutboundOnionPayload {
                                });
                        },
                        Self::BlindedReceive {
-                               amt_msat, total_msat, outgoing_cltv_value, encrypted_tlvs,
+                               sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, encrypted_tlvs,
                                intro_node_blinding_point,
                        } => {
                                _encode_varint_length_prefixed_tlv!(w, {
-                                       (2, HighZeroBytesDroppedBigSize(*amt_msat), required),
-                                       (4, HighZeroBytesDroppedBigSize(*outgoing_cltv_value), required),
+                                       (2, HighZeroBytesDroppedBigSize(*sender_intended_htlc_amt_msat), required),
+                                       (4, HighZeroBytesDroppedBigSize(*cltv_expiry_height), required),
                                        (10, *encrypted_tlvs, required_vec),
                                        (12, intro_node_blinding_point, option),
                                        (18, HighZeroBytesDroppedBigSize(*total_msat), required)
@@ -2393,7 +2394,7 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                                payment_relay,
                                                payment_constraints,
                                                features,
-                                               intro_node_blinding_point: intro_node_blinding_point.ok_or(DecodeError::InvalidValue)?,
+                                               intro_node_blinding_point,
                                        })
                                },
                                ChaChaPolyReadAdapter { readable: BlindedPaymentTlvs::Receive(ReceiveTlvs {
@@ -2401,9 +2402,9 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                })} => {
                                        if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
                                        Ok(Self::BlindedReceive {
-                                               amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+                                               sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
                                                total_msat: total_msat.ok_or(DecodeError::InvalidValue)?,
-                                               outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
+                                               cltv_expiry_height: cltv_value.ok_or(DecodeError::InvalidValue)?,
                                                payment_secret,
                                                payment_constraints,
                                                intro_node_blinding_point,
@@ -2432,8 +2433,8 @@ impl<NS: Deref> ReadableArgs<(Option<PublicKey>, &NS)> for InboundOnionPayload w
                                payment_data,
                                payment_metadata: payment_metadata.map(|w| w.0),
                                keysend_preimage,
-                               amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
-                               outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
+                               sender_intended_htlc_amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+                               cltv_expiry_height: cltv_value.ok_or(DecodeError::InvalidValue)?,
                                custom_tlvs,
                        })
                }
@@ -4019,8 +4020,8 @@ mod tests {
                        payment_data: None,
                        payment_metadata: None,
                        keysend_preimage: None,
-                       amt_msat: 0x0badf00d01020304,
-                       outgoing_cltv_value: 0xffffffff,
+                       sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+                       cltv_expiry_height: 0xffffffff,
                        custom_tlvs: vec![],
                };
                let encoded_value = outbound_msg.encode();
@@ -4030,10 +4031,10 @@ mod tests {
                let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
                let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), (None, &&node_signer)).unwrap();
                if let msgs::InboundOnionPayload::Receive {
-                       payment_data: None, amt_msat, outgoing_cltv_value, ..
+                       payment_data: None, sender_intended_htlc_amt_msat, cltv_expiry_height, ..
                } = inbound_msg {
-                       assert_eq!(amt_msat, 0x0badf00d01020304);
-                       assert_eq!(outgoing_cltv_value, 0xffffffff);
+                       assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304);
+                       assert_eq!(cltv_expiry_height, 0xffffffff);
                } else { panic!(); }
        }
 
@@ -4047,8 +4048,8 @@ mod tests {
                        }),
                        payment_metadata: None,
                        keysend_preimage: None,
-                       amt_msat: 0x0badf00d01020304,
-                       outgoing_cltv_value: 0xffffffff,
+                       sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+                       cltv_expiry_height: 0xffffffff,
                        custom_tlvs: vec![],
                };
                let encoded_value = outbound_msg.encode();
@@ -4062,14 +4063,14 @@ mod tests {
                                payment_secret,
                                total_msat: 0x1badca1f
                        }),
-                       amt_msat, outgoing_cltv_value,
+                       sender_intended_htlc_amt_msat, cltv_expiry_height,
                        payment_metadata: None,
                        keysend_preimage: None,
                        custom_tlvs,
                } = inbound_msg  {
                        assert_eq!(payment_secret, expected_payment_secret);
-                       assert_eq!(amt_msat, 0x0badf00d01020304);
-                       assert_eq!(outgoing_cltv_value, 0xffffffff);
+                       assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304);
+                       assert_eq!(cltv_expiry_height, 0xffffffff);
                        assert_eq!(custom_tlvs, vec![]);
                } else { panic!(); }
        }
@@ -4087,8 +4088,8 @@ mod tests {
                        payment_metadata: None,
                        keysend_preimage: None,
                        custom_tlvs: bad_type_range_tlvs,
-                       amt_msat: 0x0badf00d01020304,
-                       outgoing_cltv_value: 0xffffffff,
+                       sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+                       cltv_expiry_height: 0xffffffff,
                };
                let encoded_value = msg.encode();
                let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
@@ -4119,8 +4120,8 @@ mod tests {
                        payment_metadata: None,
                        keysend_preimage: None,
                        custom_tlvs: expected_custom_tlvs.clone(),
-                       amt_msat: 0x0badf00d01020304,
-                       outgoing_cltv_value: 0xffffffff,
+                       sender_intended_htlc_amt_msat: 0x0badf00d01020304,
+                       cltv_expiry_height: 0xffffffff,
                };
                let encoded_value = msg.encode();
                let target_value = <Vec<u8>>::from_hex("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap();
@@ -4132,12 +4133,12 @@ mod tests {
                        payment_metadata: None,
                        keysend_preimage: None,
                        custom_tlvs,
-                       amt_msat,
-                       outgoing_cltv_value,
+                       sender_intended_htlc_amt_msat,
+                       cltv_expiry_height: outgoing_cltv_value,
                        ..
                } = inbound_msg {
                        assert_eq!(custom_tlvs, expected_custom_tlvs);
-                       assert_eq!(amt_msat, 0x0badf00d01020304);
+                       assert_eq!(sender_intended_htlc_amt_msat, 0x0badf00d01020304);
                        assert_eq!(outgoing_cltv_value, 0xffffffff);
                } else { panic!(); }
        }
index 5966dce91039db227155264deb0557a2ed2012ff..00843d5e4e93d0ec11feb609e9d5009c98e85203 100644 (file)
@@ -12,7 +12,7 @@ use crate::blinded_path;
 use crate::blinded_path::payment::{PaymentConstraints, PaymentRelay};
 use crate::chain::channelmonitor::{HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
 use crate::ln::PaymentHash;
-use crate::ln::channelmanager::{BlindedForward, CLTV_FAR_FAR_AWAY, HTLCFailureMsg, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting};
+use crate::ln::channelmanager::{BlindedFailure, BlindedForward, CLTV_FAR_FAR_AWAY, HTLCFailureMsg, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting};
 use crate::ln::features::BlindedHopFeatures;
 use crate::ln::msgs;
 use crate::ln::onion_utils;
@@ -25,7 +25,7 @@ use core::ops::Deref;
 
 /// Invalid inbound onion payment.
 #[derive(Debug)]
-pub struct InboundOnionErr {
+pub struct InboundHTLCErr {
        /// BOLT 4 error code.
        pub err_code: u16,
        /// Data attached to this error.
@@ -63,7 +63,7 @@ pub(super) fn create_fwd_pending_htlc_info(
        msg: &msgs::UpdateAddHTLC, hop_data: msgs::InboundOnionPayload, hop_hmac: [u8; 32],
        new_packet_bytes: [u8; onion_utils::ONION_DATA_LEN], shared_secret: [u8; 32],
        next_packet_pubkey_opt: Option<Result<PublicKey, secp256k1::Error>>
-) -> Result<PendingHTLCInfo, InboundOnionErr> {
+) -> Result<PendingHTLCInfo, InboundHTLCErr> {
        debug_assert!(next_packet_pubkey_opt.is_some());
        let outgoing_packet = msgs::OnionPacket {
                version: 0,
@@ -73,7 +73,7 @@ pub(super) fn create_fwd_pending_htlc_info(
        };
 
        let (
-               short_channel_id, amt_to_forward, outgoing_cltv_value, inbound_blinding_point
+               short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point
        ) = match hop_data {
                msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } =>
                        (short_channel_id, amt_to_forward, outgoing_cltv_value, None),
@@ -85,16 +85,16 @@ pub(super) fn create_fwd_pending_htlc_info(
                        ).map_err(|()| {
                                // We should be returning malformed here if `msg.blinding_point` is set, but this is
                                // unreachable right now since we checked it in `decode_update_add_htlc_onion`.
-                               InboundOnionErr {
+                               InboundHTLCErr {
                                        msg: "Underflow calculating outbound amount or cltv value for blinded forward",
                                        err_code: INVALID_ONION_BLINDING,
                                        err_data: vec![0; 32],
                                }
                        })?;
-                       (short_channel_id, amt_to_forward, outgoing_cltv_value, Some(intro_node_blinding_point))
+                       (short_channel_id, amt_to_forward, outgoing_cltv_value, intro_node_blinding_point)
                },
                msgs::InboundOnionPayload::Receive { .. } | msgs::InboundOnionPayload::BlindedReceive { .. } =>
-                       return Err(InboundOnionErr {
+                       return Err(InboundHTLCErr {
                                msg: "Final Node OnionHopData provided for us as an intermediary node",
                                err_code: 0x4000 | 22,
                                err_data: Vec::new(),
@@ -105,7 +105,13 @@ pub(super) fn create_fwd_pending_htlc_info(
                routing: PendingHTLCRouting::Forward {
                        onion_packet: outgoing_packet,
                        short_channel_id,
-                       blinded: inbound_blinding_point.map(|bp| BlindedForward { inbound_blinding_point: bp }),
+                       blinded: intro_node_blinding_point.or(msg.blinding_point)
+                               .map(|bp| BlindedForward {
+                                       inbound_blinding_point: bp,
+                                       failure: intro_node_blinding_point
+                                               .map(|_| BlindedFailure::FromIntroductionNode)
+                                               .unwrap_or(BlindedFailure::FromBlindedNode),
+                               }),
                },
                payment_hash: msg.payment_hash,
                incoming_shared_secret: shared_secret,
@@ -120,41 +126,44 @@ pub(super) fn create_recv_pending_htlc_info(
        hop_data: msgs::InboundOnionPayload, shared_secret: [u8; 32], payment_hash: PaymentHash,
        amt_msat: u64, cltv_expiry: u32, phantom_shared_secret: Option<[u8; 32]>, allow_underpay: bool,
        counterparty_skimmed_fee_msat: Option<u64>, current_height: u32, accept_mpp_keysend: bool,
-) -> Result<PendingHTLCInfo, InboundOnionErr> {
+) -> Result<PendingHTLCInfo, InboundHTLCErr> {
        let (
-               payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, outgoing_cltv_value,
+               payment_data, keysend_preimage, custom_tlvs, onion_amt_msat, onion_cltv_expiry,
                payment_metadata, requires_blinded_error
        ) = match hop_data {
                msgs::InboundOnionPayload::Receive {
-                       payment_data, keysend_preimage, custom_tlvs, amt_msat, outgoing_cltv_value, payment_metadata, ..
+                       payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
+                       cltv_expiry_height, payment_metadata, ..
                } =>
-                       (payment_data, keysend_preimage, custom_tlvs, amt_msat, outgoing_cltv_value, payment_metadata,
-                        false),
+                       (payment_data, keysend_preimage, custom_tlvs, sender_intended_htlc_amt_msat,
+                        cltv_expiry_height, payment_metadata, false),
                msgs::InboundOnionPayload::BlindedReceive {
-                       amt_msat, total_msat, outgoing_cltv_value, payment_secret, intro_node_blinding_point,
-                       payment_constraints, ..
+                       sender_intended_htlc_amt_msat, total_msat, cltv_expiry_height, payment_secret,
+                       intro_node_blinding_point, payment_constraints, ..
                } => {
-                       check_blinded_payment_constraints(amt_msat, cltv_expiry, &payment_constraints)
+                       check_blinded_payment_constraints(
+                               sender_intended_htlc_amt_msat, cltv_expiry, &payment_constraints
+                       )
                                .map_err(|()| {
-                                       InboundOnionErr {
+                                       InboundHTLCErr {
                                                err_code: INVALID_ONION_BLINDING,
                                                err_data: vec![0; 32],
                                                msg: "Amount or cltv_expiry violated blinded payment constraints",
                                        }
                                })?;
                        let payment_data = msgs::FinalOnionHopData { payment_secret, total_msat };
-                       (Some(payment_data), None, Vec::new(), amt_msat, outgoing_cltv_value, None,
-                        intro_node_blinding_point.is_none())
+                       (Some(payment_data), None, Vec::new(), sender_intended_htlc_amt_msat, cltv_expiry_height,
+                        None, intro_node_blinding_point.is_none())
                }
                msgs::InboundOnionPayload::Forward { .. } => {
-                       return Err(InboundOnionErr {
+                       return Err(InboundHTLCErr {
                                err_code: 0x4000|22,
                                err_data: Vec::new(),
                                msg: "Got non final data with an HMAC of 0",
                        })
                },
                msgs::InboundOnionPayload::BlindedForward { .. } => {
-                       return Err(InboundOnionErr {
+                       return Err(InboundHTLCErr {
                                err_code: INVALID_ONION_BLINDING,
                                err_data: vec![0; 32],
                                msg: "Got blinded non final data with an HMAC of 0",
@@ -162,8 +171,8 @@ pub(super) fn create_recv_pending_htlc_info(
                }
        };
        // final_incorrect_cltv_expiry
-       if outgoing_cltv_value > cltv_expiry {
-               return Err(InboundOnionErr {
+       if onion_cltv_expiry > cltv_expiry {
+               return Err(InboundHTLCErr {
                        msg: "Upstream node set CLTV to less than the CLTV set by the sender",
                        err_code: 18,
                        err_data: cltv_expiry.to_be_bytes().to_vec()
@@ -180,7 +189,7 @@ pub(super) fn create_recv_pending_htlc_info(
                let mut err_data = Vec::with_capacity(12);
                err_data.extend_from_slice(&amt_msat.to_be_bytes());
                err_data.extend_from_slice(&current_height.to_be_bytes());
-               return Err(InboundOnionErr {
+               return Err(InboundHTLCErr {
                        err_code: 0x4000 | 15, err_data,
                        msg: "The final CLTV expiry is too soon to handle",
                });
@@ -189,7 +198,7 @@ pub(super) fn create_recv_pending_htlc_info(
                (allow_underpay && onion_amt_msat >
                 amt_msat.saturating_add(counterparty_skimmed_fee_msat.unwrap_or(0)))
        {
-               return Err(InboundOnionErr {
+               return Err(InboundHTLCErr {
                        err_code: 19,
                        err_data: amt_msat.to_be_bytes().to_vec(),
                        msg: "Upstream node sent less than we were supposed to receive in payment",
@@ -204,14 +213,14 @@ pub(super) fn create_recv_pending_htlc_info(
                // time discrepancies due to a hash collision with X.
                let hashed_preimage = PaymentHash(Sha256::hash(&payment_preimage.0).to_byte_array());
                if hashed_preimage != payment_hash {
-                       return Err(InboundOnionErr {
+                       return Err(InboundHTLCErr {
                                err_code: 0x4000|22,
                                err_data: Vec::new(),
                                msg: "Payment preimage didn't match payment hash",
                        });
                }
                if !accept_mpp_keysend && payment_data.is_some() {
-                       return Err(InboundOnionErr {
+                       return Err(InboundHTLCErr {
                                err_code: 0x4000|22,
                                err_data: Vec::new(),
                                msg: "We don't support MPP keysend payments",
@@ -221,20 +230,20 @@ pub(super) fn create_recv_pending_htlc_info(
                        payment_data,
                        payment_preimage,
                        payment_metadata,
-                       incoming_cltv_expiry: outgoing_cltv_value,
+                       incoming_cltv_expiry: onion_cltv_expiry,
                        custom_tlvs,
                }
        } else if let Some(data) = payment_data {
                PendingHTLCRouting::Receive {
                        payment_data: data,
                        payment_metadata,
-                       incoming_cltv_expiry: outgoing_cltv_value,
+                       incoming_cltv_expiry: onion_cltv_expiry,
                        phantom_shared_secret,
                        custom_tlvs,
                        requires_blinded_error,
                }
        } else {
-               return Err(InboundOnionErr {
+               return Err(InboundHTLCErr {
                        err_code: 0x4000|0x2000|3,
                        err_data: Vec::new(),
                        msg: "We require payment_secrets",
@@ -246,7 +255,7 @@ pub(super) fn create_recv_pending_htlc_info(
                incoming_shared_secret: shared_secret,
                incoming_amt_msat: Some(amt_msat),
                outgoing_amt_msat: onion_amt_msat,
-               outgoing_cltv_value,
+               outgoing_cltv_value: onion_cltv_expiry,
                skimmed_fee_msat: counterparty_skimmed_fee_msat,
        })
 }
@@ -263,7 +272,7 @@ pub(super) fn create_recv_pending_htlc_info(
 pub fn peel_payment_onion<NS: Deref, L: Deref, T: secp256k1::Verification>(
        msg: &msgs::UpdateAddHTLC, node_signer: &NS, logger: &L, secp_ctx: &Secp256k1<T>,
        cur_height: u32, accept_mpp_keysend: bool, allow_skimmed_fees: bool,
-) -> Result<PendingHTLCInfo, InboundOnionErr>
+) -> Result<PendingHTLCInfo, InboundHTLCErr>
 where
        NS::Target: NodeSigner,
        L::Target: Logger,
@@ -276,7 +285,7 @@ where
                        HTLCFailureMsg::Relay(r) => (0x4000 | 22, r.reason.data),
                };
                let msg = "Failed to decode update add htlc onion";
-               InboundOnionErr { msg, err_code, err_data }
+               InboundHTLCErr { msg, err_code, err_data }
        })?;
        Ok(match hop {
                onion_utils::Hop::Forward { next_hop_data, next_hop_hmac, new_packet_bytes } => {
@@ -285,7 +294,7 @@ where
                        } = match next_packet_details_opt {
                                Some(next_packet_details) => next_packet_details,
                                // Forward should always include the next hop details
-                               None => return Err(InboundOnionErr {
+                               None => return Err(InboundHTLCErr {
                                        msg: "Failed to decode update add htlc onion",
                                        err_code: 0x4000 | 22,
                                        err_data: Vec::new(),
@@ -295,7 +304,7 @@ where
                        if let Err((err_msg, code)) = check_incoming_htlc_cltv(
                                cur_height, outgoing_cltv_value, msg.cltv_expiry
                        ) {
-                               return Err(InboundOnionErr {
+                               return Err(InboundHTLCErr {
                                        msg: err_msg,
                                        err_code: code,
                                        err_data: Vec::new(),
index ea6563d445d9161d977dbcd4f76eb1503b98e103..4b39276c066c77ec5975be569c274081158750ed 100644 (file)
@@ -14,7 +14,8 @@ use crate::ln::wire::Encode;
 use crate::routing::gossip::NetworkUpdate;
 use crate::routing::router::{BlindedTail, Path, RouteHop};
 use crate::sign::NodeSigner;
-use crate::util::chacha20::{ChaCha20, ChaChaReader};
+use crate::crypto::chacha20::ChaCha20;
+use crate::crypto::streams::ChaChaReader;
 use crate::util::errors::{self, APIError};
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer, LengthCalculatingWriter};
 use crate::util::logger::Logger;
@@ -188,11 +189,10 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
                                for (i, blinded_hop) in hops.iter().enumerate() {
                                        if i == hops.len() - 1 {
                                                cur_value_msat += final_value_msat;
-                                               cur_cltv += excess_final_cltv_expiry_delta;
                                                res.push(msgs::OutboundOnionPayload::BlindedReceive {
-                                                       amt_msat: *final_value_msat,
+                                                       sender_intended_htlc_amt_msat: *final_value_msat,
                                                        total_msat,
-                                                       outgoing_cltv_value: cltv,
+                                                       cltv_expiry_height: cur_cltv + excess_final_cltv_expiry_delta,
                                                        encrypted_tlvs: blinded_hop.encrypted_payload.clone(),
                                                        intro_node_blinding_point: blinding_point.take(),
                                                });
@@ -214,8 +214,8 @@ pub(super) fn build_onion_payloads(path: &Path, total_msat: u64, mut recipient_o
                                        payment_metadata: recipient_onion.payment_metadata.take(),
                                        keysend_preimage: *keysend_preimage,
                                        custom_tlvs: recipient_onion.custom_tlvs.clone(),
-                                       amt_msat: value_msat,
-                                       outgoing_cltv_value: cltv,
+                                       sender_intended_htlc_amt_msat: value_msat,
+                                       cltv_expiry_height: cltv,
                                });
                        }
                } else {
index c9e1ac47886956eb3a6532d6008ca6d6e62992f7..51e34bdb96967428e432cba2c8a082e1f6352b72 100644 (file)
@@ -24,8 +24,8 @@ use bitcoin::secp256k1;
 
 use hex::DisplayHex;
 
-use crate::util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
-use crate::util::crypto::hkdf_extract_expand_twice;
+use crate::crypto::chacha20poly1305rfc::ChaCha20Poly1305RFC;
+use crate::crypto::utils::hkdf_extract_expand_twice;
 use crate::util::ser::VecWriter;
 
 use core::ops::Deref;
@@ -188,7 +188,7 @@ impl PeerChannelEncryptor {
                nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
 
                let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
-               if !chacha.decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]) {
+               if chacha.variable_time_decrypt(&cyphertext[0..cyphertext.len() - 16], res, &cyphertext[cyphertext.len() - 16..]).is_err() {
                        return Err(LightningError{err: "Bad MAC".to_owned(), action: msgs::ErrorAction::DisconnectPeer{ msg: None }});
                }
                Ok(())
index 9f49b67932bc02c5972f5b7b1351a933df15eacb..6d46558b188b60c2433f51f002121bad268df60c 100644 (file)
@@ -31,8 +31,10 @@ use crate::ln::peer_channel_encryptor::{PeerChannelEncryptor, NextNoiseStep, Mes
 use crate::ln::wire;
 use crate::ln::wire::{Encode, Type};
 #[cfg(not(c_bindings))]
-use crate::onion_message::{SimpleArcOnionMessenger, SimpleRefOnionMessenger};
-use crate::onion_message::{CustomOnionMessageHandler, OffersMessage, OffersMessageHandler, OnionMessageContents, PendingOnionMessage};
+use crate::onion_message::messenger::{SimpleArcOnionMessenger, SimpleRefOnionMessenger};
+use crate::onion_message::messenger::{CustomOnionMessageHandler, PendingOnionMessage};
+use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
+use crate::onion_message::packet::OnionMessageContents;
 use crate::routing::gossip::{NodeId, NodeAlias};
 use crate::util::atomic_counter::AtomicCounter;
 use crate::util::logger::{Logger, WithContext};
@@ -303,6 +305,7 @@ impl ChannelMessageHandler for ErroringMessageHandler {
                features.set_channel_type_optional();
                features.set_scid_privacy_optional();
                features.set_zero_conf_optional();
+               features.set_route_blinding_optional();
                features
        }
 
@@ -384,7 +387,7 @@ pub struct MessageHandler<CM: Deref, RM: Deref, OM: Deref, CustomM: Deref> where
        /// A message handler which handles onion messages. This should generally be an
        /// [`OnionMessenger`], but can also be an [`IgnoringMessageHandler`].
        ///
-       /// [`OnionMessenger`]: crate::onion_message::OnionMessenger
+       /// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
        pub onion_message_handler: OM,
 
        /// A message handler which handles custom messages. The only LDK-provided implementation is
@@ -1607,7 +1610,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                }
 
                if let wire::Message::GossipTimestampFilter(_msg) = message {
-                       // When supporting gossip messages, start inital gossip sync only after we receive
+                       // When supporting gossip messages, start initial gossip sync only after we receive
                        // a GossipTimestampFilter
                        if peer_lock.their_features.as_ref().unwrap().supports_gossip_queries() &&
                                !peer_lock.sent_gossip_timestamp_filter {
@@ -2214,7 +2217,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                                        log_pubkey!(node_id));
                                                                        }
                                                                        // We do not have the peers write lock, so we just store that we're
-                                                                       // about to disconenct the peer and do it after we finish
+                                                                       // about to disconnect the peer and do it after we finish
                                                                        // processing most messages.
                                                                        let msg = msg.map(|msg| wire::Message::<<<CMH as core::ops::Deref>::Target as wire::CustomMessageReader>::CustomMessage>::Error(msg));
                                                                        peers_to_disconnect.insert(node_id, msg);
@@ -2223,7 +2226,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                        log_trace!(logger, "Handling DisconnectPeer HandleError event in peer_handler for node {} with message {}",
                                                                                log_pubkey!(node_id), msg.data);
                                                                        // We do not have the peers write lock, so we just store that we're
-                                                                       // about to disconenct the peer and do it after we finish
+                                                                       // about to disconnect the peer and do it after we finish
                                                                        // processing most messages.
                                                                        peers_to_disconnect.insert(node_id, Some(wire::Message::Warning(msg)));
                                                                },
index b0031a6c3f4e05cd41823ceb9fa785ab3fb91722..23d27b18943c7514af3224e16904268c08df999e 100644 (file)
@@ -16,7 +16,9 @@ use crate::ln::msgs::{self, DecodeError, OnionMessageHandler, SocketAddress};
 use crate::sign::{EntropySource, NodeSigner, Recipient};
 use crate::util::ser::{FixedLengthReader, LengthReadable, Writeable, Writer};
 use crate::util::test_utils;
-use super::{CustomOnionMessageHandler, Destination, MessageRouter, OffersMessage, OffersMessageHandler, OnionMessageContents, OnionMessagePath, OnionMessenger, PendingOnionMessage, SendError};
+use super::messenger::{CustomOnionMessageHandler, Destination, MessageRouter, OnionMessagePath, OnionMessenger, PendingOnionMessage, SendError};
+use super::offers::{OffersMessage, OffersMessageHandler};
+use super::packet::{OnionMessageContents, Packet};
 
 use bitcoin::network::constants::Network;
 use bitcoin::hashes::hex::FromHex;
@@ -571,8 +573,8 @@ fn spec_test_vector() {
        let sender_to_alice_packet_bytes_len = sender_to_alice_packet_bytes.len() as u64;
        let mut reader = io::Cursor::new(sender_to_alice_packet_bytes);
        let mut packet_reader = FixedLengthReader::new(&mut reader, sender_to_alice_packet_bytes_len);
-       let sender_to_alice_packet: super::Packet =
-               <super::Packet as LengthReadable>::read(&mut packet_reader).unwrap();
+       let sender_to_alice_packet: Packet =
+               <Packet as LengthReadable>::read(&mut packet_reader).unwrap();
        let secp_ctx = Secp256k1::new();
        let sender_to_alice_om = msgs::OnionMessage {
                blinding_point: PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&<Vec<u8>>::from_hex("6363636363636363636363636363636363636363636363636363636363636363").unwrap()).unwrap()),
index a8ffcc02466f5afa918bf299e7a41572d24b72fc..5dc3bb422e67efffc880465ad5ab3769ce48fc7a 100644 (file)
@@ -7,8 +7,8 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-//! LDK sends, receives, and forwards onion messages via the [`OnionMessenger`]. See its docs for
-//! more information.
+//! LDK sends, receives, and forwards onion messages via this [`OnionMessenger`], which lives here,
+//! as well as various types, traits, and utilities that it uses.
 
 use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::hmac::{Hmac, HmacEngine};
@@ -26,7 +26,7 @@ use crate::ln::features::{InitFeatures, NodeFeatures};
 use crate::ln::msgs::{self, OnionMessage, OnionMessageHandler, SocketAddress};
 use crate::ln::onion_utils;
 use crate::routing::gossip::{NetworkGraph, NodeId};
-pub use super::packet::OnionMessageContents;
+use super::packet::OnionMessageContents;
 use super::packet::ParsedOnionMessageContents;
 use super::offers::OffersMessageHandler;
 use super::packet::{BIG_PACKET_HOP_DATA_LEN, ForwardControlTlvs, Packet, Payload, ReceiveControlTlvs, SMALL_PACKET_HOP_DATA_LEN};
@@ -74,7 +74,8 @@ pub(super) const MAX_TIMER_TICKS: usize = 2;
 /// # use lightning::blinded_path::BlindedPath;
 /// # use lightning::sign::{EntropySource, KeysManager};
 /// # use lightning::ln::peer_handler::IgnoringMessageHandler;
-/// # use lightning::onion_message::{OnionMessageContents, Destination, MessageRouter, OnionMessagePath, OnionMessenger};
+/// # use lightning::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath, OnionMessenger};
+/// # use lightning::onion_message::packet::OnionMessageContents;
 /// # use lightning::util::logger::{Logger, Record};
 /// # use lightning::util::ser::{Writeable, Writer};
 /// # use lightning::io;
index d106a542fd368156f0a4f7959c37919d8e1821ec..05a8b7d6fbd033922fb140ea97d326287aec8757 100644 (file)
 //!
 //! [offers]: <https://github.com/lightning/bolts/pull/798>
 //! [blinded paths]: crate::blinded_path::BlindedPath
+//! [`OnionMessenger`]: self::messenger::OnionMessenger
 
-mod messenger;
-mod offers;
-mod packet;
+pub mod messenger;
+pub mod offers;
+pub mod packet;
 #[cfg(test)]
 mod functional_tests;
-
-// Re-export structs so they can be imported with just the `onion_message::` module prefix.
-pub use self::messenger::{CustomOnionMessageHandler, DefaultMessageRouter, Destination, MessageRouter, OnionMessageContents, OnionMessagePath, OnionMessenger, PeeledOnion, PendingOnionMessage, SendError};
-pub use self::messenger::{create_onion_message, peel_onion_message};
-#[cfg(not(c_bindings))]
-pub use self::messenger::{SimpleArcOnionMessenger, SimpleRefOnionMessenger};
-pub use self::offers::{OffersMessage, OffersMessageHandler};
-pub use self::packet::{Packet, ParsedOnionMessageContents};
-pub(crate) use self::packet::ControlTlvs;
-pub(crate) use self::messenger::new_pending_onion_message;
index a65c0393a1e922042482cd3d16dca877cf110ea2..6672b5dfcdd0f3e33025c4bfe0654d6cfd2b0e56 100644 (file)
@@ -17,7 +17,7 @@ use crate::offers::invoice_error::InvoiceError;
 use crate::offers::invoice_request::InvoiceRequest;
 use crate::offers::invoice::Bolt12Invoice;
 use crate::offers::parse::Bolt12ParseError;
-use crate::onion_message::OnionMessageContents;
+use crate::onion_message::packet::OnionMessageContents;
 use crate::util::logger::Logger;
 use crate::util::ser::{Readable, ReadableArgs, Writeable, Writer};
 #[cfg(not(c_bindings))]
@@ -39,7 +39,7 @@ pub trait OffersMessageHandler {
        ///
        /// The returned [`OffersMessage`], if any, is enqueued to be sent by [`OnionMessenger`].
        ///
-       /// [`OnionMessenger`]: crate::onion_message::OnionMessenger
+       /// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger
        fn handle_message(&self, message: OffersMessage) -> Option<OffersMessage>;
 
        /// Releases any [`OffersMessage`]s that need to be sent.
@@ -54,7 +54,7 @@ pub trait OffersMessageHandler {
        /// Typically, this is used for messages initiating a payment flow rather than in response to
        /// another message. The latter should use the return value of [`Self::handle_message`].
        #[cfg(c_bindings)]
-       fn release_pending_messages(&self) -> Vec<(OffersMessage, crate::onion_message::Destination, Option<crate::blinded_path::BlindedPath>)> { vec![] }
+       fn release_pending_messages(&self) -> Vec<(OffersMessage, crate::onion_message::messenger::Destination, Option<crate::blinded_path::BlindedPath>)> { vec![] }
 }
 
 /// Possible BOLT 12 Offers messages sent and received via an [`OnionMessage`].
index 5ce02c54d08800b777a0c2c3a25f27ba1ffae462..d9349fdadbfaba6c1f0d08c265c48bf14da49bb7 100644 (file)
@@ -19,7 +19,7 @@ use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils;
 use super::messenger::CustomOnionMessageHandler;
 use super::offers::OffersMessage;
-use crate::util::chacha20poly1305rfc::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
+use crate::crypto::streams::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
 use crate::util::logger::Logger;
 use crate::util::ser::{BigSize, FixedLengthReader, LengthRead, LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer};
 
index c72e5cd9ae77577485c9fbecb5bd9bd5bc1904e2..436a37144b459a4e73d03bace511b875b47e4386 100644 (file)
@@ -20,13 +20,13 @@ use crate::ln::channelmanager::{ChannelDetails, PaymentId};
 use crate::ln::features::{BlindedHopFeatures, Bolt11InvoiceFeatures, Bolt12InvoiceFeatures, ChannelFeatures, NodeFeatures};
 use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
 use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice};
-use crate::onion_message::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath};
+use crate::onion_message::messenger::{DefaultMessageRouter, Destination, MessageRouter, OnionMessagePath};
 use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
 use crate::routing::scoring::{ChannelUsage, LockableScore, ScoreLookUp};
 use crate::sign::EntropySource;
 use crate::util::ser::{Writeable, Readable, ReadableArgs, Writer};
 use crate::util::logger::{Level, Logger};
-use crate::util::chacha20::ChaCha20;
+use crate::crypto::chacha20::ChaCha20;
 
 use crate::io;
 use crate::prelude::*;
@@ -114,19 +114,14 @@ impl<G: Deref<Target = NetworkGraph<L>> + Clone, L: Deref, S: Deref, SP: Sized,
                                        None => return None,
                                };
                                let payment_relay: PaymentRelay = match details.counterparty.forwarding_info {
-                                       Some(forwarding_info) => forwarding_info.into(),
+                                       Some(forwarding_info) => match forwarding_info.try_into() {
+                                               Ok(payment_relay) => payment_relay,
+                                               Err(()) => return None,
+                                       },
                                        None => return None,
                                };
 
-                               // Avoid exposing esoteric CLTV expiry deltas
-                               let cltv_expiry_delta = match payment_relay.cltv_expiry_delta {
-                                       0..=40 => 40u32,
-                                       41..=80 => 80u32,
-                                       81..=144 => 144u32,
-                                       145..=216 => 216u32,
-                                       _ => return None,
-                               };
-
+                               let cltv_expiry_delta = payment_relay.cltv_expiry_delta as u32;
                                let payment_constraints = PaymentConstraints {
                                        max_cltv_expiry: tlvs.payment_constraints.max_cltv_expiry + cltv_expiry_delta,
                                        htlc_minimum_msat: details.inbound_htlc_minimum_msat.unwrap_or(0),
@@ -2745,7 +2740,7 @@ where L::Target: Logger {
                                                }
                                        }
 
-                                       // Means we succesfully traversed from the payer to the payee, now
+                                       // Means we successfully traversed from the payer to the payee, now
                                        // save this path for the payment route. Also, update the liquidity
                                        // remaining on the used hops, so that we take them into account
                                        // while looking for more paths.
@@ -3234,7 +3229,7 @@ mod tests {
        use crate::offers::invoice::BlindedPayInfo;
        use crate::util::config::UserConfig;
        use crate::util::test_utils as ln_test_utils;
-       use crate::util::chacha20::ChaCha20;
+       use crate::crypto::chacha20::ChaCha20;
        use crate::util::ser::{Readable, Writeable};
        #[cfg(c_bindings)]
        use crate::util::ser::Writer;
@@ -7842,7 +7837,7 @@ mod tests {
        fn do_min_htlc_overpay_violates_max_htlc(blinded_payee: bool) {
                // Test that if overpaying to meet a later hop's min_htlc and causes us to violate an earlier
                // hop's max_htlc, we don't consider that candidate hop valid. Previously we would add this hop
-               // to `targets` and build an invalid path with it, and subsquently hit a debug panic asserting
+               // to `targets` and build an invalid path with it, and subsequently hit a debug panic asserting
                // that the used liquidity for a hop was less than its available liquidity limit.
                let secp_ctx = Secp256k1::new();
                let logger = Arc::new(ln_test_utils::TestLogger::new());
@@ -8491,7 +8486,7 @@ pub(crate) mod bench_utils {
                                                        }
                                                        break;
                                                }
-                                               // If we couldn't find a path with a higer amount, reduce and try again.
+                                               // If we couldn't find a path with a higher amount, reduce and try again.
                                                score_amt /= 100;
                                        }
 
index 4e418f049bbc9867a7a2a7920706e17c135ed23e..c4bb6fb8020ed8d5d1ee3c32a862f44b19a82737 100644 (file)
@@ -38,7 +38,7 @@ use bitcoin::secp256k1::schnorr;
 use bitcoin::{secp256k1, Sequence, Witness, Txid};
 
 use crate::util::transaction_utils;
-use crate::util::crypto::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
+use crate::crypto::utils::{hkdf_extract_expand_twice, sign, sign_with_aux_rand};
 use crate::util::ser::{Writeable, Writer, Readable, ReadableArgs};
 use crate::chain::transaction::OutPoint;
 use crate::ln::channel::ANCHOR_OUTPUT_VALUE_SATOSHI;
@@ -65,7 +65,7 @@ use crate::sign::ecdsa::{EcdsaChannelSigner, WriteableEcdsaChannelSigner};
 #[cfg(taproot)]
 use crate::sign::taproot::TaprootChannelSigner;
 use crate::util::atomic_counter::AtomicCounter;
-use crate::util::chacha20::ChaCha20;
+use crate::crypto::chacha20::ChaCha20;
 use crate::util::invoice::construct_invoice_preimage;
 
 pub(crate) mod type_resolver;
diff --git a/lightning/src/util/chacha20.rs b/lightning/src/util/chacha20.rs
deleted file mode 100644 (file)
index 865a09f..0000000
+++ /dev/null
@@ -1,701 +0,0 @@
-// This file was stolen from rust-crypto.
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-
-use crate::io;
-
-#[cfg(not(fuzzing))]
-mod real_chacha {
-       use core::cmp;
-       use core::convert::TryInto;
-
-       #[derive(Clone, Copy, PartialEq, Eq)]
-       #[allow(non_camel_case_types)]
-       struct u32x4(pub u32, pub u32, pub u32, pub u32);
-       impl ::core::ops::Add for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn add(self, rhs: u32x4) -> u32x4 {
-                       u32x4(self.0.wrapping_add(rhs.0),
-                             self.1.wrapping_add(rhs.1),
-                             self.2.wrapping_add(rhs.2),
-                             self.3.wrapping_add(rhs.3))
-               }
-       }
-       impl ::core::ops::Sub for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn sub(self, rhs: u32x4) -> u32x4 {
-                       u32x4(self.0.wrapping_sub(rhs.0),
-                             self.1.wrapping_sub(rhs.1),
-                             self.2.wrapping_sub(rhs.2),
-                             self.3.wrapping_sub(rhs.3))
-               }
-       }
-       impl ::core::ops::BitXor for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn bitxor(self, rhs: u32x4) -> u32x4 {
-                       u32x4(self.0 ^ rhs.0, self.1 ^ rhs.1, self.2 ^ rhs.2, self.3 ^ rhs.3)
-               }
-       }
-       impl ::core::ops::Shr<u8> for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn shr(self, shr: u8) -> u32x4 {
-                       u32x4(self.0 >> shr, self.1 >> shr, self.2 >> shr, self.3 >> shr)
-               }
-       }
-       impl ::core::ops::Shl<u8> for u32x4 {
-               type Output = u32x4;
-               #[inline]
-               fn shl(self, shl: u8) -> u32x4 {
-                       u32x4(self.0 << shl, self.1 << shl, self.2 << shl, self.3 << shl)
-               }
-       }
-       impl u32x4 {
-               #[inline]
-               fn from_bytes(bytes: &[u8]) -> Self {
-                       assert_eq!(bytes.len(), 4*4);
-                       Self (
-                               u32::from_le_bytes(bytes[0*4..1*4].try_into().expect("len is 4")),
-                               u32::from_le_bytes(bytes[1*4..2*4].try_into().expect("len is 4")),
-                               u32::from_le_bytes(bytes[2*4..3*4].try_into().expect("len is 4")),
-                               u32::from_le_bytes(bytes[3*4..4*4].try_into().expect("len is 4")),
-                       )
-               }
-       }
-
-       const BLOCK_SIZE: usize = 64;
-
-       #[derive(Clone,Copy)]
-       struct ChaChaState {
-               a: u32x4,
-               b: u32x4,
-               c: u32x4,
-               d: u32x4
-       }
-
-       #[derive(Copy)]
-       pub struct ChaCha20 {
-               state  : ChaChaState,
-               output : [u8; BLOCK_SIZE],
-               offset : usize,
-       }
-
-       impl Clone for ChaCha20 { fn clone(&self) -> ChaCha20 { *self } }
-
-       macro_rules! swizzle {
-               ($b: expr, $c: expr, $d: expr) => {{
-                       let u32x4(b10, b11, b12, b13) = $b;
-                       $b = u32x4(b11, b12, b13, b10);
-                       let u32x4(c10, c11, c12, c13) = $c;
-                       $c = u32x4(c12, c13,c10, c11);
-                       let u32x4(d10, d11, d12, d13) = $d;
-                       $d = u32x4(d13, d10, d11, d12);
-               }}
-       }
-
-       macro_rules! state_to_buffer {
-               ($state: expr, $output: expr) => {{
-                       let u32x4(a1, a2, a3, a4) = $state.a;
-                       let u32x4(b1, b2, b3, b4) = $state.b;
-                       let u32x4(c1, c2, c3, c4) = $state.c;
-                       let u32x4(d1, d2, d3, d4) = $state.d;
-                       let lens = [
-                               a1,a2,a3,a4,
-                               b1,b2,b3,b4,
-                               c1,c2,c3,c4,
-                               d1,d2,d3,d4
-                       ];
-                       for i in 0..lens.len() {
-                               $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
-                       }
-               }}
-       }
-
-       macro_rules! round{
-               ($state: expr) => {{
-                       $state.a = $state.a + $state.b;
-                       rotate!($state.d, $state.a, 16);
-                       $state.c = $state.c + $state.d;
-                       rotate!($state.b, $state.c, 12);
-                       $state.a = $state.a + $state.b;
-                       rotate!($state.d, $state.a, 8);
-                       $state.c = $state.c + $state.d;
-                       rotate!($state.b, $state.c, 7);
-               }}
-       }
-
-       macro_rules! rotate {
-               ($a: expr, $b: expr, $rot: expr) => {{
-                       let v = $a ^ $b;
-                       let r = 32 - $rot;
-                       let right = v >> r;
-                       $a = (v << $rot) ^ right
-               }}
-       }
-
-       impl ChaCha20 {
-               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
-                       assert!(key.len() == 16 || key.len() == 32);
-                       assert!(nonce.len() == 8 || nonce.len() == 12);
-
-                       ChaCha20{ state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 }
-               }
-
-               /// Get one block from a ChaCha stream.
-               pub fn get_single_block(key: &[u8; 32], nonce: &[u8; 16]) -> [u8; 32] {
-                       let mut chacha = ChaCha20 { state: ChaCha20::expand(key, nonce), output: [0u8; BLOCK_SIZE], offset: 64 };
-                       let mut chacha_bytes = [0; 32];
-                       chacha.process_in_place(&mut chacha_bytes);
-                       chacha_bytes
-               }
-
-               /// Encrypts `src` into `dest` using a single block from a ChaCha stream. Passing `dest` as
-               /// `src` in a second call will decrypt it.
-               pub fn encrypt_single_block(
-                       key: &[u8; 32], nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
-               ) {
-                       debug_assert_eq!(dest.len(), src.len());
-                       debug_assert!(dest.len() <= 32);
-
-                       let block = ChaCha20::get_single_block(key, nonce);
-                       for i in 0..dest.len() {
-                               dest[i] = block[i] ^ src[i];
-                       }
-               }
-
-               /// Same as `encrypt_single_block` only operates on a fixed-size input in-place.
-               pub fn encrypt_single_block_in_place(
-                       key: &[u8; 32], nonce: &[u8; 16], bytes: &mut [u8; 32]
-               ) {
-                       let block = ChaCha20::get_single_block(key, nonce);
-                       for i in 0..bytes.len() {
-                               bytes[i] = block[i] ^ bytes[i];
-                       }
-               }
-
-               fn expand(key: &[u8], nonce: &[u8]) -> ChaChaState {
-                       let constant = match key.len() {
-                               16 => b"expand 16-byte k",
-                               32 => b"expand 32-byte k",
-                               _  => unreachable!(),
-                       };
-                       ChaChaState {
-                               a: u32x4::from_bytes(&constant[0..16]),
-                               b: u32x4::from_bytes(&key[0..16]),
-                               c: if key.len() == 16 {
-                                       u32x4::from_bytes(&key[0..16])
-                               } else {
-                                       u32x4::from_bytes(&key[16..32])
-                               },
-                               d: if nonce.len() == 16 {
-                                       u32x4::from_bytes(&nonce[0..16])
-                               } else if nonce.len() == 12 {
-                                       let mut nonce4 = [0; 4*4];
-                                       nonce4[4..].copy_from_slice(nonce);
-                                       u32x4::from_bytes(&nonce4)
-                               } else {
-                                       let mut nonce4 = [0; 4*4];
-                                       nonce4[8..].copy_from_slice(nonce);
-                                       u32x4::from_bytes(&nonce4)
-                               }
-                       }
-               }
-
-               // put the the next BLOCK_SIZE keystream bytes into self.output
-               fn update(&mut self) {
-                       let mut state = self.state;
-
-                       for _ in 0..10 {
-                               round!(state);
-                               swizzle!(state.b, state.c, state.d);
-                               round!(state);
-                               swizzle!(state.d, state.c, state.b);
-                       }
-                       state.a = state.a + self.state.a;
-                       state.b = state.b + self.state.b;
-                       state.c = state.c + self.state.c;
-                       state.d = state.d + self.state.d;
-
-                       state_to_buffer!(state, self.output);
-
-                       self.state.d = self.state.d + u32x4(1, 0, 0, 0);
-                       let u32x4(c12, _, _, _) = self.state.d;
-                       if c12 == 0 {
-                               // we could increment the other counter word with an 8 byte nonce
-                               // but other implementations like boringssl have this same
-                               // limitation
-                               panic!("counter is exhausted");
-                       }
-
-                       self.offset = 0;
-               }
-
-               #[inline] // Useful cause input may be 0s on stack that should be optimized out
-               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
-                       assert!(input.len() == output.len());
-                       let len = input.len();
-                       let mut i = 0;
-                       while i < len {
-                               // If there is no keystream available in the output buffer,
-                               // generate the next block.
-                               if self.offset == BLOCK_SIZE {
-                                       self.update();
-                               }
-
-                               // Process the min(available keystream, remaining input length).
-                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
-                               // explicitly assert lengths to avoid bounds checks:
-                               assert!(output.len() >= i + count);
-                               assert!(input.len() >= i + count);
-                               assert!(self.output.len() >= self.offset + count);
-                               for j in 0..count {
-                                       output[i + j] = input[i + j] ^ self.output[self.offset + j];
-                               }
-                               i += count;
-                               self.offset += count;
-                       }
-               }
-
-               pub fn process_in_place(&mut self, input_output: &mut [u8]) {
-                       let len = input_output.len();
-                       let mut i = 0;
-                       while i < len {
-                               // If there is no keystream available in the output buffer,
-                               // generate the next block.
-                               if self.offset == BLOCK_SIZE {
-                                       self.update();
-                               }
-
-                               // Process the min(available keystream, remaining input length).
-                               let count = cmp::min(BLOCK_SIZE - self.offset, len - i);
-                               // explicitly assert lengths to avoid bounds checks:
-                               assert!(input_output.len() >= i + count);
-                               assert!(self.output.len() >= self.offset + count);
-                               for j in 0..count {
-                                       input_output[i + j] ^= self.output[self.offset + j];
-                               }
-                               i += count;
-                               self.offset += count;
-                       }
-               }
-
-               #[cfg(test)]
-               pub fn seek_to_block(&mut self, block_offset: u32) {
-                       self.state.d.0 = block_offset;
-                       self.update();
-               }
-       }
-}
-#[cfg(not(fuzzing))]
-pub use self::real_chacha::ChaCha20;
-
-#[cfg(fuzzing)]
-mod fuzzy_chacha {
-       pub struct ChaCha20 {}
-
-       impl ChaCha20 {
-               pub fn new(key: &[u8], nonce: &[u8]) -> ChaCha20 {
-                       assert!(key.len() == 16 || key.len() == 32);
-                       assert!(nonce.len() == 8 || nonce.len() == 12);
-                       Self {}
-               }
-
-               pub fn get_single_block(_key: &[u8; 32], _nonce: &[u8; 16]) -> [u8; 32] {
-                       [0; 32]
-               }
-
-               pub fn encrypt_single_block(
-                       _key: &[u8; 32], _nonce: &[u8; 16], dest: &mut [u8], src: &[u8]
-               ) {
-                       debug_assert_eq!(dest.len(), src.len());
-                       debug_assert!(dest.len() <= 32);
-               }
-
-               pub fn encrypt_single_block_in_place(
-                       _key: &[u8; 32], _nonce: &[u8; 16], _bytes: &mut [u8; 32]
-               ) {}
-
-               pub fn process(&mut self, input: &[u8], output: &mut [u8]) {
-                       output.copy_from_slice(input);
-               }
-
-               pub fn process_in_place(&mut self, _input_output: &mut [u8]) {}
-       }
-}
-#[cfg(fuzzing)]
-pub use self::fuzzy_chacha::ChaCha20;
-
-pub(crate) struct ChaChaReader<'a, R: io::Read> {
-       pub chacha: &'a mut ChaCha20,
-       pub read: R,
-}
-impl<'a, R: io::Read> io::Read for ChaChaReader<'a, R> {
-       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
-               let res = self.read.read(dest)?;
-               if res > 0 {
-                       self.chacha.process_in_place(&mut dest[0..res]);
-               }
-               Ok(res)
-       }
-}
-
-#[cfg(test)]
-mod test {
-       use crate::prelude::*;
-       use core::iter::repeat;
-
-       use super::ChaCha20;
-       use std::convert::TryInto;
-
-       #[test]
-       fn test_chacha20_256_tls_vectors() {
-               struct TestVector {
-                       key:   [u8; 32],
-                       nonce: [u8; 8],
-                       keystream: Vec<u8>,
-               }
-               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
-               let test_vectors = vec!(
-                       TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
-                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
-                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
-                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
-                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
-                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
-                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
-                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
-                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
-                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
-                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
-                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
-                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
-                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
-                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
-                               keystream: vec!(
-                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
-                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
-                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
-                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
-                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
-                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
-                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
-                                       0x44, 0x5f, 0x41, 0xe3,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
-                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
-                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
-                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
-                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
-                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
-                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
-                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-                               ],
-                               nonce: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
-                               keystream: vec!(
-                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
-                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
-                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
-                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
-                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
-                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
-                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
-                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
-                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
-                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
-                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
-                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
-                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
-                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
-                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
-                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
-                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
-                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
-                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
-                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
-                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
-                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
-                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
-                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
-                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
-                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
-                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
-                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
-                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
-                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
-                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
-                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
-                               ),
-                       },
-               );
-
-               for tv in test_vectors.iter() {
-                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
-                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
-                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
-                       c.process(&input[..], &mut output[..]);
-                       assert_eq!(output, tv.keystream);
-               }
-       }
-
-       #[test]
-       fn test_chacha20_256_tls_vectors_96_nonce() {
-               struct TestVector {
-                       key:   [u8; 32],
-                       nonce: [u8; 12],
-                       keystream: Vec<u8>,
-               }
-               // taken from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
-               let test_vectors = vec!(
-                       TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
-                                       0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
-                                       0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
-                                       0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
-                                       0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
-                                       0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
-                                       0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
-                                       0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0x45, 0x40, 0xf0, 0x5a, 0x9f, 0x1f, 0xb2, 0x96,
-                                       0xd7, 0x73, 0x6e, 0x7b, 0x20, 0x8e, 0x3c, 0x96,
-                                       0xeb, 0x4f, 0xe1, 0x83, 0x46, 0x88, 0xd2, 0x60,
-                                       0x4f, 0x45, 0x09, 0x52, 0xed, 0x43, 0x2d, 0x41,
-                                       0xbb, 0xe2, 0xa0, 0xb6, 0xea, 0x75, 0x66, 0xd2,
-                                       0xa5, 0xd1, 0xe7, 0xe2, 0x0d, 0x42, 0xaf, 0x2c,
-                                       0x53, 0xd7, 0x92, 0xb1, 0xc4, 0x3f, 0xea, 0x81,
-                                       0x7e, 0x9a, 0xd2, 0x75, 0xae, 0x54, 0x69, 0x63,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ],
-                               keystream: vec!(
-                                       0xde, 0x9c, 0xba, 0x7b, 0xf3, 0xd6, 0x9e, 0xf5,
-                                       0xe7, 0x86, 0xdc, 0x63, 0x97, 0x3f, 0x65, 0x3a,
-                                       0x0b, 0x49, 0xe0, 0x15, 0xad, 0xbf, 0xf7, 0x13,
-                                       0x4f, 0xcb, 0x7d, 0xf1, 0x37, 0x82, 0x10, 0x31,
-                                       0xe8, 0x5a, 0x05, 0x02, 0x78, 0xa7, 0x08, 0x45,
-                                       0x27, 0x21, 0x4f, 0x73, 0xef, 0xc7, 0xfa, 0x5b,
-                                       0x52, 0x77, 0x06, 0x2e, 0xb7, 0xa0, 0x43, 0x3e,
-                                       0x44, 0x5f, 0x41, 0xe3,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                               ],
-                               nonce: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
-                               keystream: vec!(
-                                       0xef, 0x3f, 0xdf, 0xd6, 0xc6, 0x15, 0x78, 0xfb,
-                                       0xf5, 0xcf, 0x35, 0xbd, 0x3d, 0xd3, 0x3b, 0x80,
-                                       0x09, 0x63, 0x16, 0x34, 0xd2, 0x1e, 0x42, 0xac,
-                                       0x33, 0x96, 0x0b, 0xd1, 0x38, 0xe5, 0x0d, 0x32,
-                                       0x11, 0x1e, 0x4c, 0xaf, 0x23, 0x7e, 0xe5, 0x3c,
-                                       0xa8, 0xad, 0x64, 0x26, 0x19, 0x4a, 0x88, 0x54,
-                                       0x5d, 0xdc, 0x49, 0x7a, 0x0b, 0x46, 0x6e, 0x7d,
-                                       0x6b, 0xbd, 0xb0, 0x04, 0x1b, 0x2f, 0x58, 0x6b,
-                               ),
-                       }, TestVector{
-                               key: [
-                                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-                               ],
-                               nonce: [0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ],
-                               keystream: vec!(
-                                       0xf7, 0x98, 0xa1, 0x89, 0xf1, 0x95, 0xe6, 0x69,
-                                       0x82, 0x10, 0x5f, 0xfb, 0x64, 0x0b, 0xb7, 0x75,
-                                       0x7f, 0x57, 0x9d, 0xa3, 0x16, 0x02, 0xfc, 0x93,
-                                       0xec, 0x01, 0xac, 0x56, 0xf8, 0x5a, 0xc3, 0xc1,
-                                       0x34, 0xa4, 0x54, 0x7b, 0x73, 0x3b, 0x46, 0x41,
-                                       0x30, 0x42, 0xc9, 0x44, 0x00, 0x49, 0x17, 0x69,
-                                       0x05, 0xd3, 0xbe, 0x59, 0xea, 0x1c, 0x53, 0xf1,
-                                       0x59, 0x16, 0x15, 0x5c, 0x2b, 0xe8, 0x24, 0x1a,
-                                       0x38, 0x00, 0x8b, 0x9a, 0x26, 0xbc, 0x35, 0x94,
-                                       0x1e, 0x24, 0x44, 0x17, 0x7c, 0x8a, 0xde, 0x66,
-                                       0x89, 0xde, 0x95, 0x26, 0x49, 0x86, 0xd9, 0x58,
-                                       0x89, 0xfb, 0x60, 0xe8, 0x46, 0x29, 0xc9, 0xbd,
-                                       0x9a, 0x5a, 0xcb, 0x1c, 0xc1, 0x18, 0xbe, 0x56,
-                                       0x3e, 0xb9, 0xb3, 0xa4, 0xa4, 0x72, 0xf8, 0x2e,
-                                       0x09, 0xa7, 0xe7, 0x78, 0x49, 0x2b, 0x56, 0x2e,
-                                       0xf7, 0x13, 0x0e, 0x88, 0xdf, 0xe0, 0x31, 0xc7,
-                                       0x9d, 0xb9, 0xd4, 0xf7, 0xc7, 0xa8, 0x99, 0x15,
-                                       0x1b, 0x9a, 0x47, 0x50, 0x32, 0xb6, 0x3f, 0xc3,
-                                       0x85, 0x24, 0x5f, 0xe0, 0x54, 0xe3, 0xdd, 0x5a,
-                                       0x97, 0xa5, 0xf5, 0x76, 0xfe, 0x06, 0x40, 0x25,
-                                       0xd3, 0xce, 0x04, 0x2c, 0x56, 0x6a, 0xb2, 0xc5,
-                                       0x07, 0xb1, 0x38, 0xdb, 0x85, 0x3e, 0x3d, 0x69,
-                                       0x59, 0x66, 0x09, 0x96, 0x54, 0x6c, 0xc9, 0xc4,
-                                       0xa6, 0xea, 0xfd, 0xc7, 0x77, 0xc0, 0x40, 0xd7,
-                                       0x0e, 0xaf, 0x46, 0xf7, 0x6d, 0xad, 0x39, 0x79,
-                                       0xe5, 0xc5, 0x36, 0x0c, 0x33, 0x17, 0x16, 0x6a,
-                                       0x1c, 0x89, 0x4c, 0x94, 0xa3, 0x71, 0x87, 0x6a,
-                                       0x94, 0xdf, 0x76, 0x28, 0xfe, 0x4e, 0xaa, 0xf2,
-                                       0xcc, 0xb2, 0x7d, 0x5a, 0xaa, 0xe0, 0xad, 0x7a,
-                                       0xd0, 0xf9, 0xd4, 0xb6, 0xad, 0x3b, 0x54, 0x09,
-                                       0x87, 0x46, 0xd4, 0x52, 0x4d, 0x38, 0x40, 0x7a,
-                                       0x6d, 0xeb, 0x3a, 0xb7, 0x8f, 0xab, 0x78, 0xc9,
-                               ),
-                       },
-               );
-
-               for tv in test_vectors.iter() {
-                       let mut c = ChaCha20::new(&tv.key, &tv.nonce);
-                       let input: Vec<u8> = repeat(0).take(tv.keystream.len()).collect();
-                       let mut output: Vec<u8> = repeat(0).take(input.len()).collect();
-                       c.process(&input[..], &mut output[..]);
-                       assert_eq!(output, tv.keystream);
-               }
-       }
-
-       #[test]
-       fn get_single_block() {
-               // Test that `get_single_block` (which takes a 16-byte nonce) is equivalent to getting a block
-               // using a 12-byte nonce, with the block starting at the counter offset given by the remaining 4
-               // bytes.
-               let key = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-               ];
-               let nonce_16bytes = [
-                       0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b
-               ];
-               let counter_pos = &nonce_16bytes[..4];
-               let nonce_12bytes = &nonce_16bytes[4..];
-
-               // Initialize a ChaCha20 instance with its counter starting at 0.
-               let mut chacha20 = ChaCha20::new(&key, nonce_12bytes);
-               // Seek its counter to the block at counter_pos.
-               chacha20.seek_to_block(u32::from_le_bytes(counter_pos.try_into().unwrap()));
-               let mut block_bytes = [0; 32];
-               chacha20.process_in_place(&mut block_bytes);
-
-               assert_eq!(ChaCha20::get_single_block(&key, &nonce_16bytes), block_bytes);
-       }
-
-       #[test]
-       fn encrypt_single_block() {
-               let key = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-               ];
-               let nonce = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-               ];
-               let bytes = [1; 32];
-
-               let mut encrypted_bytes = [0; 32];
-               ChaCha20::encrypt_single_block(&key, &nonce, &mut encrypted_bytes, &bytes);
-
-               let mut decrypted_bytes = [0; 32];
-               ChaCha20::encrypt_single_block(&key, &nonce, &mut decrypted_bytes, &encrypted_bytes);
-
-               assert_eq!(bytes, decrypted_bytes);
-       }
-
-       #[test]
-       fn encrypt_single_block_in_place() {
-               let key = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-                       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-                       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-               ];
-               let nonce = [
-                       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-                       0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-               ];
-               let unencrypted_bytes = [1; 32];
-               let mut bytes = unencrypted_bytes;
-
-               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
-               assert_ne!(bytes, unencrypted_bytes);
-
-               ChaCha20::encrypt_single_block_in_place(&key, &nonce, &mut bytes);
-               assert_eq!(bytes, unencrypted_bytes);
-       }
-}
diff --git a/lightning/src/util/chacha20poly1305rfc.rs b/lightning/src/util/chacha20poly1305rfc.rs
deleted file mode 100644 (file)
index d5792e0..0000000
+++ /dev/null
@@ -1,427 +0,0 @@
-// ring has a garbage API so its use is avoided, but rust-crypto doesn't have RFC-variant poly1305
-// Instead, we steal rust-crypto's implementation and tweak it to match the RFC.
-//
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-//
-// This is a port of Andrew Moons poly1305-donna
-// https://github.com/floodyberry/poly1305-donna
-
-use crate::ln::msgs::DecodeError;
-use crate::util::ser::{FixedLengthReader, LengthRead, LengthReadableArgs, Readable, Writeable, Writer};
-use crate::io::{self, Read, Write};
-
-#[cfg(not(fuzzing))]
-mod real_chachapoly {
-       use crate::util::chacha20::ChaCha20;
-       use crate::util::poly1305::Poly1305;
-       use bitcoin::hashes::cmp::fixed_time_eq;
-
-       #[derive(Clone, Copy)]
-       pub struct ChaCha20Poly1305RFC {
-               cipher: ChaCha20,
-               mac: Poly1305,
-               finished: bool,
-               data_len: usize,
-               aad_len: u64,
-       }
-
-       impl ChaCha20Poly1305RFC {
-               #[inline]
-               fn pad_mac_16(mac: &mut Poly1305, len: usize) {
-                       if len % 16 != 0 {
-                               mac.input(&[0; 16][0..16 - (len % 16)]);
-                       }
-               }
-               pub fn new(key: &[u8], nonce: &[u8], aad: &[u8]) -> ChaCha20Poly1305RFC {
-                       assert!(key.len() == 16 || key.len() == 32);
-                       assert!(nonce.len() == 12);
-
-                       // Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
-                       assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
-
-                       let mut cipher = ChaCha20::new(key, &nonce[4..]);
-                       let mut mac_key = [0u8; 64];
-                       let zero_key = [0u8; 64];
-                       cipher.process(&zero_key, &mut mac_key);
-
-                       let mut mac = Poly1305::new(&mac_key[..32]);
-                       mac.input(aad);
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut mac, aad.len());
-
-                       ChaCha20Poly1305RFC {
-                               cipher,
-                               mac,
-                               finished: false,
-                               data_len: 0,
-                               aad_len: aad.len() as u64,
-                       }
-               }
-
-               pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
-                       assert!(input.len() == output.len());
-                       assert!(self.finished == false);
-                       self.cipher.process(input, output);
-                       self.data_len += input.len();
-                       self.mac.input(output);
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
-                       self.finished = true;
-                       self.mac.input(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-                       self.mac.raw_result(out_tag);
-               }
-
-               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
-                       self.encrypt_in_place(input_output);
-                       self.finish_and_get_tag(out_tag);
-               }
-
-               // Encrypt `input_output` in-place. To finish and calculate the tag, use `finish_and_get_tag`
-               // below.
-               pub(super) fn encrypt_in_place(&mut self, input_output: &mut [u8]) {
-                       debug_assert!(self.finished == false);
-                       self.cipher.process_in_place(input_output);
-                       self.data_len += input_output.len();
-                       self.mac.input(input_output);
-               }
-
-               // If we were previously encrypting with `encrypt_in_place`, this method can be used to finish
-               // encrypting and calculate the tag.
-               pub(super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
-                       debug_assert!(self.finished == false);
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
-                       self.finished = true;
-                       self.mac.input(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-                       self.mac.raw_result(out_tag);
-               }
-
-               pub fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
-                       assert!(input.len() == output.len());
-                       assert!(self.finished == false);
-
-                       self.finished = true;
-
-                       self.mac.input(input);
-
-                       self.data_len += input.len();
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
-                       self.mac.input(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-
-                       let mut calc_tag =  [0u8; 16];
-                       self.mac.raw_result(&mut calc_tag);
-                       if fixed_time_eq(&calc_tag, tag) {
-                               self.cipher.process(input, output);
-                               true
-                       } else {
-                               false
-                       }
-               }
-
-               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
-                       self.decrypt_in_place(input_output);
-                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
-               }
-
-               /// Decrypt in place, without checking the tag. Use `finish_and_check_tag` to check it
-               /// later when decryption finishes.
-               ///
-               /// Should never be `pub` because the public API should always enforce tag checking.
-               pub(super) fn decrypt_in_place(&mut self, input_output: &mut [u8]) {
-                       debug_assert!(self.finished == false);
-                       self.mac.input(input_output);
-                       self.data_len += input_output.len();
-                       self.cipher.process_in_place(input_output);
-               }
-
-               /// If we were previously decrypting with `just_decrypt_in_place`, this method must be used
-               /// to check the tag. Returns whether or not the tag is valid.
-               pub(super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
-                       debug_assert!(self.finished == false);
-                       self.finished = true;
-                       ChaCha20Poly1305RFC::pad_mac_16(&mut self.mac, self.data_len);
-                       self.mac.input(&self.aad_len.to_le_bytes());
-                       self.mac.input(&(self.data_len as u64).to_le_bytes());
-
-                       let mut calc_tag =  [0u8; 16];
-                       self.mac.raw_result(&mut calc_tag);
-                       if fixed_time_eq(&calc_tag, tag) {
-                               true
-                       } else {
-                               false
-                       }
-               }
-       }
-}
-#[cfg(not(fuzzing))]
-pub use self::real_chachapoly::ChaCha20Poly1305RFC;
-
-/// Enables simultaneously reading and decrypting a ChaCha20Poly1305RFC stream from a std::io::Read.
-struct ChaChaPolyReader<'a, R: Read> {
-       pub chacha: &'a mut ChaCha20Poly1305RFC,
-       pub read: R,
-}
-
-impl<'a, R: Read> Read for ChaChaPolyReader<'a, R> {
-       // Decrypt bytes from Self::read into `dest`.
-       // `ChaCha20Poly1305RFC::finish_and_check_tag` must be called to check the tag after all reads
-       // complete.
-       fn read(&mut self, dest: &mut [u8]) -> Result<usize, io::Error> {
-               let res = self.read.read(dest)?;
-               if res > 0 {
-                       self.chacha.decrypt_in_place(&mut dest[0..res]);
-               }
-               Ok(res)
-       }
-}
-
-/// Enables simultaneously writing and encrypting a byte stream into a Writer.
-struct ChaChaPolyWriter<'a, W: Writer> {
-       pub chacha: &'a mut ChaCha20Poly1305RFC,
-       pub write: &'a mut W,
-}
-
-impl<'a, W: Writer> Writer for ChaChaPolyWriter<'a, W> {
-       // Encrypt then write bytes from `src` into Self::write.
-       // `ChaCha20Poly1305RFC::finish_and_get_tag` can be called to retrieve the tag after all writes
-       // complete.
-       fn write_all(&mut self, src: &[u8]) -> Result<(), io::Error> {
-               let mut src_idx = 0;
-               while src_idx < src.len() {
-                       let mut write_buffer = [0; 8192];
-                       let bytes_written = (&mut write_buffer[..]).write(&src[src_idx..]).expect("In-memory writes can't fail");
-                       self.chacha.encrypt_in_place(&mut write_buffer[..bytes_written]);
-                       self.write.write_all(&write_buffer[..bytes_written])?;
-                       src_idx += bytes_written;
-               }
-               Ok(())
-       }
-}
-
-/// Enables the use of the serialization macros for objects that need to be simultaneously encrypted and
-/// serialized. This allows us to avoid an intermediate Vec allocation.
-pub(crate) struct ChaChaPolyWriteAdapter<'a, W: Writeable> {
-       pub rho: [u8; 32],
-       pub writeable: &'a W,
-}
-
-impl<'a, W: Writeable> ChaChaPolyWriteAdapter<'a, W> {
-       #[allow(unused)] // This will be used for onion messages soon
-       pub fn new(rho: [u8; 32], writeable: &'a W) -> ChaChaPolyWriteAdapter<'a, W> {
-               Self { rho, writeable }
-       }
-}
-
-impl<'a, T: Writeable> Writeable for ChaChaPolyWriteAdapter<'a, T> {
-       // Simultaneously write and encrypt Self::writeable.
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
-               let mut chacha = ChaCha20Poly1305RFC::new(&self.rho, &[0; 12], &[]);
-               let mut chacha_stream = ChaChaPolyWriter { chacha: &mut chacha, write: w };
-               self.writeable.write(&mut chacha_stream)?;
-               let mut tag = [0 as u8; 16];
-               chacha.finish_and_get_tag(&mut tag);
-               tag.write(w)?;
-
-               Ok(())
-       }
-}
-
-/// Enables the use of the serialization macros for objects that need to be simultaneously decrypted and
-/// deserialized. This allows us to avoid an intermediate Vec allocation.
-pub(crate) struct ChaChaPolyReadAdapter<R: Readable> {
-       pub readable: R,
-}
-
-impl<T: Readable> LengthReadableArgs<[u8; 32]> for ChaChaPolyReadAdapter<T> {
-       // Simultaneously read and decrypt an object from a LengthRead, storing it in Self::readable.
-       // LengthRead must be used instead of std::io::Read because we need the total length to separate
-       // out the tag at the end.
-       fn read<R: LengthRead>(mut r: &mut R, secret: [u8; 32]) -> Result<Self, DecodeError> {
-               if r.total_bytes() < 16 { return Err(DecodeError::InvalidValue) }
-
-               let mut chacha = ChaCha20Poly1305RFC::new(&secret, &[0; 12], &[]);
-               let decrypted_len = r.total_bytes() - 16;
-               let s = FixedLengthReader::new(&mut r, decrypted_len);
-               let mut chacha_stream = ChaChaPolyReader { chacha: &mut chacha, read: s };
-               let readable: T = Readable::read(&mut chacha_stream)?;
-               chacha_stream.read.eat_remaining()?;
-
-               let mut tag = [0 as u8; 16];
-               r.read_exact(&mut tag)?;
-               if !chacha.finish_and_check_tag(&tag) {
-                       return Err(DecodeError::InvalidValue)
-               }
-
-               Ok(Self { readable })
-       }
-}
-
-#[cfg(fuzzing)]
-mod fuzzy_chachapoly {
-       #[derive(Clone, Copy)]
-       pub struct ChaCha20Poly1305RFC {
-               tag: [u8; 16],
-               finished: bool,
-       }
-       impl ChaCha20Poly1305RFC {
-               pub fn new(key: &[u8], nonce: &[u8], _aad: &[u8]) -> ChaCha20Poly1305RFC {
-                       assert!(key.len() == 16 || key.len() == 32);
-                       assert!(nonce.len() == 12);
-
-                       // Ehh, I'm too lazy to *also* tweak ChaCha20 to make it RFC-compliant
-                       assert!(nonce[0] == 0 && nonce[1] == 0 && nonce[2] == 0 && nonce[3] == 0);
-
-                       let mut tag = [0; 16];
-                       tag.copy_from_slice(&key[0..16]);
-
-                       ChaCha20Poly1305RFC {
-                               tag,
-                               finished: false,
-                       }
-               }
-
-               pub fn encrypt(&mut self, input: &[u8], output: &mut [u8], out_tag: &mut [u8]) {
-                       assert!(input.len() == output.len());
-                       assert!(self.finished == false);
-
-                       output.copy_from_slice(&input);
-                       out_tag.copy_from_slice(&self.tag);
-                       self.finished = true;
-               }
-
-               pub fn encrypt_full_message_in_place(&mut self, input_output: &mut [u8], out_tag: &mut [u8]) {
-                       self.encrypt_in_place(input_output);
-                       self.finish_and_get_tag(out_tag);
-               }
-
-               pub(super) fn encrypt_in_place(&mut self, _input_output: &mut [u8]) {
-                       assert!(self.finished == false);
-               }
-
-               pub(super) fn finish_and_get_tag(&mut self, out_tag: &mut [u8]) {
-                       assert!(self.finished == false);
-                       out_tag.copy_from_slice(&self.tag);
-                       self.finished = true;
-               }
-
-               pub fn decrypt(&mut self, input: &[u8], output: &mut [u8], tag: &[u8]) -> bool {
-                       assert!(input.len() == output.len());
-                       assert!(self.finished == false);
-
-                       if tag[..] != self.tag[..] { return false; }
-                       output.copy_from_slice(input);
-                       self.finished = true;
-                       true
-               }
-
-               pub fn check_decrypt_in_place(&mut self, input_output: &mut [u8], tag: &[u8]) -> Result<(), ()> {
-                       self.decrypt_in_place(input_output);
-                       if self.finish_and_check_tag(tag) { Ok(()) } else { Err(()) }
-               }
-
-               pub(super) fn decrypt_in_place(&mut self, _input: &mut [u8]) {
-                       assert!(self.finished == false);
-               }
-
-               pub(super) fn finish_and_check_tag(&mut self, tag: &[u8]) -> bool {
-                       if tag[..] != self.tag[..] { return false; }
-                       self.finished = true;
-                       true
-               }
-       }
-}
-#[cfg(fuzzing)]
-pub use self::fuzzy_chachapoly::ChaCha20Poly1305RFC;
-
-#[cfg(test)]
-mod tests {
-       use crate::ln::msgs::DecodeError;
-       use super::{ChaChaPolyReadAdapter, ChaChaPolyWriteAdapter};
-       use crate::util::ser::{self, FixedLengthReader, LengthReadableArgs, Writeable};
-
-       // Used for for testing various lengths of serialization.
-       #[derive(Debug, PartialEq, Eq)]
-       struct TestWriteable {
-               field1: Vec<u8>,
-               field2: Vec<u8>,
-               field3: Vec<u8>,
-       }
-       impl_writeable_tlv_based!(TestWriteable, {
-               (1, field1, required_vec),
-               (2, field2, required_vec),
-               (3, field3, required_vec),
-       });
-
-       #[test]
-       fn test_chacha_stream_adapters() {
-               // Check that ChaChaPolyReadAdapter and ChaChaPolyWriteAdapter correctly encode and decode an
-               // encrypted object.
-               macro_rules! check_object_read_write {
-                       ($obj: expr) => {
-                               // First, serialize the object, encrypted with ChaCha20Poly1305.
-                               let rho = [42; 32];
-                               let writeable_len = $obj.serialized_length() as u64 + 16;
-                               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &$obj);
-                               let encrypted_writeable_bytes = write_adapter.encode();
-                               let encrypted_writeable = &encrypted_writeable_bytes[..];
-
-                               // Now deserialize the object back and make sure it matches the original.
-                               let mut rd = FixedLengthReader::new(encrypted_writeable, writeable_len);
-                               let read_adapter = <ChaChaPolyReadAdapter<TestWriteable>>::read(&mut rd, rho).unwrap();
-                               assert_eq!($obj, read_adapter.readable);
-                       };
-               }
-
-               // Try a big object that will require multiple write buffers.
-               let big_writeable = TestWriteable {
-                       field1: vec![43],
-                       field2: vec![44; 4192],
-                       field3: vec![45; 4192 + 1],
-               };
-               check_object_read_write!(big_writeable);
-
-               // Try a small object that fits into one write buffer.
-               let small_writeable = TestWriteable {
-                       field1: vec![43],
-                       field2: vec![44],
-                       field3: vec![45],
-               };
-               check_object_read_write!(small_writeable);
-       }
-
-       fn do_chacha_stream_adapters_ser_macros() -> Result<(), DecodeError> {
-               let writeable = TestWriteable {
-                       field1: vec![43],
-                       field2: vec![44; 4192],
-                       field3: vec![45; 4192 + 1],
-               };
-
-               // First, serialize the object into a TLV stream, encrypted with ChaCha20Poly1305.
-               let rho = [42; 32];
-               let write_adapter = ChaChaPolyWriteAdapter::new(rho, &writeable);
-               let mut writer = ser::VecWriter(Vec::new());
-               encode_tlv_stream!(&mut writer, {
-                       (1, write_adapter, required),
-               });
-
-               // Now deserialize the object back and make sure it matches the original.
-               let mut read_adapter: Option<ChaChaPolyReadAdapter<TestWriteable>> = None;
-               decode_tlv_stream!(&writer.0[..], {
-                       (1, read_adapter, (option: LengthReadableArgs, rho)),
-               });
-               assert_eq!(writeable, read_adapter.unwrap().readable);
-
-               Ok(())
-       }
-
-       #[test]
-       fn chacha_stream_adapters_ser_macros() {
-               // Test that our stream adapters work as expected with the TLV macros.
-               // This also serves to test the `option: $trait` variant of the `_decode_tlv` ser macro.
-               do_chacha_stream_adapters_ser_macros().unwrap()
-       }
-}
diff --git a/lightning/src/util/crypto.rs b/lightning/src/util/crypto.rs
deleted file mode 100644 (file)
index 98963c7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-use bitcoin::hashes::{Hash, HashEngine};
-use bitcoin::hashes::hmac::{Hmac, HmacEngine};
-use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::secp256k1::{Message, Secp256k1, SecretKey, ecdsa::Signature, Signing};
-
-use crate::sign::EntropySource;
-
-use core::ops::Deref;
-
-macro_rules! hkdf_extract_expand {
-       ($salt: expr, $ikm: expr) => {{
-               let mut hmac = HmacEngine::<Sha256>::new($salt);
-               hmac.input($ikm);
-               let prk = Hmac::from_engine(hmac).to_byte_array();
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&[1; 1]);
-               let t1 = Hmac::from_engine(hmac).to_byte_array();
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&t1);
-               hmac.input(&[2; 1]);
-               (t1, Hmac::from_engine(hmac).to_byte_array(), prk)
-       }};
-       ($salt: expr, $ikm: expr, 2) => {{
-               let (k1, k2, _) = hkdf_extract_expand!($salt, $ikm);
-               (k1, k2)
-       }};
-       ($salt: expr, $ikm: expr, 5) => {{
-               let (k1, k2, prk) = hkdf_extract_expand!($salt, $ikm);
-
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&k2);
-               hmac.input(&[3; 1]);
-               let k3 = Hmac::from_engine(hmac).to_byte_array();
-
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&k3);
-               hmac.input(&[4; 1]);
-               let k4 = Hmac::from_engine(hmac).to_byte_array();
-
-               let mut hmac = HmacEngine::<Sha256>::new(&prk[..]);
-               hmac.input(&k4);
-               hmac.input(&[5; 1]);
-               let k5 = Hmac::from_engine(hmac).to_byte_array();
-
-               (k1, k2, k3, k4, k5)
-       }}
-}
-
-pub fn hkdf_extract_expand_twice(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32]) {
-       hkdf_extract_expand!(salt, ikm, 2)
-}
-
-pub fn hkdf_extract_expand_5x(salt: &[u8], ikm: &[u8]) -> ([u8; 32], [u8; 32], [u8; 32], [u8; 32], [u8; 32]) {
-       hkdf_extract_expand!(salt, ikm, 5)
-}
-
-#[inline]
-pub fn sign<C: Signing>(ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey) -> Signature {
-       #[cfg(feature = "grind_signatures")]
-       let sig = ctx.sign_ecdsa_low_r(msg, sk);
-       #[cfg(not(feature = "grind_signatures"))]
-       let sig = ctx.sign_ecdsa(msg, sk);
-       sig
-}
-
-#[inline]
-#[allow(unused_variables)]
-pub fn sign_with_aux_rand<C: Signing, ES: Deref>(
-       ctx: &Secp256k1<C>, msg: &Message, sk: &SecretKey, entropy_source: &ES
-) -> Signature where ES::Target: EntropySource {
-       #[cfg(feature = "grind_signatures")]
-       let sig = loop {
-               let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
-               if sig.serialize_compact()[0] < 0x80 {
-                       break sig;
-               }
-       };
-       #[cfg(all(not(feature = "grind_signatures"), not(feature = "_test_vectors")))]
-       let sig = ctx.sign_ecdsa_with_noncedata(msg, sk, &entropy_source.get_secure_random_bytes());
-       #[cfg(all(not(feature = "grind_signatures"), feature = "_test_vectors"))]
-       let sig = sign(ctx, msg, sk);
-       sig
-}
index e86885a83dbd0160b42bc103ecb5e737ea39bb7b..f2116032786ce9c6bbed6de0c4e1d82883874ba0 100644 (file)
@@ -29,10 +29,6 @@ pub(crate) mod base32;
 
 pub(crate) mod atomic_counter;
 pub(crate) mod byte_utils;
-pub(crate) mod chacha20;
-#[cfg(not(fuzzing))]
-pub(crate) mod poly1305;
-pub(crate) mod chacha20poly1305rfc;
 pub(crate) mod transaction_utils;
 pub(crate) mod scid_utils;
 pub(crate) mod time;
@@ -43,9 +39,6 @@ pub mod indexed_map;
 #[macro_use]
 pub(crate) mod macro_logger;
 
-/// Cryptography utilities.
-pub(crate) mod crypto;
-
 // These have to come after macro_logger to build
 pub mod logger;
 pub mod config;
diff --git a/lightning/src/util/poly1305.rs b/lightning/src/util/poly1305.rs
deleted file mode 100644 (file)
index 1abda74..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
-// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
-// You may not use this file except in accordance with one or both of these
-// licenses.
-
-// This is a port of Andrew Moons poly1305-donna
-// https://github.com/floodyberry/poly1305-donna
-
-use core::cmp::min;
-use core::convert::TryInto;
-
-#[derive(Clone, Copy)]
-pub struct Poly1305 {
-       r         : [u32; 5],
-       h         : [u32; 5],
-       pad       : [u32; 4],
-       leftover  : usize,
-       buffer    : [u8; 16],
-       finalized : bool,
-}
-
-impl Poly1305 {
-       pub fn new(key: &[u8]) -> Poly1305 {
-               assert!(key.len() == 32);
-               let mut poly = Poly1305{ r: [0u32; 5], h: [0u32; 5], pad: [0u32; 4], leftover: 0, buffer: [0u8; 16], finalized: false };
-
-               // r &= 0xffffffc0ffffffc0ffffffc0fffffff
-               poly.r[0] = (u32::from_le_bytes(key[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
-               poly.r[1] = (u32::from_le_bytes(key[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffff03;
-               poly.r[2] = (u32::from_le_bytes(key[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffc0ff;
-               poly.r[3] = (u32::from_le_bytes(key[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3f03fff;
-               poly.r[4] = (u32::from_le_bytes(key[12..16].try_into().expect("len is 4")) >> 8) & 0x00fffff;
-
-               poly.pad[0] = u32::from_le_bytes(key[16..20].try_into().expect("len is 4"));
-               poly.pad[1] = u32::from_le_bytes(key[20..24].try_into().expect("len is 4"));
-               poly.pad[2] = u32::from_le_bytes(key[24..28].try_into().expect("len is 4"));
-               poly.pad[3] = u32::from_le_bytes(key[28..32].try_into().expect("len is 4"));
-
-               poly
-       }
-
-       fn block(&mut self, m: &[u8]) {
-               let hibit : u32 = if self.finalized { 0 } else { 1 << 24 };
-
-               let r0 = self.r[0];
-               let r1 = self.r[1];
-               let r2 = self.r[2];
-               let r3 = self.r[3];
-               let r4 = self.r[4];
-
-               let s1 = r1 * 5;
-               let s2 = r2 * 5;
-               let s3 = r3 * 5;
-               let s4 = r4 * 5;
-
-               let mut h0 = self.h[0];
-               let mut h1 = self.h[1];
-               let mut h2 = self.h[2];
-               let mut h3 = self.h[3];
-               let mut h4 = self.h[4];
-
-               // h += m
-               h0 += (u32::from_le_bytes(m[ 0.. 4].try_into().expect("len is 4"))     ) & 0x3ffffff;
-               h1 += (u32::from_le_bytes(m[ 3.. 7].try_into().expect("len is 4")) >> 2) & 0x3ffffff;
-               h2 += (u32::from_le_bytes(m[ 6..10].try_into().expect("len is 4")) >> 4) & 0x3ffffff;
-               h3 += (u32::from_le_bytes(m[ 9..13].try_into().expect("len is 4")) >> 6) & 0x3ffffff;
-               h4 += (u32::from_le_bytes(m[12..16].try_into().expect("len is 4")) >> 8) | hibit;
-
-               // h *= r
-               let     d0 = (h0 as u64 * r0 as u64) + (h1 as u64 * s4 as u64) + (h2 as u64 * s3 as u64) + (h3 as u64 * s2 as u64) + (h4 as u64 * s1 as u64);
-               let mut d1 = (h0 as u64 * r1 as u64) + (h1 as u64 * r0 as u64) + (h2 as u64 * s4 as u64) + (h3 as u64 * s3 as u64) + (h4 as u64 * s2 as u64);
-               let mut d2 = (h0 as u64 * r2 as u64) + (h1 as u64 * r1 as u64) + (h2 as u64 * r0 as u64) + (h3 as u64 * s4 as u64) + (h4 as u64 * s3 as u64);
-               let mut d3 = (h0 as u64 * r3 as u64) + (h1 as u64 * r2 as u64) + (h2 as u64 * r1 as u64) + (h3 as u64 * r0 as u64) + (h4 as u64 * s4 as u64);
-               let mut d4 = (h0 as u64 * r4 as u64) + (h1 as u64 * r3 as u64) + (h2 as u64 * r2 as u64) + (h3 as u64 * r1 as u64) + (h4 as u64 * r0 as u64);
-
-               // (partial) h %= p
-               let mut c : u32;
-                               c = (d0 >> 26) as u32; h0 = d0 as u32 & 0x3ffffff;
-               d1 += c as u64; c = (d1 >> 26) as u32; h1 = d1 as u32 & 0x3ffffff;
-               d2 += c as u64; c = (d2 >> 26) as u32; h2 = d2 as u32 & 0x3ffffff;
-               d3 += c as u64; c = (d3 >> 26) as u32; h3 = d3 as u32 & 0x3ffffff;
-               d4 += c as u64; c = (d4 >> 26) as u32; h4 = d4 as u32 & 0x3ffffff;
-               h0 += c * 5;    c = h0 >> 26; h0 = h0 & 0x3ffffff;
-               h1 += c;
-
-               self.h[0] = h0;
-               self.h[1] = h1;
-               self.h[2] = h2;
-               self.h[3] = h3;
-               self.h[4] = h4;
-       }
-
-       pub fn finish(&mut self) {
-               if self.leftover > 0 {
-                       self.buffer[self.leftover] = 1;
-                       for i in self.leftover+1..16 {
-                               self.buffer[i] = 0;
-                       }
-                       self.finalized = true;
-                       let tmp = self.buffer;
-                       self.block(&tmp);
-               }
-
-               // fully carry h
-               let mut h0 = self.h[0];
-               let mut h1 = self.h[1];
-               let mut h2 = self.h[2];
-               let mut h3 = self.h[3];
-               let mut h4 = self.h[4];
-
-               let mut c : u32;
-                            c = h1 >> 26; h1 = h1 & 0x3ffffff;
-               h2 +=     c; c = h2 >> 26; h2 = h2 & 0x3ffffff;
-               h3 +=     c; c = h3 >> 26; h3 = h3 & 0x3ffffff;
-               h4 +=     c; c = h4 >> 26; h4 = h4 & 0x3ffffff;
-               h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff;
-               h1 +=     c;
-
-               // compute h + -p
-               let mut g0 = h0.wrapping_add(5); c = g0 >> 26; g0 &= 0x3ffffff;
-               let mut g1 = h1.wrapping_add(c); c = g1 >> 26; g1 &= 0x3ffffff;
-               let mut g2 = h2.wrapping_add(c); c = g2 >> 26; g2 &= 0x3ffffff;
-               let mut g3 = h3.wrapping_add(c); c = g3 >> 26; g3 &= 0x3ffffff;
-               let mut g4 = h4.wrapping_add(c).wrapping_sub(1 << 26);
-
-               // select h if h < p, or h + -p if h >= p
-               let mut mask = (g4 >> (32 - 1)).wrapping_sub(1);
-               g0 &= mask;
-               g1 &= mask;
-               g2 &= mask;
-               g3 &= mask;
-               g4 &= mask;
-               mask = !mask;
-               h0 = (h0 & mask) | g0;
-               h1 = (h1 & mask) | g1;
-               h2 = (h2 & mask) | g2;
-               h3 = (h3 & mask) | g3;
-               h4 = (h4 & mask) | g4;
-
-               // h = h % (2^128)
-               h0 = ((h0      ) | (h1 << 26)) & 0xffffffff;
-               h1 = ((h1 >>  6) | (h2 << 20)) & 0xffffffff;
-               h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff;
-               h3 = ((h3 >> 18) | (h4 <<  8)) & 0xffffffff;
-
-               // h = mac = (h + pad) % (2^128)
-               let mut f : u64;
-               f = h0 as u64 + self.pad[0] as u64            ; h0 = f as u32;
-               f = h1 as u64 + self.pad[1] as u64 + (f >> 32); h1 = f as u32;
-               f = h2 as u64 + self.pad[2] as u64 + (f >> 32); h2 = f as u32;
-               f = h3 as u64 + self.pad[3] as u64 + (f >> 32); h3 = f as u32;
-
-               self.h[0] = h0;
-               self.h[1] = h1;
-               self.h[2] = h2;
-               self.h[3] = h3;
-       }
-
-       pub fn input(&mut self, data: &[u8]) {
-               assert!(!self.finalized);
-               let mut m = data;
-
-               if self.leftover > 0 {
-                       let want = min(16 - self.leftover, m.len());
-                       for i in 0..want {
-                               self.buffer[self.leftover+i] = m[i];
-                       }
-                       m = &m[want..];
-                       self.leftover += want;
-
-                       if self.leftover < 16 {
-                               return;
-                       }
-
-                       // self.block(self.buffer[..]);
-                       let tmp = self.buffer;
-                       self.block(&tmp);
-
-                       self.leftover = 0;
-               }
-
-               while m.len() >= 16 {
-                       self.block(&m[0..16]);
-                       m = &m[16..];
-               }
-
-               for i in 0..m.len() {
-                       self.buffer[i] = m[i];
-               }
-               self.leftover = m.len();
-       }
-
-       pub fn raw_result(&mut self, output: &mut [u8]) {
-               assert!(output.len() >= 16);
-               if !self.finalized{
-                       self.finish();
-               }
-               output[0..4].copy_from_slice(&self.h[0].to_le_bytes());
-               output[4..8].copy_from_slice(&self.h[1].to_le_bytes());
-               output[8..12].copy_from_slice(&self.h[2].to_le_bytes());
-               output[12..16].copy_from_slice(&self.h[3].to_le_bytes());
-       }
-}
-
-#[cfg(test)]
-mod test {
-       use crate::prelude::*;
-       use core::iter::repeat;
-
-       use crate::util::poly1305::Poly1305;
-
-       fn poly1305(key: &[u8], msg: &[u8], mac: &mut [u8]) {
-               let mut poly = Poly1305::new(key);
-               poly.input(msg);
-               poly.raw_result(mac);
-       }
-
-       #[test]
-       fn test_nacl_vector() {
-               let key = [
-                       0xee,0xa6,0xa7,0x25,0x1c,0x1e,0x72,0x91,
-                       0x6d,0x11,0xc2,0xcb,0x21,0x4d,0x3c,0x25,
-                       0x25,0x39,0x12,0x1d,0x8e,0x23,0x4e,0x65,
-                       0x2d,0x65,0x1f,0xa4,0xc8,0xcf,0xf8,0x80,
-               ];
-
-               let msg = [
-                       0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73,
-                       0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce,
-                       0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4,
-                       0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a,
-                       0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b,
-                       0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72,
-                       0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2,
-                       0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38,
-                       0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a,
-                       0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae,
-                       0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea,
-                       0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda,
-                       0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde,
-                       0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3,
-                       0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6,
-                       0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74,
-                       0xe3,0x55,0xa5,
-               ];
-
-               let expected = [
-                       0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5,
-                       0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9,
-               ];
-
-               let mut mac = [0u8; 16];
-               poly1305(&key, &msg, &mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-
-               let mut poly = Poly1305::new(&key);
-               poly.input(&msg[0..32]);
-               poly.input(&msg[32..96]);
-               poly.input(&msg[96..112]);
-               poly.input(&msg[112..120]);
-               poly.input(&msg[120..124]);
-               poly.input(&msg[124..126]);
-               poly.input(&msg[126..127]);
-               poly.input(&msg[127..128]);
-               poly.input(&msg[128..129]);
-               poly.input(&msg[129..130]);
-               poly.input(&msg[130..131]);
-               poly.raw_result(&mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-       }
-
-       #[test]
-       fn donna_self_test() {
-               let wrap_key = [
-                       0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               ];
-
-               let wrap_msg = [
-                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-               ];
-
-               let wrap_mac = [
-                       0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-               ];
-
-               let mut mac = [0u8; 16];
-               poly1305(&wrap_key, &wrap_msg, &mut mac);
-               assert_eq!(&mac[..], &wrap_mac[..]);
-
-               let total_key = [
-                       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff,
-                       0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff, 0xff,
-                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-                       0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-               ];
-
-               let total_mac = [
-                       0x64, 0xaf, 0xe2, 0xe8, 0xd6, 0xad, 0x7b, 0xbd,
-                       0xd2, 0x87, 0xf9, 0x7c, 0x44, 0x62, 0x3d, 0x39,
-               ];
-
-               let mut tpoly = Poly1305::new(&total_key);
-               for i in 0..256 {
-                       let key: Vec<u8> = repeat(i as u8).take(32).collect();
-                       let msg: Vec<u8> = repeat(i as u8).take(256).collect();
-                       let mut mac = [0u8; 16];
-                       poly1305(&key[..], &msg[0..i], &mut mac);
-                       tpoly.input(&mac);
-               }
-               tpoly.raw_result(&mut mac);
-               assert_eq!(&mac[..], &total_mac[..]);
-       }
-
-       #[test]
-       fn test_tls_vectors() {
-               // from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
-               let key = b"this is 32-byte key for Poly1305";
-               let msg = [0u8; 32];
-               let expected = [
-                       0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6,
-                       0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03, 0x07,
-               ];
-               let mut mac = [0u8; 16];
-               poly1305(key, &msg, &mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-
-               let msg = b"Hello world!";
-               let expected= [
-                       0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16,
-                       0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2, 0xf0,
-               ];
-               poly1305(key, msg, &mut mac);
-               assert_eq!(&mac[..], &expected[..]);
-       }
-}
index fbbcc69a133e0966e8bd937d1838ac8dc4fd5c17..45b24fd14b042e563e7d64f9dc978684f21eab3a 100644 (file)
@@ -69,7 +69,7 @@ pub(crate) mod fake_scid {
        use bitcoin::blockdata::constants::ChainHash;
        use bitcoin::network::constants::Network;
        use crate::sign::EntropySource;
-       use crate::util::chacha20::ChaCha20;
+       use crate::crypto::chacha20::ChaCha20;
        use crate::util::scid_utils;
 
        use core::convert::TryInto;
index a006d37e90e434f92905cd66a06138820ff731b1..1c45c4a4c5d3f3d36120c6ce5fffb515c5032cb3 100644 (file)
@@ -32,7 +32,7 @@ use crate::ln::msgs::LightningError;
 use crate::ln::script::ShutdownScript;
 use crate::offers::invoice::{BlindedPayInfo, UnsignedBolt12Invoice};
 use crate::offers::invoice_request::UnsignedInvoiceRequest;
-use crate::onion_message::{Destination, MessageRouter, OnionMessagePath};
+use crate::onion_message::messenger::{Destination, MessageRouter, OnionMessagePath};
 use crate::routing::gossip::{EffectiveCapacity, NetworkGraph, NodeId, RoutingFees};
 use crate::routing::utxo::{UtxoLookup, UtxoLookupError, UtxoResult};
 use crate::routing::router::{find_route, InFlightHtlcs, Path, Route, RouteParameters, RouteHintHop, Router, ScorerAccountingForInFlightHtlcs};
index 37c036da9594747ea81b142e151ff960c2892dad..14e6bbe64a24524367661da70772f603538c3b55 100644 (file)
@@ -491,7 +491,7 @@ mod tests {
        }
 
        // Rather annoyingly, there's no safe way in Rust std to construct a Waker despite it being
-       // totally possible to construct from a trait implementation (though somewhat less effecient
+       // totally possible to construct from a trait implementation (though somewhat less efficient
        // compared to a raw VTable). Instead, we have to write out a lot of boilerplate to build a
        // waker, which we do here with a trivial Arc<AtomicBool> data element to track woke-ness.
        const WAKER_V_TABLE: RawWakerVTable = RawWakerVTable::new(waker_clone, wake, wake_by_ref, drop);