mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 23:30:59 +01:00
Implement update_fee handling
This commit is contained in:
parent
2b9ee0995f
commit
1dbc6fb0ef
4 changed files with 169 additions and 25 deletions
|
@ -285,6 +285,24 @@ pub(super) struct Channel {
|
||||||
pending_inbound_htlcs: Vec<InboundHTLCOutput>,
|
pending_inbound_htlcs: Vec<InboundHTLCOutput>,
|
||||||
pending_outbound_htlcs: Vec<OutboundHTLCOutput>,
|
pending_outbound_htlcs: Vec<OutboundHTLCOutput>,
|
||||||
holding_cell_htlc_updates: Vec<HTLCUpdateAwaitingACK>,
|
holding_cell_htlc_updates: Vec<HTLCUpdateAwaitingACK>,
|
||||||
|
|
||||||
|
// 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<u64>,
|
||||||
|
// 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<u64>,
|
||||||
next_local_htlc_id: u64,
|
next_local_htlc_id: u64,
|
||||||
next_remote_htlc_id: u64,
|
next_remote_htlc_id: u64,
|
||||||
channel_update_count: u32,
|
channel_update_count: u32,
|
||||||
|
@ -445,6 +463,8 @@ impl Channel {
|
||||||
pending_inbound_htlcs: Vec::new(),
|
pending_inbound_htlcs: Vec::new(),
|
||||||
pending_outbound_htlcs: Vec::new(),
|
pending_outbound_htlcs: Vec::new(),
|
||||||
holding_cell_htlc_updates: Vec::new(),
|
holding_cell_htlc_updates: Vec::new(),
|
||||||
|
pending_update_fee: None,
|
||||||
|
holding_cell_update_fee: None,
|
||||||
next_local_htlc_id: 0,
|
next_local_htlc_id: 0,
|
||||||
next_remote_htlc_id: 0,
|
next_remote_htlc_id: 0,
|
||||||
channel_update_count: 1,
|
channel_update_count: 1,
|
||||||
|
@ -603,6 +623,8 @@ impl Channel {
|
||||||
pending_inbound_htlcs: Vec::new(),
|
pending_inbound_htlcs: Vec::new(),
|
||||||
pending_outbound_htlcs: Vec::new(),
|
pending_outbound_htlcs: Vec::new(),
|
||||||
holding_cell_htlc_updates: Vec::new(),
|
holding_cell_htlc_updates: Vec::new(),
|
||||||
|
pending_update_fee: None,
|
||||||
|
holding_cell_update_fee: None,
|
||||||
next_local_htlc_id: 0,
|
next_local_htlc_id: 0,
|
||||||
next_remote_htlc_id: 0,
|
next_remote_htlc_id: 0,
|
||||||
channel_update_count: 1,
|
channel_update_count: 1,
|
||||||
|
@ -695,7 +717,7 @@ impl Channel {
|
||||||
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
|
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
|
||||||
/// which peer generated this transaction and "to whom" this transaction flows.
|
/// which peer generated this transaction and "to whom" this transaction flows.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool) -> (Transaction, Vec<HTLCOutputInCommitment>) {
|
fn build_commitment_transaction(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, feerate_per_kw: u64) -> (Transaction, Vec<HTLCOutputInCommitment>) {
|
||||||
let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number);
|
let obscured_commitment_transaction_number = self.get_commitment_transaction_number_obscure_factor() ^ (INITIAL_COMMITMENT_NUMBER - commitment_number);
|
||||||
|
|
||||||
let txins = {
|
let txins = {
|
||||||
|
@ -719,7 +741,7 @@ impl Channel {
|
||||||
macro_rules! add_htlc_output {
|
macro_rules! add_htlc_output {
|
||||||
($htlc: expr, $outbound: expr) => {
|
($htlc: expr, $outbound: expr) => {
|
||||||
if $outbound == local { // "offered HTLC output"
|
if $outbound == local { // "offered HTLC output"
|
||||||
if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) {
|
if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000) {
|
||||||
let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
|
let htlc_in_tx = get_htlc_in_commitment!($htlc, true);
|
||||||
txouts.push((TxOut {
|
txouts.push((TxOut {
|
||||||
script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
|
script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
|
||||||
|
@ -727,7 +749,7 @@ impl Channel {
|
||||||
}, Some(htlc_in_tx)));
|
}, Some(htlc_in_tx)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (self.feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) {
|
if $htlc.amount_msat / 1000 >= dust_limit_satoshis + (feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000) {
|
||||||
let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
|
let htlc_in_tx = get_htlc_in_commitment!($htlc, false);
|
||||||
txouts.push((TxOut { // "received HTLC output"
|
txouts.push((TxOut { // "received HTLC output"
|
||||||
script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
|
script_pubkey: chan_utils::get_htlc_redeemscript(&htlc_in_tx, &keys).to_v0_p2wsh(),
|
||||||
|
@ -791,7 +813,8 @@ impl Channel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let total_fee: u64 = self.feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
|
|
||||||
|
let total_fee: u64 = feerate_per_kw * (COMMITMENT_TX_BASE_WEIGHT + (txouts.len() as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
|
||||||
let value_to_self: i64 = ((self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset) / 1000 - if self.channel_outbound { total_fee as i64 } else { 0 };
|
let value_to_self: i64 = ((self.value_to_self_msat - local_htlc_total_msat) as i64 + value_to_self_msat_offset) / 1000 - if self.channel_outbound { total_fee as i64 } else { 0 };
|
||||||
let value_to_remote: i64 = (((self.channel_value_satoshis * 1000 - self.value_to_self_msat - remote_htlc_total_msat) as i64 - value_to_self_msat_offset) / 1000) - if self.channel_outbound { 0 } else { total_fee as i64 };
|
let value_to_remote: i64 = (((self.channel_value_satoshis * 1000 - self.value_to_self_msat - remote_htlc_total_msat) as i64 - value_to_self_msat_offset) / 1000) - if self.channel_outbound { 0 } else { total_fee as i64 };
|
||||||
|
|
||||||
|
@ -983,8 +1006,8 @@ impl Channel {
|
||||||
/// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
|
/// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
|
||||||
/// @local is used only to convert relevant internal structures which refer to remote vs local
|
/// @local is used only to convert relevant internal structures which refer to remote vs local
|
||||||
/// to decide value of outputs and direction of HTLCs.
|
/// to decide value of outputs and direction of HTLCs.
|
||||||
fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys) -> Transaction {
|
fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys, feerate_per_kw: u64) -> Transaction {
|
||||||
chan_utils::build_htlc_transaction(prev_hash, self.feerate_per_kw, if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key)
|
chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_htlc_tx_signature(&self, tx: &Transaction, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(Script, Signature, bool), HandleError> {
|
fn create_htlc_tx_signature(&self, tx: &Transaction, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(Script, Signature, bool), HandleError> {
|
||||||
|
@ -1282,14 +1305,14 @@ impl Channel {
|
||||||
let funding_script = self.get_funding_redeemscript();
|
let funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
||||||
let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false).0;
|
let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
|
||||||
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
||||||
|
|
||||||
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
|
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
|
||||||
secp_call!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer", self.channel_id());
|
secp_call!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer", self.channel_id());
|
||||||
|
|
||||||
let remote_keys = self.build_remote_transaction_keys()?;
|
let remote_keys = self.build_remote_transaction_keys()?;
|
||||||
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false).0;
|
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
|
||||||
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
||||||
|
|
||||||
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
|
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
|
||||||
|
@ -1356,7 +1379,7 @@ impl Channel {
|
||||||
let funding_script = self.get_funding_redeemscript();
|
let funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
||||||
let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false).0;
|
let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
|
||||||
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
||||||
|
|
||||||
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
|
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
|
||||||
|
@ -1567,7 +1590,14 @@ impl Channel {
|
||||||
let funding_script = self.get_funding_redeemscript();
|
let funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
||||||
let mut local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false);
|
|
||||||
|
let feerate_per_kw = if !self.channel_outbound && self.pending_update_fee.is_some() {
|
||||||
|
self.pending_update_fee.unwrap()
|
||||||
|
} else {
|
||||||
|
self.feerate_per_kw
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, feerate_per_kw);
|
||||||
let local_commitment_txid = local_commitment_tx.0.txid();
|
let local_commitment_txid = local_commitment_tx.0.txid();
|
||||||
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
||||||
secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer", self.channel_id());
|
secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "Invalid commitment tx signature from peer", self.channel_id());
|
||||||
|
@ -1582,7 +1612,7 @@ impl Channel {
|
||||||
|
|
||||||
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len());
|
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len());
|
||||||
for (idx, ref htlc) in local_commitment_tx.1.iter().enumerate() {
|
for (idx, ref htlc) in local_commitment_tx.1.iter().enumerate() {
|
||||||
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, htlc, true, &local_keys);
|
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, htlc, true, &local_keys, feerate_per_kw);
|
||||||
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
|
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
|
||||||
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
|
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
|
||||||
secp_call!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx siganture from peer", self.channel_id());
|
secp_call!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx siganture from peer", self.channel_id());
|
||||||
|
@ -1600,9 +1630,22 @@ impl Channel {
|
||||||
let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 1);
|
let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 1);
|
||||||
|
|
||||||
// Update state now that we've passed all the can-fail calls...
|
// Update state now that we've passed all the can-fail calls...
|
||||||
|
let mut need_our_commitment = false;
|
||||||
|
if !self.channel_outbound {
|
||||||
|
if let Some(fee_update) = self.pending_update_fee {
|
||||||
|
self.feerate_per_kw = fee_update;
|
||||||
|
// We later use the presence of pending_update_fee to indicate we should generate a
|
||||||
|
// commitment_signed upon receipt of revoke_and_ack, so we can only set it to None
|
||||||
|
// if we're not awaiting a revoke (ie will send a commitment_signed now).
|
||||||
|
if (self.channel_state & ChannelState::AwaitingRemoteRevoke as u32) == 0 {
|
||||||
|
need_our_commitment = true;
|
||||||
|
self.pending_update_fee = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs);
|
self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs);
|
||||||
|
|
||||||
let mut need_our_commitment = false;
|
|
||||||
for htlc in self.pending_inbound_htlcs.iter_mut() {
|
for htlc in self.pending_inbound_htlcs.iter_mut() {
|
||||||
if htlc.state == InboundHTLCState::RemoteAnnounced {
|
if htlc.state == InboundHTLCState::RemoteAnnounced {
|
||||||
htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce;
|
htlc.state = InboundHTLCState::AwaitingRemoteRevokeToAnnounce;
|
||||||
|
@ -1637,7 +1680,7 @@ impl Channel {
|
||||||
/// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them
|
/// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them
|
||||||
/// fulfilling or failing the last pending HTLC)
|
/// fulfilling or failing the last pending HTLC)
|
||||||
fn free_holding_cell_htlcs(&mut self) -> Result<Option<(msgs::CommitmentUpdate, ChannelMonitor)>, HandleError> {
|
fn free_holding_cell_htlcs(&mut self) -> Result<Option<(msgs::CommitmentUpdate, ChannelMonitor)>, HandleError> {
|
||||||
if self.holding_cell_htlc_updates.len() != 0 {
|
if self.holding_cell_htlc_updates.len() != 0 || self.holding_cell_update_fee.is_some() {
|
||||||
let mut htlc_updates = Vec::new();
|
let mut htlc_updates = Vec::new();
|
||||||
mem::swap(&mut htlc_updates, &mut self.holding_cell_htlc_updates);
|
mem::swap(&mut htlc_updates, &mut self.holding_cell_htlc_updates);
|
||||||
let mut update_add_htlcs = Vec::with_capacity(htlc_updates.len());
|
let mut update_add_htlcs = Vec::with_capacity(htlc_updates.len());
|
||||||
|
@ -1694,18 +1737,28 @@ impl Channel {
|
||||||
//fail it back the route, if its a temporary issue we can ignore it...
|
//fail it back the route, if its a temporary issue we can ignore it...
|
||||||
match err {
|
match err {
|
||||||
None => {
|
None => {
|
||||||
if update_add_htlcs.is_empty() && update_fulfill_htlcs.is_empty() && update_fail_htlcs.is_empty() {
|
if update_add_htlcs.is_empty() && update_fulfill_htlcs.is_empty() && update_fail_htlcs.is_empty() && self.holding_cell_update_fee.is_none() {
|
||||||
// This should never actually happen and indicates we got some Errs back
|
// This should never actually happen and indicates we got some Errs back
|
||||||
// from update_fulfill_htlc/update_fail_htlc, but we handle it anyway in
|
// from update_fulfill_htlc/update_fail_htlc, but we handle it anyway in
|
||||||
// case there is some strange way to hit duplicate HTLC removes.
|
// case there is some strange way to hit duplicate HTLC removes.
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
let update_fee = if let Some(feerate) = self.holding_cell_update_fee {
|
||||||
|
self.pending_update_fee = self.holding_cell_update_fee.take();
|
||||||
|
Some(msgs::UpdateFee {
|
||||||
|
channel_id: self.channel_id,
|
||||||
|
feerate_per_kw: feerate as u32,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
|
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
|
||||||
Ok(Some((msgs::CommitmentUpdate {
|
Ok(Some((msgs::CommitmentUpdate {
|
||||||
update_add_htlcs,
|
update_add_htlcs,
|
||||||
update_fulfill_htlcs,
|
update_fulfill_htlcs,
|
||||||
update_fail_htlcs,
|
update_fail_htlcs,
|
||||||
update_fail_malformed_htlcs: Vec::new(),
|
update_fail_malformed_htlcs: Vec::new(),
|
||||||
|
update_fee: update_fee,
|
||||||
commitment_signed,
|
commitment_signed,
|
||||||
}, monitor_update)))
|
}, monitor_update)))
|
||||||
},
|
},
|
||||||
|
@ -1801,6 +1854,24 @@ impl Channel {
|
||||||
}
|
}
|
||||||
self.value_to_self_msat = (self.value_to_self_msat as i64 + value_to_self_msat_diff) as u64;
|
self.value_to_self_msat = (self.value_to_self_msat as i64 + value_to_self_msat_diff) as u64;
|
||||||
|
|
||||||
|
if self.channel_outbound {
|
||||||
|
if let Some(feerate) = self.pending_update_fee.take() {
|
||||||
|
self.feerate_per_kw = feerate;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let Some(feerate) = self.pending_update_fee {
|
||||||
|
// Because a node cannot send two commitment_signed's in a row without getting a
|
||||||
|
// revoke_and_ack from us (as it would otherwise not know the per_commitment_point
|
||||||
|
// it should use to create keys with) and because a node can't send a
|
||||||
|
// commitment_signed without changes, checking if the feerate is equal to the
|
||||||
|
// pending feerate update is sufficient to detect require_commitment.
|
||||||
|
if feerate == self.feerate_per_kw {
|
||||||
|
require_commitment = true;
|
||||||
|
self.pending_update_fee = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match self.free_holding_cell_htlcs()? {
|
match self.free_holding_cell_htlcs()? {
|
||||||
Some(mut commitment_update) => {
|
Some(mut commitment_update) => {
|
||||||
commitment_update.0.update_fail_htlcs.reserve(update_fail_htlcs.len());
|
commitment_update.0.update_fail_htlcs.reserve(update_fail_htlcs.len());
|
||||||
|
@ -1821,6 +1892,7 @@ impl Channel {
|
||||||
update_fulfill_htlcs: Vec::new(),
|
update_fulfill_htlcs: Vec::new(),
|
||||||
update_fail_htlcs,
|
update_fail_htlcs,
|
||||||
update_fail_malformed_htlcs,
|
update_fail_malformed_htlcs,
|
||||||
|
update_fee: None,
|
||||||
commitment_signed
|
commitment_signed
|
||||||
}), to_forward_infos, revoked_htlcs, monitor_update))
|
}), to_forward_infos, revoked_htlcs, monitor_update))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1828,6 +1900,43 @@ impl Channel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a pending update to this channel. See the doc for send_htlc for
|
||||||
|
/// further details on the optionness of the return value.
|
||||||
|
/// You MUST call send_commitment prior to any other calls on this Channel
|
||||||
|
fn send_update_fee(&mut self, feerate_per_kw: u64) -> Option<msgs::UpdateFee> {
|
||||||
|
if !self.channel_outbound {
|
||||||
|
panic!("Cannot send fee from inbound channel");
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.is_usable() {
|
||||||
|
panic!("Cannot update fee until channel is fully established and we haven't started shutting down");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
|
||||||
|
self.holding_cell_update_fee = Some(feerate_per_kw);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert!(self.pending_update_fee.is_none());
|
||||||
|
self.pending_update_fee = Some(feerate_per_kw);
|
||||||
|
|
||||||
|
Some(msgs::UpdateFee {
|
||||||
|
channel_id: self.channel_id,
|
||||||
|
feerate_per_kw: feerate_per_kw as u32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_update_fee_and_commit(&mut self, feerate_per_kw: u64) -> Result<Option<(msgs::UpdateFee, msgs::CommitmentSigned, ChannelMonitor)>, HandleError> {
|
||||||
|
match self.send_update_fee(feerate_per_kw) {
|
||||||
|
Some(update_fee) => {
|
||||||
|
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
|
||||||
|
Ok(Some((update_fee, commitment_signed, monitor_update)))
|
||||||
|
},
|
||||||
|
None => Ok(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes any uncommitted HTLCs, to be used on peer disconnection, including any pending
|
/// Removes any uncommitted HTLCs, to be used on peer disconnection, including any pending
|
||||||
|
@ -1904,8 +2013,9 @@ impl Channel {
|
||||||
return Err(HandleError{err: "Peer sent update_fee when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fee when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
|
return Err(HandleError{err: "Peer sent update_fee when we needed a channel_reestablish", action: Some(msgs::ErrorAction::SendErrorMessage{msg: msgs::ErrorMessage{data: "Peer sent update_fee when we needed a channel_reestablish".to_string(), channel_id: msg.channel_id}})});
|
||||||
}
|
}
|
||||||
Channel::check_remote_fee(fee_estimator, msg.feerate_per_kw)?;
|
Channel::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.channel_update_count += 1;
|
||||||
self.feerate_per_kw = msg.feerate_per_kw as u64;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1981,6 +2091,7 @@ impl Channel {
|
||||||
update_fulfill_htlcs: Vec::new(),
|
update_fulfill_htlcs: Vec::new(),
|
||||||
update_fail_htlcs: Vec::new(),
|
update_fail_htlcs: Vec::new(),
|
||||||
update_fail_malformed_htlcs: Vec::new(),
|
update_fail_malformed_htlcs: Vec::new(),
|
||||||
|
update_fee: None,
|
||||||
commitment_signed: self.send_commitment_no_state_update().expect("It looks like we failed to re-generate a commitment_signed we had previously sent?").0,
|
commitment_signed: self.send_commitment_no_state_update().expect("It looks like we failed to re-generate a commitment_signed we had previously sent?").0,
|
||||||
}), None));
|
}), None));
|
||||||
} else {
|
} else {
|
||||||
|
@ -2230,6 +2341,11 @@ impl Channel {
|
||||||
self.channel_value_satoshis
|
self.channel_value_satoshis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub fn get_feerate(&self) -> u64 {
|
||||||
|
self.feerate_per_kw
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Testing purpose only, should be changed in another way after #81
|
//TODO: Testing purpose only, should be changed in another way after #81
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn get_local_keys(&self) -> &ChannelKeys {
|
pub fn get_local_keys(&self) -> &ChannelKeys {
|
||||||
|
@ -2245,6 +2361,10 @@ impl Channel {
|
||||||
self.announce_publicly
|
self.announce_publicly
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_outbound(&self) -> bool {
|
||||||
|
self.channel_outbound
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the fee we'd want to charge for adding an HTLC output to this Channel
|
/// Gets the fee we'd want to charge for adding an HTLC output to this Channel
|
||||||
/// Allowed in any state (including after shutdown)
|
/// 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(&self, fee_estimator: &FeeEstimator) -> u32 {
|
||||||
|
@ -2469,7 +2589,7 @@ impl Channel {
|
||||||
let funding_script = self.get_funding_redeemscript();
|
let funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
let remote_keys = self.build_remote_transaction_keys()?;
|
let remote_keys = self.build_remote_transaction_keys()?;
|
||||||
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false).0;
|
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
|
||||||
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
||||||
|
|
||||||
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
|
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
|
||||||
|
@ -2672,7 +2792,7 @@ impl Channel {
|
||||||
if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) {
|
if (self.channel_state & (ChannelState::PeerDisconnected as u32)) == (ChannelState::PeerDisconnected as u32) {
|
||||||
panic!("Cannot create commitment tx while disconnected, as send_htlc will have returned an Err so a send_commitment precondition has been violated");
|
panic!("Cannot create commitment tx while disconnected, as send_htlc will have returned an Err so a send_commitment precondition has been violated");
|
||||||
}
|
}
|
||||||
let mut have_updates = false; // TODO initialize with "have we sent a fee update?"
|
let mut have_updates = self.pending_update_fee.is_some();
|
||||||
for htlc in self.pending_outbound_htlcs.iter() {
|
for htlc in self.pending_outbound_htlcs.iter() {
|
||||||
if htlc.state == OutboundHTLCState::LocalAnnounced {
|
if htlc.state == OutboundHTLCState::LocalAnnounced {
|
||||||
have_updates = true;
|
have_updates = true;
|
||||||
|
@ -2716,8 +2836,15 @@ impl Channel {
|
||||||
fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<HTLCOutputInCommitment>)), HandleError> {
|
fn send_commitment_no_state_update(&self) -> Result<(msgs::CommitmentSigned, (Transaction, Vec<HTLCOutputInCommitment>)), HandleError> {
|
||||||
let funding_script = self.get_funding_redeemscript();
|
let funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
|
let mut feerate_per_kw = self.feerate_per_kw;
|
||||||
|
if let Some(feerate) = self.pending_update_fee {
|
||||||
|
if self.channel_outbound {
|
||||||
|
feerate_per_kw = feerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let remote_keys = self.build_remote_transaction_keys()?;
|
let remote_keys = self.build_remote_transaction_keys()?;
|
||||||
let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true);
|
let remote_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, true, feerate_per_kw);
|
||||||
let remote_commitment_txid = remote_commitment_tx.0.txid();
|
let remote_commitment_txid = remote_commitment_tx.0.txid();
|
||||||
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_commitment_tx.0).sighash_all(&remote_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
|
||||||
let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key);
|
let our_sig = self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key);
|
||||||
|
@ -2725,7 +2852,7 @@ impl Channel {
|
||||||
let mut htlc_sigs = Vec::new();
|
let mut htlc_sigs = Vec::new();
|
||||||
|
|
||||||
for ref htlc in remote_commitment_tx.1.iter() {
|
for ref htlc in remote_commitment_tx.1.iter() {
|
||||||
let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys);
|
let htlc_tx = self.build_htlc_transaction(&remote_commitment_txid, htlc, false, &remote_keys, feerate_per_kw);
|
||||||
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
|
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &remote_keys);
|
||||||
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
|
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
|
||||||
let our_htlc_key = secp_derived_key!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), self.channel_id());
|
let our_htlc_key = secp_derived_key!(chan_utils::derive_private_key(&self.secp_ctx, &remote_keys.per_commitment_point, &self.local_keys.htlc_base_key), self.channel_id());
|
||||||
|
@ -2927,7 +3054,7 @@ mod tests {
|
||||||
|
|
||||||
macro_rules! test_commitment {
|
macro_rules! test_commitment {
|
||||||
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
|
( $their_sig_hex: expr, $our_sig_hex: expr, $tx_hex: expr) => {
|
||||||
unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false);
|
unsigned_tx = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, chan.feerate_per_kw);
|
||||||
let their_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap();
|
let their_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap();
|
||||||
let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();
|
let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();
|
||||||
secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap();
|
secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap();
|
||||||
|
@ -2944,7 +3071,7 @@ mod tests {
|
||||||
let remote_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap();
|
let remote_signature = Signature::from_der(&secp_ctx, &hex::decode($their_sig_hex).unwrap()[..]).unwrap();
|
||||||
|
|
||||||
let ref htlc = unsigned_tx.1[$htlc_idx];
|
let ref htlc = unsigned_tx.1[$htlc_idx];
|
||||||
let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys);
|
let mut htlc_tx = chan.build_htlc_transaction(&unsigned_tx.0.txid(), &htlc, true, &keys, chan.feerate_per_kw);
|
||||||
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
|
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
|
||||||
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
|
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
|
||||||
secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap();
|
secp_ctx.verify(&htlc_sighash, &remote_signature, &keys.b_htlc_key).unwrap();
|
||||||
|
|
|
@ -1046,6 +1046,7 @@ impl ChannelManager {
|
||||||
update_fulfill_htlcs: Vec::new(),
|
update_fulfill_htlcs: Vec::new(),
|
||||||
update_fail_htlcs: Vec::new(),
|
update_fail_htlcs: Vec::new(),
|
||||||
update_fail_malformed_htlcs: Vec::new(),
|
update_fail_malformed_htlcs: Vec::new(),
|
||||||
|
update_fee: None,
|
||||||
commitment_signed,
|
commitment_signed,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1212,6 +1213,7 @@ impl ChannelManager {
|
||||||
update_fulfill_htlcs: Vec::new(),
|
update_fulfill_htlcs: Vec::new(),
|
||||||
update_fail_htlcs: Vec::new(),
|
update_fail_htlcs: Vec::new(),
|
||||||
update_fail_malformed_htlcs: Vec::new(),
|
update_fail_malformed_htlcs: Vec::new(),
|
||||||
|
update_fee: None,
|
||||||
commitment_signed: commitment_msg,
|
commitment_signed: commitment_msg,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
@ -1333,6 +1335,7 @@ impl ChannelManager {
|
||||||
update_fulfill_htlcs: Vec::new(),
|
update_fulfill_htlcs: Vec::new(),
|
||||||
update_fail_htlcs: vec![msg],
|
update_fail_htlcs: vec![msg],
|
||||||
update_fail_malformed_htlcs: Vec::new(),
|
update_fail_malformed_htlcs: Vec::new(),
|
||||||
|
update_fee: None,
|
||||||
commitment_signed: commitment_msg,
|
commitment_signed: commitment_msg,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -1414,6 +1417,7 @@ impl ChannelManager {
|
||||||
update_fulfill_htlcs: vec![msg],
|
update_fulfill_htlcs: vec![msg],
|
||||||
update_fail_htlcs: Vec::new(),
|
update_fail_htlcs: Vec::new(),
|
||||||
update_fail_malformed_htlcs: Vec::new(),
|
update_fail_malformed_htlcs: Vec::new(),
|
||||||
|
update_fee: None,
|
||||||
commitment_signed: commitment_msg,
|
commitment_signed: commitment_msg,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2682,10 +2686,11 @@ mod tests {
|
||||||
impl SendEvent {
|
impl SendEvent {
|
||||||
fn from_event(event: Event) -> SendEvent {
|
fn from_event(event: Event) -> SendEvent {
|
||||||
match event {
|
match event {
|
||||||
Event::UpdateHTLCs { node_id, updates: msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, commitment_signed } } => {
|
Event::UpdateHTLCs { node_id, updates: msgs::CommitmentUpdate { update_add_htlcs, update_fulfill_htlcs, update_fail_htlcs, update_fail_malformed_htlcs, update_fee, commitment_signed } } => {
|
||||||
assert!(update_fulfill_htlcs.is_empty());
|
assert!(update_fulfill_htlcs.is_empty());
|
||||||
assert!(update_fail_htlcs.is_empty());
|
assert!(update_fail_htlcs.is_empty());
|
||||||
assert!(update_fail_malformed_htlcs.is_empty());
|
assert!(update_fail_malformed_htlcs.is_empty());
|
||||||
|
assert!(update_fee.is_none());
|
||||||
SendEvent { node_id: node_id, msgs: update_add_htlcs, commitment_msg: commitment_signed }
|
SendEvent { node_id: node_id, msgs: update_add_htlcs, commitment_msg: commitment_signed }
|
||||||
},
|
},
|
||||||
_ => panic!("Unexpected event type!"),
|
_ => panic!("Unexpected event type!"),
|
||||||
|
@ -2830,11 +2835,12 @@ mod tests {
|
||||||
if !skip_last || idx != expected_route.len() - 1 {
|
if !skip_last || idx != expected_route.len() - 1 {
|
||||||
assert_eq!(events.len(), 1);
|
assert_eq!(events.len(), 1);
|
||||||
match events[0] {
|
match events[0] {
|
||||||
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed } } => {
|
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
|
||||||
assert!(update_add_htlcs.is_empty());
|
assert!(update_add_htlcs.is_empty());
|
||||||
assert_eq!(update_fulfill_htlcs.len(), 1);
|
assert_eq!(update_fulfill_htlcs.len(), 1);
|
||||||
assert!(update_fail_htlcs.is_empty());
|
assert!(update_fail_htlcs.is_empty());
|
||||||
assert!(update_fail_malformed_htlcs.is_empty());
|
assert!(update_fail_malformed_htlcs.is_empty());
|
||||||
|
assert!(update_fee.is_none());
|
||||||
expected_next_node = node_id.clone();
|
expected_next_node = node_id.clone();
|
||||||
next_msgs = Some((update_fulfill_htlcs[0].clone(), commitment_signed.clone()));
|
next_msgs = Some((update_fulfill_htlcs[0].clone(), commitment_signed.clone()));
|
||||||
},
|
},
|
||||||
|
@ -2929,11 +2935,12 @@ mod tests {
|
||||||
if !skip_last || idx != expected_route.len() - 1 {
|
if !skip_last || idx != expected_route.len() - 1 {
|
||||||
assert_eq!(events.len(), 1);
|
assert_eq!(events.len(), 1);
|
||||||
match events[0] {
|
match events[0] {
|
||||||
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed } } => {
|
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
|
||||||
assert!(update_add_htlcs.is_empty());
|
assert!(update_add_htlcs.is_empty());
|
||||||
assert!(update_fulfill_htlcs.is_empty());
|
assert!(update_fulfill_htlcs.is_empty());
|
||||||
assert_eq!(update_fail_htlcs.len(), 1);
|
assert_eq!(update_fail_htlcs.len(), 1);
|
||||||
assert!(update_fail_malformed_htlcs.is_empty());
|
assert!(update_fail_malformed_htlcs.is_empty());
|
||||||
|
assert!(update_fee.is_none());
|
||||||
expected_next_node = node_id.clone();
|
expected_next_node = node_id.clone();
|
||||||
next_msgs = Some((update_fail_htlcs[0].clone(), commitment_signed.clone()));
|
next_msgs = Some((update_fail_htlcs[0].clone(), commitment_signed.clone()));
|
||||||
},
|
},
|
||||||
|
|
|
@ -467,6 +467,7 @@ pub struct CommitmentUpdate {
|
||||||
pub(crate) update_fulfill_htlcs: Vec<UpdateFulfillHTLC>,
|
pub(crate) update_fulfill_htlcs: Vec<UpdateFulfillHTLC>,
|
||||||
pub(crate) update_fail_htlcs: Vec<UpdateFailHTLC>,
|
pub(crate) update_fail_htlcs: Vec<UpdateFailHTLC>,
|
||||||
pub(crate) update_fail_malformed_htlcs: Vec<UpdateFailMalformedHTLC>,
|
pub(crate) update_fail_malformed_htlcs: Vec<UpdateFailMalformedHTLC>,
|
||||||
|
pub(crate) update_fee: Option<UpdateFee>,
|
||||||
pub(crate) commitment_signed: CommitmentSigned,
|
pub(crate) commitment_signed: CommitmentSigned,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -647,6 +647,9 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
||||||
for resp in resps.update_fail_htlcs {
|
for resp in resps.update_fail_htlcs {
|
||||||
encode_and_send_msg!(resp, 131);
|
encode_and_send_msg!(resp, 131);
|
||||||
}
|
}
|
||||||
|
if let Some(resp) = resps.update_fee {
|
||||||
|
encode_and_send_msg!(resp, 134);
|
||||||
|
}
|
||||||
encode_and_send_msg!(resps.commitment_signed, 132);
|
encode_and_send_msg!(resps.commitment_signed, 132);
|
||||||
},
|
},
|
||||||
None => {},
|
None => {},
|
||||||
|
@ -676,6 +679,9 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
||||||
for resp in resps.update_fail_htlcs {
|
for resp in resps.update_fail_htlcs {
|
||||||
encode_and_send_msg!(resp, 131);
|
encode_and_send_msg!(resp, 131);
|
||||||
}
|
}
|
||||||
|
if let Some(resp) = resps.update_fee {
|
||||||
|
encode_and_send_msg!(resp, 134);
|
||||||
|
}
|
||||||
encode_and_send_msg!(resps.commitment_signed, 132);
|
encode_and_send_msg!(resps.commitment_signed, 132);
|
||||||
},
|
},
|
||||||
None => {},
|
None => {},
|
||||||
|
@ -820,7 +826,7 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
||||||
Self::do_attempt_write_data(&mut descriptor, peer);
|
Self::do_attempt_write_data(&mut descriptor, peer);
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref commitment_signed } } => {
|
Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fulfill_htlcs, ref update_fail_htlcs, ref update_fail_malformed_htlcs, ref update_fee, ref commitment_signed } } => {
|
||||||
log_trace!(self, "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails for channel {}",
|
log_trace!(self, "Handling UpdateHTLCs event in peer_handler for node {} with {} adds, {} fulfills, {} fails for channel {}",
|
||||||
log_pubkey!(node_id),
|
log_pubkey!(node_id),
|
||||||
update_add_htlcs.len(),
|
update_add_htlcs.len(),
|
||||||
|
@ -842,6 +848,9 @@ impl<Descriptor: SocketDescriptor> PeerManager<Descriptor> {
|
||||||
for msg in update_fail_malformed_htlcs {
|
for msg in update_fail_malformed_htlcs {
|
||||||
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 135)));
|
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 135)));
|
||||||
}
|
}
|
||||||
|
if let &Some(ref msg) = update_fee {
|
||||||
|
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(msg, 134)));
|
||||||
|
}
|
||||||
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(commitment_signed, 132)));
|
peer.pending_outbound_buffer.push_back(peer.channel_encryptor.encrypt_message(&encode_msg!(commitment_signed, 132)));
|
||||||
Self::do_attempt_write_data(&mut descriptor, peer);
|
Self::do_attempt_write_data(&mut descriptor, peer);
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Reference in a new issue