}
}
-/// General Err type for ChannelMonitor actions. Generally, this implies that the data provided is
-/// inconsistent with the ChannelMonitor being called. eg for ChannelMonitor::update_monitor this
-/// means you tried to update a monitor for a different channel or the ChannelMonitorUpdate was
-/// corrupted.
-/// Contains a developer-readable error message.
-#[derive(Clone, Debug)]
-pub struct MonitorUpdateError(pub &'static str);
-
/// An event to be processed by the ChannelManager.
#[derive(Clone, PartialEq)]
pub enum MonitorEvent {
}
#[cfg(test)]
- fn provide_secret(&self, idx: u64, secret: [u8; 32]) -> Result<(), MonitorUpdateError> {
+ fn provide_secret(&self, idx: u64, secret: [u8; 32]) -> Result<(), &'static str> {
self.inner.lock().unwrap().provide_secret(idx, secret)
}
#[cfg(test)]
fn provide_latest_holder_commitment_tx(
- &self,
- holder_commitment_tx: HolderCommitmentTransaction,
+ &self, holder_commitment_tx: HolderCommitmentTransaction,
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
- ) -> Result<(), MonitorUpdateError> {
- self.inner.lock().unwrap().provide_latest_holder_commitment_tx(
- holder_commitment_tx, htlc_outputs)
+ ) -> Result<(), ()> {
+ self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs).map_err(|_| ())
}
#[cfg(test)]
broadcaster: &B,
fee_estimator: &F,
logger: &L,
- ) -> Result<(), MonitorUpdateError>
+ ) -> Result<(), ()>
where
B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
/// Inserts a revocation secret into this channel monitor. Prunes old preimages if neither
/// needed by holder commitment transactions HTCLs nor by counterparty ones. Unless we haven't already seen
/// counterparty commitment transaction's secret, they are de facto pruned (we can use revocation key).
- fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), MonitorUpdateError> {
+ fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), &'static str> {
if let Err(()) = self.commitment_secrets.provide_secret(idx, secret) {
- return Err(MonitorUpdateError("Previous secret did not match new one"));
+ return Err("Previous secret did not match new one");
}
// Prune HTLCs from the previous counterparty commitment tx so we don't generate failure/fulfill
/// is important that any clones of this channel monitor (including remote clones) by kept
/// up-to-date as our holder commitment transaction is updated.
/// Panics if set_on_holder_tx_csv has never been called.
- fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
+ fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), &'static str> {
// block for Rust 1.34 compat
let mut new_holder_commitment_tx = {
let trusted_tx = holder_commitment_tx.trust();
mem::swap(&mut new_holder_commitment_tx, &mut self.current_holder_commitment_tx);
self.prev_holder_signed_commitment_tx = Some(new_holder_commitment_tx);
if self.holder_tx_signed {
- return Err(MonitorUpdateError("Latest holder commitment signed has already been signed, update is rejected"));
+ return Err("Latest holder commitment signed has already been signed, update is rejected");
}
Ok(())
}
self.pending_monitor_events.push(MonitorEvent::CommitmentTxConfirmed(self.funding_info.0));
}
- pub fn update_monitor<B: Deref, F: Deref, L: Deref>(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), MonitorUpdateError>
+ pub fn update_monitor<B: Deref, F: Deref, L: Deref>(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), ()>
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
if self.lockdown_from_offchain { panic!(); }
if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone()) {
log_error!(logger, "Providing latest holder commitment transaction failed/was refused:");
- log_error!(logger, " {}", e.0);
- ret = Err(e);
+ log_error!(logger, " {}", e);
+ ret = Err(());
}
}
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_revocation_point } => {
log_trace!(logger, "Updating ChannelMonitor with commitment secret");
if let Err(e) = self.provide_secret(*idx, *secret) {
log_error!(logger, "Providing latest counterparty commitment secret failed/was refused:");
- log_error!(logger, " {}", e.0);
- ret = Err(e);
+ log_error!(logger, " {}", e);
+ ret = Err(());
}
},
ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } => {
self.latest_update_id = updates.update_id;
if ret.is_ok() && self.funding_spend_seen {
- ret = Err(MonitorUpdateError("Counterparty attempted to update commitment after funding was spent"));
- }
- ret
+ log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
+ Err(())
+ } else { ret }
}
pub fn get_latest_update_id(&self) -> u64 {
tx.output[transaction_output_index as usize].value != htlc.amount_msat / 1000 {
return (claimable_outpoints, (commitment_txid, watch_outputs)); // Corrupted per_commitment_data, fuck this user
}
- let revk_htlc_outp = RevokedHTLCOutput::build(per_commitment_point, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, htlc.amount_msat / 1000, htlc.clone());
+ let revk_htlc_outp = RevokedHTLCOutput::build(per_commitment_point, self.counterparty_commitment_params.counterparty_delayed_payment_base_key, self.counterparty_commitment_params.counterparty_htlc_base_key, per_commitment_key, htlc.amount_msat / 1000, htlc.clone(), self.onchain_tx_handler.channel_transaction_parameters.opt_anchors.is_some());
let justice_package = PackageTemplate::build_package(commitment_txid, transaction_output_index, PackageSolvingData::RevokedHTLCOutput(revk_htlc_outp), htlc.cltv_expiry, true, height);
claimable_outpoints.push(justice_package);
}
use ::{check_added_monitors, check_closed_broadcast, check_closed_event, check_spends, get_local_commitment_txn, get_monitor, get_route_and_payment_hash, unwrap_send_err};
use chain::{BestBlock, Confirm};
use chain::channelmonitor::ChannelMonitor;
- use chain::package::{WEIGHT_OFFERED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_RECEIVED_HTLC, WEIGHT_REVOKED_OUTPUT};
+ use chain::package::{weight_offered_htlc, weight_received_htlc, weight_revoked_offered_htlc, weight_revoked_received_htlc, WEIGHT_REVOKED_OUTPUT};
use chain::transaction::OutPoint;
use chain::keysinterface::InMemorySigner;
use ln::{PaymentPreimage, PaymentHash};
SecretKey::from_slice(&[41; 32]).unwrap(),
SecretKey::from_slice(&[41; 32]).unwrap(),
SecretKey::from_slice(&[41; 32]).unwrap(),
+ SecretKey::from_slice(&[41; 32]).unwrap(),
[41; 32],
0,
[0; 32]
let secp_ctx = Secp256k1::new();
let privkey = SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap();
let pubkey = PublicKey::from_secret_key(&secp_ctx, &privkey);
- let mut sum_actual_sigs = 0;
macro_rules! sign_input {
($sighash_parts: expr, $idx: expr, $amount: expr, $weight: expr, $sum_actual_sigs: expr, $opt_anchors: expr) => {
let htlc = HTLCOutputInCommitment {
- offered: if *$weight == WEIGHT_REVOKED_OFFERED_HTLC || *$weight == WEIGHT_OFFERED_HTLC { true } else { false },
+ offered: if *$weight == weight_revoked_offered_htlc($opt_anchors) || *$weight == weight_offered_htlc($opt_anchors) { true } else { false },
amount_msat: 0,
cltv_expiry: 2 << 16,
payment_hash: PaymentHash([1; 32]),
let sig = secp_ctx.sign(&sighash, &privkey);
$sighash_parts.access_witness($idx).push(sig.serialize_der().to_vec());
$sighash_parts.access_witness($idx)[0].push(SigHashType::All as u8);
- sum_actual_sigs += $sighash_parts.access_witness($idx)[0].len();
+ $sum_actual_sigs += $sighash_parts.access_witness($idx)[0].len();
if *$weight == WEIGHT_REVOKED_OUTPUT {
$sighash_parts.access_witness($idx).push(vec!(1));
- } else if *$weight == WEIGHT_REVOKED_OFFERED_HTLC || *$weight == WEIGHT_REVOKED_RECEIVED_HTLC {
+ } else if *$weight == weight_revoked_offered_htlc($opt_anchors) || *$weight == weight_revoked_received_htlc($opt_anchors) {
$sighash_parts.access_witness($idx).push(pubkey.clone().serialize().to_vec());
- } else if *$weight == WEIGHT_RECEIVED_HTLC {
+ } else if *$weight == weight_received_htlc($opt_anchors) {
$sighash_parts.access_witness($idx).push(vec![0]);
} else {
$sighash_parts.access_witness($idx).push(PaymentPreimage([1; 32]).0.to_vec());
let txid = Txid::from_hex("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d").unwrap();
// Justice tx with 1 to_holder, 2 revoked offered HTLCs, 1 revoked received HTLCs
- let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
- for i in 0..4 {
- claim_tx.input.push(TxIn {
- previous_output: BitcoinOutPoint {
- txid,
- vout: i,
- },
- script_sig: Script::new(),
- sequence: 0xfffffffd,
- witness: Vec::new(),
+ for &opt_anchors in [false, true].iter() {
+ let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
+ let mut sum_actual_sigs = 0;
+ for i in 0..4 {
+ claim_tx.input.push(TxIn {
+ previous_output: BitcoinOutPoint {
+ txid,
+ vout: i,
+ },
+ script_sig: Script::new(),
+ sequence: 0xfffffffd,
+ witness: Vec::new(),
+ });
+ }
+ claim_tx.output.push(TxOut {
+ script_pubkey: script_pubkey.clone(),
+ value: 0,
});
- }
- claim_tx.output.push(TxOut {
- script_pubkey: script_pubkey.clone(),
- value: 0,
- });
- let base_weight = claim_tx.get_weight();
- let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_OFFERED_HTLC, WEIGHT_REVOKED_RECEIVED_HTLC];
- let mut inputs_total_weight = 2; // count segwit flags
- {
- let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
- for (idx, inp) in inputs_weight.iter().enumerate() {
- sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, false);
- inputs_total_weight += inp;
+ let base_weight = claim_tx.get_weight();
+ let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT, weight_revoked_offered_htlc(opt_anchors), weight_revoked_offered_htlc(opt_anchors), weight_revoked_received_htlc(opt_anchors)];
+ let mut inputs_total_weight = 2; // count segwit flags
+ {
+ let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
+ for (idx, inp) in inputs_weight.iter().enumerate() {
+ sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, opt_anchors);
+ inputs_total_weight += inp;
+ }
}
+ assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_weight.len() - sum_actual_sigs));
}
- assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_weight.len() - sum_actual_sigs));
// Claim tx with 1 offered HTLCs, 3 received HTLCs
- claim_tx.input.clear();
- sum_actual_sigs = 0;
- for i in 0..4 {
+ for &opt_anchors in [false, true].iter() {
+ let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
+ let mut sum_actual_sigs = 0;
+ for i in 0..4 {
+ claim_tx.input.push(TxIn {
+ previous_output: BitcoinOutPoint {
+ txid,
+ vout: i,
+ },
+ script_sig: Script::new(),
+ sequence: 0xfffffffd,
+ witness: Vec::new(),
+ });
+ }
+ claim_tx.output.push(TxOut {
+ script_pubkey: script_pubkey.clone(),
+ value: 0,
+ });
+ let base_weight = claim_tx.get_weight();
+ let inputs_weight = vec![weight_offered_htlc(opt_anchors), weight_received_htlc(opt_anchors), weight_received_htlc(opt_anchors), weight_received_htlc(opt_anchors)];
+ let mut inputs_total_weight = 2; // count segwit flags
+ {
+ let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
+ for (idx, inp) in inputs_weight.iter().enumerate() {
+ sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, opt_anchors);
+ inputs_total_weight += inp;
+ }
+ }
+ assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_weight.len() - sum_actual_sigs));
+ }
+
+ // Justice tx with 1 revoked HTLC-Success tx output
+ for &opt_anchors in [false, true].iter() {
+ let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
+ let mut sum_actual_sigs = 0;
claim_tx.input.push(TxIn {
previous_output: BitcoinOutPoint {
txid,
- vout: i,
+ vout: 0,
},
script_sig: Script::new(),
sequence: 0xfffffffd,
witness: Vec::new(),
});
- }
- let base_weight = claim_tx.get_weight();
- let inputs_weight = vec![WEIGHT_OFFERED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_RECEIVED_HTLC, WEIGHT_RECEIVED_HTLC];
- let mut inputs_total_weight = 2; // count segwit flags
- {
- let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
- for (idx, inp) in inputs_weight.iter().enumerate() {
- sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, false);
- inputs_total_weight += inp;
- }
- }
- assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_sig */ (73 * inputs_weight.len() - sum_actual_sigs));
-
- // Justice tx with 1 revoked HTLC-Success tx output
- claim_tx.input.clear();
- sum_actual_sigs = 0;
- claim_tx.input.push(TxIn {
- previous_output: BitcoinOutPoint {
- txid,
- vout: 0,
- },
- script_sig: Script::new(),
- sequence: 0xfffffffd,
- witness: Vec::new(),
- });
- let base_weight = claim_tx.get_weight();
- let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT];
- let mut inputs_total_weight = 2; // count segwit flags
- {
- let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
- for (idx, inp) in inputs_weight.iter().enumerate() {
- sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, false);
- inputs_total_weight += inp;
+ claim_tx.output.push(TxOut {
+ script_pubkey: script_pubkey.clone(),
+ value: 0,
+ });
+ let base_weight = claim_tx.get_weight();
+ let inputs_weight = vec![WEIGHT_REVOKED_OUTPUT];
+ let mut inputs_total_weight = 2; // count segwit flags
+ {
+ let mut sighash_parts = bip143::SigHashCache::new(&mut claim_tx);
+ for (idx, inp) in inputs_weight.iter().enumerate() {
+ sign_input!(sighash_parts, idx, 0, inp, sum_actual_sigs, opt_anchors);
+ inputs_total_weight += inp;
+ }
}
+ assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_weight.len() - sum_actual_sigs));
}
- assert_eq!(base_weight + inputs_total_weight as usize, claim_tx.get_weight() + /* max_length_isg */ (73 * inputs_weight.len() - sum_actual_sigs));
}
// Further testing is done in the ChannelManager integration tests.