use util::{transaction_utils,rng};
use util::sha2::Sha256;
use util::logger::{Logger, Record};
+use util::errors::APIError;
use std;
use std::default::Default;
#[derive(PartialEq)]
enum HTLCState {
/// Added by remote, to be included in next local commitment tx.
+ /// Implies HTLCOutput::outbound: false
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.
+ /// Implies HTLCOutput::outbound: false
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.
+ /// Implies HTLCOutput::outbound: true
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
/// 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).
+ /// Implies HTLCOutput::outbound: true
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).
+ /// Implies HTLCOutput::outbound: true
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.
+ /// Implies HTLCOutput::outbound: true
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.
+ /// Implies HTLCOutput::outbound: true
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
/// 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).
+ /// Implies HTLCOutput::outbound: false
LocalRemoved,
/// Removed by us, sent a new commitment_signed and got a revoke_and_ack. Just waiting on an
/// updated local commitment transaction. Implies local_removed_fulfilled.
+ /// Implies HTLCOutput::outbound: false
LocalRemovedAwaitingCommitment,
}
}
// Constructors:
-
- /// panics if channel_value_satoshis is >= `MAX_FUNDING_SATOSHIS`
- pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, announce_publicly: bool, user_id: u64, logger: Arc<Logger>) -> Channel {
+ pub fn new_outbound(fee_estimator: &FeeEstimator, chan_keys: ChannelKeys, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, announce_publicly: bool, user_id: u64, logger: Arc<Logger>) -> Result<Channel, APIError> {
if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
- panic!("funding value > 2^24");
+ return Err(APIError::APIMisuseError{err: "funding value > 2^24"});
+ }
+
+ if push_msat > channel_value_satoshis * 1000 {
+ return Err(APIError::APIMisuseError{err: "push value > channel value"});
}
let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
&chan_keys.htlc_base_key,
BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
- Channel {
+ Ok(Channel {
user_id: user_id,
channel_id: rng::rand_u832(),
local_keys: chan_keys,
cur_local_commitment_transaction_number: (1 << 48) - 1,
cur_remote_commitment_transaction_number: (1 << 48) - 1,
- value_to_self_msat: channel_value_satoshis * 1000, //TODO: give them something on open? Parameterize it?
+ value_to_self_msat: channel_value_satoshis * 1000 - push_msat,
pending_htlcs: Vec::new(),
holding_cell_htlc_updates: Vec::new(),
next_local_htlc_id: 0,
channel_monitor: channel_monitor,
logger,
- }
+ })
}
fn check_remote_fee(fee_estimator: &FeeEstimator, feerate_per_kw: u32) -> Result<(), HandleError> {
for (idx, htlc) in self.pending_htlcs.iter().enumerate() {
if !htlc.outbound && htlc.payment_hash == payment_hash_calc {
if pending_idx != std::usize::MAX {
- panic!("Duplicate HTLC payment_hash, you probably re-used payment preimages, NEVER DO THIS!");
+ panic!("Duplicate HTLC payment_hash, ChannelManager should have prevented this!");
}
pending_idx = idx;
}
if htlc.state == HTLCState::Committed {
htlc.state = HTLCState::LocalRemoved;
htlc.local_removed_fulfilled = true;
- } else if htlc.state == HTLCState::RemoteAnnounced {
- panic!("Somehow forwarded HTLC prior to remote revocation!");
+ } else if htlc.state == HTLCState::RemoteAnnounced || htlc.state == HTLCState::AwaitingRemoteRevokeToAnnounce || htlc.state == HTLCState::AwaitingAnnouncedRemoteRevoke {
+ // Theoretically we can hit this if we get the preimage on an HTLC prior to us
+ // having forwarded it to anyone. This implies that the sender is busted as someone
+ // else knows the preimage, but handling this case and implementing the logic to
+ // take their money would be a lot of (never-tested) code to handle a case that
+ // hopefully never happens. Instead, we make sure we get the preimage into the
+ // channel_monitor and pretend we didn't just see the preimage.
+ return Ok((None, Some(self.channel_monitor.clone())));
} else if htlc.state == HTLCState::LocalRemoved || htlc.state == HTLCState::LocalRemovedAwaitingCommitment {
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", action: None});
} else {
// Methods to get unprompted messages to send to the remote end (or where we already returned
// something in the handler for the message that prompted this message):
- pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> Result<msgs::OpenChannel, HandleError> {
+ pub fn get_open_channel(&self, chain_hash: Sha256dHash, fee_estimator: &FeeEstimator) -> Result<msgs::OpenChannel, APIError> {
if !self.channel_outbound {
panic!("Tried to open a channel for an inbound channel?");
}
if self.channel_state != ChannelState::OurInitSent as u32 {
- return Err(HandleError{err: "Cannot generate an open_channel after we've moved forward", action: None});
+ panic!("Cannot generate an open_channel after we've moved forward");
}
if self.cur_local_commitment_transaction_number != (1 << 48) - 1 {
chain_hash: chain_hash,
temporary_channel_id: self.channel_id,
funding_satoshis: self.channel_value_satoshis,
- push_msat: 0, //TODO: Something about feerate?
+ push_msat: self.channel_value_satoshis * 1000 - self.value_to_self_msat,
dust_limit_satoshis: self.our_dust_limit_satoshis,
max_htlc_value_in_flight_msat: Channel::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis),
channel_reserve_satoshis: Channel::get_our_channel_reserve_satoshis(self.channel_value_satoshis),
assert_eq!(PublicKey::from_secret_key(&secp_ctx, &chan_keys.funding_key).unwrap().serialize()[..],
hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
- let mut chan = Channel::new_outbound(&feeest, chan_keys, PublicKey::new(), 10000000, false, 42, Arc::clone(&logger)); // Nothing uses their network key in this test
+ let mut chan = Channel::new_outbound(&feeest, chan_keys, PublicKey::new(), 10000000, 100000, false, 42, Arc::clone(&logger)).unwrap(); // Nothing uses their network key in this test
chan.their_to_self_delay = 144;
chan.our_dust_limit_satoshis = 546;