X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fln%2Fchannel.rs;h=a8550932d5ad597e4e16bef4cfdfe7ae68f8df3f;hb=b9a155d75f723f0e99f7bf7faf0abe5c7b492dfd;hp=fc67085250a3e1f429d53dcffa06f7ff3455a0d9;hpb=e571c7ac4011c458970e780fa1b7b92136f06f2d;p=rust-lightning diff --git a/src/ln/channel.rs b/src/ln/channel.rs index fc670852..a8550932 100644 --- a/src/ln/channel.rs +++ b/src/ln/channel.rs @@ -14,20 +14,24 @@ use crypto::digest::Digest; use crypto::hkdf::{hkdf_extract,hkdf_expand}; use ln::msgs; -use ln::msgs::{HandleError, MsgEncodable}; +use ln::msgs::{ErrorAction, HandleError}; use ln::channelmonitor::ChannelMonitor; -use ln::channelmanager::{PendingForwardHTLCInfo, HTLCFailReason}; +use ln::channelmanager::{PendingHTLCStatus, HTLCSource, PendingForwardHTLCInfo, HTLCFailReason, HTLCFailureMsg}; 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::ser::Writeable; use util::sha2::Sha256; +use util::logger::Logger; +use util::errors::APIError; use std; use std::default::Default; use std::{cmp,mem}; use std::time::Instant; +use std::sync::{Arc}; pub struct ChannelKeys { pub funding_key: SecretKey, @@ -84,7 +88,7 @@ impl ChannelKeys { } #[derive(PartialEq)] -enum HTLCState { +enum InboundHTLCState { /// 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 @@ -99,6 +103,34 @@ enum HTLCState { /// We have included this HTLC in our latest commitment_signed and are now just waiting on a /// revoke_and_ack. AwaitingAnnouncedRemoteRevoke, + Committed, + /// 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 drop it. + /// 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). That said, ChannelMonitor does this for us (see + /// ChannelMonitor::would_broadcast_at_height) so we actually remove the HTLC from our own + /// local state before then, once we're sure that the next commitment_signed and + /// ChannelMonitor::provide_latest_local_commitment_tx_info will not include this HTLC. + LocalRemoved, +} + +struct InboundHTLCOutput { + htlc_id: u64, + amount_msat: u64, + cltv_expiry: u32, + payment_hash: [u8; 32], + state: InboundHTLCState, + /// If we're in LocalRemoved, set to true if we fulfilled the HTLC, and can claim money + local_removed_fulfilled: bool, + /// state pre-Committed implies pending_forward_state, otherwise it must be None + pending_forward_state: Option, +} + +#[derive(PartialEq)] +enum OutboundHTLCState { /// 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 @@ -126,42 +158,26 @@ enum HTLCState { /// 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 { //TODO: Refactor into Outbound/InboundHTLCOutput (will save memory and fewer panics) - outbound: bool, // ie to an HTLC-Timeout transaction +struct OutboundHTLCOutput { htlc_id: u64, amount_msat: u64, cltv_expiry: u32, payment_hash: [u8; 32], - state: HTLCState, - /// If we're in a Remote* removed state, set if they failed, otherwise None + state: OutboundHTLCState, + source: HTLCSource, + /// If we're in a 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, } -impl HTLCOutput { - fn get_in_commitment(&self, offered: bool) -> HTLCOutputInCommitment { +macro_rules! get_htlc_in_commitment { + ($htlc: expr, $offered: expr) => { HTLCOutputInCommitment { - offered: offered, - amount_msat: self.amount_msat, - cltv_expiry: self.cltv_expiry, - payment_hash: self.payment_hash, + offered: $offered, + amount_msat: $htlc.amount_msat, + cltv_expiry: $htlc.cltv_expiry, + payment_hash: $htlc.payment_hash, transaction_output_index: 0 } } @@ -174,19 +190,27 @@ enum HTLCUpdateAwaitingACK { amount_msat: u64, cltv_expiry: u32, payment_hash: [u8; 32], + source: HTLCSource, 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 + htlc_id: u64, }, FailHTLC { - payment_hash: [u8; 32], + htlc_id: u64, err_packet: msgs::OnionErrorPacket, }, } +/// There are a few "states" and then a number of flags which can be applied: +/// We first move through init with OurInitSent -> TheirInitSent -> FundingCreated -> FundingSent. +/// TheirFundingLocked and OurFundingLocked then get set on FundingSent, and when both are set we +/// move on to ChannelFunded. +/// Note that PeerDisconnected can be set on both ChannelFunded and FundingSent. +/// ChannelFunded can then get all remaining flags set on it, until we finish shutdown, then we +/// move on to ShutdownComplete, at which point most calls into this channel are disallowed. enum ChannelState { /// Implies we have (or are prepared to) send our open_channel/accept_channel message OurInitSent = (1 << 0), @@ -207,39 +231,45 @@ enum ChannelState { /// Once both TheirFundingLocked and OurFundingLocked are set, state moves on to ChannelFunded. OurFundingLocked = (1 << 5), ChannelFunded = 64, + /// Flag which is set on ChannelFunded and FundingSent indicating remote side is considered + /// "disconnected" and no updates are allowed until after we've done a channel_reestablish + /// dance. + PeerDisconnected = (1 << 7), /// Flag which implies that we have sent a commitment_signed but are awaiting the responding /// revoke_and_ack message. During this time period, we can't generate new commitment_signed /// messages as then we will be unable to determine which HTLCs they included in their /// revoke_and_ack implicit ACK, so instead we have to hold them away temporarily to be sent /// later. /// Flag is set on ChannelFunded. - AwaitingRemoteRevoke = (1 << 7), + AwaitingRemoteRevoke = (1 << 8), /// 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), + RemoteShutdownSent = (1 << 9), /// 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), + LocalShutdownSent = (1 << 10), /// 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), + ShutdownComplete = 2048, } const BOTH_SIDES_SHUTDOWN_MASK: u32 = (ChannelState::LocalShutdownSent as u32 | ChannelState::RemoteShutdownSent as u32); +const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1; + // 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 // calling channel_id() before we're set up or things like get_outbound_funding_signed on an // inbound channel. -pub struct Channel { +pub(super) struct Channel { user_id: u64, channel_id: [u8; 32], channel_state: u32, channel_outbound: bool, - secp_ctx: Secp256k1, + secp_ctx: Secp256k1, announce_publicly: bool, channel_value_satoshis: u64, @@ -252,8 +282,27 @@ pub struct Channel { cur_local_commitment_transaction_number: u64, cur_remote_commitment_transaction_number: u64, value_to_self_msat: u64, // Excluding all pending_htlcs, excluding fees - pending_htlcs: Vec, + pending_inbound_htlcs: Vec, + pending_outbound_htlcs: Vec, holding_cell_htlc_updates: Vec, + + // pending_update_fee is filled when sending and receiving update_fee + // For outbound channel, feerate_per_kw is updated with the value from + // pending_update_fee when revoke_and_ack is received + // + // For inbound channel, feerate_per_kw is updated when it receives + // commitment_signed and revoke_and_ack is generated + // The pending value is kept when another pair of update_fee and commitment_signed + // is received during AwaitingRemoteRevoke and relieved when the expected + // revoke_and_ack is received and new commitment_signed is generated to be + // sent to the funder. Otherwise, the pending value is removed when receiving + // commitment_signed. + pending_update_fee: Option, + // update_fee() during ChannelState::AwaitingRemoteRevoke is hold in + // holdina_cell_update_fee then moved to pending_udpate_fee when revoke_and_ack + // is received. holding_cell_update_fee is updated when there are additional + // update_fee() during ChannelState::AwaitingRemoteRevoke. + holding_cell_update_fee: Option, next_local_htlc_id: u64, next_remote_htlc_id: u64, channel_update_count: u32, @@ -271,7 +320,7 @@ pub struct Channel { /// 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 /// could miss the funding_tx_confirmed_in block as well, but it serves as a useful fallback. - funding_tx_confirmed_in: Sha256dHash, + funding_tx_confirmed_in: Option, short_channel_id: Option, /// Used to deduplicate block_connected callbacks last_block_connected: Sha256dHash, @@ -290,12 +339,12 @@ pub struct Channel { their_max_accepted_htlcs: u16, //implied by OUR_MAX_HTLCS: our_max_accepted_htlcs: u16, - their_funding_pubkey: PublicKey, - their_revocation_basepoint: PublicKey, - their_payment_basepoint: PublicKey, - their_delayed_payment_basepoint: PublicKey, - their_htlc_basepoint: PublicKey, - their_cur_commitment_point: PublicKey, + their_funding_pubkey: Option, + their_revocation_basepoint: Option, + their_payment_basepoint: Option, + their_delayed_payment_basepoint: Option, + their_htlc_basepoint: Option, + their_cur_commitment_point: Option, their_prev_commitment_point: Option, their_node_id: PublicKey, @@ -303,10 +352,11 @@ pub struct Channel { their_shutdown_scriptpubkey: Option