X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=26a3d2061be644cd90292ca680577830fe559b2c;hb=1228663b3e04765c6f8a243d76a1c09ef1d926bc;hp=6c6dacc84c3821c2285b0156a62498dc068b6a49;hpb=ab56b81acd9da3a697dfc37fc4cb43cd8fbb1a2c;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index 6c6dacc8..26a3d206 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -17,15 +17,16 @@ use crypto::hkdf::{hkdf_extract,hkdf_expand}; use ln::msgs; use ln::msgs::{HandleError, MsgEncodable}; use ln::channelmonitor::ChannelMonitor; -use ln::channelmanager::PendingForwardHTLCInfo; -use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment}; +use ln::channelmanager::{PendingForwardHTLCInfo, HTLCFailReason}; +use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; +use chain::transaction::OutPoint; use util::{transaction_utils,rng}; use util::sha2::Sha256; use std::default::Default; -use std::cmp; +use std::{cmp,mem}; use std::time::Instant; pub struct ChannelKeys { @@ -43,7 +44,7 @@ impl ChannelKeys { pub fn new_from_seed(seed: &[u8; 32]) -> Result { let mut prk = [0; 32]; hkdf_extract(Sha256::new(), b"rust-lightning key gen salt", seed, &mut prk); - let secp_ctx = Secp256k1::new(); + let secp_ctx = Secp256k1::without_caps(); let mut okm = [0; 32]; hkdf_expand(Sha256::new(), &prk, b"rust-lightning funding key info", &mut okm); @@ -84,19 +85,73 @@ impl ChannelKeys { #[derive(PartialEq)] enum HTLCState { + /// Added by remote, to be included in next local commitment tx. RemoteAnnounced, + /// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but + /// the remote side hasn't yet revoked their previous state, which we need them to do before we + /// accept this HTLC. Implies AwaitingRemoteRevoke. + /// We also have not yet included this HTLC in a commitment_signed message, and are waiting on + /// a remote revoke_and_ack on a previous state before we can do so. + AwaitingRemoteRevokeToAnnounce, + /// Included in a received commitment_signed message (implying we've revoke_and_ack'ed it), but + /// the remote side hasn't yet revoked their previous state, which we need them to do before we + /// accept this HTLC. Implies AwaitingRemoteRevoke. + /// We have included this HTLC in our latest commitment_signed and are now just waiting on a + /// revoke_and_ack. + AwaitingAnnouncedRemoteRevoke, + /// Added by us and included in a commitment_signed (if we were AwaitingRemoteRevoke when we + /// created it we would have put it in the holding cell instead). When they next revoke_and_ack + /// we will promote to Committed (note that they may not accept it until the next time we + /// revoke, but we dont really care about that: + /// * they've revoked, so worst case we can announce an old state and get our (option on) + /// money back (though we wont), and, + /// * we'll send them a revoke when they send a commitment_signed, and since only they're + /// allowed to remove it, the "can only be removed once committed on both sides" requirement + /// doesn't matter to us and its up to them to enforce it, worst-case they jump ahead but + /// we'll never get out of sync). LocalAnnounced, Committed, + /// Remote removed this (outbound) HTLC. We're waiting on their commitment_signed to finalize + /// the change (though they'll need to revoke before we fail the payment). + RemoteRemoved, + /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but + /// the remote side hasn't yet revoked their previous state, which we need them to do before we + /// can do any backwards failing. Implies AwaitingRemoteRevoke. + /// We also have not yet removed this HTLC in a commitment_signed message, and are waiting on a + /// remote revoke_and_ack on a previous state before we can do so. + AwaitingRemoteRevokeToRemove, + /// Remote removed this and sent a commitment_signed (implying we've revoke_and_ack'ed it), but + /// the remote side hasn't yet revoked their previous state, which we need them to do before we + /// can do any backwards failing. Implies AwaitingRemoteRevoke. + /// We have removed this HTLC in our latest commitment_signed and are now just waiting on a + /// revoke_and_ack to drop completely. + AwaitingRemovedRemoteRevoke, + /// Removed by us and a new commitment_signed was sent (if we were AwaitingRemoteRevoke when we + /// created it we would have put it in the holding cell instead). When they next revoke_and_ack + /// we'll promote to LocalRemovedAwaitingCommitment if we fulfilled, otherwise we'll drop at + /// that point. + /// Note that we have to keep an eye on the HTLC until we've received a broadcastable + /// commitment transaction without it as otherwise we'll have to force-close the channel to + /// claim it before the timeout (obviously doesn't apply to revoked HTLCs that we can't claim + /// anyway). + LocalRemoved, + /// Removed by us, sent a new commitment_signed and got a revoke_and_ack. Just waiting on an + /// updated local commitment transaction. + LocalRemovedAwaitingCommitment, } -struct HTLCOutput { +struct HTLCOutput { //TODO: Refactor into Outbound/InboundHTLCOutput (will save memory and fewer panics) outbound: bool, // ie to an HTLC-Timeout transaction htlc_id: u64, amount_msat: u64, cltv_expiry: u32, payment_hash: [u8; 32], state: HTLCState, - // state == RemoteAnnounced implies pending_forward_state, otherwise it must be None + /// If we're in a Remote* removed state, set if they failed, otherwise None + fail_reason: Option, + /// If we're in LocalRemoved*, set to true if we fulfilled the HTLC, and can claim money + local_removed_fulfilled: bool, + /// state pre-committed Remote* implies pending_forward_state, otherwise it must be None pending_forward_state: Option, } @@ -113,13 +168,23 @@ impl HTLCOutput { } /// See AwaitingRemoteRevoke ChannelState for more info -struct HTLCOutputAwaitingACK { - // always outbound - amount_msat: u64, - cltv_expiry: u32, - payment_hash: [u8; 32], - onion_routing_packet: msgs::OnionPacket, - time_created: Instant, //TODO: Some kind of timeout thing-a-majig +enum HTLCUpdateAwaitingACK { + AddHTLC { + // always outbound + amount_msat: u64, + cltv_expiry: u32, + payment_hash: [u8; 32], + onion_routing_packet: msgs::OnionPacket, + time_created: Instant, //TODO: Some kind of timeout thing-a-majig + }, + ClaimHTLC { + payment_preimage: [u8; 32], + payment_hash: [u8; 32], // Only here for effecient duplicate detection + }, + FailHTLC { + payment_hash: [u8; 32], + err_packet: msgs::OnionErrorPacket, + }, } enum ChannelState { @@ -149,7 +214,20 @@ enum ChannelState { /// later. /// Flag is set on ChannelFunded. AwaitingRemoteRevoke = (1 << 7), + /// Flag which is set on ChannelFunded or FundingSent after receiving a shutdown message from + /// the remote end. If set, they may not add any new HTLCs to the channel, and we are expected + /// to respond with our own shutdown message when possible. + RemoteShutdownSent = (1 << 8), + /// Flag which is set on ChannelFunded or FundingSent after sending a shutdown message. At this + /// point, we may not add any new HTLCs to the channel. + /// TODO: Investigate some kind of timeout mechanism by which point the remote end must provide + /// us their shutdown. + LocalShutdownSent = (1 << 9), + /// We've successfully negotiated a closing_signed dance. At this point ChannelManager is about + /// to drop us, but we store this anyway. + ShutdownComplete = (1 << 10), } +const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 | ChannelState::RemoteShutdownSent as u32); // TODO: We should refactor this to be an Inbound/OutboundChannel until initial setup handshaking // has been completed, and then turn into a Channel to get compiler-time enforcement of things like @@ -171,12 +249,20 @@ pub struct Channel { cur_remote_commitment_transaction_number: u64, value_to_self_msat: u64, // Excluding all pending_htlcs, excluding fees pending_htlcs: Vec, - holding_cell_htlcs: Vec, + holding_cell_htlc_updates: Vec, next_local_htlc_id: u64, next_remote_htlc_id: u64, channel_update_count: u32, feerate_per_kw: u64, + #[cfg(test)] + // Used in ChannelManager's tests to send a revoked transaction + pub last_local_commitment_txn: Vec, + #[cfg(not(test))] + last_local_commitment_txn: Vec, + + last_sent_closing_fee: Option<(u64, u64)>, // (feerate, fee) + /// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this /// to detect unconfirmation after a serialize-unserialize roudtrip where we may not see a full /// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we @@ -206,12 +292,16 @@ pub struct Channel { their_delayed_payment_basepoint: PublicKey, their_htlc_basepoint: PublicKey, their_cur_commitment_point: PublicKey, + + their_prev_commitment_point: Option, their_node_id: PublicKey, + their_shutdown_scriptpubkey: Option