use std::default::Default;
use std::{cmp,mem,fmt};
use std::sync::{Arc};
+use std::ops::Deref;
#[cfg(test)]
pub struct ChannelValueStat {
holding_cell_update_fee: Option<u64>,
next_local_htlc_id: u64,
next_remote_htlc_id: u64,
- channel_update_count: u32,
+ update_time_counter: u32,
feerate_per_kw: u64,
#[cfg(debug_assertions)]
cmp::max(at_open_background_feerate * B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT / 1000, 546) //TODO
}
- fn derive_our_htlc_minimum_msat(_at_open_channel_feerate_per_kw: u64) -> u64 {
- 1000 // TODO
- }
-
// Constructors:
- pub fn new_outbound(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface<ChanKeySigner = ChanSigner>>, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, APIError> {
+ pub fn new_outbound<K: Deref, F: Deref>(fee_estimator: &F, keys_provider: &K, their_node_id: PublicKey, channel_value_satoshis: u64, push_msat: u64, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, APIError>
+ where K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
+ F::Target: FeeEstimator,
+ {
let chan_keys = keys_provider.get_channel_keys(false, channel_value_satoshis);
if channel_value_satoshis >= MAX_FUNDING_SATOSHIS {
holding_cell_update_fee: None,
next_local_htlc_id: 0,
next_remote_htlc_id: 0,
- channel_update_count: 1,
+ update_time_counter: 1,
resend_order: RAACommitmentOrder::CommitmentFirst,
their_max_htlc_value_in_flight_msat: 0,
their_channel_reserve_satoshis: 0,
their_htlc_minimum_msat: 0,
- our_htlc_minimum_msat: Channel::<ChanSigner>::derive_our_htlc_minimum_msat(feerate),
+ our_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
their_to_self_delay: 0,
our_to_self_delay: config.own_channel_config.our_to_self_delay,
their_max_accepted_htlcs: 0,
})
}
- fn check_remote_fee(fee_estimator: &FeeEstimator, feerate_per_kw: u32) -> Result<(), ChannelError> {
+ fn check_remote_fee<F: Deref>(fee_estimator: &F, feerate_per_kw: u32) -> Result<(), ChannelError>
+ where F::Target: FeeEstimator
+ {
if (feerate_per_kw as u64) < fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) {
return Err(ChannelError::Close("Peer's feerate much too low"));
}
/// Creates a new channel from a remote sides' request for one.
/// Assumes chain_hash has already been checked and corresponds with what we expect!
- pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface<ChanKeySigner = ChanSigner>>, their_node_id: PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, ChannelError> {
+ pub fn new_from_req<K: Deref, F: Deref>(fee_estimator: &F, keys_provider: &K, their_node_id: PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, ChannelError>
+ where K::Target: KeysInterface<ChanKeySigner = ChanSigner>,
+ F::Target: FeeEstimator
+ {
let mut chan_keys = keys_provider.get_channel_keys(true, msg.funding_satoshis);
let their_pubkeys = ChannelPublicKeys {
funding_pubkey: msg.funding_pubkey,
holding_cell_update_fee: None,
next_local_htlc_id: 0,
next_remote_htlc_id: 0,
- channel_update_count: 1,
+ update_time_counter: 1,
resend_order: RAACommitmentOrder::CommitmentFirst,
their_max_htlc_value_in_flight_msat: cmp::min(msg.max_htlc_value_in_flight_msat, msg.funding_satoshis * 1000),
their_channel_reserve_satoshis: msg.channel_reserve_satoshis,
their_htlc_minimum_msat: msg.htlc_minimum_msat,
- our_htlc_minimum_msat: Channel::<ChanSigner>::derive_our_htlc_minimum_msat(msg.feerate_per_kw as u64),
+ our_htlc_minimum_msat: if config.own_channel_config.our_htlc_minimum_msat == 0 { 1 } else { config.own_channel_config.our_htlc_minimum_msat },
their_to_self_delay: msg.to_self_delay,
our_to_self_delay: config.own_channel_config.our_to_self_delay,
their_max_accepted_htlcs: msg.max_accepted_htlcs,
self.channel_state |= ChannelState::TheirFundingLocked as u32;
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS);
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
} else if (self.channel_state & (ChannelState::ChannelFunded as u32) != 0 &&
// Note that funding_signed/funding_created will have decremented both by 1!
self.cur_local_commitment_transaction_number == INITIAL_COMMITMENT_NUMBER - 1 &&
if msg.amount_msat > self.channel_value_satoshis * 1000 {
return Err(ChannelError::Close("Remote side tried to send more than the total value of the channel"));
}
+ if msg.amount_msat == 0 {
+ return Err(ChannelError::Close("Remote side tried to send a 0-msat HTLC"));
+ }
if msg.amount_msat < self.our_htlc_minimum_msat {
return Err(ChannelError::Close("Remote side tried to send less than our minimum HTLC value"));
}
Ok(())
}
- pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned, fee_estimator: &FeeEstimator) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, Option<msgs::ClosingSigned>, ChannelMonitorUpdate), (Option<ChannelMonitorUpdate>, ChannelError)> {
+ pub fn commitment_signed<F: Deref>(&mut self, msg: &msgs::CommitmentSigned, fee_estimator: &F) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, Option<msgs::ClosingSigned>, ChannelMonitorUpdate), (Option<ChannelMonitorUpdate>, ChannelError)> where F::Target: FeeEstimator {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err((None, ChannelError::Close("Got commitment signed message when channel was not in an operational state")));
}
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
- pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &FeeEstimator) -> Result<(Option<msgs::CommitmentUpdate>, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option<msgs::ClosingSigned>, ChannelMonitorUpdate), ChannelError> {
+ pub fn revoke_and_ack<F: Deref>(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &F) -> Result<(Option<msgs::CommitmentUpdate>, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option<msgs::ClosingSigned>, ChannelMonitorUpdate), ChannelError>
+ where F::Target: FeeEstimator
+ {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(ChannelError::Close("Got revoke/ACK message when channel was not in an operational state"));
}
(raa, commitment_update, order, forwards, failures, needs_broadcast_safe, funding_locked)
}
- pub fn update_fee(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::UpdateFee) -> Result<(), ChannelError> {
+ pub fn update_fee<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::UpdateFee) -> Result<(), ChannelError>
+ where F::Target: FeeEstimator
+ {
if self.channel_outbound {
return Err(ChannelError::Close("Non-funding remote tried to update channel fee"));
}
}
Channel::<ChanSigner>::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
self.pending_update_fee = Some(msg.feerate_per_kw as u64);
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
Ok(())
}
}
}
- fn maybe_propose_first_closing_signed(&mut self, fee_estimator: &FeeEstimator) -> Option<msgs::ClosingSigned> {
+ fn maybe_propose_first_closing_signed<F: Deref>(&mut self, fee_estimator: &F) -> Option<msgs::ClosingSigned>
+ where F::Target: FeeEstimator
+ {
if !self.channel_outbound || !self.pending_inbound_htlcs.is_empty() || !self.pending_outbound_htlcs.is_empty() ||
self.channel_state & (BOTH_SIDES_SHUTDOWN_MASK | ChannelState::AwaitingRemoteRevoke as u32) != BOTH_SIDES_SHUTDOWN_MASK ||
self.last_sent_closing_fee.is_some() || self.pending_update_fee.is_some() {
})
}
- pub fn shutdown(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, PaymentHash)>), ChannelError> {
+ pub fn shutdown<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::Shutdown) -> Result<(Option<msgs::Shutdown>, Option<msgs::ClosingSigned>, Vec<(HTLCSource, PaymentHash)>), ChannelError>
+ where F::Target: FeeEstimator
+ {
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
return Err(ChannelError::Close("Peer sent shutdown when we needed a channel_reestablish"));
}
// From here on out, we may not fail!
self.channel_state |= ChannelState::RemoteShutdownSent as u32;
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
// We can't send our shutdown until we've committed all of our pending HTLCs, but the
// remote side is unlikely to accept any new HTLCs, so we go ahead and "free" any holding
};
self.channel_state |= ChannelState::LocalShutdownSent as u32;
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
}
tx.input[0].witness.push(self.get_funding_redeemscript().into_bytes());
}
- pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError> {
+ pub fn closing_signed<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), ChannelError>
+ where F::Target: FeeEstimator
+ {
if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
return Err(ChannelError::Close("Remote end sent us a closing_signed before both sides provided a shutdown"));
}
if last_fee == msg.fee_satoshis {
self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig);
self.channel_state = ChannelState::ShutdownComplete as u32;
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
return Ok((None, Some(closing_tx)));
}
}
self.build_signed_closing_transaction(&mut closing_tx, &msg.signature, &our_sig);
self.channel_state = ChannelState::ShutdownComplete as u32;
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
Ok((Some(msgs::ClosingSigned {
channel_id: self.channel_id,
}
/// Allowed in any state (including after shutdown)
- pub fn get_channel_update_count(&self) -> u32 {
- self.channel_update_count
+ pub fn get_update_time_counter(&self) -> u32 {
+ self.update_time_counter
}
pub fn get_latest_monitor_update_id(&self) -> u64 {
/// Gets the fee we'd want to charge for adding an HTLC output to this Channel
/// Allowed in any state (including after shutdown)
- pub fn get_our_fee_base_msat(&self, fee_estimator: &FeeEstimator) -> u32 {
+ pub fn get_our_fee_base_msat<F: Deref>(&self, fee_estimator: &F) -> u32
+ where F::Target: FeeEstimator
+ {
// For lack of a better metric, we calculate what it would cost to consolidate the new HTLC
// output value back into a transaction with the regular channel output:
panic!("Client called ChannelManager::funding_transaction_generated with bogus transaction!");
}
self.channel_state = ChannelState::ShutdownComplete as u32;
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
return Err(msgs::ErrorMessage {
channel_id: self.channel_id(),
data: "funding tx had wrong script/value".to_owned()
}
if header.bitcoin_hash() != self.last_block_connected {
self.last_block_connected = header.bitcoin_hash();
+ self.update_time_counter = cmp::max(self.update_time_counter, header.time);
if let Some(channel_monitor) = self.channel_monitor.as_mut() {
channel_monitor.last_block_hash = self.last_block_connected;
}
true
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::TheirFundingLocked as u32) {
self.channel_state = ChannelState::ChannelFunded as u32 | (self.channel_state & MULTI_STATE_FLAGS);
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
true
} else if non_shutdown_state == (ChannelState::FundingSent as u32 | ChannelState::OurFundingLocked as u32) {
// We got a reorg but not enough to trigger a force close, just update
// 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) -> msgs::OpenChannel {
+ pub fn get_open_channel<F: Deref>(&self, chain_hash: Sha256dHash, fee_estimator: &F) -> msgs::OpenChannel
+ where F::Target: FeeEstimator
+ {
if !self.channel_outbound {
panic!("Tried to open a channel for an inbound channel?");
}
if amount_msat > self.channel_value_satoshis * 1000 {
return Err(ChannelError::Ignore("Cannot send more than the total value of the channel"));
}
+
+ if amount_msat == 0 {
+ return Err(ChannelError::Ignore("Cannot send 0-msat HTLC"));
+ }
+
if amount_msat < self.their_htlc_minimum_msat {
return Err(ChannelError::Ignore("Cannot send less than their minimum HTLC value"));
}
} else {
self.channel_state |= ChannelState::LocalShutdownSent as u32;
}
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
// Go ahead and drop holding cell updates as we'd rather fail payments than wait to send
// our shutdown until we've committed all of the pending changes.
}
self.channel_state = ChannelState::ShutdownComplete as u32;
- self.channel_update_count += 1;
+ self.update_time_counter += 1;
if self.channel_monitor.is_some() {
(self.channel_monitor.as_mut().unwrap().get_latest_local_commitment_txn(), dropped_outbound_htlcs)
} else {
}
}
-impl<R: ::std::io::Read> Readable<R> for InboundHTLCRemovalReason {
- fn read(reader: &mut R) -> Result<Self, DecodeError> {
- Ok(match <u8 as Readable<R>>::read(reader)? {
+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)?),
}
}
- macro_rules! write_option {
- ($thing: expr) => {
- match &$thing {
- &None => 0u8.write(writer)?,
- &Some(ref v) => {
- 1u8.write(writer)?;
- v.write(writer)?;
- },
- }
- }
- }
-
(self.pending_outbound_htlcs.len() as u64).write(writer)?;
for htlc in self.pending_outbound_htlcs.iter() {
htlc.htlc_id.write(writer)?;
},
&OutboundHTLCState::RemoteRemoved(ref fail_reason) => {
2u8.write(writer)?;
- write_option!(*fail_reason);
+ fail_reason.write(writer)?;
},
&OutboundHTLCState::AwaitingRemoteRevokeToRemove(ref fail_reason) => {
3u8.write(writer)?;
- write_option!(*fail_reason);
+ fail_reason.write(writer)?;
},
&OutboundHTLCState::AwaitingRemovedRemoteRevoke(ref fail_reason) => {
4u8.write(writer)?;
- write_option!(*fail_reason);
+ fail_reason.write(writer)?;
},
}
}
fail_reason.write(writer)?;
}
- write_option!(self.pending_update_fee);
- write_option!(self.holding_cell_update_fee);
+ self.pending_update_fee.write(writer)?;
+ self.holding_cell_update_fee.write(writer)?;
self.next_local_htlc_id.write(writer)?;
(self.next_remote_htlc_id - dropped_inbound_htlcs).write(writer)?;
- self.channel_update_count.write(writer)?;
+ self.update_time_counter.write(writer)?;
self.feerate_per_kw.write(writer)?;
match self.last_sent_closing_fee {
None => 0u8.write(writer)?,
}
- write_option!(self.funding_txo);
- write_option!(self.funding_tx_confirmed_in);
- write_option!(self.short_channel_id);
+ self.funding_txo.write(writer)?;
+ self.funding_tx_confirmed_in.write(writer)?;
+ self.short_channel_id.write(writer)?;
self.last_block_connected.write(writer)?;
self.funding_tx_confirmations.write(writer)?;
self.their_max_accepted_htlcs.write(writer)?;
self.minimum_depth.write(writer)?;
- write_option!(self.their_pubkeys);
- write_option!(self.their_cur_commitment_point);
+ self.their_pubkeys.write(writer)?;
+ self.their_cur_commitment_point.write(writer)?;
- write_option!(self.their_prev_commitment_point);
+ self.their_prev_commitment_point.write(writer)?;
self.their_node_id.write(writer)?;
- write_option!(self.their_shutdown_scriptpubkey);
+ self.their_shutdown_scriptpubkey.write(writer)?;
self.commitment_secrets.write(writer)?;
}
}
-impl<R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R, Arc<Logger>> for Channel<ChanSigner> {
- fn read(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
+impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for Channel<ChanSigner> {
+ fn read<R : ::std::io::Read>(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
let _ver: u8 = Readable::read(reader)?;
let min_ver: u8 = Readable::read(reader)?;
if min_ver > SERIALIZATION_VERSION {
amount_msat: Readable::read(reader)?,
cltv_expiry: Readable::read(reader)?,
payment_hash: Readable::read(reader)?,
- state: match <u8 as Readable<R>>::read(reader)? {
+ state: match <u8 as Readable>::read(reader)? {
1 => InboundHTLCState::AwaitingRemoteRevokeToAnnounce(Readable::read(reader)?),
2 => InboundHTLCState::AwaitingAnnouncedRemoteRevoke(Readable::read(reader)?),
3 => InboundHTLCState::Committed,
cltv_expiry: Readable::read(reader)?,
payment_hash: Readable::read(reader)?,
source: Readable::read(reader)?,
- state: match <u8 as Readable<R>>::read(reader)? {
+ state: match <u8 as Readable>::read(reader)? {
0 => OutboundHTLCState::LocalAnnounced(Box::new(Readable::read(reader)?)),
1 => OutboundHTLCState::Committed,
2 => OutboundHTLCState::RemoteRemoved(Readable::read(reader)?),
let holding_cell_htlc_update_count: u64 = Readable::read(reader)?;
let mut holding_cell_htlc_updates = Vec::with_capacity(cmp::min(holding_cell_htlc_update_count as usize, OUR_MAX_HTLCS as usize*2));
for _ in 0..holding_cell_htlc_update_count {
- holding_cell_htlc_updates.push(match <u8 as Readable<R>>::read(reader)? {
+ holding_cell_htlc_updates.push(match <u8 as Readable>::read(reader)? {
0 => HTLCUpdateAwaitingACK::AddHTLC {
amount_msat: Readable::read(reader)?,
cltv_expiry: Readable::read(reader)?,
});
}
- let resend_order = match <u8 as Readable<R>>::read(reader)? {
+ let resend_order = match <u8 as Readable>::read(reader)? {
0 => RAACommitmentOrder::CommitmentFirst,
1 => RAACommitmentOrder::RevokeAndACKFirst,
_ => return Err(DecodeError::InvalidValue),
let next_local_htlc_id = Readable::read(reader)?;
let next_remote_htlc_id = Readable::read(reader)?;
- let channel_update_count = Readable::read(reader)?;
+ let update_time_counter = Readable::read(reader)?;
let feerate_per_kw = Readable::read(reader)?;
- let last_sent_closing_fee = match <u8 as Readable<R>>::read(reader)? {
+ let last_sent_closing_fee = match <u8 as Readable>::read(reader)? {
0 => None,
1 => Some((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)),
_ => return Err(DecodeError::InvalidValue),
holding_cell_update_fee,
next_local_htlc_id,
next_remote_htlc_id,
- channel_update_count,
+ update_time_counter,
feerate_per_kw,
#[cfg(debug_assertions)]
assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..],
hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
- let keys_provider: Arc<KeysInterface<ChanKeySigner = InMemoryChannelKeys>> = Arc::new(Keys { chan_keys });
+ let keys_provider = Keys { chan_keys };
let their_node_id = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
let mut config = UserConfig::default();
config.channel_options.announced_channel = false;
- let mut chan = Channel::<InMemoryChannelKeys>::new_outbound(&feeest, &keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test
+ let mut chan = Channel::<InMemoryChannelKeys>::new_outbound(&&feeest, &&keys_provider, their_node_id, 10000000, 100000, 42, Arc::clone(&logger), &config).unwrap(); // Nothing uses their network key in this test
chan.their_to_self_delay = 144;
chan.our_dust_limit_satoshis = 546;