Merge pull request #490 from jkczyz/2020-02-initial-routing-sync
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Mon, 10 Feb 2020 22:18:48 +0000 (22:18 +0000)
committerGitHub <noreply@github.com>
Mon, 10 Feb 2020 22:18:48 +0000 (22:18 +0000)
Refactor logic for setting initial_routing_sync feature bit

README.md
lightning/src/ln/channel.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/peer_handler.rs

index fd264c8c2d928459f3c98abd948372ff6f83880d..b8807aad57873e45920b41d5b401226789c95791 100644 (file)
--- a/README.md
+++ b/README.md
@@ -5,8 +5,16 @@ Rust-Lightning, not Rusty's Lightning!
 
 Documentation can be found at [docs.rs](https://docs.rs/lightning/)
 
-Currently somewhere near 50% towards usable, published to see if there is any
-real interest from folks in using a lightning rust library.
+The project implements all of the BOLT specifications in the 1.0 spec except
+for [channel queries](https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#query-messages). The
+implementation has pretty good test coverage that is expected to continue to
+improve. There are a number of internal refactorings being done now that will
+make the code base more welcoming to new contributors. It is also anticipated
+that as developers begin using the API, the lessons from that will result in
+changes to the API, so any developer using this API at this stage should be prepared
+to embrace that. The current state is sufficient for a developer or project to
+experiment with it. Recent increased contribution rate to the project is expected
+to lead to a high quality, stable, production-worthy implementation in 2020.
 
 The goal is to provide a full-featured but also incredibly flexible lightning
 implementation, allowing the user to decide how they wish to use it. With that
index c86136d6070a8f2c7909f8f3b39c743689ecd1f9..231ee832befe77a32c1166c8ab2ba87151623934 100644 (file)
@@ -240,7 +240,10 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
        secp_ctx: Secp256k1<secp256k1::All>,
        channel_value_satoshis: u64,
 
+       #[cfg(not(test))]
        local_keys: ChanSigner,
+       #[cfg(test)]
+       pub(super) local_keys: ChanSigner,
        shutdown_pubkey: PublicKey,
 
        // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction
@@ -1995,6 +1998,17 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret)
                        .map_err(|e| ChannelError::Close(e.0))?;
 
+               if self.channel_state & ChannelState::AwaitingRemoteRevoke as u32 == 0 {
+                       // Our counterparty seems to have burned their coins to us (by revoking a state when we
+                       // haven't given them a new commitment transaction to broadcast). We should probably
+                       // take advantage of this by updating our channel monitor, sending them an error, and
+                       // waiting for them to broadcast their latest (now-revoked claim). But, that would be a
+                       // lot of work, and there's some chance this is all a misunderstanding anyway.
+                       // We have to do *something*, though, since our signer may get mad at us for otherwise
+                       // jumping a remote commitment number, so best to just force-close and move on.
+                       return Err(ChannelError::Close("Received an unexpected revoke_and_ack"));
+               }
+
                // Update state now that we've passed all the can-fail calls...
                // (note that we may still fail to generate the new commitment_signed message, but that's
                // OK, we step the channel here and *then* if the new generation fails we can fail the
index ddd5f56b19959e1f5b9025f62c9354ea6aeacd00..4006c87a684a62d5d1a82a6e202a5a900bdd2f86 100644 (file)
@@ -9,7 +9,7 @@ use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
 use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT};
 use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
 use ln::channel::{Channel, ChannelError};
-use ln::onion_utils;
+use ln::{chan_utils, onion_utils};
 use ln::router::{Route, RouteHop};
 use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use ln::msgs;
@@ -6972,6 +6972,32 @@ fn test_set_outpoints_partial_claiming() {
        }
 }
 
+#[test]
+fn test_counterparty_raa_skip_no_crash() {
+       // Previously, if our counterparty sent two RAAs in a row without us having provided a
+       // commitment transaction, we would have happily carried on and provided them the next
+       // commitment transaction based on one RAA forward. This would probably eventually have led to
+       // channel closure, but it would not have resulted in funds loss. Still, our
+       // EnforcingChannelKeys would have paniced as it doesn't like jumps into the future. Here, we
+       // check simply that the channel is closed in response to such an RAA, but don't check whether
+       // we decide to punish our counterparty for revoking their funds (as we don't currently
+       // implement that).
+       let node_cfgs = create_node_cfgs(2);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+       let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2;
+
+       let commitment_seed = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&channel_id).unwrap().local_keys.commitment_seed().clone();
+       const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
+       let next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(),
+               &SecretKey::from_slice(&chan_utils::build_commitment_secret(&commitment_seed, INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
+       let per_commitment_secret = chan_utils::build_commitment_secret(&commitment_seed, INITIAL_COMMITMENT_NUMBER);
+
+       nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(),
+               &msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point });
+       assert_eq!(check_closed_broadcast!(nodes[1], true).unwrap().data, "Received an unexpected revoke_and_ack");
+}
+
 #[test]
 fn test_bump_txn_sanitize_tracking_maps() {
        // Sanitizing pendning_claim_request and claimable_outpoints used to be buggy,
index 2e7ce4e2973ce57d54c2285a1fd6e2792542711b..6576da806afb48c938791f47c0fee55880b5452a 100644 (file)
@@ -512,37 +512,6 @@ impl<Descriptor: SocketDescriptor, CM: Deref> PeerManager<Descriptor, CM> where
                                                                }
                                                        }
 
-                                                       macro_rules! try_potential_decodeerror {
-                                                               ($thing: expr) => {
-                                                                       match $thing {
-                                                                               Ok(x) => x,
-                                                                               Err(e) => {
-                                                                                       match e {
-                                                                                               msgs::DecodeError::UnknownVersion => return Err(PeerHandleError{ no_connection_possible: false }),
-                                                                                               msgs::DecodeError::UnknownRequiredFeature => {
-                                                                                                       log_debug!(self, "Got a channel/node announcement with an known required feature flag, you may want to update!");
-                                                                                                       continue;
-                                                                                               },
-                                                                                               msgs::DecodeError::InvalidValue => {
-                                                                                                       log_debug!(self, "Got an invalid value while deserializing message");
-                                                                                                       return Err(PeerHandleError{ no_connection_possible: false });
-                                                                                               },
-                                                                                               msgs::DecodeError::ShortRead => {
-                                                                                                       log_debug!(self, "Deserialization failed due to shortness of message");
-                                                                                                       return Err(PeerHandleError{ no_connection_possible: false });
-                                                                                               },
-                                                                                               msgs::DecodeError::ExtraAddressesPerType => {
-                                                                                                       log_debug!(self, "Error decoding message, ignoring due to lnd spec incompatibility. See https://github.com/lightningnetwork/lnd/issues/1407");
-                                                                                                       continue;
-                                                                                               },
-                                                                                               msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError{ no_connection_possible: false }),
-                                                                                               msgs::DecodeError::Io(_) => return Err(PeerHandleError{ no_connection_possible: false }),
-                                                                                       }
-                                                                               }
-                                                                       };
-                                                               }
-                                                       }
-
                                                        macro_rules! insert_node_id {
                                                                () => {
                                                                        match peers.node_id_to_descriptor.entry(peer.their_node_id.unwrap()) {
@@ -607,7 +576,34 @@ impl<Descriptor: SocketDescriptor, CM: Deref> PeerManager<Descriptor, CM> where
                                                                                peer.pending_read_is_header = true;
 
                                                                                let mut reader = ::std::io::Cursor::new(&msg_data[..]);
-                                                                               let message = try_potential_decodeerror!(wire::read(&mut reader));
+                                                                               let message_result = wire::read(&mut reader);
+                                                                               let message = match message_result {
+                                                                                       Ok(x) => x,
+                                                                                       Err(e) => {
+                                                                                               match e {
+                                                                                                       msgs::DecodeError::UnknownVersion => return Err(PeerHandleError { no_connection_possible: false }),
+                                                                                                       msgs::DecodeError::UnknownRequiredFeature => {
+                                                                                                               log_debug!(self, "Got a channel/node announcement with an known required feature flag, you may want to update!");
+                                                                                                               continue;
+                                                                                                       }
+                                                                                                       msgs::DecodeError::InvalidValue => {
+                                                                                                               log_debug!(self, "Got an invalid value while deserializing message");
+                                                                                                               return Err(PeerHandleError { no_connection_possible: false });
+                                                                                                       }
+                                                                                                       msgs::DecodeError::ShortRead => {
+                                                                                                               log_debug!(self, "Deserialization failed due to shortness of message");
+                                                                                                               return Err(PeerHandleError { no_connection_possible: false });
+                                                                                                       }
+                                                                                                       msgs::DecodeError::ExtraAddressesPerType => {
+                                                                                                               log_debug!(self, "Error decoding message, ignoring due to lnd spec incompatibility. See https://github.com/lightningnetwork/lnd/issues/1407");
+                                                                                                               continue;
+                                                                                                       }
+                                                                                                       msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError { no_connection_possible: false }),
+                                                                                                       msgs::DecodeError::Io(_) => return Err(PeerHandleError { no_connection_possible: false }),
+                                                                                               }
+                                                                                       }
+                                                                               };
+
                                                                                log_trace!(self, "Received message of type {} from {}", message.type_id(), log_pubkey!(peer.their_node_id.unwrap()));
 
                                                                                // Need an Init as first message