-impl<R: ::std::io::Read> Readable<R> for ChannelMonitor {
- fn read(reader: &mut R) -> Result<Self, DecodeError> {
- // TODO: read_to_end and then deserializing from that vector is really dumb, we should
- // actually use the fancy serialization framework we have instead of hacking around it.
- let mut datavec = Vec::new();
- reader.read_to_end(&mut datavec)?;
- let data = &datavec;
-
- let mut read_pos = 0;
- macro_rules! read_bytes {
- ($byte_count: expr) => {
- {
- if ($byte_count as usize) > data.len() - read_pos {
- return Err(DecodeError::ShortRead);
+ /// Check if any transaction broadcasted is resolving HTLC output by a success or timeout on a local
+ /// or remote commitment tx, if so send back the source, preimage if found and payment_hash of resolved HTLC
+ fn is_resolving_htlc_output(&mut self, tx: &Transaction) -> Vec<(HTLCSource, Option<PaymentPreimage>, PaymentHash)> {
+ let mut htlc_updated = Vec::new();
+
+ 'outer_loop: for input in &tx.input {
+ let mut payment_data = None;
+ let revocation_sig_claim = (input.witness.len() == 3 && input.witness[2].len() == OFFERED_HTLC_SCRIPT_WEIGHT && input.witness[1].len() == 33)
+ || (input.witness.len() == 3 && input.witness[2].len() == ACCEPTED_HTLC_SCRIPT_WEIGHT && input.witness[1].len() == 33);
+ let accepted_preimage_claim = input.witness.len() == 5 && input.witness[4].len() == ACCEPTED_HTLC_SCRIPT_WEIGHT;
+ let offered_preimage_claim = input.witness.len() == 3 && input.witness[2].len() == OFFERED_HTLC_SCRIPT_WEIGHT;
+
+ macro_rules! log_claim {
+ ($source: expr, $local_tx: expr, $outbound_htlc: expr, $payment_hash: expr, $source_avail: expr) => {
+ // We found the output in question, but aren't failing it backwards
+ // as we have no corresponding source. This implies either it is an
+ // inbound HTLC or an outbound HTLC on a revoked transaction.
+ if ($local_tx && revocation_sig_claim) ||
+ ($outbound_htlc && !$source_avail && (accepted_preimage_claim || offered_preimage_claim)) {
+ log_error!(self, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}!",
+ $source, input.previous_output.txid, input.previous_output.vout, tx.txid(),
+ if $outbound_htlc { "outbound" } else { "inbound" }, log_bytes!($payment_hash.0),
+ if revocation_sig_claim { "revocation sig" } else { "preimage claim after we'd passed the HTLC resolution back" });
+ } else {
+ log_info!(self, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}",
+ $source, input.previous_output.txid, input.previous_output.vout, tx.txid(),
+ if $outbound_htlc { "outbound" } else { "inbound" }, log_bytes!($payment_hash.0),
+ if revocation_sig_claim { "revocation sig" } else if accepted_preimage_claim || offered_preimage_claim { "preimage" } else { "timeout" });
+ }
+ }
+ }
+
+ macro_rules! scan_commitment {
+ ($htlc_outputs: expr, $htlc_sources: expr, $source: expr, $local_tx: expr) => {
+ for &(ref payment_hash, ref source, ref vout) in $htlc_sources.iter() {
+ if &Some(input.previous_output.vout) == vout {
+ log_claim!($source, $local_tx, true, payment_hash, true);
+ // We have a resolution of an HTLC either from one of our latest
+ // local commitment transactions or an unrevoked remote commitment
+ // transaction. This implies we either learned a preimage, the HTLC
+ // has timed out, or we screwed up. In any case, we should now
+ // resolve the source HTLC with the original sender.
+ payment_data = Some((source.clone(), *payment_hash));
+ }
+ }
+ if payment_data.is_none() {
+ for htlc_output in $htlc_outputs {
+ if input.previous_output.vout == htlc_output.transaction_output_index {
+ log_claim!($source, $local_tx, $local_tx == htlc_output.offered, htlc_output.payment_hash, false);
+ continue 'outer_loop;
+ }
+ }