Merge pull request #936 from TheBlueMatt/2021-05-spendable-event-locktime-delay
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Tue, 8 Jun 2021 01:53:03 +0000 (01:53 +0000)
committerGitHub <noreply@github.com>
Tue, 8 Jun 2021 01:53:03 +0000 (01:53 +0000)
Delay DelayedPaymentOutput spendable events until the CSV delay

29 files changed:
.github/workflows/build.yml
Cargo.toml
fuzz/src/chanmon_consistency.rs
fuzz/src/full_stack.rs
lightning-invoice/src/de.rs
lightning-invoice/src/lib.rs
lightning-invoice/src/ser.rs
lightning/src/chain/channelmonitor.rs
lightning/src/chain/keysinterface.rs
lightning/src/chain/mod.rs
lightning/src/chain/onchaintx.rs
lightning/src/chain/package.rs
lightning/src/chain/transaction.rs
lightning/src/ln/chan_utils.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/msgs.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/peer_channel_encryptor.rs
lightning/src/ln/wire.rs
lightning/src/routing/network_graph.rs
lightning/src/routing/router.rs
lightning/src/util/byte_utils.rs
lightning/src/util/chacha20.rs
lightning/src/util/events.rs
lightning/src/util/mod.rs
lightning/src/util/poly1305.rs
lightning/src/util/ser.rs
lightning/src/util/ser_macros.rs

index 61e961690fe68b0491ea5b8be556aa658d257f53..d24b2be7a45dc3fd7a0b4f95f741552b6a8424a4 100644 (file)
@@ -143,13 +143,13 @@ jobs:
         id: cache-graph
         uses: actions/cache@v2
         with:
-          path: lightning/net_graph-2021-05-27.bin
-          key: ldk-net_graph-45d86ead641d-2021-05-27.bin
+          path: lightning/net_graph-2021-05-31.bin
+          key: ldk-net_graph-v0.0.15-2021-05-31.bin
       - name: Fetch routing graph snapshot
         if: steps.cache-graph.outputs.cache-hit != 'true'
         run: |
-          wget -O lightning/net_graph-2021-05-27.bin https://bitcoin.ninja/ldk-net_graph-45d86ead641d-2021-05-27.bin
-          if [ "$(sha256sum lightning/net_graph-2021-05-27.bin | awk '{ print $1 }')" != "3d6261187cfa583255d978efb908b51c2f4dc4ad9a7160cd2c5263c9a4830121" ]; then
+          wget -O lightning/net_graph-2021-05-31.bin https://bitcoin.ninja/ldk-net_graph-v0.0.15-2021-05-31.bin
+          if [ "$(sha256sum lightning/net_graph-2021-05-31.bin | awk '{ print $1 }')" != "05a5361278f68ee2afd086cc04a1f927a63924be451f3221d380533acfacc303" ]; then
             echo "Bad hash"
             exit 1
           fi
index 597d4efbabb4e8cca00458db04ddfa2b3bb29c9c..df32ac5d9cf047ea597a75a0736de6f0a3537ce5 100644 (file)
@@ -22,3 +22,8 @@ panic = "abort"
 opt-level = 3
 lto = true
 panic = "abort"
+
+[profile.bench]
+opt-level = 3
+codegen-units = 1
+lto = true
index 1b255791f7cdeecaba8a2c94cd0f1805142df1a2..085e4cb7402b4545fff6415ae871459977d6e3f5 100644 (file)
@@ -512,8 +512,10 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
 
        let mut chan_a_disconnected = false;
        let mut chan_b_disconnected = false;
+       let mut ab_events = Vec::new();
        let mut ba_events = Vec::new();
        let mut bc_events = Vec::new();
+       let mut cb_events = Vec::new();
 
        let mut node_a_ser = VecWriter(Vec::new());
        nodes[0].write(&mut node_a_ser).unwrap();
@@ -546,26 +548,87 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
        }
 
        loop {
+               // Push any events from Node B onto ba_events and bc_events
+               macro_rules! push_excess_b_events {
+                       ($excess_events: expr, $expect_drop_node: expr) => { {
+                               let a_id = nodes[0].get_our_node_id();
+                               let expect_drop_node: Option<usize> = $expect_drop_node;
+                               let expect_drop_id = if let Some(id) = expect_drop_node { Some(nodes[id].get_our_node_id()) } else { None };
+                               for event in $excess_events {
+                                       let push_a = match event {
+                                               events::MessageSendEvent::UpdateHTLCs { ref node_id, .. } => {
+                                                       if Some(*node_id) == expect_drop_id { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
+                                                       *node_id == a_id
+                                               },
+                                               events::MessageSendEvent::SendRevokeAndACK { ref node_id, .. } => {
+                                                       if Some(*node_id) == expect_drop_id { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
+                                                       *node_id == a_id
+                                               },
+                                               events::MessageSendEvent::SendChannelReestablish { ref node_id, .. } => {
+                                                       if Some(*node_id) == expect_drop_id { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
+                                                       *node_id == a_id
+                                               },
+                                               events::MessageSendEvent::SendFundingLocked { .. } => continue,
+                                               events::MessageSendEvent::SendAnnouncementSignatures { .. } => continue,
+                                               events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => continue,
+                                               _ => panic!("Unhandled message event"),
+                                       };
+                                       if push_a { ba_events.push(event); } else { bc_events.push(event); }
+                               }
+                       } }
+               }
+
+               // While delivering messages, we select across three possible message selection processes
+               // to ensure we get as much coverage as possible. See the individual enum variants for more
+               // details.
+               #[derive(PartialEq)]
+               enum ProcessMessages {
+                       /// Deliver all available messages, including fetching any new messages from
+                       /// `get_and_clear_pending_msg_events()` (which may have side effects).
+                       AllMessages,
+                       /// Call `get_and_clear_pending_msg_events()` first, and then deliver up to one
+                       /// message (which may already be queued).
+                       OneMessage,
+                       /// Deliver up to one already-queued message. This avoids any potential side-effects
+                       /// of `get_and_clear_pending_msg_events()` (eg freeing the HTLC holding cell), which
+                       /// provides potentially more coverage.
+                       OnePendingMessage,
+               }
+
                macro_rules! process_msg_events {
-                       ($node: expr, $corrupt_forward: expr) => { {
-                               let events = if $node == 1 {
+                       ($node: expr, $corrupt_forward: expr, $limit_events: expr) => { {
+                               let mut events = if $node == 1 {
                                        let mut new_events = Vec::new();
                                        mem::swap(&mut new_events, &mut ba_events);
                                        new_events.extend_from_slice(&bc_events[..]);
                                        bc_events.clear();
                                        new_events
-                               } else { Vec::new() };
+                               } else if $node == 0 {
+                                       let mut new_events = Vec::new();
+                                       mem::swap(&mut new_events, &mut ab_events);
+                                       new_events
+                               } else {
+                                       let mut new_events = Vec::new();
+                                       mem::swap(&mut new_events, &mut cb_events);
+                                       new_events
+                               };
+                               let mut new_events = Vec::new();
+                               if $limit_events != ProcessMessages::OnePendingMessage {
+                                       new_events = nodes[$node].get_and_clear_pending_msg_events();
+                               }
                                let mut had_events = false;
-                               for event in events.iter().chain(nodes[$node].get_and_clear_pending_msg_events().iter()) {
+                               let mut events_iter = events.drain(..).chain(new_events.drain(..));
+                               let mut extra_ev = None;
+                               for event in &mut events_iter {
                                        had_events = true;
                                        match event {
-                                               events::MessageSendEvent::UpdateHTLCs { ref node_id, updates: CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, ref update_fulfill_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
+                                               events::MessageSendEvent::UpdateHTLCs { node_id, updates: CommitmentUpdate { update_add_htlcs, update_fail_htlcs, update_fulfill_htlcs, update_fail_malformed_htlcs, update_fee, commitment_signed } } => {
                                                        for dest in nodes.iter() {
-                                                               if dest.get_our_node_id() == *node_id {
+                                                               if dest.get_our_node_id() == node_id {
                                                                        assert!(update_fee.is_none());
-                                                                       for update_add in update_add_htlcs {
+                                                                       for update_add in update_add_htlcs.iter() {
                                                                                if !$corrupt_forward {
-                                                                                       dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &update_add);
+                                                                                       dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), update_add);
                                                                                } else {
                                                                                        // Corrupt the update_add_htlc message so that its HMAC
                                                                                        // check will fail and we generate a
@@ -577,16 +640,31 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                                                        dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), &new_msg);
                                                                                }
                                                                        }
-                                                                       for update_fulfill in update_fulfill_htlcs {
-                                                                               dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), &update_fulfill);
+                                                                       for update_fulfill in update_fulfill_htlcs.iter() {
+                                                                               dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), update_fulfill);
                                                                        }
-                                                                       for update_fail in update_fail_htlcs {
-                                                                               dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), &update_fail);
+                                                                       for update_fail in update_fail_htlcs.iter() {
+                                                                               dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), update_fail);
                                                                        }
-                                                                       for update_fail_malformed in update_fail_malformed_htlcs {
-                                                                               dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), &update_fail_malformed);
+                                                                       for update_fail_malformed in update_fail_malformed_htlcs.iter() {
+                                                                               dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), update_fail_malformed);
+                                                                       }
+                                                                       let processed_change = !update_add_htlcs.is_empty() || !update_fulfill_htlcs.is_empty() ||
+                                                                               !update_fail_htlcs.is_empty() || !update_fail_malformed_htlcs.is_empty();
+                                                                       if $limit_events != ProcessMessages::AllMessages && processed_change {
+                                                                               // If we only want to process some messages, don't deliver the CS until later.
+                                                                               extra_ev = Some(events::MessageSendEvent::UpdateHTLCs { node_id, updates: CommitmentUpdate {
+                                                                                       update_add_htlcs: Vec::new(),
+                                                                                       update_fail_htlcs: Vec::new(),
+                                                                                       update_fulfill_htlcs: Vec::new(),
+                                                                                       update_fail_malformed_htlcs: Vec::new(),
+                                                                                       update_fee: None,
+                                                                                       commitment_signed
+                                                                               } });
+                                                                               break;
                                                                        }
                                                                        dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed);
+                                                                       break;
                                                                }
                                                        }
                                                },
@@ -616,6 +694,18 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                },
                                                _ => panic!("Unhandled message event"),
                                        }
+                                       if $limit_events != ProcessMessages::AllMessages {
+                                               break;
+                                       }
+                               }
+                               if $node == 1 {
+                                       push_excess_b_events!(extra_ev.into_iter().chain(events_iter), None);
+                               } else if $node == 0 {
+                                       if let Some(ev) = extra_ev { ab_events.push(ev); }
+                                       for event in events_iter { ab_events.push(event); }
+                               } else {
+                                       if let Some(ev) = extra_ev { cb_events.push(ev); }
+                                       for event in events_iter { cb_events.push(event); }
                                }
                                had_events
                        } }
@@ -635,6 +725,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                        _ => panic!("Unhandled message event"),
                                                }
                                        }
+                                       push_excess_b_events!(nodes[1].get_and_clear_pending_msg_events().drain(..), Some(0));
+                                       ab_events.clear();
                                        ba_events.clear();
                                } else {
                                        for event in nodes[2].get_and_clear_pending_msg_events() {
@@ -648,28 +740,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                        _ => panic!("Unhandled message event"),
                                                }
                                        }
+                                       push_excess_b_events!(nodes[1].get_and_clear_pending_msg_events().drain(..), Some(2));
                                        bc_events.clear();
-                               }
-                               let mut events = nodes[1].get_and_clear_pending_msg_events();
-                               let drop_node_id = if $counterparty_id == 0 { nodes[0].get_our_node_id() } else { nodes[2].get_our_node_id() };
-                               let msg_sink = if $counterparty_id == 0 { &mut bc_events } else { &mut ba_events };
-                               for event in events.drain(..) {
-                                       let push = match event {
-                                               events::MessageSendEvent::UpdateHTLCs { ref node_id, .. } => {
-                                                       if *node_id != drop_node_id { true } else { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
-                                               },
-                                               events::MessageSendEvent::SendRevokeAndACK { ref node_id, .. } => {
-                                                       if *node_id != drop_node_id { true } else { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
-                                               },
-                                               events::MessageSendEvent::SendChannelReestablish { ref node_id, .. } => {
-                                                       if *node_id != drop_node_id { true } else { panic!("peer_disconnected should drop msgs bound for the disconnected peer"); }
-                                               },
-                                               events::MessageSendEvent::SendFundingLocked { .. } => false,
-                                               events::MessageSendEvent::SendAnnouncementSignatures { .. } => false,
-                                               events::MessageSendEvent::PaymentFailureNetworkUpdate { .. } => false,
-                                               _ => panic!("Unhandled message event"),
-                                       };
-                                       if push { msg_sink.push(event); }
+                                       cb_events.clear();
                                }
                        } }
                }
@@ -785,20 +858,37 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                }
                        },
 
-                       0x10 => { process_msg_events!(0, true); },
-                       0x11 => { process_msg_events!(0, false); },
-                       0x12 => { process_events!(0, true); },
-                       0x13 => { process_events!(0, false); },
-                       0x14 => { process_msg_events!(1, true); },
-                       0x15 => { process_msg_events!(1, false); },
-                       0x16 => { process_events!(1, true); },
-                       0x17 => { process_events!(1, false); },
-                       0x18 => { process_msg_events!(2, true); },
-                       0x19 => { process_msg_events!(2, false); },
-                       0x1a => { process_events!(2, true); },
-                       0x1b => { process_events!(2, false); },
-
-                       0x1c => {
+                       0x10 => { process_msg_events!(0, true, ProcessMessages::AllMessages); },
+                       0x11 => { process_msg_events!(0, false, ProcessMessages::AllMessages); },
+                       0x12 => { process_msg_events!(0, true, ProcessMessages::OneMessage); },
+                       0x13 => { process_msg_events!(0, false, ProcessMessages::OneMessage); },
+                       0x14 => { process_msg_events!(0, true, ProcessMessages::OnePendingMessage); },
+                       0x15 => { process_msg_events!(0, false, ProcessMessages::OnePendingMessage); },
+
+                       0x16 => { process_events!(0, true); },
+                       0x17 => { process_events!(0, false); },
+
+                       0x18 => { process_msg_events!(1, true, ProcessMessages::AllMessages); },
+                       0x19 => { process_msg_events!(1, false, ProcessMessages::AllMessages); },
+                       0x1a => { process_msg_events!(1, true, ProcessMessages::OneMessage); },
+                       0x1b => { process_msg_events!(1, false, ProcessMessages::OneMessage); },
+                       0x1c => { process_msg_events!(1, true, ProcessMessages::OnePendingMessage); },
+                       0x1d => { process_msg_events!(1, false, ProcessMessages::OnePendingMessage); },
+
+                       0x1e => { process_events!(1, true); },
+                       0x1f => { process_events!(1, false); },
+
+                       0x20 => { process_msg_events!(2, true, ProcessMessages::AllMessages); },
+                       0x21 => { process_msg_events!(2, false, ProcessMessages::AllMessages); },
+                       0x22 => { process_msg_events!(2, true, ProcessMessages::OneMessage); },
+                       0x23 => { process_msg_events!(2, false, ProcessMessages::OneMessage); },
+                       0x24 => { process_msg_events!(2, true, ProcessMessages::OnePendingMessage); },
+                       0x25 => { process_msg_events!(2, false, ProcessMessages::OnePendingMessage); },
+
+                       0x26 => { process_events!(2, true); },
+                       0x27 => { process_events!(2, false); },
+
+                       0x2c => {
                                if !chan_a_disconnected {
                                        nodes[1].peer_disconnected(&nodes[0].get_our_node_id(), false);
                                        chan_a_disconnected = true;
@@ -812,11 +902,12 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                nodes[0] = new_node_a;
                                monitor_a = new_monitor_a;
                        },
-                       0x1d => {
+                       0x2d => {
                                if !chan_a_disconnected {
                                        nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false);
                                        chan_a_disconnected = true;
                                        nodes[0].get_and_clear_pending_msg_events();
+                                       ab_events.clear();
                                        ba_events.clear();
                                }
                                if !chan_b_disconnected {
@@ -824,12 +915,13 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                        chan_b_disconnected = true;
                                        nodes[2].get_and_clear_pending_msg_events();
                                        bc_events.clear();
+                                       cb_events.clear();
                                }
                                let (new_node_b, new_monitor_b) = reload_node!(node_b_ser, 1, monitor_b, keys_manager_b);
                                nodes[1] = new_node_b;
                                monitor_b = new_monitor_b;
                        },
-                       0x1e => {
+                       0x2e => {
                                if !chan_b_disconnected {
                                        nodes[1].peer_disconnected(&nodes[2].get_our_node_id(), false);
                                        chan_b_disconnected = true;
@@ -845,61 +937,61 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                        },
 
                        // 1/10th the channel size:
-                       0x20 => { send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id); },
-                       0x21 => { send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id); },
-                       0x22 => { send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id); },
-                       0x23 => { send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id); },
-                       0x24 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000_000, &mut payment_id); },
-                       0x25 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000_000, &mut payment_id); },
-
-                       0x28 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000_000, &mut payment_id); },
-                       0x29 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000_000, &mut payment_id); },
-                       0x2a => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000_000, &mut payment_id); },
-                       0x2b => { send_payment(&nodes[2], &nodes[1], chan_b, 1_000_000, &mut payment_id); },
-                       0x2c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1_000_000, &mut payment_id); },
-                       0x2d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1_000_000, &mut payment_id); },
-
-                       0x30 => { send_payment(&nodes[0], &nodes[1], chan_a, 100_000, &mut payment_id); },
-                       0x31 => { send_payment(&nodes[1], &nodes[0], chan_a, 100_000, &mut payment_id); },
-                       0x32 => { send_payment(&nodes[1], &nodes[2], chan_b, 100_000, &mut payment_id); },
-                       0x33 => { send_payment(&nodes[2], &nodes[1], chan_b, 100_000, &mut payment_id); },
-                       0x34 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 100_000, &mut payment_id); },
-                       0x35 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 100_000, &mut payment_id); },
-
-                       0x38 => { send_payment(&nodes[0], &nodes[1], chan_a, 10_000, &mut payment_id); },
-                       0x39 => { send_payment(&nodes[1], &nodes[0], chan_a, 10_000, &mut payment_id); },
-                       0x3a => { send_payment(&nodes[1], &nodes[2], chan_b, 10_000, &mut payment_id); },
-                       0x3b => { send_payment(&nodes[2], &nodes[1], chan_b, 10_000, &mut payment_id); },
-                       0x3c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000, &mut payment_id); },
-                       0x3d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000, &mut payment_id); },
-
-                       0x40 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000, &mut payment_id); },
-                       0x41 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000, &mut payment_id); },
-                       0x42 => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000, &mut payment_id); },
-                       0x43 => { send_payment(&nodes[2], &nodes[1], chan_b, 1_000, &mut payment_id); },
-                       0x44 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1_000, &mut payment_id); },
-                       0x45 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1_000, &mut payment_id); },
-
-                       0x48 => { send_payment(&nodes[0], &nodes[1], chan_a, 100, &mut payment_id); },
-                       0x49 => { send_payment(&nodes[1], &nodes[0], chan_a, 100, &mut payment_id); },
-                       0x4a => { send_payment(&nodes[1], &nodes[2], chan_b, 100, &mut payment_id); },
-                       0x4b => { send_payment(&nodes[2], &nodes[1], chan_b, 100, &mut payment_id); },
-                       0x4c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 100, &mut payment_id); },
-                       0x4d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 100, &mut payment_id); },
-
-                       0x50 => { send_payment(&nodes[0], &nodes[1], chan_a, 10, &mut payment_id); },
-                       0x51 => { send_payment(&nodes[1], &nodes[0], chan_a, 10, &mut payment_id); },
-                       0x52 => { send_payment(&nodes[1], &nodes[2], chan_b, 10, &mut payment_id); },
-                       0x53 => { send_payment(&nodes[2], &nodes[1], chan_b, 10, &mut payment_id); },
-                       0x54 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10, &mut payment_id); },
-                       0x55 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10, &mut payment_id); },
-
-                       0x58 => { send_payment(&nodes[0], &nodes[1], chan_a, 1, &mut payment_id); },
-                       0x59 => { send_payment(&nodes[1], &nodes[0], chan_a, 1, &mut payment_id); },
-                       0x5a => { send_payment(&nodes[1], &nodes[2], chan_b, 1, &mut payment_id); },
-                       0x5b => { send_payment(&nodes[2], &nodes[1], chan_b, 1, &mut payment_id); },
-                       0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); },
-                       0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); },
+                       0x30 => { send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id); },
+                       0x31 => { send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id); },
+                       0x32 => { send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id); },
+                       0x33 => { send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id); },
+                       0x34 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000_000, &mut payment_id); },
+                       0x35 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000_000, &mut payment_id); },
+
+                       0x38 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000_000, &mut payment_id); },
+                       0x39 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000_000, &mut payment_id); },
+                       0x3a => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000_000, &mut payment_id); },
+                       0x3b => { send_payment(&nodes[2], &nodes[1], chan_b, 1_000_000, &mut payment_id); },
+                       0x3c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1_000_000, &mut payment_id); },
+                       0x3d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1_000_000, &mut payment_id); },
+
+                       0x40 => { send_payment(&nodes[0], &nodes[1], chan_a, 100_000, &mut payment_id); },
+                       0x41 => { send_payment(&nodes[1], &nodes[0], chan_a, 100_000, &mut payment_id); },
+                       0x42 => { send_payment(&nodes[1], &nodes[2], chan_b, 100_000, &mut payment_id); },
+                       0x43 => { send_payment(&nodes[2], &nodes[1], chan_b, 100_000, &mut payment_id); },
+                       0x44 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 100_000, &mut payment_id); },
+                       0x45 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 100_000, &mut payment_id); },
+
+                       0x48 => { send_payment(&nodes[0], &nodes[1], chan_a, 10_000, &mut payment_id); },
+                       0x49 => { send_payment(&nodes[1], &nodes[0], chan_a, 10_000, &mut payment_id); },
+                       0x4a => { send_payment(&nodes[1], &nodes[2], chan_b, 10_000, &mut payment_id); },
+                       0x4b => { send_payment(&nodes[2], &nodes[1], chan_b, 10_000, &mut payment_id); },
+                       0x4c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10_000, &mut payment_id); },
+                       0x4d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10_000, &mut payment_id); },
+
+                       0x50 => { send_payment(&nodes[0], &nodes[1], chan_a, 1_000, &mut payment_id); },
+                       0x51 => { send_payment(&nodes[1], &nodes[0], chan_a, 1_000, &mut payment_id); },
+                       0x52 => { send_payment(&nodes[1], &nodes[2], chan_b, 1_000, &mut payment_id); },
+                       0x53 => { send_payment(&nodes[2], &nodes[1], chan_b, 1_000, &mut payment_id); },
+                       0x54 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1_000, &mut payment_id); },
+                       0x55 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1_000, &mut payment_id); },
+
+                       0x58 => { send_payment(&nodes[0], &nodes[1], chan_a, 100, &mut payment_id); },
+                       0x59 => { send_payment(&nodes[1], &nodes[0], chan_a, 100, &mut payment_id); },
+                       0x5a => { send_payment(&nodes[1], &nodes[2], chan_b, 100, &mut payment_id); },
+                       0x5b => { send_payment(&nodes[2], &nodes[1], chan_b, 100, &mut payment_id); },
+                       0x5c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 100, &mut payment_id); },
+                       0x5d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 100, &mut payment_id); },
+
+                       0x60 => { send_payment(&nodes[0], &nodes[1], chan_a, 10, &mut payment_id); },
+                       0x61 => { send_payment(&nodes[1], &nodes[0], chan_a, 10, &mut payment_id); },
+                       0x62 => { send_payment(&nodes[1], &nodes[2], chan_b, 10, &mut payment_id); },
+                       0x63 => { send_payment(&nodes[2], &nodes[1], chan_b, 10, &mut payment_id); },
+                       0x64 => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 10, &mut payment_id); },
+                       0x65 => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 10, &mut payment_id); },
+
+                       0x68 => { send_payment(&nodes[0], &nodes[1], chan_a, 1, &mut payment_id); },
+                       0x69 => { send_payment(&nodes[1], &nodes[0], chan_a, 1, &mut payment_id); },
+                       0x6a => { send_payment(&nodes[1], &nodes[2], chan_b, 1, &mut payment_id); },
+                       0x6b => { send_payment(&nodes[2], &nodes[1], chan_b, 1, &mut payment_id); },
+                       0x6c => { send_hop_payment(&nodes[0], &nodes[1], chan_a, &nodes[2], chan_b, 1, &mut payment_id); },
+                       0x6d => { send_hop_payment(&nodes[2], &nodes[1], chan_b, &nodes[0], chan_a, 1, &mut payment_id); },
 
                        0xff => {
                                // Test that no channel is in a stuck state where neither party can send funds even
@@ -938,9 +1030,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                for i in 0..std::usize::MAX {
                                        if i == 100 { panic!("It may take may iterations to settle the state, but it should not take forever"); }
                                        // Then, make sure any current forwards make their way to their destination
-                                       if process_msg_events!(0, false) { continue; }
-                                       if process_msg_events!(1, false) { continue; }
-                                       if process_msg_events!(2, false) { continue; }
+                                       if process_msg_events!(0, false, ProcessMessages::AllMessages) { continue; }
+                                       if process_msg_events!(1, false, ProcessMessages::AllMessages) { continue; }
+                                       if process_msg_events!(2, false, ProcessMessages::AllMessages) { continue; }
                                        // ...making sure any pending PendingHTLCsForwardable events are handled and
                                        // payments claimed.
                                        if process_events!(0, false) { continue; }
index adfd2a8309cc5e3091770b2091729f46eff365da..fe5599fb05ddce155e124b00d2ce5aaa74405b05 100644 (file)
@@ -39,6 +39,7 @@ use lightning::ln::msgs::DecodeError;
 use lightning::routing::router::get_route;
 use lightning::routing::network_graph::NetGraphMsgHandler;
 use lightning::util::config::UserConfig;
+use lightning::util::errors::APIError;
 use lightning::util::events::Event;
 use lightning::util::enforcing_trait_impls::EnforcingSigner;
 use lightning::util::logger::Logger;
@@ -531,12 +532,18 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                                                        continue 'outer_loop;
                                                }
                                        };
-                                       channelmanager.funding_transaction_generated(&funding_generation.0, tx.clone()).unwrap();
+                                       if let Err(e) = channelmanager.funding_transaction_generated(&funding_generation.0, tx.clone()) {
+                                               // It's possible the channel has been closed in the mean time, but any other
+                                               // failure may be a bug.
+                                               if let APIError::ChannelUnavailable { err } = e {
+                                                       assert_eq!(err, "No such channel");
+                                               } else { panic!(); }
+                                       }
                                        pending_funding_signatures.insert(funding_output, tx);
                                }
                        },
                        11 => {
-                               let mut txn = broadcast.txn_broadcasted.lock().unwrap();
+                               let mut txn = broadcast.txn_broadcasted.lock().unwrap().split_off(0);
                                if !txn.is_empty() {
                                        loss_detector.connect_block(&txn[..]);
                                        for _ in 2..100 {
index 3610bc4b67fab01f11283aed957c1fe71ccb4731..47557665b4bf4b473a90657280c9b807ebadbfdc 100644 (file)
@@ -185,6 +185,7 @@ impl FromStr for super::Currency {
                        "tb" => Ok(Currency::BitcoinTestnet),
                        "bcrt" => Ok(Currency::Regtest),
                        "sb" => Ok(Currency::Simnet),
+                       "tbs" => Ok(Currency::Signet),
                        _ => Err(ParseError::UnknownCurrency)
                }
        }
@@ -774,6 +775,7 @@ mod test {
                assert_eq!("tb".parse::<Currency>(), Ok(Currency::BitcoinTestnet));
                assert_eq!("bcrt".parse::<Currency>(), Ok(Currency::Regtest));
                assert_eq!("sb".parse::<Currency>(), Ok(Currency::Simnet));
+               assert_eq!("tbs".parse::<Currency>(), Ok(Currency::Signet));
                assert_eq!("something_else".parse::<Currency>(), Err(ParseError::UnknownCurrency))
        }
 
index 29c093dec95925f19f86d745ecdf54bd98856851..064b3626537c2d93b753e6dd9095522010131a77 100644 (file)
@@ -328,8 +328,11 @@ pub enum Currency {
        /// Bitcoin regtest
        Regtest,
 
-       /// Bitcoin simnet/signet
+       /// Bitcoin simnet
        Simnet,
+
+       /// Bitcoin signet
+       Signet,
 }
 
 /// Tagged field which may have an unknown tag
index 8811926782348a263735b55824ea74fb65d662cb..885ea2684f2295665ebd0ac8800b90e08f7685ed 100644 (file)
@@ -153,6 +153,7 @@ impl Display for Currency {
                        Currency::BitcoinTestnet => "tb",
                        Currency::Regtest => "bcrt",
                        Currency::Simnet => "sb",
+                       Currency::Signet => "tbs",
                };
                write!(f, "{}", currency_code)
        }
@@ -473,6 +474,7 @@ mod test {
                assert_eq!("tb", Currency::BitcoinTestnet.to_string());
                assert_eq!("bcrt", Currency::Regtest.to_string());
                assert_eq!("sb", Currency::Simnet.to_string());
+               assert_eq!("tbs", Currency::Signet.to_string());
        }
 
        #[test]
index 8ae4c13309f5585e23829faa13f503f24c1318bc..a0f5eb71d7b3fdf69ef076183fdb1ccc76ff0fc4 100644 (file)
@@ -47,7 +47,7 @@ use chain::onchaintx::OnchainTxHandler;
 use chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
 use chain::Filter;
 use util::logger::Logger;
-use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48};
+use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48, OptionDeserWrapper};
 use util::byte_utils;
 use util::events::Event;
 
@@ -90,22 +90,26 @@ pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
 
 impl Writeable for ChannelMonitorUpdate {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
                self.update_id.write(w)?;
                (self.updates.len() as u64).write(w)?;
                for update_step in self.updates.iter() {
                        update_step.write(w)?;
                }
+               write_tlv_fields!(w, {}, {});
                Ok(())
        }
 }
 impl Readable for ChannelMonitorUpdate {
        fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let _ver = read_ver_prefix!(r, SERIALIZATION_VERSION);
                let update_id: u64 = Readable::read(r)?;
                let len: u64 = Readable::read(r)?;
                let mut updates = Vec::with_capacity(cmp::min(len as usize, MAX_ALLOC_SIZE / ::core::mem::size_of::<ChannelMonitorUpdateStep>()));
                for _ in 0..len {
                        updates.push(Readable::read(r)?);
                }
+               read_tlv_fields!(r, {}, {});
                Ok(Self { update_id, updates })
        }
 }
@@ -198,7 +202,12 @@ pub struct HTLCUpdate {
        pub(crate) payment_preimage: Option<PaymentPreimage>,
        pub(crate) source: HTLCSource
 }
-impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
+impl_writeable_tlv_based!(HTLCUpdate, {
+       (0, payment_hash),
+       (2, source),
+}, {
+       (4, payment_preimage)
+}, {});
 
 /// If an HTLC expires within this many blocks, don't try to claim it in a shared transaction,
 /// instead claiming it in its own individual transaction.
@@ -264,6 +273,17 @@ struct HolderSignedTx {
        feerate_per_kw: u32,
        htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
 }
+impl_writeable_tlv_based!(HolderSignedTx, {
+       (0, txid),
+       (2, revocation_key),
+       (4, a_htlc_key),
+       (6, b_htlc_key),
+       (8, delayed_payment_key),
+       (10, per_commitment_point),
+       (12, feerate_per_kw),
+}, {}, {
+       (14, htlc_outputs)
+});
 
 /// We use this to track counterparty commitment transactions and htlcs outputs and
 /// use it to generate any justice or 2nd-stage preimage/timeout transactions.
@@ -277,9 +297,6 @@ struct CounterpartyCommitmentTransaction {
 
 impl Writeable for CounterpartyCommitmentTransaction {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               self.counterparty_delayed_payment_base_key.write(w)?;
-               self.counterparty_htlc_base_key.write(w)?;
-               w.write_all(&byte_utils::be16_to_array(self.on_counterparty_tx_csv))?;
                w.write_all(&byte_utils::be64_to_array(self.per_htlc.len() as u64))?;
                for (ref txid, ref htlcs) in self.per_htlc.iter() {
                        w.write_all(&txid[..])?;
@@ -288,15 +305,17 @@ impl Writeable for CounterpartyCommitmentTransaction {
                                htlc.write(w)?;
                        }
                }
+               write_tlv_fields!(w, {
+                       (0, self.counterparty_delayed_payment_base_key),
+                       (2, self.counterparty_htlc_base_key),
+                       (4, self.on_counterparty_tx_csv),
+               }, {});
                Ok(())
        }
 }
 impl Readable for CounterpartyCommitmentTransaction {
        fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
                let counterparty_commitment_transaction = {
-                       let counterparty_delayed_payment_base_key = Readable::read(r)?;
-                       let counterparty_htlc_base_key = Readable::read(r)?;
-                       let on_counterparty_tx_csv: u16 = Readable::read(r)?;
                        let per_htlc_len: u64 = Readable::read(r)?;
                        let mut per_htlc = HashMap::with_capacity(cmp::min(per_htlc_len as usize, MAX_ALLOC_SIZE / 64));
                        for _  in 0..per_htlc_len {
@@ -311,9 +330,17 @@ impl Readable for CounterpartyCommitmentTransaction {
                                        return Err(DecodeError::InvalidValue);
                                }
                        }
+                       let mut counterparty_delayed_payment_base_key = OptionDeserWrapper(None);
+                       let mut counterparty_htlc_base_key = OptionDeserWrapper(None);
+                       let mut on_counterparty_tx_csv: u16 = 0;
+                       read_tlv_fields!(r, {
+                               (0, counterparty_delayed_payment_base_key),
+                               (2, counterparty_htlc_base_key),
+                               (4, on_counterparty_tx_csv),
+                       }, {});
                        CounterpartyCommitmentTransaction {
-                               counterparty_delayed_payment_base_key,
-                               counterparty_htlc_base_key,
+                               counterparty_delayed_payment_base_key: counterparty_delayed_payment_base_key.0.unwrap(),
+                               counterparty_htlc_base_key: counterparty_htlc_base_key.0.unwrap(),
                                on_counterparty_tx_csv,
                                per_htlc,
                        }
@@ -359,13 +386,30 @@ enum OnchainEvent {
        /// inbound HTLC in backward channel. Note, in case of preimage, we pass info to upstream without delay as we can
        /// only win from it, so it's never an OnchainEvent
        HTLCUpdate {
-               htlc_update: (HTLCSource, PaymentHash),
+               source: HTLCSource,
+               payment_hash: PaymentHash,
        },
        MaturingOutput {
                descriptor: SpendableOutputDescriptor,
        },
 }
 
+impl_writeable_tlv_based!(OnchainEventEntry, {
+       (0, txid),
+       (2, height),
+       (4, event),
+}, {}, {});
+
+impl_writeable_tlv_based_enum!(OnchainEvent,
+       (0, HTLCUpdate) => {
+               (0, source),
+               (2, payment_hash),
+       }, {}, {},
+       (1, MaturingOutput) => {
+               (0, descriptor),
+       }, {}, {},
+;);
+
 #[cfg_attr(any(test, feature = "fuzztarget", feature = "_test_utils"), derive(PartialEq))]
 #[derive(Clone)]
 pub(crate) enum ChannelMonitorUpdateStep {
@@ -395,98 +439,30 @@ pub(crate) enum ChannelMonitorUpdateStep {
        },
 }
 
-impl Writeable for ChannelMonitorUpdateStep {
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { ref commitment_tx, ref htlc_outputs } => {
-                               0u8.write(w)?;
-                               commitment_tx.write(w)?;
-                               (htlc_outputs.len() as u64).write(w)?;
-                               for &(ref output, ref signature, ref source) in htlc_outputs.iter() {
-                                       output.write(w)?;
-                                       signature.write(w)?;
-                                       source.write(w)?;
-                               }
-                       }
-                       &ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, ref htlc_outputs, ref commitment_number, ref their_revocation_point } => {
-                               1u8.write(w)?;
-                               commitment_txid.write(w)?;
-                               commitment_number.write(w)?;
-                               their_revocation_point.write(w)?;
-                               (htlc_outputs.len() as u64).write(w)?;
-                               for &(ref output, ref source) in htlc_outputs.iter() {
-                                       output.write(w)?;
-                                       source.as_ref().map(|b| b.as_ref()).write(w)?;
-                               }
-                       },
-                       &ChannelMonitorUpdateStep::PaymentPreimage { ref payment_preimage } => {
-                               2u8.write(w)?;
-                               payment_preimage.write(w)?;
-                       },
-                       &ChannelMonitorUpdateStep::CommitmentSecret { ref idx, ref secret } => {
-                               3u8.write(w)?;
-                               idx.write(w)?;
-                               secret.write(w)?;
-                       },
-                       &ChannelMonitorUpdateStep::ChannelForceClosed { ref should_broadcast } => {
-                               4u8.write(w)?;
-                               should_broadcast.write(w)?;
-                       },
-               }
-               Ok(())
-       }
-}
-impl Readable for ChannelMonitorUpdateStep {
-       fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
-               match Readable::read(r)? {
-                       0u8 => {
-                               Ok(ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
-                                       commitment_tx: Readable::read(r)?,
-                                       htlc_outputs: {
-                                               let len: u64 = Readable::read(r)?;
-                                               let mut res = Vec::new();
-                                               for _ in 0..len {
-                                                       res.push((Readable::read(r)?, Readable::read(r)?, Readable::read(r)?));
-                                               }
-                                               res
-                                       },
-                               })
-                       },
-                       1u8 => {
-                               Ok(ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo {
-                                       commitment_txid: Readable::read(r)?,
-                                       commitment_number: Readable::read(r)?,
-                                       their_revocation_point: Readable::read(r)?,
-                                       htlc_outputs: {
-                                               let len: u64 = Readable::read(r)?;
-                                               let mut res = Vec::new();
-                                               for _ in 0..len {
-                                                       res.push((Readable::read(r)?, <Option<HTLCSource> as Readable>::read(r)?.map(|o| Box::new(o))));
-                                               }
-                                               res
-                                       },
-                               })
-                       },
-                       2u8 => {
-                               Ok(ChannelMonitorUpdateStep::PaymentPreimage {
-                                       payment_preimage: Readable::read(r)?,
-                               })
-                       },
-                       3u8 => {
-                               Ok(ChannelMonitorUpdateStep::CommitmentSecret {
-                                       idx: Readable::read(r)?,
-                                       secret: Readable::read(r)?,
-                               })
-                       },
-                       4u8 => {
-                               Ok(ChannelMonitorUpdateStep::ChannelForceClosed {
-                                       should_broadcast: Readable::read(r)?
-                               })
-                       },
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
+impl_writeable_tlv_based_enum!(ChannelMonitorUpdateStep,
+       (0, LatestHolderCommitmentTXInfo) => {
+               (0, commitment_tx),
+       }, {}, {
+               (2, htlc_outputs),
+       },
+       (1, LatestCounterpartyCommitmentTXInfo) => {
+               (0, commitment_txid),
+               (2, commitment_number),
+               (4, their_revocation_point),
+       }, {}, {
+               (6, htlc_outputs),
+       },
+       (2, PaymentPreimage) => {
+               (0, payment_preimage),
+       }, {}, {},
+       (3, CommitmentSecret) => {
+               (0, idx),
+               (2, secret),
+       }, {}, {},
+       (4, ChannelForceClosed) => {
+               (0, should_broadcast),
+       }, {}, {},
+;);
 
 /// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
 /// on-chain transactions to ensure no loss of funds occurs.
@@ -670,6 +646,7 @@ impl<Signer: Sign> Writeable for ChannelMonitor<Signer> {
        }
 }
 
+// These are also used for ChannelMonitorUpdate, above.
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
@@ -761,38 +738,14 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
                        writer.write_all(&byte_utils::be48_to_array(*commitment_number))?;
                }
 
-               macro_rules! serialize_holder_tx {
-                       ($holder_tx: expr) => {
-                               $holder_tx.txid.write(writer)?;
-                               writer.write_all(&$holder_tx.revocation_key.serialize())?;
-                               writer.write_all(&$holder_tx.a_htlc_key.serialize())?;
-                               writer.write_all(&$holder_tx.b_htlc_key.serialize())?;
-                               writer.write_all(&$holder_tx.delayed_payment_key.serialize())?;
-                               writer.write_all(&$holder_tx.per_commitment_point.serialize())?;
-
-                               writer.write_all(&byte_utils::be32_to_array($holder_tx.feerate_per_kw))?;
-                               writer.write_all(&byte_utils::be64_to_array($holder_tx.htlc_outputs.len() as u64))?;
-                               for &(ref htlc_output, ref sig, ref htlc_source) in $holder_tx.htlc_outputs.iter() {
-                                       serialize_htlc_in_commitment!(htlc_output);
-                                       if let &Some(ref their_sig) = sig {
-                                               1u8.write(writer)?;
-                                               writer.write_all(&their_sig.serialize_compact())?;
-                                       } else {
-                                               0u8.write(writer)?;
-                                       }
-                                       htlc_source.write(writer)?;
-                               }
-                       }
-               }
-
                if let Some(ref prev_holder_tx) = self.prev_holder_signed_commitment_tx {
                        writer.write_all(&[1; 1])?;
-                       serialize_holder_tx!(prev_holder_tx);
+                       prev_holder_tx.write(writer)?;
                } else {
                        writer.write_all(&[0; 1])?;
                }
 
-               serialize_holder_tx!(self.current_holder_commitment_tx);
+               self.current_holder_commitment_tx.write(writer)?;
 
                writer.write_all(&byte_utils::be48_to_array(self.current_counterparty_commitment_number))?;
                writer.write_all(&byte_utils::be48_to_array(self.current_holder_commitment_number))?;
@@ -823,19 +776,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
 
                writer.write_all(&byte_utils::be64_to_array(self.onchain_events_awaiting_threshold_conf.len() as u64))?;
                for ref entry in self.onchain_events_awaiting_threshold_conf.iter() {
-                       entry.txid.write(writer)?;
-                       writer.write_all(&byte_utils::be32_to_array(entry.height))?;
-                       match entry.event {
-                               OnchainEvent::HTLCUpdate { ref htlc_update } => {
-                                       0u8.write(writer)?;
-                                       htlc_update.0.write(writer)?;
-                                       htlc_update.1.write(writer)?;
-                               },
-                               OnchainEvent::MaturingOutput { ref descriptor } => {
-                                       1u8.write(writer)?;
-                                       descriptor.write(writer)?;
-                               },
-                       }
+                       entry.write(writer)?;
                }
 
                (self.outputs_to_watch.len() as u64).write(writer)?;
@@ -1617,17 +1558,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                                        self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
                                                                                if entry.height != height { return true; }
                                                                                match entry.event {
-                                                                                        OnchainEvent::HTLCUpdate { ref htlc_update } => {
-                                                                                                htlc_update.0 != **source
-                                                                                        },
-                                                                                        _ => true,
+                                                                                       OnchainEvent::HTLCUpdate { source: ref update_source, .. } => {
+                                                                                               *update_source != **source
+                                                                                       },
+                                                                                       _ => true,
                                                                                }
                                                                        });
                                                                        let entry = OnchainEventEntry {
                                                                                txid: *$txid,
                                                                                height,
                                                                                event: OnchainEvent::HTLCUpdate {
-                                                                                       htlc_update: ((**source).clone(), htlc.payment_hash.clone())
+                                                                                       source: (**source).clone(),
+                                                                                       payment_hash: htlc.payment_hash.clone(),
                                                                                },
                                                                        };
                                                                        log_info!(logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of revoked counterparty commitment transaction, waiting for confirmation (at height {})", log_bytes!(htlc.payment_hash.0), $commitment_tx, entry.confirmation_threshold());
@@ -1683,17 +1625,18 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                                self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
                                                                        if entry.height != height { return true; }
                                                                        match entry.event {
-                                                                                OnchainEvent::HTLCUpdate { ref htlc_update } => {
-                                                                                        htlc_update.0 != **source
-                                                                                },
-                                                                                _ => true,
+                                                                               OnchainEvent::HTLCUpdate { source: ref update_source, .. } => {
+                                                                                       *update_source != **source
+                                                                               },
+                                                                               _ => true,
                                                                        }
                                                                });
                                                                self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry {
                                                                        txid: *$txid,
                                                                        height,
                                                                        event: OnchainEvent::HTLCUpdate {
-                                                                               htlc_update: ((**source).clone(), htlc.payment_hash.clone())
+                                                                               source: (**source).clone(),
+                                                                               payment_hash: htlc.payment_hash.clone(),
                                                                        },
                                                                });
                                                        }
@@ -1837,16 +1780,16 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
                                        if entry.height != height { return true; }
                                        match entry.event {
-                                                OnchainEvent::HTLCUpdate { ref htlc_update } => {
-                                                        htlc_update.0 != $source
-                                                },
-                                                _ => true,
+                                               OnchainEvent::HTLCUpdate { source: ref update_source, .. } => {
+                                                       *update_source != $source
+                                               },
+                                               _ => true,
                                        }
                                });
                                let entry = OnchainEventEntry {
                                        txid: commitment_txid,
                                        height,
-                                       event: OnchainEvent::HTLCUpdate { htlc_update: ($source, $payment_hash) },
+                                       event: OnchainEvent::HTLCUpdate { source: $source, payment_hash: $payment_hash },
                                };
                                log_trace!(logger, "Failing HTLC with payment_hash {} from {} holder commitment tx due to broadcast of transaction, waiting confirmation (at height{})", log_bytes!($payment_hash.0), $commitment_tx, entry.confirmation_threshold());
                                self.onchain_events_awaiting_threshold_conf.push(entry);
@@ -2117,7 +2060,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                let unmatured_htlcs: Vec<_> = self.onchain_events_awaiting_threshold_conf
                        .iter()
                        .filter_map(|entry| match &entry.event {
-                               OnchainEvent::HTLCUpdate { htlc_update } => Some(htlc_update.0.clone()),
+                               OnchainEvent::HTLCUpdate { source, .. } => Some(source),
                                OnchainEvent::MaturingOutput { .. } => None,
                        })
                        .collect();
@@ -2127,28 +2070,28 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                // Produce actionable events from on-chain events having reached their threshold.
                for entry in onchain_events_reaching_threshold_conf.drain(..) {
                        match entry.event {
-                               OnchainEvent::HTLCUpdate { htlc_update } => {
+                               OnchainEvent::HTLCUpdate { ref source, payment_hash } => {
                                        // Check for duplicate HTLC resolutions.
                                        #[cfg(debug_assertions)]
                                        {
                                                debug_assert!(
-                                                       unmatured_htlcs.iter().find(|&htlc| htlc == &htlc_update.0).is_none(),
+                                                       unmatured_htlcs.iter().find(|&htlc| htlc == &source).is_none(),
                                                        "An unmature HTLC transaction conflicts with a maturing one; failed to \
                                                         call either transaction_unconfirmed for the conflicting transaction \
                                                         or block_disconnected for a block containing it.");
                                                debug_assert!(
-                                                       matured_htlcs.iter().find(|&htlc| htlc == &htlc_update.0).is_none(),
+                                                       matured_htlcs.iter().find(|&htlc| htlc == source).is_none(),
                                                        "A matured HTLC transaction conflicts with a maturing one; failed to \
                                                         call either transaction_unconfirmed for the conflicting transaction \
                                                         or block_disconnected for a block containing it.");
-                                               matured_htlcs.push(htlc_update.0.clone());
+                                               matured_htlcs.push(source.clone());
                                        }
 
-                                       log_trace!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!((htlc_update.1).0));
+                                       log_trace!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!(payment_hash.0));
                                        self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
-                                               payment_hash: htlc_update.1,
+                                               payment_hash: payment_hash,
                                                payment_preimage: None,
-                                               source: htlc_update.0,
+                                               source: source.clone(),
                                        }));
                                },
                                OnchainEvent::MaturingOutput { descriptor } => {
@@ -2445,16 +2388,16 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                        self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
                                                if entry.height != height { return true; }
                                                match entry.event {
-                                                        OnchainEvent::HTLCUpdate { ref htlc_update } => {
-                                                                htlc_update.0 != source
-                                                        },
-                                                        _ => true,
+                                                       OnchainEvent::HTLCUpdate { source: ref htlc_source, .. } => {
+                                                               *htlc_source != source
+                                                       },
+                                                       _ => true,
                                                }
                                        });
                                        let entry = OnchainEventEntry {
                                                txid: tx.txid(),
                                                height,
-                                               event: OnchainEvent::HTLCUpdate { htlc_update: (source, payment_hash) },
+                                               event: OnchainEvent::HTLCUpdate { source: source, payment_hash: payment_hash },
                                        };
                                        log_info!(logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height{})", log_bytes!(payment_hash.0), entry.confirmation_threshold());
                                        self.onchain_events_awaiting_threshold_conf.push(entry);
@@ -2731,46 +2674,14 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                        }
                }
 
-               macro_rules! read_holder_tx {
-                       () => {
-                               {
-                                       let txid = Readable::read(reader)?;
-                                       let revocation_key = Readable::read(reader)?;
-                                       let a_htlc_key = Readable::read(reader)?;
-                                       let b_htlc_key = Readable::read(reader)?;
-                                       let delayed_payment_key = Readable::read(reader)?;
-                                       let per_commitment_point = Readable::read(reader)?;
-                                       let feerate_per_kw: u32 = Readable::read(reader)?;
-
-                                       let htlcs_len: u64 = Readable::read(reader)?;
-                                       let mut htlcs = Vec::with_capacity(cmp::min(htlcs_len as usize, MAX_ALLOC_SIZE / 128));
-                                       for _ in 0..htlcs_len {
-                                               let htlc = read_htlc_in_commitment!();
-                                               let sigs = match <u8 as Readable>::read(reader)? {
-                                                       0 => None,
-                                                       1 => Some(Readable::read(reader)?),
-                                                       _ => return Err(DecodeError::InvalidValue),
-                                               };
-                                               htlcs.push((htlc, sigs, Readable::read(reader)?));
-                                       }
-
-                                       HolderSignedTx {
-                                               txid,
-                                               revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw,
-                                               htlc_outputs: htlcs
-                                       }
-                               }
-                       }
-               }
-
                let prev_holder_signed_commitment_tx = match <u8 as Readable>::read(reader)? {
                        0 => None,
                        1 => {
-                               Some(read_holder_tx!())
+                               Some(Readable::read(reader)?)
                        },
                        _ => return Err(DecodeError::InvalidValue),
                };
-               let current_holder_commitment_tx = read_holder_tx!();
+               let current_holder_commitment_tx = Readable::read(reader)?;
 
                let current_counterparty_commitment_number = <U48 as Readable>::read(reader)?.0;
                let current_holder_commitment_number = <U48 as Readable>::read(reader)?.0;
@@ -2809,25 +2720,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                let waiting_threshold_conf_len: u64 = Readable::read(reader)?;
                let mut onchain_events_awaiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128));
                for _ in 0..waiting_threshold_conf_len {
-                       let txid = Readable::read(reader)?;
-                       let height = Readable::read(reader)?;
-                       let event = match <u8 as Readable>::read(reader)? {
-                               0 => {
-                                       let htlc_source = Readable::read(reader)?;
-                                       let hash = Readable::read(reader)?;
-                                       OnchainEvent::HTLCUpdate {
-                                               htlc_update: (htlc_source, hash)
-                                       }
-                               },
-                               1 => {
-                                       let descriptor = Readable::read(reader)?;
-                                       OnchainEvent::MaturingOutput {
-                                               descriptor
-                                       }
-                               },
-                               _ => return Err(DecodeError::InvalidValue),
-                       };
-                       onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { txid, height, event });
+                       onchain_events_awaiting_threshold_conf.push(Readable::read(reader)?);
                }
 
                let outputs_to_watch_len: u64 = Readable::read(reader)?;
index 1f11856200841b011a058a812d2133507b7a9e55..84d83196472142d4c4334dcba5bf2d1e0ffafb0b 100644 (file)
@@ -73,6 +73,16 @@ impl DelayedPaymentOutputDescriptor {
        pub const MAX_WITNESS_LENGTH: usize = 1 + 73 + 1 + chan_utils::REVOKEABLE_REDEEMSCRIPT_MAX_LENGTH + 1;
 }
 
+impl_writeable_tlv_based!(DelayedPaymentOutputDescriptor, {
+       (0, outpoint),
+       (2, per_commitment_point),
+       (4, to_self_delay),
+       (6, output),
+       (8, revocation_pubkey),
+       (10, channel_keys_id),
+       (12, channel_value_satoshis),
+}, {}, {});
+
 /// Information about a spendable output to our "payment key". See
 /// SpendableOutputDescriptor::StaticPaymentOutput for more details on how to spend this.
 #[derive(Clone, Debug, PartialEq)]
@@ -94,6 +104,12 @@ impl StaticPaymentOutputDescriptor {
        // redeemscript push length.
        pub const MAX_WITNESS_LENGTH: usize = 1 + 73 + 34;
 }
+impl_writeable_tlv_based!(StaticPaymentOutputDescriptor, {
+       (0, outpoint),
+       (2, output),
+       (4, channel_keys_id),
+       (6, channel_value_satoshis),
+}, {}, {});
 
 /// When on-chain outputs are created by rust-lightning (which our counterparty is not able to
 /// claim at any point in the future) an event is generated which you must track and be able to
@@ -152,62 +168,15 @@ pub enum SpendableOutputDescriptor {
        StaticPaymentOutput(StaticPaymentOutputDescriptor),
 }
 
-impl Writeable for SpendableOutputDescriptor {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
-                               0u8.write(writer)?;
-                               outpoint.write(writer)?;
-                               output.write(writer)?;
-                       },
-                       &SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor) => {
-                               1u8.write(writer)?;
-                               descriptor.outpoint.write(writer)?;
-                               descriptor.per_commitment_point.write(writer)?;
-                               descriptor.to_self_delay.write(writer)?;
-                               descriptor.output.write(writer)?;
-                               descriptor.revocation_pubkey.write(writer)?;
-                               descriptor.channel_keys_id.write(writer)?;
-                               descriptor.channel_value_satoshis.write(writer)?;
-                       },
-                       &SpendableOutputDescriptor::StaticPaymentOutput(ref descriptor) => {
-                               2u8.write(writer)?;
-                               descriptor.outpoint.write(writer)?;
-                               descriptor.output.write(writer)?;
-                               descriptor.channel_keys_id.write(writer)?;
-                               descriptor.channel_value_satoshis.write(writer)?;
-                       },
-               }
-               Ok(())
-       }
-}
-
-impl Readable for SpendableOutputDescriptor {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               match Readable::read(reader)? {
-                       0u8 => Ok(SpendableOutputDescriptor::StaticOutput {
-                               outpoint: Readable::read(reader)?,
-                               output: Readable::read(reader)?,
-                       }),
-                       1u8 => Ok(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
-                               outpoint: Readable::read(reader)?,
-                               per_commitment_point: Readable::read(reader)?,
-                               to_self_delay: Readable::read(reader)?,
-                               output: Readable::read(reader)?,
-                               revocation_pubkey: Readable::read(reader)?,
-                               channel_keys_id: Readable::read(reader)?,
-                               channel_value_satoshis: Readable::read(reader)?,
-                       })),
-                       2u8 => Ok(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
-                               outpoint: Readable::read(reader)?,
-                               output: Readable::read(reader)?,
-                               channel_keys_id: Readable::read(reader)?,
-                               channel_value_satoshis: Readable::read(reader)?,
-                       })),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
+impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
+       (0, StaticOutput) => {
+               (0, outpoint),
+               (2, output),
+       }, {}, {},
+;
+       (1, DelayedPaymentOutput),
+       (2, StaticPaymentOutput),
+);
 
 /// A trait to sign lightning channel transactions as described in BOLT 3.
 ///
index e4bb66c7e755905058fa7b0f44520046773b5601..8f27e40baeaf1e3b5d43dade8a05da0bb08dfdcb 100644 (file)
@@ -239,6 +239,7 @@ pub trait Filter {
 ///
 /// [`ChannelMonitor`]: channelmonitor::ChannelMonitor
 /// [`ChannelMonitor::block_connected`]: channelmonitor::ChannelMonitor::block_connected
+#[derive(Clone, PartialEq, Hash)]
 pub struct WatchedOutput {
        /// First block where the transaction output may have been spent.
        pub block_hash: Option<BlockHash>,
index 1f604422f5ccf5890c0901a4e43a2fd7bea56393..dd4d1d8f0b37f844c8262673cafc6e1b98407585 100644 (file)
@@ -79,6 +79,21 @@ enum OnchainEvent {
        }
 }
 
+impl_writeable_tlv_based!(OnchainEventEntry, {
+       (0, txid),
+       (2, height),
+       (4, event),
+}, {}, {});
+
+impl_writeable_tlv_based_enum!(OnchainEvent,
+       (0, Claim) => {
+               (0, claim_request),
+       }, {}, {},
+       (1, ContentiousOutpoint) => {
+               (0, package),
+       }, {}, {},
+;);
+
 impl Readable for Option<Vec<Option<(usize, Signature)>>> {
        fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
                match Readable::read(reader)? {
@@ -219,18 +234,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
 
                writer.write_all(&byte_utils::be64_to_array(self.onchain_events_awaiting_threshold_conf.len() as u64))?;
                for ref entry in self.onchain_events_awaiting_threshold_conf.iter() {
-                       entry.txid.write(writer)?;
-                       writer.write_all(&byte_utils::be32_to_array(entry.height))?;
-                       match entry.event {
-                               OnchainEvent::Claim { ref claim_request } => {
-                                       writer.write_all(&[0; 1])?;
-                                       claim_request.write(writer)?;
-                               },
-                               OnchainEvent::ContentiousOutpoint { ref package } => {
-                                       writer.write_all(&[1; 1])?;
-                                       package.write(writer)?;
-                               }
-                       }
+                       entry.write(writer)?;
                }
 
                write_tlv_fields!(writer, {}, {});
@@ -292,24 +296,7 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
                let waiting_threshold_conf_len: u64 = Readable::read(reader)?;
                let mut onchain_events_awaiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128));
                for _ in 0..waiting_threshold_conf_len {
-                       let txid = Readable::read(reader)?;
-                       let height = Readable::read(reader)?;
-                       let event = match <u8 as Readable>::read(reader)? {
-                               0 => {
-                                       let claim_request = Readable::read(reader)?;
-                                       OnchainEvent::Claim {
-                                               claim_request
-                                       }
-                               },
-                               1 => {
-                                       let package = Readable::read(reader)?;
-                                       OnchainEvent::ContentiousOutpoint {
-                                               package
-                                       }
-                               }
-                               _ => return Err(DecodeError::InvalidValue),
-                       };
-                       onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { txid, height, event });
+                       onchain_events_awaiting_threshold_conf.push(Readable::read(reader)?);
                }
 
                read_tlv_fields!(reader, {}, {});
index a7339468991f93f462ab132ee6104b7860a4fb70..bd983ecd9163589b19b12f85199c9d851d0fb5f0 100644 (file)
@@ -404,65 +404,14 @@ impl PackageSolvingData {
        }
 }
 
-impl Writeable for PackageSolvingData {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       PackageSolvingData::RevokedOutput(ref revoked_outp) => {
-                               0u8.write(writer)?;
-                               revoked_outp.write(writer)?;
-                       },
-                       PackageSolvingData::RevokedHTLCOutput(ref revoked_outp) => {
-                               1u8.write(writer)?;
-                               revoked_outp.write(writer)?;
-                       },
-                       PackageSolvingData::CounterpartyOfferedHTLCOutput(ref counterparty_outp) => {
-                               2u8.write(writer)?;
-                               counterparty_outp.write(writer)?;
-                       },
-                       PackageSolvingData::CounterpartyReceivedHTLCOutput(ref counterparty_outp) => {
-                               3u8.write(writer)?;
-                               counterparty_outp.write(writer)?;
-                       },
-                       PackageSolvingData::HolderHTLCOutput(ref holder_outp) => {
-                               4u8.write(writer)?;
-                               holder_outp.write(writer)?;
-                       },
-                       PackageSolvingData::HolderFundingOutput(ref funding_outp) => {
-                               5u8.write(writer)?;
-                               funding_outp.write(writer)?;
-                       }
-               }
-               Ok(())
-       }
-}
-
-impl Readable for PackageSolvingData {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               let byte = <u8 as Readable>::read(reader)?;
-               let solving_data = match byte {
-                       0 => {
-                               PackageSolvingData::RevokedOutput(Readable::read(reader)?)
-                       },
-                       1 => {
-                               PackageSolvingData::RevokedHTLCOutput(Readable::read(reader)?)
-                       },
-                       2 => {
-                               PackageSolvingData::CounterpartyOfferedHTLCOutput(Readable::read(reader)?)
-                       },
-                       3 => {
-                               PackageSolvingData::CounterpartyReceivedHTLCOutput(Readable::read(reader)?)
-                       },
-                       4 => {
-                               PackageSolvingData::HolderHTLCOutput(Readable::read(reader)?)
-                       },
-                       5 => {
-                               PackageSolvingData::HolderFundingOutput(Readable::read(reader)?)
-                       }
-                       _ => return Err(DecodeError::UnknownVersion)
-               };
-               Ok(solving_data)
-       }
-}
+impl_writeable_tlv_based_enum!(PackageSolvingData, ;
+       (0, RevokedOutput),
+       (1, RevokedHTLCOutput),
+       (2, CounterpartyOfferedHTLCOutput),
+       (3, CounterpartyReceivedHTLCOutput),
+       (4, HolderHTLCOutput),
+       (5, HolderFundingOutput),
+);
 
 /// A malleable package might be aggregated with other packages to save on fees.
 /// A untractable package has been counter-signed and aggregable will break cached counterparty
index 4db5fbed6a8b9ed50f476f93c5a9581243857e33..502eb895b2683e4ad3b7fa5bc34f367111781ede 100644 (file)
@@ -73,14 +73,6 @@ impl OutPoint {
                        vout: self.index as u32,
                }
        }
-
-       /// Creates a dummy BitcoinOutPoint, useful for deserializing into.
-       pub(crate) fn null() -> Self {
-               Self {
-                       txid: Default::default(),
-                       index: 0
-               }
-       }
 }
 
 impl_writeable!(OutPoint, 0, { txid, index });
index 81b0df09607250d2a4a6c5c634c6d9fe2094a3e8..b698558e1b26b5a6c7a18cd142f4c8bce6e341b5 100644 (file)
@@ -22,7 +22,7 @@ use bitcoin::hash_types::{Txid, PubkeyHash};
 
 use ln::{PaymentHash, PaymentPreimage};
 use ln::msgs::DecodeError;
-use util::ser::{Readable, Writeable, Writer, MAX_BUF_SIZE};
+use util::ser::{Readable, Writeable, Writer};
 use util::byte_utils;
 
 use bitcoin::hash_types::WPubkeyHash;
@@ -36,18 +36,11 @@ use core::cmp;
 use ln::chan_utils;
 use util::transaction_utils::sort_outputs;
 use ln::channel::INITIAL_COMMITMENT_NUMBER;
-use std::io::Read;
 use core::ops::Deref;
 use chain;
 
-// Maximum size of a serialized HTLCOutputInCommitment
-pub(crate) const HTLC_OUTPUT_IN_COMMITMENT_SIZE: usize = 1 + 8 + 4 + 32 + 5;
-
 pub(crate) const MAX_HTLCS: u16 = 483;
 
-// This checks that the buffer size is greater than the maximum possible size for serialized HTLCS
-const _EXCESS_BUFFER_SIZE: usize = MAX_BUF_SIZE - MAX_HTLCS as usize * HTLC_OUTPUT_IN_COMMITMENT_SIZE;
-
 pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
 pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
 
@@ -866,44 +859,16 @@ impl PartialEq for CommitmentTransaction {
        }
 }
 
-/// (C-not exported) as users never need to call this directly
-impl Writeable for Vec<HTLCOutputInCommitment> {
-       #[inline]
-       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               (self.len() as u16).write(w)?;
-               for e in self.iter() {
-                       e.write(w)?;
-               }
-               Ok(())
-       }
-}
-
-/// (C-not exported) as users never need to call this directly
-impl Readable for Vec<HTLCOutputInCommitment> {
-       #[inline]
-       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let len: u16 = Readable::read(r)?;
-               let byte_size = (len as usize)
-                       .checked_mul(HTLC_OUTPUT_IN_COMMITMENT_SIZE)
-                       .ok_or(DecodeError::BadLengthDescriptor)?;
-               if byte_size > MAX_BUF_SIZE {
-                       return Err(DecodeError::BadLengthDescriptor);
-               }
-               let mut ret = Vec::with_capacity(len as usize);
-               for _ in 0..len { ret.push(HTLCOutputInCommitment::read(r)?); }
-               Ok(ret)
-       }
-}
-
 impl_writeable_tlv_based!(CommitmentTransaction, {
        (0, commitment_number),
        (2, to_broadcaster_value_sat),
        (4, to_countersignatory_value_sat),
        (6, feerate_per_kw),
-       (8, htlcs),
-       (10, keys),
-       (12, built),
-}, {}, {});
+       (8, keys),
+       (10, built),
+}, {}, {
+       (12, htlcs),
+});
 
 impl CommitmentTransaction {
        /// Construct an object of the class while assigning transaction output indices to HTLCs.
index 1c1b85ca1727aa90e9902b8130230571a28cc7cf..f8c8c15be95ad660f2803125092a6bcac288f8ee 100644 (file)
@@ -1428,9 +1428,6 @@ impl<Signer: Sign> Channel<Signer> {
                if msg.channel_reserve_satoshis > self.channel_value_satoshis {
                        return Err(ChannelError::Close(format!("Bogus channel_reserve_satoshis ({}). Must not be greater than ({})", msg.channel_reserve_satoshis, self.channel_value_satoshis)));
                }
-               if msg.dust_limit_satoshis > msg.channel_reserve_satoshis {
-                       return Err(ChannelError::Close(format!("Bogus channel_reserve ({}) and dust_limit ({})", msg.channel_reserve_satoshis, msg.dust_limit_satoshis)));
-               }
                if msg.channel_reserve_satoshis < self.holder_dust_limit_satoshis {
                        return Err(ChannelError::Close(format!("Peer never wants payout outputs? channel_reserve_satoshis was ({}). dust_limit is ({})", msg.channel_reserve_satoshis, self.holder_dust_limit_satoshis)));
                }
@@ -4382,37 +4379,11 @@ fn is_unsupported_shutdown_script(their_features: &InitFeatures, script: &Script
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl Writeable for InboundHTLCRemovalReason {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &InboundHTLCRemovalReason::FailRelay(ref error_packet) => {
-                               0u8.write(writer)?;
-                               error_packet.write(writer)?;
-                       },
-                       &InboundHTLCRemovalReason::FailMalformed((ref onion_hash, ref err_code)) => {
-                               1u8.write(writer)?;
-                               onion_hash.write(writer)?;
-                               err_code.write(writer)?;
-                       },
-                       &InboundHTLCRemovalReason::Fulfill(ref payment_preimage) => {
-                               2u8.write(writer)?;
-                               payment_preimage.write(writer)?;
-                       },
-               }
-               Ok(())
-       }
-}
-
-impl Readable for InboundHTLCRemovalReason {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               Ok(match <u8 as Readable>::read(reader)? {
-                       0 => InboundHTLCRemovalReason::FailRelay(Readable::read(reader)?),
-                       1 => InboundHTLCRemovalReason::FailMalformed((Readable::read(reader)?, Readable::read(reader)?)),
-                       2 => InboundHTLCRemovalReason::Fulfill(Readable::read(reader)?),
-                       _ => return Err(DecodeError::InvalidValue),
-               })
-       }
-}
+impl_writeable_tlv_based_enum!(InboundHTLCRemovalReason,;
+       (0, FailRelay),
+       (1, FailMalformed),
+       (2, Fulfill),
+);
 
 impl Writeable for ChannelUpdateStatus {
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
@@ -4519,9 +4490,10 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
                                &OutboundHTLCState::Committed => {
                                        1u8.write(writer)?;
                                },
-                               &OutboundHTLCState::RemoteRemoved(ref fail_reason) => {
-                                       2u8.write(writer)?;
-                                       fail_reason.write(writer)?;
+                               &OutboundHTLCState::RemoteRemoved(_) => {
+                                       // Treat this as a Committed because we haven't received the CS - they'll
+                                       // resend the claim/fail on reconnect as we all (hopefully) the missing CS.
+                                       1u8.write(writer)?;
                                },
                                &OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref fail_reason) => {
                                        3u8.write(writer)?;
index 9c1f8ecfd97d54b474efc61eab62015238cf5e11..13a993fd965596dc41e12a387bc178ea31372b35 100644 (file)
@@ -498,6 +498,7 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
 /// Typically, the block-specific parameters are derived from the best block hash for the network,
 /// as a newly constructed `ChannelManager` will not have created any channels yet. These parameters
 /// are not needed when deserializing a previously constructed `ChannelManager`.
+#[derive(Clone, Copy, PartialEq)]
 pub struct ChainParameters {
        /// The network for determining the `chain_hash` in Lightning messages.
        pub network: Network,
@@ -509,7 +510,7 @@ pub struct ChainParameters {
 }
 
 /// The best known block as identified by its hash and height.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, PartialEq)]
 pub struct BestBlock {
        block_hash: BlockHash,
        height: u32,
@@ -2321,7 +2322,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
        }
 
        #[cfg(any(test, feature = "_test_utils"))]
-       pub(crate) fn test_process_background_events(&self) {
+       /// Process background events, for functional testing
+       pub fn test_process_background_events(&self) {
                self.process_background_events();
        }
 
@@ -4317,43 +4319,16 @@ impl PersistenceNotifier {
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl Writeable for PendingHTLCRouting {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match &self {
-                       &PendingHTLCRouting::Forward { ref onion_packet, ref short_channel_id } => {
-                               0u8.write(writer)?;
-                               onion_packet.write(writer)?;
-                               short_channel_id.write(writer)?;
-                       },
-                       &PendingHTLCRouting::Receive { ref payment_data, ref incoming_cltv_expiry } => {
-                               1u8.write(writer)?;
-                               payment_data.payment_secret.write(writer)?;
-                               payment_data.total_msat.write(writer)?;
-                               incoming_cltv_expiry.write(writer)?;
-                       },
-               }
-               Ok(())
-       }
-}
-
-impl Readable for PendingHTLCRouting {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<PendingHTLCRouting, DecodeError> {
-               match Readable::read(reader)? {
-                       0u8 => Ok(PendingHTLCRouting::Forward {
-                               onion_packet: Readable::read(reader)?,
-                               short_channel_id: Readable::read(reader)?,
-                       }),
-                       1u8 => Ok(PendingHTLCRouting::Receive {
-                               payment_data: msgs::FinalOnionHopData {
-                                       payment_secret: Readable::read(reader)?,
-                                       total_msat: Readable::read(reader)?,
-                               },
-                               incoming_cltv_expiry: Readable::read(reader)?,
-                       }),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
+impl_writeable_tlv_based_enum!(PendingHTLCRouting,
+       (0, Forward) => {
+               (0, onion_packet),
+               (2, short_channel_id),
+       }, {}, {},
+       (1, Receive) => {
+               (0, payment_data),
+               (2, incoming_cltv_expiry),
+       }, {}, {}
+;);
 
 impl_writeable_tlv_based!(PendingHTLCInfo, {
        (0, routing),
@@ -4363,57 +4338,14 @@ impl_writeable_tlv_based!(PendingHTLCInfo, {
        (8, outgoing_cltv_value)
 }, {}, {});
 
-impl Writeable for HTLCFailureMsg {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &HTLCFailureMsg::Relay(ref fail_msg) => {
-                               0u8.write(writer)?;
-                               fail_msg.write(writer)?;
-                       },
-                       &HTLCFailureMsg::Malformed(ref fail_msg) => {
-                               1u8.write(writer)?;
-                               fail_msg.write(writer)?;
-                       }
-               }
-               Ok(())
-       }
-}
-
-impl Readable for HTLCFailureMsg {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCFailureMsg, DecodeError> {
-               match <u8 as Readable>::read(reader)? {
-                       0 => Ok(HTLCFailureMsg::Relay(Readable::read(reader)?)),
-                       1 => Ok(HTLCFailureMsg::Malformed(Readable::read(reader)?)),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
-
-impl Writeable for PendingHTLCStatus {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &PendingHTLCStatus::Forward(ref forward_info) => {
-                               0u8.write(writer)?;
-                               forward_info.write(writer)?;
-                       },
-                       &PendingHTLCStatus::Fail(ref fail_msg) => {
-                               1u8.write(writer)?;
-                               fail_msg.write(writer)?;
-                       }
-               }
-               Ok(())
-       }
-}
-
-impl Readable for PendingHTLCStatus {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<PendingHTLCStatus, DecodeError> {
-               match <u8 as Readable>::read(reader)? {
-                       0 => Ok(PendingHTLCStatus::Forward(Readable::read(reader)?)),
-                       1 => Ok(PendingHTLCStatus::Fail(Readable::read(reader)?)),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
+impl_writeable_tlv_based_enum!(HTLCFailureMsg, ;
+       (0, Relay),
+       (1, Malformed),
+);
+impl_writeable_tlv_based_enum!(PendingHTLCStatus, ;
+       (0, Forward),
+       (1, Fail),
+);
 
 impl_writeable_tlv_based!(HTLCPreviousHopData, {
        (0, short_channel_id),
@@ -4422,148 +4354,46 @@ impl_writeable_tlv_based!(HTLCPreviousHopData, {
        (6, incoming_packet_shared_secret)
 }, {}, {});
 
-impl Writeable for ClaimableHTLC {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               write_tlv_fields!(writer, {
-                       (0, self.prev_hop),
-                       (2, self.value),
-                       (4, self.payment_data.payment_secret),
-                       (6, self.payment_data.total_msat),
-                       (8, self.cltv_expiry)
-               }, {});
-               Ok(())
-       }
-}
-
-impl Readable for ClaimableHTLC {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               let mut prev_hop = HTLCPreviousHopData {
-                       short_channel_id: 0, htlc_id: 0,
-                       incoming_packet_shared_secret: [0; 32],
-                       outpoint: OutPoint::null(),
-               };
-               let mut value = 0;
-               let mut payment_secret = PaymentSecret([0; 32]);
-               let mut total_msat = 0;
-               let mut cltv_expiry = 0;
-               read_tlv_fields!(reader, {
-                       (0, prev_hop),
-                       (2, value),
-                       (4, payment_secret),
-                       (6, total_msat),
-                       (8, cltv_expiry)
-               }, {});
-               Ok(ClaimableHTLC {
-                       prev_hop,
-                       value,
-                       payment_data: msgs::FinalOnionHopData {
-                               payment_secret,
-                               total_msat,
-                       },
-                       cltv_expiry,
-               })
-       }
-}
-
-impl Writeable for HTLCSource {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &HTLCSource::PreviousHopData(ref hop_data) => {
-                               0u8.write(writer)?;
-                               hop_data.write(writer)?;
-                       },
-                       &HTLCSource::OutboundRoute { ref path, ref session_priv, ref first_hop_htlc_msat } => {
-                               1u8.write(writer)?;
-                               path.write(writer)?;
-                               session_priv.write(writer)?;
-                               first_hop_htlc_msat.write(writer)?;
-                       }
-               }
-               Ok(())
-       }
-}
-
-impl Readable for HTLCSource {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCSource, DecodeError> {
-               match <u8 as Readable>::read(reader)? {
-                       0 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)),
-                       1 => Ok(HTLCSource::OutboundRoute {
-                               path: Readable::read(reader)?,
-                               session_priv: Readable::read(reader)?,
-                               first_hop_htlc_msat: Readable::read(reader)?,
-                       }),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
-
-impl Writeable for HTLCFailReason {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &HTLCFailReason::LightningError { ref err } => {
-                               0u8.write(writer)?;
-                               err.write(writer)?;
-                       },
-                       &HTLCFailReason::Reason { ref failure_code, ref data } => {
-                               1u8.write(writer)?;
-                               failure_code.write(writer)?;
-                               data.write(writer)?;
-                       }
-               }
-               Ok(())
-       }
-}
-
-impl Readable for HTLCFailReason {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCFailReason, DecodeError> {
-               match <u8 as Readable>::read(reader)? {
-                       0 => Ok(HTLCFailReason::LightningError { err: Readable::read(reader)? }),
-                       1 => Ok(HTLCFailReason::Reason {
-                               failure_code: Readable::read(reader)?,
-                               data: Readable::read(reader)?,
-                       }),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
-
-impl Writeable for HTLCForwardInfo {
-       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               match self {
-                       &HTLCForwardInfo::AddHTLC { ref prev_short_channel_id, ref prev_funding_outpoint, ref prev_htlc_id, ref forward_info } => {
-                               0u8.write(writer)?;
-                               prev_short_channel_id.write(writer)?;
-                               prev_funding_outpoint.write(writer)?;
-                               prev_htlc_id.write(writer)?;
-                               forward_info.write(writer)?;
-                       },
-                       &HTLCForwardInfo::FailHTLC { ref htlc_id, ref err_packet } => {
-                               1u8.write(writer)?;
-                               htlc_id.write(writer)?;
-                               err_packet.write(writer)?;
-                       },
-               }
-               Ok(())
-       }
-}
+impl_writeable_tlv_based!(ClaimableHTLC, {
+       (0, prev_hop),
+       (2, value),
+       (4, payment_data),
+       (6, cltv_expiry),
+}, {}, {});
 
-impl Readable for HTLCForwardInfo {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<HTLCForwardInfo, DecodeError> {
-               match <u8 as Readable>::read(reader)? {
-                       0 => Ok(HTLCForwardInfo::AddHTLC {
-                               prev_short_channel_id: Readable::read(reader)?,
-                               prev_funding_outpoint: Readable::read(reader)?,
-                               prev_htlc_id: Readable::read(reader)?,
-                               forward_info: Readable::read(reader)?,
-                       }),
-                       1 => Ok(HTLCForwardInfo::FailHTLC {
-                               htlc_id: Readable::read(reader)?,
-                               err_packet: Readable::read(reader)?,
-                       }),
-                       _ => Err(DecodeError::InvalidValue),
-               }
-       }
-}
+impl_writeable_tlv_based_enum!(HTLCSource,
+       (0, OutboundRoute) => {
+               (0, session_priv),
+               (2, first_hop_htlc_msat),
+       }, {}, {
+               (4, path),
+       };
+       (1, PreviousHopData)
+);
+
+impl_writeable_tlv_based_enum!(HTLCFailReason,
+       (0, LightningError) => {
+               (0, err),
+       }, {}, {},
+       (1, Reason) => {
+               (0, failure_code),
+       }, {}, {
+               (2, data),
+       },
+;);
+
+impl_writeable_tlv_based_enum!(HTLCForwardInfo,
+       (0, AddHTLC) => {
+               (0, forward_info),
+               (2, prev_short_channel_id),
+               (4, prev_htlc_id),
+               (6, prev_funding_outpoint),
+       }, {}, {},
+       (1, FailHTLC) => {
+               (0, htlc_id),
+               (2, err_packet),
+       }, {}, {},
+;);
 
 impl_writeable_tlv_based!(PendingInboundPayment, {
        (0, payment_secret),
index eec1a053802fd7476ce1b43f0518b4ef339c1dfb..f02a478357b8c32598ad5c4096abe905482d5c8e 100644 (file)
@@ -46,7 +46,7 @@ use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000;
 
 /// An error in decoding a message or struct.
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum DecodeError {
        /// A version byte specified something we don't know how to handle.
        /// Includes unknown realm byte in an OnionHopData packet
index f80fd676c75d14397ac2e4c693f64cc3b2fffa50..0deb8b74fdcfc1542cb56f044dd387b83af72c7a 100644 (file)
@@ -11,7 +11,6 @@ use ln::{PaymentHash, PaymentSecret};
 use ln::channelmanager::HTLCSource;
 use ln::msgs;
 use routing::router::RouteHop;
-use util::byte_utils;
 use util::chacha20::ChaCha20;
 use util::errors::{self, APIError};
 use util::ser::{Readable, Writeable, LengthCalculatingWriter};
@@ -29,6 +28,7 @@ use bitcoin::secp256k1;
 
 use prelude::*;
 use std::io::Cursor;
+use core::convert::TryInto;
 use core::ops::Deref;
 
 pub(super) struct OnionKeys {
@@ -367,7 +367,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                const NODE: u16 = 0x2000;
                                                const UPDATE: u16 = 0x1000;
 
-                                               let error_code = byte_utils::slice_to_be16(&error_code_slice);
+                                               let error_code = u16::from_be_bytes(error_code_slice.try_into().expect("len is 2"));
                                                error_code_ret = Some(error_code);
                                                error_packet_ret = Some(err_packet.failuremsg[2..].to_vec());
 
@@ -394,7 +394,7 @@ pub(super) fn process_onion_failure<T: secp256k1::Signing, L: Deref>(secp_ctx: &
                                                }
                                                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 = byte_utils::slice_to_be16(&update_len_slice) as usize;
+                                                               let update_len = u16::from_be_bytes(update_len_slice.try_into().expect("len is 2")) as usize;
                                                                if let Some(update_slice) = err_packet.failuremsg.get(debug_field_size + 4..debug_field_size + 4 + update_len) {
                                                                        if let Ok(chan_update) = msgs::ChannelUpdate::read(&mut Cursor::new(&update_slice)) {
                                                                                // if channel_update should NOT have caused the failure:
index 76385fc8b063221259fbe3b99d791e49e28cfa15..7b42c68a578154aedcc0116cffac9c1a4ee5d799 100644 (file)
@@ -21,7 +21,6 @@ use bitcoin::secp256k1::ecdh::SharedSecret;
 use bitcoin::secp256k1;
 
 use util::chacha20poly1305rfc::ChaCha20Poly1305RFC;
-use util::byte_utils;
 use bitcoin::hashes::hex::ToHex;
 
 /// Maximum Lightning message data length according to
@@ -141,7 +140,7 @@ impl PeerChannelEncryptor {
        #[inline]
        fn encrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], plaintext: &[u8]) {
                let mut nonce = [0; 12];
-               nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n));
+               nonce[4..].copy_from_slice(&n.to_le_bytes()[..]);
 
                let mut chacha = ChaCha20Poly1305RFC::new(key, &nonce, h);
                let mut tag = [0; 16];
@@ -152,7 +151,7 @@ impl PeerChannelEncryptor {
        #[inline]
        fn decrypt_with_ad(res: &mut[u8], n: u64, key: &[u8; 32], h: &[u8], cyphertext: &[u8]) -> Result<(), LightningError> {
                let mut nonce = [0; 12];
-               nonce[4..].copy_from_slice(&byte_utils::le64_to_array(n));
+               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..]) {
@@ -406,7 +405,7 @@ impl PeerChannelEncryptor {
                                        *sn = 0;
                                }
 
-                               Self::encrypt_with_ad(&mut res[0..16+2], *sn, sk, &[0; 0], &byte_utils::be16_to_array(msg.len() as u16));
+                               Self::encrypt_with_ad(&mut res[0..16+2], *sn, sk, &[0; 0], &(msg.len() as u16).to_be_bytes());
                                *sn += 1;
 
                                Self::encrypt_with_ad(&mut res[16+2..], *sn, sk, &[0; 0], msg);
@@ -435,7 +434,7 @@ impl PeerChannelEncryptor {
                                let mut res = [0; 2];
                                Self::decrypt_with_ad(&mut res, *rn, rk, &[0; 0], msg)?;
                                *rn += 1;
-                               Ok(byte_utils::slice_to_be16(&res))
+                               Ok(u16::from_be_bytes(res))
                        },
                        _ => panic!("Tried to decrypt a message prior to noise handshake completion"),
                }
index 3433d9e1a3968681d2fb9356807cfeeed26ebc2c..58d336ba06942206e306423e8b643e86a982c8aa 100644 (file)
@@ -350,8 +350,8 @@ impl Encode for msgs::GossipTimestampFilter {
 #[cfg(test)]
 mod tests {
        use super::*;
-       use util::byte_utils;
        use prelude::*;
+       use core::convert::TryInto;
 
        // Big-endian wire encoding of Pong message (type = 19, byteslen = 2).
        const ENCODED_PONG: [u8; 6] = [0u8, 19u8, 0u8, 2u8, 0u8, 0u8];
@@ -397,7 +397,7 @@ mod tests {
 
        #[test]
        fn read_unknown_message() {
-               let buffer = &byte_utils::be16_to_array(::core::u16::MAX);
+               let buffer = &::core::u16::MAX.to_be_bytes();
                let mut reader = ::std::io::Cursor::new(buffer);
                let message = read(&mut reader).unwrap();
                match message {
@@ -414,7 +414,7 @@ mod tests {
 
                let type_length = ::core::mem::size_of::<u16>();
                let (type_bytes, payload_bytes) = buffer.split_at(type_length);
-               assert_eq!(byte_utils::slice_to_be16(type_bytes), msgs::Pong::TYPE);
+               assert_eq!(u16::from_be_bytes(type_bytes.try_into().unwrap()), msgs::Pong::TYPE);
                assert_eq!(payload_bytes, &ENCODED_PONG[type_length..]);
        }
 
index 4b90cad4432e5de98a3fb63d7416777d5cd6a5b7..b4448f72204b30d8e61841cc9e8563700685283b 100644 (file)
@@ -2424,3 +2424,30 @@ mod tests {
                assert!(result.is_err());
        }
 }
+
+#[cfg(all(test, feature = "unstable"))]
+mod benches {
+       use super::*;
+
+       use test::Bencher;
+       use std::io::Read;
+
+       #[bench]
+       fn read_network_graph(bench: &mut Bencher) {
+               let mut d = ::routing::router::test_utils::get_route_file().unwrap();
+               let mut v = Vec::new();
+               d.read_to_end(&mut v).unwrap();
+               bench.iter(|| {
+                       let _ = NetworkGraph::read(&mut std::io::Cursor::new(&v)).unwrap();
+               });
+       }
+
+       #[bench]
+       fn write_network_graph(bench: &mut Bencher) {
+               let mut d = ::routing::router::test_utils::get_route_file().unwrap();
+               let net_graph = NetworkGraph::read(&mut d).unwrap();
+               bench.iter(|| {
+                       let _ = net_graph.encode();
+               });
+       }
+}
index 46fe93e779962f4be80a1873a4884228921f6a72..52ac9b77578c0586a6586c58ffff17f4b9e80e98 100644 (file)
@@ -49,40 +49,14 @@ pub struct RouteHop {
        pub cltv_expiry_delta: u32,
 }
 
-/// (C-not exported)
-impl Writeable for Vec<RouteHop> {
-       fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               (self.len() as u8).write(writer)?;
-               for hop in self.iter() {
-                       hop.pubkey.write(writer)?;
-                       hop.node_features.write(writer)?;
-                       hop.short_channel_id.write(writer)?;
-                       hop.channel_features.write(writer)?;
-                       hop.fee_msat.write(writer)?;
-                       hop.cltv_expiry_delta.write(writer)?;
-               }
-               Ok(())
-       }
-}
-
-/// (C-not exported)
-impl Readable for Vec<RouteHop> {
-       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Vec<RouteHop>, DecodeError> {
-               let hops_count: u8 = Readable::read(reader)?;
-               let mut hops = Vec::with_capacity(hops_count as usize);
-               for _ in 0..hops_count {
-                       hops.push(RouteHop {
-                               pubkey: Readable::read(reader)?,
-                               node_features: Readable::read(reader)?,
-                               short_channel_id: Readable::read(reader)?,
-                               channel_features: Readable::read(reader)?,
-                               fee_msat: Readable::read(reader)?,
-                               cltv_expiry_delta: Readable::read(reader)?,
-                       });
-               }
-               Ok(hops)
-       }
-}
+impl_writeable_tlv_based!(RouteHop, {
+       (0, pubkey),
+       (2, node_features),
+       (4, short_channel_id),
+       (6, channel_features),
+       (8, fee_msat),
+       (10, cltv_expiry_delta),
+}, {}, {});
 
 /// A route directs a payment from the sender (us) to the recipient. If the recipient supports MPP,
 /// it can take multiple paths. Each path is composed of one or more hops through the network.
@@ -105,7 +79,10 @@ impl Writeable for Route {
                write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
                (self.paths.len() as u64).write(writer)?;
                for hops in self.paths.iter() {
-                       hops.write(writer)?;
+                       (hops.len() as u8).write(writer)?;
+                       for hop in hops.iter() {
+                               hop.write(writer)?;
+                       }
                }
                write_tlv_fields!(writer, {}, {});
                Ok(())
@@ -118,7 +95,12 @@ impl Readable for Route {
                let path_count: u64 = Readable::read(reader)?;
                let mut paths = Vec::with_capacity(cmp::min(path_count, 128) as usize);
                for _ in 0..path_count {
-                       paths.push(Readable::read(reader)?);
+                       let hop_count: u8 = Readable::read(reader)?;
+                       let mut hops = Vec::with_capacity(hop_count as usize);
+                       for _ in 0..hop_count {
+                               hops.push(Readable::read(reader)?);
+                       }
+                       paths.push(hops);
                }
                read_tlv_fields!(reader, {}, {});
                Ok(Route { paths })
@@ -3856,30 +3838,6 @@ mod tests {
                }
        }
 
-       use std::fs::File;
-       use util::ser::Readable;
-       /// Tries to open a network graph file, or panics with a URL to fetch it.
-       pub(super) fn get_route_file() -> Result<std::fs::File, std::io::Error> {
-               let res = File::open("net_graph-2021-05-27.bin") // By default we're run in RL/lightning
-                       .or_else(|_| File::open("lightning/net_graph-2021-05-27.bin")) // We may be run manually in RL/
-                       .or_else(|_| { // Fall back to guessing based on the binary location
-                               // path is likely something like .../rust-lightning/target/debug/deps/lightning-...
-                               let mut path = std::env::current_exe().unwrap();
-                               path.pop(); // lightning-...
-                               path.pop(); // deps
-                               path.pop(); // debug
-                               path.pop(); // target
-                               path.push("lightning");
-                               path.push("net_graph-2021-05-27.bin");
-                               eprintln!("{}", path.to_str().unwrap());
-                               File::open(path)
-                       });
-               #[cfg(require_route_graph_test)]
-               return Ok(res.expect("Didn't have route graph and was configured to require it"));
-               #[cfg(not(require_route_graph_test))]
-               return res;
-       }
-
        pub(super) fn random_init_seed() -> u64 {
                // Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.
                use core::hash::{BuildHasher, Hasher};
@@ -3887,13 +3845,14 @@ mod tests {
                println!("Using seed of {}", seed);
                seed
        }
+       use util::ser::Readable;
 
        #[test]
        fn generate_routes() {
-               let mut d = match get_route_file() {
+               let mut d = match super::test_utils::get_route_file() {
                        Ok(f) => f,
-                       Err(_) => {
-                               eprintln!("Please fetch https://bitcoin.ninja/ldk-net_graph-45d86ead641d-2021-05-27.bin and place it at lightning/net_graph-2021-05-27.bin");
+                       Err(e) => {
+                               eprintln!("{}", e);
                                return;
                        },
                };
@@ -3917,10 +3876,10 @@ mod tests {
 
        #[test]
        fn generate_routes_mpp() {
-               let mut d = match get_route_file() {
+               let mut d = match super::test_utils::get_route_file() {
                        Ok(f) => f,
-                       Err(_) => {
-                               eprintln!("Please fetch https://bitcoin.ninja/ldk-net_graph-45d86ead641d-2021-05-27.bin and place it at lightning/net_graph-2021-05-27.bin");
+                       Err(e) => {
+                               eprintln!("{}", e);
                                return;
                        },
                };
@@ -3943,12 +3902,38 @@ mod tests {
        }
 }
 
+#[cfg(test)]
+pub(crate) mod test_utils {
+       use std::fs::File;
+       /// Tries to open a network graph file, or panics with a URL to fetch it.
+       pub(crate) fn get_route_file() -> Result<std::fs::File, &'static str> {
+               let res = File::open("net_graph-2021-05-31.bin") // By default we're run in RL/lightning
+                       .or_else(|_| File::open("lightning/net_graph-2021-05-31.bin")) // We may be run manually in RL/
+                       .or_else(|_| { // Fall back to guessing based on the binary location
+                               // path is likely something like .../rust-lightning/target/debug/deps/lightning-...
+                               let mut path = std::env::current_exe().unwrap();
+                               path.pop(); // lightning-...
+                               path.pop(); // deps
+                               path.pop(); // debug
+                               path.pop(); // target
+                               path.push("lightning");
+                               path.push("net_graph-2021-05-31.bin");
+                               eprintln!("{}", path.to_str().unwrap());
+                               File::open(path)
+                       })
+               .map_err(|_| "Please fetch https://bitcoin.ninja/ldk-net_graph-v0.0.15-2021-05-31.bin and place it at lightning/net_graph-2021-05-31.bin");
+               #[cfg(require_route_graph_test)]
+               return Ok(res.unwrap());
+               #[cfg(not(require_route_graph_test))]
+               return res;
+       }
+}
+
 #[cfg(all(test, feature = "unstable"))]
 mod benches {
        use super::*;
        use util::logger::{Logger, Record};
 
-       use prelude::*;
        use test::Bencher;
 
        struct DummyLogger {}
@@ -3958,8 +3943,7 @@ mod benches {
 
        #[bench]
        fn generate_routes(bench: &mut Bencher) {
-               let mut d = tests::get_route_file()
-                       .expect("Please fetch https://bitcoin.ninja/ldk-net_graph-45d86ead641d-2021-05-27.bin and place it at lightning/net_graph-2021-05-27.bin");
+               let mut d = test_utils::get_route_file().unwrap();
                let graph = NetworkGraph::read(&mut d).unwrap();
 
                // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
@@ -3990,8 +3974,7 @@ mod benches {
 
        #[bench]
        fn generate_mpp_routes(bench: &mut Bencher) {
-               let mut d = tests::get_route_file()
-                       .expect("Please fetch https://bitcoin.ninja/ldk-net_graph-45d86ead641d-2021-05-27.bin and place it at lightning/net_graph-2021-05-27.bin");
+               let mut d = test_utils::get_route_file().unwrap();
                let graph = NetworkGraph::read(&mut d).unwrap();
 
                // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
index 8ae3649780634cd6a6b2c3243222cc9f40b1e782..0c6530f29e0eb1cb8b937f9842b9c83eb3d504be 100644 (file)
@@ -7,26 +7,6 @@
 // You may not use this file except in accordance with one or both of these
 // licenses.
 
-#[inline]
-pub fn slice_to_be16(v: &[u8]) -> u16 {
-       ((v[0] as u16) << 8*1) |
-       ((v[1] as u16) << 8*0)
-}
-#[inline]
-pub fn slice_to_be32(v: &[u8]) -> u32 {
-       ((v[0] as u32) << 8*3) |
-       ((v[1] as u32) << 8*2) |
-       ((v[2] as u32) << 8*1) |
-       ((v[3] as u32) << 8*0)
-}
-#[cfg(not(feature = "fuzztarget"))] // Used only by poly1305
-#[inline]
-pub fn slice_to_le32(v: &[u8]) -> u32 {
-       ((v[0] as u32) << 8*0) |
-       ((v[1] as u32) << 8*1) |
-       ((v[2] as u32) << 8*2) |
-       ((v[3] as u32) << 8*3)
-}
 #[inline]
 pub fn slice_to_be48(v: &[u8]) -> u64 {
        ((v[0] as u64) << 8*5) |
@@ -64,16 +44,6 @@ pub fn be32_to_array(u: u32) -> [u8; 4] {
        v[3] = ((u >> 8*0) & 0xff) as u8;
        v
 }
-#[cfg(not(feature = "fuzztarget"))] // Used only by poly1305
-#[inline]
-pub fn le32_to_array(u: u32) -> [u8; 4] {
-       let mut v = [0; 4];
-       v[0] = ((u >> 8*0) & 0xff) as u8;
-       v[1] = ((u >> 8*1) & 0xff) as u8;
-       v[2] = ((u >> 8*2) & 0xff) as u8;
-       v[3] = ((u >> 8*3) & 0xff) as u8;
-       v
-}
 #[inline]
 pub fn be48_to_array(u: u64) -> [u8; 6] {
        assert!(u & 0xffff_0000_0000_0000 == 0);
@@ -120,14 +90,10 @@ mod tests {
        
        #[test]
        fn test_all() {
-               assert_eq!(slice_to_be16(&[0xde, 0xad]), 0xdead);
-               assert_eq!(slice_to_be32(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef);
-               assert_eq!(slice_to_le32(&[0xef, 0xbe, 0xad, 0xde]), 0xdeadbeef);
                assert_eq!(slice_to_be48(&[0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad]), 0xdeadbeef1bad);
                assert_eq!(slice_to_be64(&[0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad, 0x1d, 0xea]), 0xdeadbeef1bad1dea);
                assert_eq!(be16_to_array(0xdead), [0xde, 0xad]);
                assert_eq!(be32_to_array(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]);
-               assert_eq!(le32_to_array(0xdeadbeef), [0xef, 0xbe, 0xad, 0xde]);
                assert_eq!(be48_to_array(0xdeadbeef1bad), [0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad]);
                assert_eq!(be64_to_array(0xdeadbeef1bad1dea), [0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad, 0x1d, 0xea]);
                assert_eq!(le64_to_array(0xdeadbeef1bad1dea), [0xea, 0x1d, 0xad, 0x1b, 0xef, 0xbe, 0xad, 0xde]);
index 69e4ed8d113d1cdb5a101a5fa1b60338a68d13be..cbf08f46c226a568d1bebc8c368e74d518624433 100644 (file)
@@ -14,7 +14,7 @@ use std::io;
 #[cfg(not(feature = "fuzztarget"))]
 mod real_chacha {
        use core::cmp;
-       use util::byte_utils::{slice_to_le32, le32_to_array};
+       use core::convert::TryInto;
 
        #[derive(Clone, Copy, PartialEq, Eq)]
        #[allow(non_camel_case_types)]
@@ -55,6 +55,17 @@ mod real_chacha {
                        u32x4(self.0 << rhs.0, self.1 << rhs.1, self.2 << rhs.2, self.3 << rhs.3)
                }
        }
+       impl u32x4 {
+               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;
 
@@ -99,7 +110,7 @@ mod real_chacha {
                                d1,d2,d3,d4
                        ];
                        for i in 0..lens.len() {
-                               $output[i*4..(i+1)*4].copy_from_slice(&le32_to_array(lens[i]));
+                               $output[i*4..(i+1)*4].copy_from_slice(&lens[i].to_le_bytes());
                        }
                }}
        }
@@ -147,54 +158,23 @@ mod real_chacha {
                                _  => unreachable!(),
                        };
                        ChaChaState {
-                               a: u32x4(
-                                       slice_to_le32(&constant[0..4]),
-                                       slice_to_le32(&constant[4..8]),
-                                       slice_to_le32(&constant[8..12]),
-                                       slice_to_le32(&constant[12..16])
-                               ),
-                               b: u32x4(
-                                       slice_to_le32(&key[0..4]),
-                                       slice_to_le32(&key[4..8]),
-                                       slice_to_le32(&key[8..12]),
-                                       slice_to_le32(&key[12..16])
-                               ),
+                               a: u32x4::from_bytes(&constant[0..16]),
+                               b: u32x4::from_bytes(&key[0..16]),
                                c: if key.len() == 16 {
-                                       u32x4(
-                                               slice_to_le32(&key[0..4]),
-                                               slice_to_le32(&key[4..8]),
-                                               slice_to_le32(&key[8..12]),
-                                               slice_to_le32(&key[12..16])
-                                       )
+                                       u32x4::from_bytes(&key[0..16])
                                } else {
-                                       u32x4(
-                                               slice_to_le32(&key[16..20]),
-                                               slice_to_le32(&key[20..24]),
-                                               slice_to_le32(&key[24..28]),
-                                               slice_to_le32(&key[28..32])
-                                       )
+                                       u32x4::from_bytes(&key[16..32])
                                },
                                d: if nonce.len() == 16 {
-                                       u32x4(
-                                               slice_to_le32(&nonce[0..4]),
-                                               slice_to_le32(&nonce[4..8]),
-                                               slice_to_le32(&nonce[8..12]),
-                                               slice_to_le32(&nonce[12..16])
-                                       )
+                                       u32x4::from_bytes(&nonce[0..16])
                                } else if nonce.len() == 12 {
-                                       u32x4(
-                                               0,
-                                               slice_to_le32(&nonce[0..4]),
-                                               slice_to_le32(&nonce[4..8]),
-                                               slice_to_le32(&nonce[8..12])
-                                       )
+                                       let mut nonce4 = [0; 4*4];
+                                       nonce4[4..].copy_from_slice(nonce);
+                                       u32x4::from_bytes(&nonce4)
                                } else {
-                                       u32x4(
-                                               0,
-                                               0,
-                                               slice_to_le32(&nonce[0..4]),
-                                               slice_to_le32(&nonce[4..8])
-                                       )
+                                       let mut nonce4 = [0; 4*4];
+                                       nonce4[8..].copy_from_slice(nonce);
+                                       u32x4::from_bytes(&nonce4)
                                }
                        }
                }
index b3c77c9ae36b561d93c81e438538a2dd684e8e8c..c8c7ad496e4dd3a62ec6e02ee046d89cf03a62f5 100644 (file)
@@ -17,7 +17,7 @@
 use ln::msgs;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
 use chain::keysinterface::SpendableOutputDescriptor;
-use util::ser::{Writeable, Writer, MaybeReadable, Readable};
+use util::ser::{Writeable, Writer, MaybeReadable, Readable, VecReadWrapper, VecWriteWrapper};
 
 use bitcoin::blockdata::script::Script;
 
@@ -147,14 +147,20 @@ impl Writeable for Event {
                        },
                        &Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, ref amt, ref user_payment_id } => {
                                1u8.write(writer)?;
-                               payment_hash.write(writer)?;
-                               payment_preimage.write(writer)?;
-                               payment_secret.write(writer)?;
-                               amt.write(writer)?;
-                               user_payment_id.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_hash),
+                                       (2, payment_secret),
+                                       (4, amt),
+                                       (6, user_payment_id),
+                               }, {
+                                       (8, payment_preimage),
+                               });
                        },
                        &Event::PaymentSent { ref payment_preimage } => {
                                2u8.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_preimage),
+                               }, {});
                                payment_preimage.write(writer)?;
                        },
                        &Event::PaymentFailed { ref payment_hash, ref rejected_by_dest,
@@ -164,24 +170,26 @@ impl Writeable for Event {
                                ref error_data,
                        } => {
                                3u8.write(writer)?;
-                               payment_hash.write(writer)?;
-                               rejected_by_dest.write(writer)?;
                                #[cfg(test)]
                                error_code.write(writer)?;
                                #[cfg(test)]
                                error_data.write(writer)?;
+                               write_tlv_fields!(writer, {
+                                       (0, payment_hash),
+                                       (2, rejected_by_dest),
+                               }, {});
                        },
                        &Event::PendingHTLCsForwardable { time_forwardable: _ } => {
                                4u8.write(writer)?;
+                               write_tlv_fields!(writer, {}, {});
                                // We don't write the time_fordwardable out at all, as we presume when the user
                                // deserializes us at least that much time has elapsed.
                        },
                        &Event::SpendableOutputs { ref outputs } => {
                                5u8.write(writer)?;
-                               (outputs.len() as u64).write(writer)?;
-                               for output in outputs.iter() {
-                                       output.write(writer)?;
-                               }
+                               write_tlv_fields!(writer, {
+                                       (0, VecWriteWrapper(outputs)),
+                               }, {});
                        },
                }
                Ok(())
@@ -191,34 +199,84 @@ impl MaybeReadable for Event {
        fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Option<Self>, msgs::DecodeError> {
                match Readable::read(reader)? {
                        0u8 => Ok(None),
-                       1u8 => Ok(Some(Event::PaymentReceived {
-                                       payment_hash: Readable::read(reader)?,
-                                       payment_preimage: Readable::read(reader)?,
-                                       payment_secret: Readable::read(reader)?,
-                                       amt: Readable::read(reader)?,
-                                       user_payment_id: Readable::read(reader)?,
-                               })),
-                       2u8 => Ok(Some(Event::PaymentSent {
-                                       payment_preimage: Readable::read(reader)?,
-                               })),
-                       3u8 => Ok(Some(Event::PaymentFailed {
-                                       payment_hash: Readable::read(reader)?,
-                                       rejected_by_dest: Readable::read(reader)?,
+                       1u8 => {
+                               let f = || {
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut payment_preimage = None;
+                                       let mut payment_secret = PaymentSecret([0; 32]);
+                                       let mut amt = 0;
+                                       let mut user_payment_id = 0;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_hash),
+                                               (2, payment_secret),
+                                               (4, amt),
+                                               (6, user_payment_id),
+                                       }, {
+                                               (8, payment_preimage),
+                                       });
+                                       Ok(Some(Event::PaymentReceived {
+                                               payment_hash,
+                                               payment_preimage,
+                                               payment_secret,
+                                               amt,
+                                               user_payment_id,
+                                       }))
+                               };
+                               f()
+                       },
+                       2u8 => {
+                               let f = || {
+                                       let mut payment_preimage = PaymentPreimage([0; 32]);
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_preimage),
+                                       }, {});
+                                       Ok(Some(Event::PaymentSent {
+                                               payment_preimage,
+                                       }))
+                               };
+                               f()
+                       },
+                       3u8 => {
+                               let f = || {
                                        #[cfg(test)]
-                                       error_code: Readable::read(reader)?,
+                                       let error_code = Readable::read(reader)?;
                                        #[cfg(test)]
-                                       error_data: Readable::read(reader)?,
-                               })),
-                       4u8 => Ok(Some(Event::PendingHTLCsForwardable {
-                                       time_forwardable: Duration::from_secs(0)
-                               })),
+                                       let error_data = Readable::read(reader)?;
+                                       let mut payment_hash = PaymentHash([0; 32]);
+                                       let mut rejected_by_dest = false;
+                                       read_tlv_fields!(reader, {
+                                               (0, payment_hash),
+                                               (2, rejected_by_dest),
+                                       }, {});
+                                       Ok(Some(Event::PaymentFailed {
+                                               payment_hash,
+                                               rejected_by_dest,
+                                               #[cfg(test)]
+                                               error_code,
+                                               #[cfg(test)]
+                                               error_data,
+                                       }))
+                               };
+                               f()
+                       },
+                       4u8 => {
+                               let f = || {
+                                       read_tlv_fields!(reader, {}, {});
+                                       Ok(Some(Event::PendingHTLCsForwardable {
+                                               time_forwardable: Duration::from_secs(0)
+                                       }))
+                               };
+                               f()
+                       },
                        5u8 => {
-                               let outputs_len: u64 = Readable::read(reader)?;
-                               let mut outputs = Vec::new();
-                               for _ in 0..outputs_len {
-                                       outputs.push(Readable::read(reader)?);
-                               }
-                               Ok(Some(Event::SpendableOutputs { outputs }))
+                               let f = || {
+                                       let mut outputs = VecReadWrapper(Vec::new());
+                                       read_tlv_fields!(reader, {
+                                               (0, outputs),
+                                       }, {});
+                                       Ok(Some(Event::SpendableOutputs { outputs: outputs.0 }))
+                               };
+                               f()
                        },
                        _ => Err(msgs::DecodeError::InvalidValue)
                }
@@ -396,6 +454,9 @@ pub trait MessageSendEventsProvider {
 /// may safely use the provider (e.g., see [`ChannelManager::process_pending_events`] and
 /// [`ChainMonitor::process_pending_events`]).
 ///
+/// (C-not implementable) As there is likely no reason for a user to implement this trait on their
+/// own type(s).
+///
 /// [`process_pending_events`]: Self::process_pending_events
 /// [`handle_event`]: EventHandler::handle_event
 /// [`ChannelManager::process_pending_events`]: crate::ln::channelmanager::ChannelManager#method.process_pending_events
index e8118a9a1a9de962af52a5f171b3d79506f4c168..cc0c3192a859fc79de02fe4bef36e8cfd2c2a2e0 100644 (file)
@@ -12,6 +12,9 @@
 #[macro_use]
 pub(crate) mod fuzz_wrappers;
 
+#[macro_use]
+pub(crate) mod ser_macros;
+
 pub mod events;
 pub mod errors;
 pub mod ser;
@@ -29,9 +32,6 @@ pub(crate) mod chacha20poly1305rfc;
 pub(crate) mod transaction_utils;
 pub(crate) mod scid_utils;
 
-#[macro_use]
-pub(crate) mod ser_macros;
-
 /// Logging macro utilities.
 #[macro_use]
 pub(crate) mod macro_logger;
index 73db1577bb6df75feac3f2a26ed8047d21b2c0f7..c329c469f4685c7a84d662b1bd43d6e6e8e12bce 100644 (file)
@@ -8,7 +8,7 @@
 // https://github.com/floodyberry/poly1305-donna
 
 use core::cmp::min;
-use util::byte_utils::{slice_to_le32, le32_to_array};
+use core::convert::TryInto;
 
 #[derive(Clone, Copy)]
 pub struct Poly1305 {
@@ -26,16 +26,16 @@ impl Poly1305 {
                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] = (slice_to_le32(&key[0..4])       ) & 0x3ffffff;
-               poly.r[1] = (slice_to_le32(&key[3..7])   >> 2) & 0x3ffff03;
-               poly.r[2] = (slice_to_le32(&key[6..10])  >> 4) & 0x3ffc0ff;
-               poly.r[3] = (slice_to_le32(&key[9..13])  >> 6) & 0x3f03fff;
-               poly.r[4] = (slice_to_le32(&key[12..16]) >> 8) & 0x00fffff;
+               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] = slice_to_le32(&key[16..20]);
-               poly.pad[1] = slice_to_le32(&key[20..24]);
-               poly.pad[2] = slice_to_le32(&key[24..28]);
-               poly.pad[3] = slice_to_le32(&key[28..32]);
+               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
        }
@@ -61,11 +61,11 @@ impl Poly1305 {
                let mut h4 = self.h[4];
 
                // h += m
-               h0 += (slice_to_le32(&m[0..4])       ) & 0x3ffffff;
-               h1 += (slice_to_le32(&m[3..7])   >> 2) & 0x3ffffff;
-               h2 += (slice_to_le32(&m[6..10])  >> 4) & 0x3ffffff;
-               h3 += (slice_to_le32(&m[9..13])  >> 6) & 0x3ffffff;
-               h4 += (slice_to_le32(&m[12..16]) >> 8) | hibit;
+               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);
@@ -196,10 +196,10 @@ impl Poly1305 {
                if !self.finalized{
                        self.finish();
                }
-               output[0..4].copy_from_slice(&le32_to_array(self.h[0]));
-               output[4..8].copy_from_slice(&le32_to_array(self.h[1]));
-               output[8..12].copy_from_slice(&le32_to_array(self.h[2]));
-               output[12..16].copy_from_slice(&le32_to_array(self.h[3]));
+               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());
        }
 }
 
index a52ba09c9c94100df8018ef3209f7469d46a5027..4e69a37d20e9fcc5e0d093804136ef9f90be1747 100644 (file)
@@ -19,7 +19,7 @@ use core::cmp;
 
 use bitcoin::secp256k1::Signature;
 use bitcoin::secp256k1::key::{PublicKey, SecretKey};
-use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, COMPACT_SIGNATURE_SIZE};
+use bitcoin::secp256k1::constants::{PUBLIC_KEY_SIZE, SECRET_KEY_SIZE, COMPACT_SIGNATURE_SIZE};
 use bitcoin::blockdata::script::Script;
 use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
 use bitcoin::consensus;
@@ -29,9 +29,8 @@ use bitcoin::hash_types::{Txid, BlockHash};
 use core::marker::Sized;
 use ln::msgs::DecodeError;
 use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
-use util::byte_utils;
 
-use util::byte_utils::{be64_to_array, be48_to_array, be32_to_array, be16_to_array, slice_to_be16, slice_to_be32, slice_to_be48, slice_to_be64};
+use util::byte_utils::{be48_to_array, slice_to_be48};
 
 /// serialization buffer size
 pub const MAX_BUF_SIZE: usize = 64 * 1024;
@@ -61,13 +60,16 @@ impl<W: Write> Writer for W {
 
 pub(crate) struct WriterWriteAdaptor<'a, W: Writer + 'a>(pub &'a mut W);
 impl<'a, W: Writer + 'a> Write for WriterWriteAdaptor<'a, W> {
+       #[inline]
        fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
                self.0.write_all(buf)
        }
+       #[inline]
        fn write(&mut self, buf: &[u8]) -> Result<usize, ::std::io::Error> {
                self.0.write_all(buf)?;
                Ok(buf.len())
        }
+       #[inline]
        fn flush(&mut self) -> Result<(), ::std::io::Error> {
                Ok(())
        }
@@ -75,10 +77,12 @@ impl<'a, W: Writer + 'a> Write for WriterWriteAdaptor<'a, W> {
 
 pub(crate) struct VecWriter(pub Vec<u8>);
 impl Writer for VecWriter {
+       #[inline]
        fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
                self.0.extend_from_slice(buf);
                Ok(())
        }
+       #[inline]
        fn size_hint(&mut self, size: usize) {
                self.0.reserve_exact(size);
        }
@@ -109,10 +113,12 @@ impl<R: Read> FixedLengthReader<R> {
                Self { read, bytes_read: 0, total_bytes }
        }
 
+       #[inline]
        pub fn bytes_remain(&mut self) -> bool {
                self.bytes_read != self.total_bytes
        }
 
+       #[inline]
        pub fn eat_remaining(&mut self) -> Result<(), DecodeError> {
                ::std::io::copy(self, &mut ::std::io::sink()).unwrap();
                if self.bytes_read != self.total_bytes {
@@ -123,6 +129,7 @@ impl<R: Read> FixedLengthReader<R> {
        }
 }
 impl<R: Read> Read for FixedLengthReader<R> {
+       #[inline]
        fn read(&mut self, dest: &mut [u8]) -> Result<usize, ::std::io::Error> {
                if self.total_bytes == self.bytes_read {
                        Ok(0)
@@ -151,6 +158,7 @@ impl<R: Read> ReadTrackingReader<R> {
        }
 }
 impl<R: Read> Read for ReadTrackingReader<R> {
+       #[inline]
        fn read(&mut self, dest: &mut [u8]) -> Result<usize, ::std::io::Error> {
                match self.read.read(dest) {
                        Ok(0) => Ok(0),
@@ -183,9 +191,19 @@ pub trait Writeable {
                0u16.write(&mut msg).unwrap();
                self.write(&mut msg).unwrap();
                let len = msg.0.len();
-               msg.0[..2].copy_from_slice(&byte_utils::be16_to_array(len as u16 - 2));
+               msg.0[..2].copy_from_slice(&(len as u16 - 2).to_be_bytes());
                msg.0
        }
+
+       /// Gets the length of this object after it has been serialized. This can be overridden to
+       /// optimize cases where we prepend an object with its length.
+       // Note that LLVM optimizes this away in most cases! Check that it isn't before you override!
+       #[inline]
+       fn serialized_length(&self) -> usize {
+               let mut len_calc = LengthCalculatingWriter(0);
+               self.write(&mut len_calc).expect("No in-memory data may fail to serialize");
+               len_calc.0
+       }
 }
 
 impl<'a, T: Writeable> Writeable for &'a T {
@@ -225,31 +243,37 @@ pub trait MaybeReadable
 
 pub(crate) struct OptionDeserWrapper<T: Readable>(pub Option<T>);
 impl<T: Readable> Readable for OptionDeserWrapper<T> {
+       #[inline]
        fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
                Ok(Self(Some(Readable::read(reader)?)))
        }
 }
 
-const MAX_ALLOC_SIZE: u64 = 64*1024;
-
+/// Wrapper to write each element of a Vec with no length prefix
 pub(crate) struct VecWriteWrapper<'a, T: Writeable>(pub &'a Vec<T>);
 impl<'a, T: Writeable> Writeable for VecWriteWrapper<'a, T> {
+       #[inline]
        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-               (self.0.len() as u64).write(writer)?;
                for ref v in self.0.iter() {
                        v.write(writer)?;
                }
                Ok(())
        }
 }
+
+/// Wrapper to read elements from a given stream until it reaches the end of the stream.
 pub(crate) struct VecReadWrapper<T: Readable>(pub Vec<T>);
 impl<T: Readable> Readable for VecReadWrapper<T> {
-       fn read<R: Read>(reader: &mut R) -> Result<Self, DecodeError> {
-               let count: u64 = Readable::read(reader)?;
-               let mut values = Vec::with_capacity(cmp::min(count, MAX_ALLOC_SIZE / (core::mem::size_of::<T>() as u64)) as usize);
-               for _ in 0..count {
-                       match Readable::read(reader) {
+       #[inline]
+       fn read<R: Read>(mut reader: &mut R) -> Result<Self, DecodeError> {
+               let mut values = Vec::new();
+               loop {
+                       let mut track_read = ReadTrackingReader::new(&mut reader);
+                       match Readable::read(&mut track_read) {
                                Ok(v) => { values.push(v); },
+                               // If we failed to read any bytes at all, we reached the end of our TLV
+                               // stream and have simply exhausted all entries.
+                               Err(ref e) if e == &DecodeError::ShortRead && !track_read.have_read => break,
                                Err(e) => return Err(e),
                        }
                }
@@ -344,18 +368,18 @@ impl Readable for BigSize {
 pub(crate) struct HighZeroBytesDroppedVarInt<T>(pub T);
 
 macro_rules! impl_writeable_primitive {
-       ($val_type:ty, $meth_write:ident, $len: expr, $meth_read:ident) => {
+       ($val_type:ty, $len: expr) => {
                impl Writeable for $val_type {
                        #[inline]
                        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
-                               writer.write_all(&$meth_write(*self))
+                               writer.write_all(&self.to_be_bytes())
                        }
                }
                impl Writeable for HighZeroBytesDroppedVarInt<$val_type> {
                        #[inline]
                        fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
                                // Skip any full leading 0 bytes when writing (in BE):
-                               writer.write_all(&$meth_write(self.0)[(self.0.leading_zeros()/8) as usize..$len])
+                               writer.write_all(&self.0.to_be_bytes()[(self.0.leading_zeros()/8) as usize..$len])
                        }
                }
                impl Readable for $val_type {
@@ -363,7 +387,7 @@ macro_rules! impl_writeable_primitive {
                        fn read<R: Read>(reader: &mut R) -> Result<$val_type, DecodeError> {
                                let mut buf = [0; $len];
                                reader.read_exact(&mut buf)?;
-                               Ok($meth_read(&buf))
+                               Ok(<$val_type>::from_be_bytes(buf))
                        }
                }
                impl Readable for HighZeroBytesDroppedVarInt<$val_type> {
@@ -382,7 +406,9 @@ macro_rules! impl_writeable_primitive {
                                }
                                if total_read_len == 0 || buf[$len] != 0 {
                                        let first_byte = $len - ($len - total_read_len);
-                                       Ok(HighZeroBytesDroppedVarInt($meth_read(&buf[first_byte..first_byte + $len])))
+                                       let mut bytes = [0; $len];
+                                       bytes.copy_from_slice(&buf[first_byte..first_byte + $len]);
+                                       Ok(HighZeroBytesDroppedVarInt(<$val_type>::from_be_bytes(bytes)))
                                } else {
                                        // If the encoding had extra zero bytes, return a failure even though we know
                                        // what they meant (as the TLV test vectors require this)
@@ -393,9 +419,9 @@ macro_rules! impl_writeable_primitive {
        }
 }
 
-impl_writeable_primitive!(u64, be64_to_array, 8, slice_to_be64);
-impl_writeable_primitive!(u32, be32_to_array, 4, slice_to_be32);
-impl_writeable_primitive!(u16, be16_to_array, 2, slice_to_be16);
+impl_writeable_primitive!(u64, 8);
+impl_writeable_primitive!(u32, 4);
+impl_writeable_primitive!(u16, 2);
 
 impl Writeable for u8 {
        #[inline]
@@ -560,6 +586,10 @@ impl Writeable for PublicKey {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
                self.serialize().write(w)
        }
+       #[inline]
+       fn serialized_length(&self) -> usize {
+               PUBLIC_KEY_SIZE
+       }
 }
 
 impl Readable for PublicKey {
@@ -574,15 +604,19 @@ impl Readable for PublicKey {
 
 impl Writeable for SecretKey {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               let mut ser = [0; 32];
+               let mut ser = [0; SECRET_KEY_SIZE];
                ser.copy_from_slice(&self[..]);
                ser.write(w)
        }
+       #[inline]
+       fn serialized_length(&self) -> usize {
+               SECRET_KEY_SIZE
+       }
 }
 
 impl Readable for SecretKey {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
-               let buf: [u8; 32] = Readable::read(r)?;
+               let buf: [u8; SECRET_KEY_SIZE] = Readable::read(r)?;
                match SecretKey::from_slice(&buf) {
                        Ok(key) => Ok(key),
                        Err(_) => return Err(DecodeError::InvalidValue),
@@ -609,6 +643,10 @@ impl Writeable for Signature {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
                self.serialize_compact().write(w)
        }
+       #[inline]
+       fn serialized_length(&self) -> usize {
+               COMPACT_SIGNATURE_SIZE
+       }
 }
 
 impl Readable for Signature {
@@ -660,14 +698,24 @@ impl Readable for PaymentSecret {
        }
 }
 
+impl<T: Writeable> Writeable for Box<T> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               T::write(&**self, w)
+       }
+}
+
+impl<T: Readable> Readable for Box<T> {
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               Ok(Box::new(Readable::read(r)?))
+       }
+}
+
 impl<T: Writeable> Writeable for Option<T> {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
                match *self {
                        None => 0u8.write(w)?,
                        Some(ref data) => {
-                               let mut len_calc = LengthCalculatingWriter(0);
-                               data.write(&mut len_calc).expect("No in-memory data may fail to serialize");
-                               BigSize(len_calc.0 as u64 + 1).write(w)?;
+                               BigSize(data.serialized_length() as u64 + 1).write(w)?;
                                data.write(w)?;
                        }
                }
@@ -788,3 +836,19 @@ impl<A: Writeable, B: Writeable> Writeable for (A, B) {
                self.1.write(w)
        }
 }
+
+impl<A: Readable, B: Readable, C: Readable> Readable for (A, B, C) {
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let a: A = Readable::read(r)?;
+               let b: B = Readable::read(r)?;
+               let c: C = Readable::read(r)?;
+               Ok((a, b, c))
+       }
+}
+impl<A: Writeable, B: Writeable, C: Writeable> Writeable for (A, B, C) {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               self.0.write(w)?;
+               self.1.write(w)?;
+               self.2.write(w)
+       }
+}
index b8119ddd5bd26a9ddb1580f2ef09c660110a7a2f..cf780ef06b2ab3093a93dc7167398302f170b5cd 100644 (file)
@@ -10,7 +10,7 @@
 macro_rules! encode_tlv {
        ($stream: expr, {$(($type: expr, $field: expr)),*}, {$(($optional_type: expr, $optional_field: expr)),*}) => { {
                #[allow(unused_imports)]
-               use util::ser::{BigSize, LengthCalculatingWriter};
+               use util::ser::BigSize;
                // Fields must be serialized in order, so we have to potentially switch between optional
                // fields and normal fields while serializing. Thus, we end up having to loop over the type
                // counts.
@@ -30,9 +30,7 @@ macro_rules! encode_tlv {
                        $(
                                if i == $type {
                                        BigSize($type).write($stream)?;
-                                       let mut len_calc = LengthCalculatingWriter(0);
-                                       $field.write(&mut len_calc)?;
-                                       BigSize(len_calc.0 as u64).write($stream)?;
+                                       BigSize($field.serialized_length() as u64).write($stream)?;
                                        $field.write($stream)?;
                                }
                        )*
@@ -40,9 +38,7 @@ macro_rules! encode_tlv {
                                if i == $optional_type {
                                        if let Some(ref field) = $optional_field {
                                                BigSize($optional_type).write($stream)?;
-                                               let mut len_calc = LengthCalculatingWriter(0);
-                                               field.write(&mut len_calc)?;
-                                               BigSize(len_calc.0 as u64).write($stream)?;
+                                               BigSize(field.serialized_length() as u64).write($stream)?;
                                                field.write($stream)?;
                                        }
                                }
@@ -51,31 +47,36 @@ macro_rules! encode_tlv {
        } }
 }
 
-macro_rules! encode_varint_length_prefixed_tlv {
-       ($stream: expr, {$(($type: expr, $field: expr)),*}, {$(($optional_type: expr, $optional_field: expr)),*}) => { {
-               use util::ser::{BigSize, LengthCalculatingWriter};
+macro_rules! get_varint_length_prefixed_tlv_length {
+       ({$(($type: expr, $field: expr)),*}, {$(($optional_type: expr, $optional_field: expr)),* $(,)*}) => { {
+               use util::ser::LengthCalculatingWriter;
                #[allow(unused_mut)]
                let mut len = LengthCalculatingWriter(0);
                {
                        $(
-                               BigSize($type).write(&mut len)?;
-                               let mut field_len = LengthCalculatingWriter(0);
-                               $field.write(&mut field_len)?;
-                               BigSize(field_len.0 as u64).write(&mut len)?;
-                               len.0 += field_len.0;
+                               BigSize($type).write(&mut len).expect("No in-memory data may fail to serialize");
+                               let field_len = $field.serialized_length();
+                               BigSize(field_len as u64).write(&mut len).expect("No in-memory data may fail to serialize");
+                               len.0 += field_len;
                        )*
                        $(
                                if let Some(ref field) = $optional_field {
-                                       BigSize($optional_type).write(&mut len)?;
-                                       let mut field_len = LengthCalculatingWriter(0);
-                                       field.write(&mut field_len)?;
-                                       BigSize(field_len.0 as u64).write(&mut len)?;
-                                       len.0 += field_len.0;
+                                       BigSize($optional_type).write(&mut len).expect("No in-memory data may fail to serialize");
+                                       let field_len = field.serialized_length();
+                                       BigSize(field_len as u64).write(&mut len).expect("No in-memory data may fail to serialize");
+                                       len.0 += field_len;
                                }
                        )*
                }
+               len.0
+       } }
+}
 
-               BigSize(len.0 as u64).write($stream)?;
+macro_rules! encode_varint_length_prefixed_tlv {
+       ($stream: expr, {$(($type: expr, $field: expr)),*}, {$(($optional_type: expr, $optional_field: expr)),*}) => { {
+               use util::ser::BigSize;
+               let len = get_varint_length_prefixed_tlv_length!({ $(($type, $field)),* }, { $(($optional_type, $optional_field)),* });
+               BigSize(len as u64).write($stream)?;
                encode_tlv!($stream, { $(($type, $field)),* }, { $(($optional_type, $optional_field)),* });
        } }
 }
@@ -173,13 +174,29 @@ macro_rules! impl_writeable {
                                        if $len != 0 {
                                                use util::ser::LengthCalculatingWriter;
                                                let mut len_calc = LengthCalculatingWriter(0);
-                                               $( self.$field.write(&mut len_calc)?; )*
+                                               $( self.$field.write(&mut len_calc).expect("No in-memory data may fail to serialize"); )*
                                                assert_eq!(len_calc.0, $len);
+                                               assert_eq!(self.serialized_length(), $len);
                                        }
                                }
                                $( self.$field.write(w)?; )*
                                Ok(())
                        }
+
+                       #[inline]
+                       fn serialized_length(&self) -> usize {
+                               if $len == 0 || cfg!(any(test, feature = "fuzztarget")) {
+                                       let mut len_calc = 0;
+                                       $( len_calc += self.$field.serialized_length(); )*
+                                       if $len != 0 {
+                                               // In tests, assert that the hard-coded length matches the actual one
+                                               assert_eq!(len_calc, $len);
+                                       } else {
+                                               return len_calc;
+                                       }
+                               }
+                               $len
+                       }
                }
 
                impl ::util::ser::Readable for $st {
@@ -192,7 +209,7 @@ macro_rules! impl_writeable {
        }
 }
 macro_rules! impl_writeable_len_match {
-       ($struct: ident, $cmp: tt, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => {
+       ($struct: ident, $cmp: tt, ($calc_len: expr), {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => {
                impl Writeable for $struct {
                        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
                                let len = match *self {
@@ -204,12 +221,30 @@ macro_rules! impl_writeable_len_match {
                                        // In tests, assert that the hard-coded length matches the actual one
                                        use util::ser::LengthCalculatingWriter;
                                        let mut len_calc = LengthCalculatingWriter(0);
-                                       $( self.$field.write(&mut len_calc)?; )*
+                                       $( self.$field.write(&mut len_calc).expect("No in-memory data may fail to serialize"); )*
                                        assert!(len_calc.0 $cmp len);
+                                       assert_eq!(len_calc.0, self.serialized_length());
                                }
                                $( self.$field.write(w)?; )*
                                Ok(())
                        }
+
+                       #[inline]
+                       fn serialized_length(&self) -> usize {
+                               if $calc_len || cfg!(any(test, feature = "fuzztarget")) {
+                                       let mut len_calc = 0;
+                                       $( len_calc += self.$field.serialized_length(); )*
+                                       if !$calc_len {
+                                               assert_eq!(len_calc, match *self {
+                                                       $($match => $length,)*
+                                               });
+                                       }
+                                       return len_calc
+                               }
+                               match *self {
+                                       $($match => $length,)*
+                               }
+                       }
                }
 
                impl ::util::ser::Readable for $struct {
@@ -220,8 +255,11 @@ macro_rules! impl_writeable_len_match {
                        }
                }
        };
+       ($struct: ident, $cmp: tt, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => {
+               impl_writeable_len_match!($struct, $cmp, (true), { $({ $match, $length }),* }, { $($field),* });
+       };
        ($struct: ident, {$({$match: pat, $length: expr}),*}, {$($field:ident),*}) => {
-               impl_writeable_len_match!($struct, ==, { $({ $match, $length }),* }, { $($field),* });
+               impl_writeable_len_match!($struct, ==, (false), { $({ $match, $length }),* }, { $($field),* });
        }
 }
 
@@ -279,7 +317,7 @@ macro_rules! read_tlv_fields {
                let tlv_len = ::util::ser::BigSize::read($stream)?;
                let mut rd = ::util::ser::FixedLengthReader::new($stream, tlv_len.0);
                decode_tlv!(&mut rd, {$(($reqtype, $reqfield)),*}, {$(($type, $field)),*});
-               rd.eat_remaining().map_err(|_| DecodeError::ShortRead)?;
+               rd.eat_remaining().map_err(|_| ::ln::msgs::DecodeError::ShortRead)?;
        } }
 }
 
@@ -287,26 +325,26 @@ macro_rules! read_tlv_fields {
 // `Self { ,,vecfield: vecfield }` which is obviously incorrect. Instead, we have to match here to
 // detect at least one empty field set and skip the potentially-extra comma.
 macro_rules! _init_tlv_based_struct {
-       ({}, {$($field: ident),*}, {$($vecfield: ident),*}) => {
-               Ok(Self {
+       ($($type: ident)::*, {}, {$($field: ident),*}, {$($vecfield: ident),*}) => {
+               Ok($($type)::* {
                        $($field),*,
                        $($vecfield: $vecfield.unwrap().0),*
                })
        };
-       ({$($reqfield: ident),*}, {}, {$($vecfield: ident),*}) => {
-               Ok(Self {
+       ($($type: ident)::*, {$($reqfield: ident),*}, {}, {$($vecfield: ident),*}) => {
+               Ok($($type)::* {
                        $($reqfield: $reqfield.0.unwrap()),*,
                        $($vecfield: $vecfield.unwrap().0),*
                })
        };
-       ({$($reqfield: ident),*}, {$($field: ident),*}, {}) => {
-               Ok(Self {
+       ($($type: ident)::*, {$($reqfield: ident),*}, {$($field: ident),*}, {}) => {
+               Ok($($type)::* {
                        $($reqfield: $reqfield.0.unwrap()),*,
                        $($field),*
                })
        };
-       ({$($reqfield: ident),*}, {$($field: ident),*}, {$($vecfield: ident),*}) => {
-               Ok(Self {
+       ($($type: ident)::*, {$($reqfield: ident),*}, {$($field: ident),*}, {$($vecfield: ident),*}) => {
+               Ok($($type)::* {
                        $($reqfield: $reqfield.0.unwrap()),*,
                        $($field),*,
                        $($vecfield: $vecfield.unwrap().0),*
@@ -325,6 +363,14 @@ macro_rules! _write_tlv_fields {
                write_tlv_fields!($stream, {$(($type, $field)),*} , {$(($optional_type, $optional_field)),*, $(($optional_type_2, $optional_field_2)),*});
        }
 }
+macro_rules! _get_tlv_len {
+       ({$(($type: expr, $field: expr)),* $(,)*}, {}, {$(($optional_type: expr, $optional_field: expr)),* $(,)*}) => {
+               get_varint_length_prefixed_tlv_length!({$(($type, $field)),*} , {$(($optional_type, $optional_field)),*})
+       };
+       ({$(($type: expr, $field: expr)),* $(,)*}, {$(($optional_type: expr, $optional_field: expr)),* $(,)*}, {$(($optional_type_2: expr, $optional_field_2: expr)),* $(,)*}) => {
+               get_varint_length_prefixed_tlv_length!({$(($type, $field)),*} , {$(($optional_type, $optional_field)),*, $(($optional_type_2, $optional_field_2)),*})
+       }
+}
 macro_rules! _read_tlv_fields {
        ($stream: expr, {$(($reqtype: expr, $reqfield: ident)),* $(,)*}, {}, {$(($type: expr, $field: ident)),* $(,)*}) => {
                read_tlv_fields!($stream, {$(($reqtype, $reqfield)),*}, {$(($type, $field)),*});
@@ -352,6 +398,21 @@ macro_rules! impl_writeable_tlv_based {
                                });
                                Ok(())
                        }
+
+                       #[inline]
+                       fn serialized_length(&self) -> usize {
+                               let len = _get_tlv_len!({
+                                       $(($reqtype, self.$reqfield)),*
+                               }, {
+                                       $(($type, self.$field)),*
+                               }, {
+                                       $(($vectype, Some(::util::ser::VecWriteWrapper(&self.$vecfield)))),*
+                               });
+                               use util::ser::{BigSize, LengthCalculatingWriter};
+                               let mut len_calc = LengthCalculatingWriter(0);
+                               BigSize(len as u64).write(&mut len_calc).expect("No in-memory data may fail to serialize");
+                               len + len_calc.0
+                       }
                }
 
                impl ::util::ser::Readable for $st {
@@ -372,7 +433,88 @@ macro_rules! impl_writeable_tlv_based {
                                }, {
                                        $(($vectype, $vecfield)),*
                                });
-                               _init_tlv_based_struct!({$($reqfield),*}, {$($field),*}, {$($vecfield),*})
+                               _init_tlv_based_struct!($st, {$($reqfield),*}, {$($field),*}, {$($vecfield),*})
+                       }
+               }
+       }
+}
+
+/// Implement Readable and Writeable for an enum, with struct variants stored as TLVs and tuple
+/// variants stored directly.
+/// The format is, for example
+/// impl_writeable_tlv_based_enum!(EnumName,
+///   (0, StructVariantA) => {(0, variant_field)}, {(1, variant_optional_field)}, {},
+///   (1, StructVariantB) => {(0, variant_field_a), (1, variant_field_b)}, {}, {(2, variant_vec_field)};
+///   (2, TupleVariantA), (3, TupleVariantB),
+/// );
+/// The type is written as a single byte, followed by any variant data.
+/// Attempts to read an unknown type byte result in DecodeError::UnknownRequiredFeature.
+macro_rules! impl_writeable_tlv_based_enum {
+       ($st: ident, $(($variant_id: expr, $variant_name: ident) =>
+               {$(($reqtype: expr, $reqfield: ident)),* $(,)*},
+               {$(($type: expr, $field: ident)),* $(,)*},
+               {$(($vectype: expr, $vecfield: ident)),* $(,)*}
+       ),* $(,)*;
+       $(($tuple_variant_id: expr, $tuple_variant_name: ident)),*  $(,)*) => {
+               impl ::util::ser::Writeable for $st {
+                       fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+                               match self {
+                                       $($st::$variant_name { $(ref $reqfield),* $(ref $field),*, $(ref $vecfield),* } => {
+                                               let id: u8 = $variant_id;
+                                               id.write(writer)?;
+                                               _write_tlv_fields!(writer, {
+                                                       $(($reqtype, $reqfield)),*
+                                               }, {
+                                                       $(($type, $field)),*
+                                               }, {
+                                                       $(($vectype, Some(::util::ser::VecWriteWrapper(&$vecfield)))),*
+                                               });
+                                       }),*
+                                       $($st::$tuple_variant_name (ref field) => {
+                                               let id: u8 = $tuple_variant_id;
+                                               id.write(writer)?;
+                                               field.write(writer)?;
+                                       }),*
+                               }
+                               Ok(())
+                       }
+               }
+
+               impl ::util::ser::Readable for $st {
+                       fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, ::ln::msgs::DecodeError> {
+                               let id: u8 = ::util::ser::Readable::read(reader)?;
+                               match id {
+                                       $($variant_id => {
+                                               // Because read_tlv_fields creates a labeled loop, we cannot call it twice
+                                               // in the same function body. Instead, we define a closure and call it.
+                                               let f = || {
+                                                       $(
+                                                               let mut $reqfield = ::util::ser::OptionDeserWrapper(None);
+                                                       )*
+                                                       $(
+                                                               let mut $field = None;
+                                                       )*
+                                                       $(
+                                                               let mut $vecfield = Some(::util::ser::VecReadWrapper(Vec::new()));
+                                                       )*
+                                                       _read_tlv_fields!(reader, {
+                                                               $(($reqtype, $reqfield)),*
+                                                       }, {
+                                                               $(($type, $field)),*
+                                                       }, {
+                                                               $(($vectype, $vecfield)),*
+                                                       });
+                                                       _init_tlv_based_struct!($st::$variant_name, {$($reqfield),*}, {$($field),*}, {$($vecfield),*})
+                                               };
+                                               f()
+                                       }),*
+                                       $($tuple_variant_id => {
+                                               Ok($st::$tuple_variant_name(Readable::read(reader)?))
+                                       }),*
+                                       _ => {
+                                               Err(DecodeError::UnknownRequiredFeature)?
+                                       },
+                               }
                        }
                }
        }
@@ -381,7 +523,7 @@ macro_rules! impl_writeable_tlv_based {
 #[cfg(test)]
 mod tests {
        use prelude::*;
-       use std::io::{Cursor, Read};
+       use std::io::Cursor;
        use ln::msgs::DecodeError;
        use util::ser::{Readable, Writeable, HighZeroBytesDroppedVarInt, VecWriter};
        use bitcoin::secp256k1::PublicKey;
@@ -451,13 +593,6 @@ mod tests {
                        (0xdeadbeef1badbeef, 0x1bad1dea, Some(0x01020304)));
        }
 
-       impl Readable for (PublicKey, u64, u64) {
-               #[inline]
-               fn read<R: Read>(reader: &mut R) -> Result<(PublicKey, u64, u64), DecodeError> {
-                       Ok((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?))
-               }
-       }
-
        // BOLT TLV test cases
        fn tlv_reader_n1(s: &[u8]) -> Result<(Option<HighZeroBytesDroppedVarInt<u64>>, Option<u64>, Option<(PublicKey, u64, u64)>, Option<u16>), DecodeError> {
                let mut s = Cursor::new(s);