/// do RBF bumping if possible.
pub struct OnchainTxHandler<ChanSigner: ChannelKeys> {
destination_script: Script,
- funding_redeemscript: Script,
local_commitment: Option<LocalCommitmentTransaction>,
prev_local_commitment: Option<LocalCommitmentTransaction>,
local_csv: u16,
impl<ChanSigner: ChannelKeys + Writeable> OnchainTxHandler<ChanSigner> {
pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
self.destination_script.write(writer)?;
- self.funding_redeemscript.write(writer)?;
self.local_commitment.write(writer)?;
self.prev_local_commitment.write(writer)?;
impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for OnchainTxHandler<ChanSigner> {
fn read<R: ::std::io::Read>(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
let destination_script = Readable::read(reader)?;
- let funding_redeemscript = Readable::read(reader)?;
let local_commitment = Readable::read(reader)?;
let prev_local_commitment = Readable::read(reader)?;
Ok(OnchainTxHandler {
destination_script,
- funding_redeemscript,
local_commitment,
prev_local_commitment,
local_csv,
}
impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
- pub(super) fn new(destination_script: Script, keys: ChanSigner, funding_redeemscript: Script, local_csv: u16, logger: Arc<Logger>) -> Self {
+ pub(super) fn new(destination_script: Script, keys: ChanSigner, local_csv: u16, logger: Arc<Logger>) -> Self {
let key_storage = keys;
OnchainTxHandler {
destination_script,
- funding_redeemscript,
local_commitment: None,
prev_local_commitment: None,
local_csv,
return None;
},
&InputMaterial::Funding { ref channel_value } => {
- if let Some(ref mut local_commitment) = self.local_commitment {
- self.key_storage.sign_local_commitment(local_commitment, &self.funding_redeemscript, *channel_value, &self.secp_ctx);
- let signed_tx = local_commitment.with_valid_witness().clone();
- let mut amt_outputs = 0;
- for outp in signed_tx.output.iter() {
- amt_outputs += outp.value;
- }
- let feerate = (channel_value - amt_outputs) * 1000 / signed_tx.get_weight() as u64;
- // Timer set to $NEVER given we can't bump tx without anchor outputs
- log_trace!(self, "Going to broadcast Local Transaction {} claiming funding output {} from {}...", signed_tx.txid(), outp.vout, outp.txid);
- return Some((None, feerate, signed_tx));
+ let signed_tx = self.get_fully_signed_local_tx().unwrap();
+ let mut amt_outputs = 0;
+ for outp in signed_tx.output.iter() {
+ amt_outputs += outp.value;
}
+ let feerate = (channel_value - amt_outputs) * 1000 / signed_tx.get_weight() as u64;
+ // Timer set to $NEVER given we can't bump tx without anchor outputs
+ log_trace!(self, "Going to broadcast Local Transaction {} claiming funding output {} from {}...", signed_tx.txid(), outp.vout, outp.txid);
+ return Some((None, feerate, signed_tx));
}
_ => unreachable!()
}
// Generate claim transactions and track them to bump if necessary at
// height timer expiration (i.e in how many blocks we're going to take action).
- for claim in new_claims {
- let mut claim_material = ClaimTxBumpMaterial { height_timer: None, feerate_previous: 0, soonest_timelock: claim.0, per_input_material: claim.1.clone() };
+ for (soonest_timelock, claim) in new_claims.drain(..) {
+ let mut claim_material = ClaimTxBumpMaterial { height_timer: None, feerate_previous: 0, soonest_timelock, per_input_material: claim };
if let Some((new_timer, new_feerate, tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator) {
claim_material.height_timer = new_timer;
claim_material.feerate_previous = new_feerate;
let txid = tx.txid();
- self.pending_claim_requests.insert(txid, claim_material);
- for k in claim.1.keys() {
+ for k in claim_material.per_input_material.keys() {
log_trace!(self, "Registering claiming request for {}:{}", k.txid, k.vout);
self.claimable_outpoints.insert(k.clone(), (txid, height));
}
+ self.pending_claim_requests.insert(txid, claim_material);
log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
broadcaster.broadcast_transaction(&tx);
}
// Build, bump and rebroadcast tx accordingly
log_trace!(self, "Bumping {} candidates", bump_candidates.len());
- let mut pending_claim_updates = Vec::with_capacity(bump_candidates.len());
for (first_claim_txid, claim_material) in bump_candidates.iter() {
if let Some((new_timer, new_feerate, bump_tx)) = self.generate_claim_tx(height, &claim_material, &*fee_estimator) {
log_trace!(self, "Broadcast onchain {}", log_tx!(bump_tx));
broadcaster.broadcast_transaction(&bump_tx);
- pending_claim_updates.push((*first_claim_txid, new_timer, new_feerate));
- }
- }
- for updates in pending_claim_updates {
- if let Some(claim_material) = self.pending_claim_requests.get_mut(&updates.0) {
- claim_material.height_timer = updates.1;
- claim_material.feerate_previous = updates.2;
+ if let Some(claim_material) = self.pending_claim_requests.get_mut(first_claim_txid) {
+ claim_material.height_timer = new_timer;
+ claim_material.feerate_previous = new_feerate;
+ }
}
}
}
Ok(())
}
- pub(super) fn get_fully_signed_local_tx(&mut self, channel_value_satoshis: u64) -> Option<Transaction> {
+ //TODO: getting lastest local transactions should be infaillible and result in us "force-closing the channel", but we may
+ // have empty local commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created,
+ // before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing
+ // to monitor before.
+ pub(super) fn get_fully_signed_local_tx(&mut self) -> Option<Transaction> {
if let Some(ref mut local_commitment) = self.local_commitment {
- self.key_storage.sign_local_commitment(local_commitment, &self.funding_redeemscript, channel_value_satoshis, &self.secp_ctx);
+ self.key_storage.sign_local_commitment(local_commitment, &self.secp_ctx);
return Some(local_commitment.with_valid_witness().clone());
}
None
}
#[cfg(test)]
- pub(super) fn get_fully_signed_copy_local_tx(&mut self, channel_value_satoshis: u64) -> Option<Transaction> {
+ pub(super) fn get_fully_signed_copy_local_tx(&mut self) -> Option<Transaction> {
if let Some(ref mut local_commitment) = self.local_commitment {
let mut local_commitment = local_commitment.clone();
- self.key_storage.unsafe_sign_local_commitment(&mut local_commitment, &self.funding_redeemscript, channel_value_satoshis, &self.secp_ctx);
+ self.key_storage.unsafe_sign_local_commitment(&mut local_commitment, &self.secp_ctx);
return Some(local_commitment.with_valid_witness().clone());
}
None