Merge pull request #1706 from jkczyz/2022-09-filtered-blocks
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Tue, 13 Sep 2022 19:50:34 +0000 (19:50 +0000)
committerGitHub <noreply@github.com>
Tue, 13 Sep 2022 19:50:34 +0000 (19:50 +0000)
Support filtered blocks in `lightning-block-sync`

22 files changed:
CHANGELOG.md
fuzz/src/peer_crypt.rs
lightning-background-processor/Cargo.toml
lightning-block-sync/Cargo.toml
lightning-invoice/Cargo.toml
lightning-invoice/src/lib.rs
lightning-net-tokio/Cargo.toml
lightning-persister/Cargo.toml
lightning-rapid-gossip-sync/Cargo.toml
lightning/Cargo.toml
lightning/src/ln/functional_tests.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/peer_channel_encryptor.rs
lightning/src/ln/peer_handler.rs
lightning/src/onion_message/blinded_route.rs
lightning/src/onion_message/functional_tests.rs
lightning/src/onion_message/messenger.rs
lightning/src/routing/scoring.rs
lightning/src/util/chacha20poly1305rfc.rs
lightning/src/util/persist.rs
pending_changelog/.empty_folder [new file with mode: 0644]
pending_changelog/1699.txt [deleted file]

index efc6218e7adf5898ada3f87e49a7821c52b82ac3..7736ce67ec6644c0aedd11ef0eed2d91427d9da0 100644 (file)
@@ -1,3 +1,97 @@
+# 0.0.111 - Sep 12, 2022 - "Saturated with Messages"
+
+## API Updates
+ * Support for relaying onion messages has been added via a new
+   `OnionMessenger` struct when passed as the `OnionMessageHandler` to a
+   `PeerManager`. Pre-encoded onion messages can also be sent and received
+   (#1503, #1650, #1652, #1688).
+ * Rate-limiting of outbound gossip syncs has been rewritten to utilize less
+   buffering inside LDK. The new rate-limiting is also used for onion messages
+   to avoid delaying other messages (#1604. #1660, #1683).
+ * Rather than spawning a full OS thread, `lightning-background-processor` has
+   a new `process_events_async` method which takes the place of a
+   `BackgroundProcessor` for those using Rust's async (#1657).
+ * `ChannelManager::get_persistable_update_future` has been added to block on
+   a ChannelManager needing re-persistence in a Rust async environment (#1657).
+ * The `Filter::register_output` return value has been removed, as it was
+   very difficult to correctly implement (i.e., without blocking). Users
+   previously using it should instead pass dependent transactions in via
+   additional `chain::Confirm::transactions_confirmed` calls (#1663).
+ * `ChannelHandshakeConfig::their_channel_reserve_proportional_millionths` has
+   been added to allow configuring counterparty reserve values (#1619).
+ * `KeysInterface::ecdh` has been added as an ECDH oracle (#1503, #1658).
+ * The `rust-bitcoin` dependency has been updated 0.29 (#1658).
+ * The `bitcoin_hashes` dependency has been updated 0.11 (#1677).
+ * `ChannelManager::broadcast_node_announcement` has been moved to
+   `PeerManager` (#1699).
+ * `channel_` and `node_announcement`s are now rebroadcast automatically to all
+   new peers which connect (#1699).
+ * `{Init,Node}Features` sent to peers/broadcasted are now fetched via the
+   various `*MessageHandler` traits, rather than hard-coded (#1701, #1688).
+ * `Event::PaymentPathFailed::rejected_by_dest` has been renamed
+   `payment_failed_permanently` (#1702).
+ * `Invoice` now derives the std `Hash` trait (#1575).
+ * `{Signed,}RawInvoice::hash` have been renamed `signable_hash` (#1714).
+ * `chain::AccessError` now derives the std `Debug` trait (#1709).
+ * `ReadOnlyNetworkGraph::list_{channels,nodes}` have been added largely for
+   users of downstream bindings (#1651).
+ * `ChannelMonitor::get_counterparty_node_id` is now available (#1635).
+
+## Bug Fixes
+ * The script compared with that returned from `chain::Access` was incorrect
+   ~half of the time, causing spurious gossip rejection (#1666).
+ * Pending in-flight HTLCs are now considered when calculating new routes,
+   ensuring, e.g. MPP retries do not take known-saturated paths (#1643).
+ * Counterparty-revoked outputs are now included in `get_claimable_balance`
+   output via a new `Balance::CounterpartyRevokedOutputClaimable` (#1495).
+ * Inbound HTLCs for which we do not (yet) have a preimage are now included in
+   `get_claimable_balance` via a `Balance::MaybePreimageClaimableHTLC` (#1673).
+ * Probes that fail prior to being sent over their first hop are correctly
+   failed with a `Event::ProbeFailed` rather than a `PaymentPathFailed` (#1704).
+ * Pending `Event::HTLCHandlingFailed`s are no longer lost on restart (#1700).
+ * HTLCs that fail prior to being sent over their first hop are now marked as
+   retryable via `!PaymentPathFailed::payment_failed_permanently` (#1702).
+ * Dust HTLCs are now considered failed in the payment tracking logic after the
+   commitment transaction confirms, allowing retry on restart (#1691).
+ * On machines with buggy "monotonic" clocks, LDK will no longer panic if time
+   goes backwards (#1692).
+
+## Backwards Compatibility
+ * The new `current_time` argument to `PeerManager` constructors must be set to
+   a UNIX timestamp for upgraded nodes; new nodes may use a counter (#1699).
+ * `Balance::CounterpartyRevokedOutputClaimable` will never be generated for
+   channels that were observed to go on-chain with LDK versions prior to
+   0.0.111 (#1495).
+ * `ChannelMonitor::get_counterparty_node_id` will return `None` for all
+   channels opened on a version of LDK prior to 0.0.110 (#1635).
+ * Setting `their_channel_reserve_proportional_millionths` to any value other
+   than the default will cause LDK versions prior to 0.0.104 to be unable to
+   read the serialized `ChannelManager` (#1619).
+
+## Security
+0.0.111 fixes a denial-of-service vulnerability which is reachable from
+untrusted input in deployments accepting 0conf channels, or via a race-condition
+in deployments creating outbound 0conf channels.
+
+ * LDK versions prior to 0.0.111 may spuriously panic when receiving a block if
+   they are awaiting the construction of a funding transaction for a 0-conf
+   channel (#1711). 0-conf support was added in LDK version 0.0.107.
+
+In total, this release features 84 files changed, 6306 insertions, 1960
+deletions in 121 commits from 11 authors, in alphabetical order:
+ * Arik Sosman
+ * Devrandom
+ * Duncan Dean
+ * Elias Rohrer
+ * Gursharan Singh
+ * Matt Corallo
+ * NicolaLS
+ * Valentine Wallace
+ * Viktor Tigerström
+ * jurvis
+ * ok300
+
+
 # 0.0.110 - 2022-07-26 - "Routing, With a Vengeance"
 
 ## API Updates
index de0443ebd5b2bd3eea3e4b117442620eae57f46d..0cb429cff738335ea8e259f86164cfc52f5ea681 100644 (file)
@@ -74,7 +74,7 @@ pub fn do_test(data: &[u8]) {
        };
        loop {
                if get_slice!(1)[0] == 0 {
-                       crypter.encrypt_message(get_slice!(slice_to_be16(get_slice!(2))));
+                       crypter.encrypt_buffer(get_slice!(slice_to_be16(get_slice!(2))));
                } else {
                        let len = match crypter.decrypt_length_header(get_slice!(16+2)) {
                                Ok(len) => len,
index c5dcae1d972ce3b656acffc7845b4946c4faf4a4..2c4d3df081b977992b0c3da671d76d1481608ca7 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "lightning-background-processor"
-version = "0.0.110"
+version = "0.0.111"
 authors = ["Valentine Wallace <vwallace@protonmail.com>"]
 license = "MIT OR Apache-2.0"
 repository = "http://github.com/lightningdevkit/rust-lightning"
@@ -15,11 +15,11 @@ rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
 bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning", features = ["std"] }
-lightning-rapid-gossip-sync = { version = "0.0.110", path = "../lightning-rapid-gossip-sync" }
+lightning = { version = "0.0.111", path = "../lightning", features = ["std"] }
+lightning-rapid-gossip-sync = { version = "0.0.111", path = "../lightning-rapid-gossip-sync" }
 futures = { version = "0.3", optional = true }
 
 [dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", features = ["_test_utils"] }
-lightning-invoice = { version = "0.18.0", path = "../lightning-invoice" }
-lightning-persister = { version = "0.0.110", path = "../lightning-persister" }
+lightning = { version = "0.0.111", path = "../lightning", features = ["_test_utils"] }
+lightning-invoice = { version = "0.19.0", path = "../lightning-invoice" }
+lightning-persister = { version = "0.0.111", path = "../lightning-persister" }
index 27fa32149f1c4cadb3864f9214767778ebd75832..d213e36dd72e6dba2e16e2e8509d76cac12d7f3c 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "lightning-block-sync"
-version = "0.0.110"
+version = "0.0.111"
 authors = ["Jeffrey Czyz", "Matt Corallo"]
 license = "MIT OR Apache-2.0"
 repository = "http://github.com/lightningdevkit/rust-lightning"
@@ -19,7 +19,7 @@ rpc-client = [ "serde", "serde_json", "chunked_transfer" ]
 
 [dependencies]
 bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
 futures = { version = "0.3" }
 tokio = { version = "1.0", features = [ "io-util", "net", "time" ], optional = true }
 serde = { version = "1.0", features = ["derive"], optional = true }
index cd67bcd36dc486d911b84a2842116ce5e1b2dd16..75571535f5654a1e5b04d0045b0a4bdf8646ee4a 100644 (file)
@@ -1,7 +1,7 @@
 [package]
 name = "lightning-invoice"
 description = "Data structures to parse and serialize BOLT11 lightning invoices"
-version = "0.18.0"
+version = "0.19.0"
 authors = ["Sebastian Geisler <sgeisler@wh2.tu-dresden.de>"]
 documentation = "https://docs.rs/lightning-invoice/"
 license = "MIT OR Apache-2.0"
@@ -20,7 +20,7 @@ std = ["bitcoin_hashes/std", "num-traits/std", "lightning/std", "bech32/std"]
 
 [dependencies]
 bech32 = { version = "0.9.0", default-features = false }
-lightning = { version = "0.0.110", path = "../lightning", default-features = false }
+lightning = { version = "0.0.111", path = "../lightning", default-features = false }
 secp256k1 = { version = "0.24.0", default-features = false, features = ["recovery", "alloc"] }
 num-traits = { version = "0.2.8", default-features = false }
 bitcoin_hashes = { version = "0.11", default-features = false }
@@ -29,6 +29,6 @@ core2 = { version = "0.3.0", default-features = false, optional = true }
 serde = { version = "1.0.118", optional = true }
 
 [dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", default-features = false, features = ["_test_utils"] }
+lightning = { version = "0.0.111", path = "../lightning", default-features = false, features = ["_test_utils"] }
 hex = "0.4"
 serde_json = { version = "1"}
index 4fc58271ed722f17d3b0392a7612915cbcc45a97..defe958a1c05406cf8eb6cdfe409c9958c26458b 100644 (file)
@@ -745,7 +745,7 @@ impl SignedRawInvoice {
        }
 
        /// The hash of the `RawInvoice` that was signed.
-       pub fn hash(&self) -> &[u8; 32] {
+       pub fn signable_hash(&self) -> &[u8; 32] {
                &self.hash
        }
 
@@ -853,8 +853,8 @@ impl RawInvoice {
                hash
        }
 
-       /// Calculate the hash of the encoded `RawInvoice`
-       pub fn hash(&self) -> [u8; 32] {
+       /// Calculate the hash of the encoded `RawInvoice` which should be signed.
+       pub fn signable_hash(&self) -> [u8; 32] {
                use bech32::ToBase32;
 
                RawInvoice::hash_from_parts(
@@ -872,7 +872,7 @@ impl RawInvoice {
        pub fn sign<F, E>(self, sign_method: F) -> Result<SignedRawInvoice, E>
                where F: FnOnce(&Message) -> Result<RecoverableSignature, E>
        {
-               let raw_hash = self.hash();
+               let raw_hash = self.signable_hash();
                let hash = Message::from_slice(&raw_hash[..])
                        .expect("Hash is 32 bytes long, same as MESSAGE_SIZE");
                let signature = sign_method(&hash)?;
@@ -1591,7 +1591,7 @@ mod test {
                        0xd5, 0x18, 0xe1, 0xc9
                ];
 
-               assert_eq!(invoice.hash(), expected_hash)
+               assert_eq!(invoice.signable_hash(), expected_hash)
        }
 
        #[test]
index a3e0cbb45860a31ab91d942cd7a8af9e858bc238..b38f400c982ad1aa5ade5999b321c12b8d6b580e 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "lightning-net-tokio"
-version = "0.0.110"
+version = "0.0.111"
 authors = ["Matt Corallo"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/lightningdevkit/rust-lightning/"
@@ -16,7 +16,7 @@ rustdoc-args = ["--cfg", "docsrs"]
 
 [dependencies]
 bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
 tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "sync", "net", "time" ] }
 
 [dev-dependencies]
index 728743c8a4da2b35629c17ef93ebf33b156cd4df..168c2ed010778e62f9b6eab250648dfde3d81cf7 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "lightning-persister"
-version = "0.0.110"
+version = "0.0.111"
 authors = ["Valentine Wallace", "Matt Corallo"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/lightningdevkit/rust-lightning/"
@@ -17,11 +17,11 @@ _bench_unstable = ["lightning/_bench_unstable"]
 
 [dependencies]
 bitcoin = "0.29.0"
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
 libc = "0.2"
 
 [target.'cfg(windows)'.dependencies]
 winapi = { version = "0.3", features = ["winbase"] }
 
 [dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", features = ["_test_utils"] }
+lightning = { version = "0.0.111", path = "../lightning", features = ["_test_utils"] }
index b8bc8437bca04f2c96e08a12f5464635195c6993..7767094479c72d9c1be74ae0a43d6df72667f707 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "lightning-rapid-gossip-sync"
-version = "0.0.110"
+version = "0.0.111"
 authors = ["Arik Sosman <git@arik.io>"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/lightningdevkit/rust-lightning"
@@ -13,8 +13,8 @@ Utility to process gossip routing data from Rapid Gossip Sync Server.
 _bench_unstable = []
 
 [dependencies]
-lightning = { version = "0.0.110", path = "../lightning" }
+lightning = { version = "0.0.111", path = "../lightning" }
 bitcoin = { version = "0.29.0", default-features = false }
 
 [dev-dependencies]
-lightning = { version = "0.0.110", path = "../lightning", features = ["_test_utils"] }
+lightning = { version = "0.0.111", path = "../lightning", features = ["_test_utils"] }
index fde54661420ec546db00e0ac6ef3d65ef3f19ba8..e6b1dc6f5a4d46b65fea3d16cc8316a1378999cd 100644 (file)
@@ -1,6 +1,6 @@
 [package]
 name = "lightning"
-version = "0.0.110"
+version = "0.0.111"
 authors = ["Matt Corallo"]
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/lightningdevkit/rust-lightning/"
index 21b7d9a7d6b4eb774bd2090faa99ad0b3de57fa5..699444a640cf1ad90020d8c6dac78b643c8b865a 100644 (file)
@@ -24,7 +24,7 @@ use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RAAC
 use ln::channel::{Channel, ChannelError};
 use ln::{chan_utils, onion_utils};
 use ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
-use routing::gossip::NetworkGraph;
+use routing::gossip::{NetworkGraph, NetworkUpdate};
 use routing::router::{PaymentParameters, Route, RouteHop, RouteParameters, find_route, get_route};
 use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
 use ln::msgs;
@@ -7166,6 +7166,85 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda
        check_added_monitors!(nodes[1], 1);
 }
 
+#[test]
+fn test_channel_failed_after_message_with_badonion_node_perm_bits_set() {
+       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 mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+       create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+
+       let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 100_000);
+
+       // First hop
+       let mut payment_event = {
+               nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
+               check_added_monitors!(nodes[0], 1);
+               SendEvent::from_node(&nodes[0])
+       };
+
+       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
+       commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false);
+       expect_pending_htlcs_forwardable!(nodes[1]);
+       check_added_monitors!(nodes[1], 1);
+       payment_event = SendEvent::from_node(&nodes[1]);
+       assert_eq!(payment_event.msgs.len(), 1);
+
+       // Second Hop
+       payment_event.msgs[0].onion_routing_packet.version = 1; // Trigger an invalid_onion_version error
+       nodes[2].node.handle_update_add_htlc(&nodes[1].node.get_our_node_id(), &payment_event.msgs[0]);
+       check_added_monitors!(nodes[2], 0);
+       commitment_signed_dance!(nodes[2], nodes[1], payment_event.commitment_msg, false, true);
+
+       let events_3 = nodes[2].node.get_and_clear_pending_msg_events();
+       assert_eq!(events_3.len(), 1);
+       match events_3[0] {
+               MessageSendEvent::UpdateHTLCs { ref updates, .. } => {
+                       let mut update_msg = updates.update_fail_malformed_htlcs[0].clone();
+                       // Set the NODE bit (BADONION and PERM already set in invalid_onion_version error)
+                       update_msg.failure_code |= 0x2000;
+
+                       nodes[1].node.handle_update_fail_malformed_htlc(&nodes[2].node.get_our_node_id(), &update_msg);
+                       commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false, true);
+               },
+               _ => panic!("Unexpected event"),
+       }
+
+       expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1],
+               vec![HTLCDestination::NextHopChannel {
+                       node_id: Some(nodes[2].node.get_our_node_id()), channel_id: chan_2.2 }]);
+       let events_4 = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(events_4.len(), 1);
+       check_added_monitors!(nodes[1], 1);
+
+       match events_4[0] {
+               MessageSendEvent::UpdateHTLCs { ref updates, .. } => {
+                       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &updates.update_fail_htlcs[0]);
+                       commitment_signed_dance!(nodes[0], nodes[1], updates.commitment_signed, false, true);
+               },
+               _ => panic!("Unexpected event"),
+       }
+
+       let events_5 = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events_5.len(), 1);
+
+       // Expect a PaymentPathFailed event with a ChannelFailure network update for the channel between
+       // the node originating the error to its next hop.
+       match events_5[0] {
+               Event::PaymentPathFailed { network_update:
+                       Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }), error_code, ..
+               } => {
+                       assert_eq!(short_channel_id, chan_2.0.contents.short_channel_id);
+                       assert!(is_permanent);
+                       assert_eq!(error_code, Some(0x8000|0x4000|0x2000|4));
+               },
+               _ => panic!("Unexpected event"),
+       }
+
+       // TODO: Test actual removal of channel from NetworkGraph when it's implemented.
+}
+
 fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
        // Dust-HTLC failure updates must be delayed until failure-trigger tx (in this case local commitment) reach ANTI_REORG_DELAY
        // We can have at most two valid local commitment tx, so both cases must be covered, and both txs must be checked to get them all as
index 3795ad5ee77d70a03e5124fc3800823f610e0634..34be2843812bc0c8a8c6e6c8e3003745ea15217d 100644 (file)
@@ -425,6 +425,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
 
                                if fixed_time_eq(&Hmac::from_engine(hmac).into_inner(), &err_packet.hmac) {
                                        if let Some(error_code_slice) = err_packet.failuremsg.get(0..2) {
+                                               const BADONION: u16 = 0x8000;
                                                const PERM: u16 = 0x4000;
                                                const NODE: u16 = 0x2000;
                                                const UPDATE: u16 = 0x1000;
@@ -445,12 +446,24 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                let mut network_update = None;
                                                let mut short_channel_id = None;
 
-                                               if error_code & NODE == NODE {
+                                               if error_code & BADONION == BADONION {
+                                                       // If the error code has the BADONION bit set, always blame the channel
+                                                       // from the node "originating" the error to its next hop. The
+                                                       // "originator" is ultimately actually claiming that its counterparty
+                                                       // is the one who is failing the HTLC.
+                                                       // If the "originator" here isn't lying we should really mark the
+                                                       // next-hop node as failed entirely, but we can't be confident in that,
+                                                       // as it would allow any node to get us to completely ban one of its
+                                                       // counterparties. Instead, we simply remove the channel in question.
+                                                       network_update = Some(NetworkUpdate::ChannelFailure {
+                                                               short_channel_id: failing_route_hop.short_channel_id,
+                                                               is_permanent: true,
+                                                       });
+                                               } else if error_code & NODE == NODE {
                                                        let is_permanent = error_code & PERM == PERM;
                                                        network_update = Some(NetworkUpdate::NodeFailure { node_id: route_hop.pubkey, is_permanent });
                                                        short_channel_id = Some(route_hop.short_channel_id);
-                                               }
-                                               else if error_code & PERM == PERM {
+                                               } else if error_code & PERM == PERM {
                                                        if !payment_failed {
                                                                network_update = Some(NetworkUpdate::ChannelFailure {
                                                                        short_channel_id: failing_route_hop.short_channel_id,
@@ -458,8 +471,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                                });
                                                                short_channel_id = Some(failing_route_hop.short_channel_id);
                                                        }
-                                               }
-                                               else if error_code & UPDATE == UPDATE {
+                                               } else if error_code & UPDATE == UPDATE {
                                                        if let Some(update_len_slice) = err_packet.failuremsg.get(debug_field_size+2..debug_field_size+4) {
                                                                let update_len = u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
                                                                if let Some(mut update_slice) = err_packet.failuremsg.get(debug_field_size + 4..debug_field_size + 4 + update_len) {
@@ -545,9 +557,6 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                        short_channel_id = Some(route_hop.short_channel_id);
                                                }
 
-                                               // TODO: Here (and a few other places) we assume that BADONION errors
-                                               // are always "sourced" from the node previous to the one which failed
-                                               // to decode the onion.
                                                res = Some((network_update, short_channel_id, !(error_code & PERM == PERM && is_from_final_node)));
 
                                                let (description, title) = errors::get_onion_error_description(error_code);
index 29fa84505fcefc55a255b842f05fd5eca84bed65..fe47f5b4e9ff7996e262fceda001495247af53dd 100644 (file)
@@ -11,6 +11,7 @@ use prelude::*;
 
 use ln::msgs::LightningError;
 use ln::msgs;
+use ln::wire;
 
 use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::sha256::Hash as Sha256;
@@ -22,6 +23,7 @@ use bitcoin::secp256k1;
 
 use util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
 use util::crypto::hkdf_extract_expand_twice;
+use util::ser::VecWriter;
 use bitcoin::hashes::hex::ToHex;
 
 /// Maximum Lightning message data length according to
@@ -142,6 +144,19 @@ impl PeerChannelEncryptor {
                res[plaintext.len()..].copy_from_slice(&tag);
        }
 
+       #[inline]
+       /// Encrypts the message in res[offset..] in-place and pushes a 16-byte tag onto the end of
+       /// res.
+       fn encrypt_in_place_with_ad(res: &mut Vec<u8>, offset: usize, n: u64, key: &[u8; 32], h: &[u8]) {
+               let mut nonce = [0; 12];
+               nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
+
+               let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
+               let mut tag = [0; 16];
+               chacha.encrypt_full_message_in_place(&mut res[offset..], &mut tag);
+               res.extend_from_slice(&tag);
+       }
+
        #[inline]
        fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), LightningError> {
                let mut nonce = [0; 12];
@@ -372,9 +387,9 @@ impl PeerChannelEncryptor {
                Ok(self.their_node_id.unwrap().clone())
        }
 
-       /// Encrypts the given message, returning the encrypted version
+       /// Encrypts the given pre-serialized message, returning the encrypted version.
        /// panics if msg.len() > 65535 or Noise handshake has not finished.
-       pub fn encrypt_message(&mut self, msg: &[u8]) -> Vec<u8> {
+       pub fn encrypt_buffer(&mut self, msg: &[u8]) -> Vec<u8> {
                if msg.len() > LN_MAX_MSG_LEN {
                        panic!("Attempted to encrypt message longer than 65535 bytes!");
                }
@@ -403,6 +418,42 @@ impl PeerChannelEncryptor {
                res
        }
 
+       /// Encrypts the given message, returning the encrypted version.
+       /// panics if the length of `message`, once encoded, is greater than 65535 or if the Noise
+       /// handshake has not finished.
+       pub fn encrypt_message<M: wire::Type>(&mut self, message: &M) -> Vec<u8> {
+               // Allocate a buffer with 2KB, fitting most common messages. Reserve the first 16+2 bytes
+               // for the 2-byte message type prefix and its MAC.
+               let mut res = VecWriter(Vec::with_capacity(2048));
+               res.0.resize(16 + 2, 0);
+               wire::write(message, &mut res).expect("In-memory messages must never fail to serialize");
+
+               let msg_len = res.0.len() - 16 - 2;
+               if msg_len > LN_MAX_MSG_LEN {
+                       panic!("Attempted to encrypt message longer than 65535 bytes!");
+               }
+
+               match self.noise_state {
+                       NoiseState::Finished { ref mut sk, ref mut sn, ref mut sck, rk: _, rn: _, rck: _ } => {
+                               if *sn >= 1000 {
+                                       let (new_sck, new_sk) = hkdf_extract_expand_twice(sck, sk);
+                                       *sck = new_sck;
+                                       *sk = new_sk;
+                                       *sn = 0;
+                               }
+
+                               Self::encrypt_with_ad(&mut res.0[0..16+2], *sn, sk, &[0; 0], &(msg_len as u16).to_be_bytes());
+                               *sn += 1;
+
+                               Self::encrypt_in_place_with_ad(&mut res.0, 16+2, *sn, sk, &[0; 0]);
+                               *sn += 1;
+                       },
+                       _ => panic!("Tried to encrypt a message prior to noise handshake completion"),
+               }
+
+               res.0
+       }
+
        /// Decrypts a message length header from the remote peer.
        /// panics if noise handshake has not yet finished or msg.len() != 18
        pub fn decrypt_length_header(&mut self, msg: &[u8]) -> Result<u16, LightningError> {
@@ -682,7 +733,7 @@ mod tests {
 
                for i in 0..1005 {
                        let msg = [0x68, 0x65, 0x6c, 0x6c, 0x6f];
-                       let res = outbound_peer.encrypt_message(&msg);
+                       let res = outbound_peer.encrypt_buffer(&msg);
                        assert_eq!(res.len(), 5 + 2*16 + 2);
 
                        let len_header = res[0..2+16].to_vec();
@@ -716,7 +767,7 @@ mod tests {
        fn max_message_len_encryption() {
                let mut outbound_peer = get_outbound_peer_for_initiator_test_vectors();
                let msg = [4u8; LN_MAX_MSG_LEN + 1];
-               outbound_peer.encrypt_message(&msg);
+               outbound_peer.encrypt_buffer(&msg);
        }
 
        #[test]
index 838927cb2367ac0e0af1fab435edb7a1170e27da..6712abeb109c59b60c687f8ecf38c150eb8d76dd 100644 (file)
@@ -25,6 +25,7 @@ use util::ser::{VecWriter, Writeable, Writer};
 use ln::peer_channel_encryptor::{PeerChannelEncryptor,NextNoiseStep};
 use ln::wire;
 use ln::wire::Encode;
+use onion_message::{SimpleArcOnionMessenger, SimpleRefOnionMessenger};
 use routing::gossip::{NetworkGraph, P2PGossipSync};
 use util::atomic_counter::AtomicCounter;
 use util::crypto::sign;
@@ -367,8 +368,10 @@ struct Peer {
 
        pending_outbound_buffer: LinkedList<Vec<u8>>,
        pending_outbound_buffer_first_msg_offset: usize,
-       // Queue gossip broadcasts separately from `pending_outbound_buffer` so we can easily prioritize
-       // channel messages over them.
+       /// Queue gossip broadcasts separately from `pending_outbound_buffer` so we can easily
+       /// prioritize channel messages over them.
+       ///
+       /// Note that these messages are *not* encrypted/MAC'd, and are only serialized.
        gossip_broadcast_buffer: LinkedList<Vec<u8>>,
        awaiting_write_event: bool,
 
@@ -459,8 +462,8 @@ impl Peer {
 /// SimpleRefPeerManager is the more appropriate type. Defining these type aliases prevents
 /// issues such as overly long function definitions.
 ///
-/// (C-not exported) as Arcs don't make sense in bindings
-pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, IgnoringMessageHandler, Arc<L>, Arc<IgnoringMessageHandler>>;
+/// (C-not exported) as `Arc`s don't make sense in bindings.
+pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArcChannelManager<M, T, F, L>>, Arc<P2PGossipSync<Arc<NetworkGraph<Arc<L>>>, Arc<C>, Arc<L>>>, Arc<SimpleArcOnionMessenger<L>>, Arc<L>, IgnoringMessageHandler>;
 
 /// SimpleRefPeerManager is a type alias for a PeerManager reference, and is the reference
 /// counterpart to the SimpleArcPeerManager type alias. Use this type by default when you don't
@@ -469,8 +472,8 @@ pub type SimpleArcPeerManager<SD, M, T, F, C, L> = PeerManager<SD, Arc<SimpleArc
 /// But if this is not necessary, using a reference is more efficient. Defining these type aliases
 /// helps with issues such as long function definitions.
 ///
-/// (C-not exported) as Arcs don't make sense in bindings
-pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L>, &'e P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, IgnoringMessageHandler, &'f L, IgnoringMessageHandler>;
+/// (C-not exported) as general type aliases don't make sense in bindings.
+pub type SimpleRefPeerManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, SD, M, T, F, C, L> = PeerManager<SD, SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L>, &'e P2PGossipSync<&'g NetworkGraph<&'f L>, &'h C, &'f L>, &'i SimpleRefOnionMessenger<'j, 'k, L>, &'f L, IgnoringMessageHandler>;
 
 /// A PeerManager manages a set of peers, described by their [`SocketDescriptor`] and marshalls
 /// socket events into messages which it passes on to its [`MessageHandler`].
@@ -822,7 +825,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                        }
                        if peer.should_buffer_gossip_broadcast() {
                                if let Some(msg) = peer.gossip_broadcast_buffer.pop_front() {
-                                       peer.pending_outbound_buffer.push_back(msg);
+                                       peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_buffer(&msg[..]));
                                }
                        }
                        if peer.should_buffer_gossip_backfill() {
@@ -941,22 +944,19 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
 
        /// Append a message to a peer's pending outbound/write buffer
        fn enqueue_message<M: wire::Type>(&self, peer: &mut Peer, message: &M) {
-               let mut buffer = VecWriter(Vec::with_capacity(2048));
-               wire::write(message, &mut buffer).unwrap(); // crash if the write failed
-
                if is_gossip_msg(message.type_id()) {
                        log_gossip!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap()));
                } else {
                        log_trace!(self.logger, "Enqueueing message {:?} to {}", message, log_pubkey!(peer.their_node_id.unwrap()))
                }
                peer.msgs_sent_since_pong += 1;
-               peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&buffer.0[..]));
+               peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(message));
        }
 
        /// Append a message to a peer's pending outbound/write gossip broadcast buffer
-       fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: &Vec<u8>) {
+       fn enqueue_encoded_gossip_broadcast(&self, peer: &mut Peer, encoded_message: Vec<u8>) {
                peer.msgs_sent_since_pong += 1;
-               peer.gossip_broadcast_buffer.push_back(peer.channel_encryptor.encrypt_message(&encoded_message[..]));
+               peer.gossip_broadcast_buffer.push_back(encoded_message);
        }
 
        fn do_read_event(&self, peer_descriptor: &mut Descriptor, data: &[u8]) -> Result<bool, PeerHandleError> {
@@ -1127,7 +1127,10 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                                                                                }
                                                                                                (_, Some(ty)) if is_gossip_msg(ty) => {
                                                                                                        log_gossip!(self.logger, "Got an invalid value while deserializing a gossip message");
-                                                                                                       self.enqueue_message(peer, &msgs::WarningMessage { channel_id: [0; 32], data: "Unreadable/bogus gossip message".to_owned() });
+                                                                                                       self.enqueue_message(peer, &msgs::WarningMessage {
+                                                                                                               channel_id: [0; 32],
+                                                                                                               data: format!("Unreadable/bogus gossip message of type {}", ty),
+                                                                                                       });
                                                                                                        continue;
                                                                                                }
                                                                                                (msgs::DecodeError::UnknownRequiredFeature, ty) => {
@@ -1435,7 +1438,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
                                                continue;
                                        }
-                                       self.enqueue_encoded_gossip_broadcast(&mut *peer, &encoded_msg);
+                                       self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
                                }
                        },
                        wire::Message::NodeAnnouncement(ref msg) => {
@@ -1458,7 +1461,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
                                                continue;
                                        }
-                                       self.enqueue_encoded_gossip_broadcast(&mut *peer, &encoded_msg);
+                                       self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
                                }
                        },
                        wire::Message::ChannelUpdate(ref msg) => {
@@ -1478,7 +1481,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
                                        if except_node.is_some() && peer.their_node_id.as_ref() == except_node {
                                                continue;
                                        }
-                                       self.enqueue_encoded_gossip_broadcast(&mut *peer, &encoded_msg);
+                                       self.enqueue_encoded_gossip_broadcast(&mut *peer, encoded_msg.clone());
                                }
                        },
                        _ => debug_assert!(false, "We shouldn't attempt to forward anything but gossip messages"),
index 9f1d8db46dd84d3477600e1d5a19015b3cb9e6aa..e47c77de35459ba0b1082117c06d7e291d052d5d 100644 (file)
@@ -11,7 +11,7 @@
 
 use bitcoin::secp256k1::{self, PublicKey, Secp256k1, SecretKey};
 
-use chain::keysinterface::{KeysInterface, Sign};
+use chain::keysinterface::KeysInterface;
 use super::utils;
 use ln::msgs::DecodeError;
 use util::chacha20poly1305rfc::ChaChaPolyWriteAdapter;
@@ -55,7 +55,7 @@ impl BlindedRoute {
        ///
        /// Errors if less than two hops are provided or if `node_pk`(s) are invalid.
        //  TODO: make all payloads the same size with padding + add dummy hops
-       pub fn new<Signer: Sign, K: KeysInterface, T: secp256k1::Signing + secp256k1::Verification>
+       pub fn new<K: KeysInterface, T: secp256k1::Signing + secp256k1::Verification>
                (node_pks: &[PublicKey], keys_manager: &K, secp_ctx: &Secp256k1<T>) -> Result<Self, ()>
        {
                if node_pks.len() < 2 { return Err(()) }
index 5fec5be51c4f331a6c899a7f1fadef55bc9048c4..9b4d2a549240cada5cc998f682a604eb864617e6 100644 (file)
@@ -98,7 +98,7 @@ fn two_unblinded_two_blinded() {
        let nodes = create_nodes(5);
 
        let secp_ctx = Secp256k1::new();
-       let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
+       let blinded_route = BlindedRoute::new(&[nodes[3].get_node_pk(), nodes[4].get_node_pk()], &*nodes[4].keys_manager, &secp_ctx).unwrap();
 
        nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::BlindedRoute(blinded_route), None).unwrap();
        pass_along_path(&nodes, None);
@@ -109,7 +109,7 @@ fn three_blinded_hops() {
        let nodes = create_nodes(4);
 
        let secp_ctx = Secp256k1::new();
-       let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+       let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
 
        nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap();
        pass_along_path(&nodes, None);
@@ -133,13 +133,13 @@ fn invalid_blinded_route_error() {
 
        // 0 hops
        let secp_ctx = Secp256k1::new();
-       let mut blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
+       let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
        blinded_route.blinded_hops.clear();
        let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
        assert_eq!(err, SendError::TooFewBlindedHops);
 
        // 1 hop
-       let mut blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
+       let mut blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], &*nodes[2].keys_manager, &secp_ctx).unwrap();
        blinded_route.blinded_hops.remove(0);
        assert_eq!(blinded_route.blinded_hops.len(), 1);
        let err = nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), None).unwrap_err();
@@ -152,7 +152,7 @@ fn reply_path() {
        let secp_ctx = Secp256k1::new();
 
        // Destination::Node
-       let reply_path = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
+       let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
        nodes[0].messenger.send_onion_message(&[nodes[1].get_node_pk(), nodes[2].get_node_pk()], Destination::Node(nodes[3].get_node_pk()), Some(reply_path)).unwrap();
        pass_along_path(&nodes, None);
        // Make sure the last node successfully decoded the reply path.
@@ -161,8 +161,8 @@ fn reply_path() {
                format!("Received an onion message with path_id: None and reply_path").to_string(), 1);
 
        // Destination::BlindedRoute
-       let blinded_route = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
-       let reply_path = BlindedRoute::new::<EnforcingSigner, _, _>(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
+       let blinded_route = BlindedRoute::new(&[nodes[1].get_node_pk(), nodes[2].get_node_pk(), nodes[3].get_node_pk()], &*nodes[3].keys_manager, &secp_ctx).unwrap();
+       let reply_path = BlindedRoute::new(&[nodes[2].get_node_pk(), nodes[1].get_node_pk(), nodes[0].get_node_pk()], &*nodes[0].keys_manager, &secp_ctx).unwrap();
 
        nodes[0].messenger.send_onion_message(&[], Destination::BlindedRoute(blinded_route), Some(reply_path)).unwrap();
        pass_along_path(&nodes, None);
index 2df01c2ba103dc118d644779aabbcf45489d6ba2..729fa813dea009d5fb043e9dca74058b918dc2ec 100644 (file)
@@ -71,7 +71,7 @@ use prelude::*;
 /// // Create a blinded route to yourself, for someone to send an onion message to.
 /// # let your_node_id = hop_node_id1;
 /// let hops = [hop_node_id3, hop_node_id4, your_node_id];
-/// let blinded_route = BlindedRoute::new::<InMemorySigner, _, _>(&hops, &keys_manager, &secp_ctx).unwrap();
+/// let blinded_route = BlindedRoute::new(&hops, &keys_manager, &secp_ctx).unwrap();
 ///
 /// // Send an empty onion message to a blinded route.
 /// # let intermediate_hops = [hop_node_id1, hop_node_id2];
@@ -378,14 +378,18 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessageProvider for OnionMessenger<S
 /// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
 /// [`SimpleArcPeerManager`]. See their docs for more details.
 ///
-///[`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
-///[`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
+/// (C-not exported) as `Arc`s don't make sense in bindings.
+///
+/// [`SimpleArcChannelManager`]: crate::ln::channelmanager::SimpleArcChannelManager
+/// [`SimpleArcPeerManager`]: crate::ln::peer_handler::SimpleArcPeerManager
 pub type SimpleArcOnionMessenger<L> = OnionMessenger<InMemorySigner, Arc<KeysManager>, Arc<L>>;
 /// Useful for simplifying the parameters of [`SimpleRefChannelManager`] and
 /// [`SimpleRefPeerManager`]. See their docs for more details.
 ///
-///[`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
-///[`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
+/// (C-not exported) as general type aliases don't make sense in bindings.
+///
+/// [`SimpleRefChannelManager`]: crate::ln::channelmanager::SimpleRefChannelManager
+/// [`SimpleRefPeerManager`]: crate::ln::peer_handler::SimpleRefPeerManager
 pub type SimpleRefOnionMessenger<'a, 'b, L> = OnionMessenger<InMemorySigner, &'a KeysManager, &'b L>;
 
 /// Construct onion packet payloads and keys for sending an onion message along the given
index a2492accf59cd9fe33fdf9d8ed533d8ff234c5a4..a3d970715872433d40572d98301b0309419876ab 100644 (file)
@@ -162,6 +162,7 @@ pub trait LockableScore<'a> {
 /// use the Persister to persist it.
 pub trait WriteableScore<'a>: LockableScore<'a> + Writeable {}
 
+#[cfg(not(c_bindings))]
 impl<'a, T> WriteableScore<'a> for T where T: LockableScore<'a> + Writeable {}
 
 /// (C-not exported)
index 1dbd91e65e0488168f59d439cdd4565f8d56803f..5fddb57eb36a0c1a2d119baeabd7d0a757509ee6 100644 (file)
@@ -74,6 +74,11 @@ mod real_chachapoly {
                        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]) {
@@ -284,6 +289,11 @@ mod fuzzy_chachapoly {
                        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);
                }
index 522c1c92ac3460773436f0dd037eb24ee8018f03..d04c3430bcc90de0ec7211c4ff12be4a8e2d6bd6 100644 (file)
@@ -26,13 +26,12 @@ pub trait KVStorePersister {
 }
 
 /// Trait that handles persisting a [`ChannelManager`], [`NetworkGraph`], and [`WriteableScore`] to disk.
-pub trait Persister<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S>
+pub trait Persister<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S: WriteableScore<'a>>
        where M::Target: 'static + chain::Watch<Signer>,
                T::Target: 'static + BroadcasterInterface,
                K::Target: 'static + KeysInterface<Signer = Signer>,
                F::Target: 'static + FeeEstimator,
                L::Target: 'static + Logger,
-               S: WriteableScore<'a>,
 {
        /// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed.
        fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), io::Error>;
@@ -44,13 +43,12 @@ pub trait Persister<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L:
        fn persist_scorer(&self, scorer: &S) -> Result<(), io::Error>;
 }
 
-impl<'a, A: KVStorePersister, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S> Persister<'a, Signer, M, T, K, F, L, S> for A
+impl<'a, A: KVStorePersister, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref, S: WriteableScore<'a>> Persister<'a, Signer, M, T, K, F, L, S> for A
        where M::Target: 'static + chain::Watch<Signer>,
                T::Target: 'static + BroadcasterInterface,
                K::Target: 'static + KeysInterface<Signer = Signer>,
                F::Target: 'static + FeeEstimator,
                L::Target: 'static + Logger,
-               S: WriteableScore<'a>,
 {
        /// Persist the given ['ChannelManager'] to disk with the name "manager", returning an error if persistence failed.
        fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), io::Error> {
diff --git a/pending_changelog/.empty_folder b/pending_changelog/.empty_folder
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/pending_changelog/1699.txt b/pending_changelog/1699.txt
deleted file mode 100644 (file)
index 75ed45d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-`broadcast_node_announcement` has been moved to `PeerManager` from `ChannelManager`.
-`PeerManager::new`'s new `current_time` argument must be set to a UNIX timestamp, not a persistent counter, for any existing nodes that upgrade.