use crate::chain::{BestBlock, WatchedOutput};
use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator};
use crate::chain::transaction::{OutPoint, TransactionData};
-use crate::chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, SignerProvider, EntropySource};
+use crate::chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, WriteableEcdsaChannelSigner, SignerProvider, EntropySource};
#[cfg(anchors)]
use crate::chain::onchaintx::ClaimEvent;
use crate::chain::onchaintx::OnchainTxHandler;
use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput};
use crate::chain::Filter;
use crate::util::logger::Logger;
-use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48, OptionDeserWrapper};
+use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48};
use crate::util::byte_utils;
use crate::util::events::Event;
#[cfg(anchors)]
use crate::io::{self, Error};
use core::convert::TryInto;
use core::ops::Deref;
-use crate::sync::Mutex;
+use crate::sync::{Mutex, LockTestExt};
/// An update generated by the underlying channel itself which contains some new information the
/// [`ChannelMonitor`] should be made aware of.
}
}
- let mut counterparty_delayed_payment_base_key = OptionDeserWrapper(None);
- let mut counterparty_htlc_base_key = OptionDeserWrapper(None);
+ let mut counterparty_delayed_payment_base_key = RequiredWrapper(None);
+ let mut counterparty_htlc_base_key = RequiredWrapper(None);
let mut on_counterparty_tx_csv: u16 = 0;
read_tlv_fields!(r, {
(0, counterparty_delayed_payment_base_key, required),
let mut transaction = None;
let mut block_hash = None;
let mut height = 0;
- let mut event = None;
+ let mut event = UpgradableRequired(None);
read_tlv_fields!(reader, {
(0, txid, required),
(1, transaction, option),
(2, height, required),
(3, block_hash, option),
- (4, event, ignorable),
+ (4, event, upgradable_required),
});
- if let Some(ev) = event {
- Ok(Some(Self { txid, transaction, height, block_hash, event: ev }))
- } else {
- Ok(None)
- }
+ Ok(Some(Self { txid, transaction, height, block_hash, event: _init_tlv_based_struct_field!(event, upgradable_required) }))
}
}
/// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the
/// returned block hash and the the current chain and then reconnecting blocks to get to the
/// best chain) upon deserializing the object!
-pub struct ChannelMonitor<Signer: Sign> {
+pub struct ChannelMonitor<Signer: WriteableEcdsaChannelSigner> {
#[cfg(test)]
pub(crate) inner: Mutex<ChannelMonitorImpl<Signer>>,
#[cfg(not(test))]
inner: Mutex<ChannelMonitorImpl<Signer>>,
}
-pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
+#[derive(PartialEq)]
+pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
latest_update_id: u64,
commitment_transaction_number_obscure_factor: u64,
/// The node_id of our counterparty
counterparty_node_id: Option<PublicKey>,
-
- secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
}
/// Transaction outputs to watch for on-chain spends.
pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>);
-#[cfg(any(test, fuzzing, feature = "_test_utils"))]
-/// Used only in testing and fuzzing to check serialization roundtrips don't change the underlying
-/// object
-impl<Signer: Sign> PartialEq for ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> PartialEq for ChannelMonitor<Signer> where Signer: PartialEq {
fn eq(&self, other: &Self) -> bool {
- let inner = self.inner.lock().unwrap();
- let other = other.inner.lock().unwrap();
- inner.eq(&other)
+ // We need some kind of total lockorder. Absent a better idea, we sort by position in
+ // memory and take locks in that order (assuming that we can't move within memory while a
+ // lock is held).
+ let ord = ((self as *const _) as usize) < ((other as *const _) as usize);
+ let a = if ord { self.inner.unsafe_well_ordered_double_lock_self() } else { other.inner.unsafe_well_ordered_double_lock_self() };
+ let b = if ord { other.inner.unsafe_well_ordered_double_lock_self() } else { self.inner.unsafe_well_ordered_double_lock_self() };
+ a.eq(&b)
}
}
-#[cfg(any(test, fuzzing, feature = "_test_utils"))]
-/// Used only in testing and fuzzing to check serialization roundtrips don't change the underlying
-/// object
-impl<Signer: Sign> PartialEq for ChannelMonitorImpl<Signer> {
- fn eq(&self, other: &Self) -> bool {
- if self.latest_update_id != other.latest_update_id ||
- self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor ||
- self.destination_script != other.destination_script ||
- self.broadcasted_holder_revokable_script != other.broadcasted_holder_revokable_script ||
- self.counterparty_payment_script != other.counterparty_payment_script ||
- self.channel_keys_id != other.channel_keys_id ||
- self.holder_revocation_basepoint != other.holder_revocation_basepoint ||
- self.funding_info != other.funding_info ||
- self.current_counterparty_commitment_txid != other.current_counterparty_commitment_txid ||
- self.prev_counterparty_commitment_txid != other.prev_counterparty_commitment_txid ||
- self.counterparty_commitment_params != other.counterparty_commitment_params ||
- self.funding_redeemscript != other.funding_redeemscript ||
- self.channel_value_satoshis != other.channel_value_satoshis ||
- self.their_cur_per_commitment_points != other.their_cur_per_commitment_points ||
- self.on_holder_tx_csv != other.on_holder_tx_csv ||
- self.commitment_secrets != other.commitment_secrets ||
- self.counterparty_claimable_outpoints != other.counterparty_claimable_outpoints ||
- self.counterparty_commitment_txn_on_chain != other.counterparty_commitment_txn_on_chain ||
- self.counterparty_hash_commitment_number != other.counterparty_hash_commitment_number ||
- self.prev_holder_signed_commitment_tx != other.prev_holder_signed_commitment_tx ||
- self.current_counterparty_commitment_number != other.current_counterparty_commitment_number ||
- self.current_holder_commitment_number != other.current_holder_commitment_number ||
- self.current_holder_commitment_tx != other.current_holder_commitment_tx ||
- self.payment_preimages != other.payment_preimages ||
- self.pending_monitor_events != other.pending_monitor_events ||
- self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly
- self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf ||
- self.outputs_to_watch != other.outputs_to_watch ||
- self.lockdown_from_offchain != other.lockdown_from_offchain ||
- self.holder_tx_signed != other.holder_tx_signed ||
- self.funding_spend_seen != other.funding_spend_seen ||
- self.funding_spend_confirmed != other.funding_spend_confirmed ||
- self.confirmed_commitment_tx_counterparty_output != other.confirmed_commitment_tx_counterparty_output ||
- self.htlcs_resolved_on_chain != other.htlcs_resolved_on_chain
- {
- false
- } else {
- true
- }
- }
-}
-
-impl<Signer: Sign> Writeable for ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitor<Signer> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
self.inner.lock().unwrap().write(writer)
}
const SERIALIZATION_VERSION: u8 = 1;
const MIN_SERIALIZATION_VERSION: u8 = 1;
-impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signer> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
}
}
-impl<Signer: Sign> ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
/// For lockorder enforcement purposes, we need to have a single site which constructs the
/// `inner` mutex, otherwise cases where we lock two monitors at the same time (eg in our
/// PartialEq implementation) we may decide a lockorder violation has occurred.
let onchain_tx_handler =
OnchainTxHandler::new(destination_script.clone(), keys,
- channel_parameters.clone(), initial_holder_commitment_tx, secp_ctx.clone());
+ channel_parameters.clone(), initial_holder_commitment_tx, secp_ctx);
let mut outputs_to_watch = HashMap::new();
outputs_to_watch.insert(funding_info.0.txid, vec![(funding_info.0.index as u32, funding_info.1.clone())]);
best_block,
counterparty_node_id: Some(counterparty_node_id),
-
- secp_ctx,
})
}
}
}
-impl<Signer: Sign> ChannelMonitorImpl<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
/// Helper for get_claimable_balances which does the work for an individual HTLC, generating up
/// to one `Balance` for the HTLC.
fn get_htlc_balance(&self, htlc: &HTLCOutputInCommitment, holder_commitment: bool,
}
}
-impl<Signer: Sign> ChannelMonitor<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
/// Gets the balances in this channel which are either claimable by us if we were to
/// force-close the channel now or which are claimable on-chain (possibly awaiting
/// confirmation).
vec![Vec::new(), Vec::new(), Vec::new(), Vec::new(), deliberately_bogus_accepted_htlc_witness_program().into()].into()
}
-impl<Signer: Sign> ChannelMonitorImpl<Signer> {
+impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitorImpl<Signer> {
/// 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).
if commitment_number >= self.get_min_seen_secret() {
let secret = self.get_secret(commitment_number).unwrap();
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
- let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
- let revocation_pubkey = chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
- let delayed_key = chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+ let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
+ let revocation_pubkey = chan_utils::derive_public_revocation_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
+ let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx, &PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
if let Some(transaction) = tx {
let revocation_pubkey = chan_utils::derive_public_revocation_key(
- &self.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
- let delayed_key = chan_utils::derive_public_key(&self.secp_ctx,
+ &self.onchain_tx_handler.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint);
+ let delayed_key = chan_utils::derive_public_key(&self.onchain_tx_handler.secp_ctx,
&per_commitment_point,
&self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
let revokeable_p2wsh = chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
Ok(key) => key,
Err(_) => return (Vec::new(), None)
};
- let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
+ let per_commitment_point = PublicKey::from_secret_key(&self.onchain_tx_handler.secp_ctx, &per_commitment_key);
let htlc_txid = tx.txid();
let mut claimable_outpoints = vec![];
}
}
-impl<Signer: Sign, T: Deref, F: Deref, L: Deref> chain::Listen for (ChannelMonitor<Signer>, T, F, L)
+impl<Signer: WriteableEcdsaChannelSigner, T: Deref, F: Deref, L: Deref> chain::Listen for (ChannelMonitor<Signer>, T, F, L)
where
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
}
}
-impl<Signer: Sign, T: Deref, F: Deref, L: Deref> chain::Confirm for (ChannelMonitor<Signer>, T, F, L)
+impl<Signer: WriteableEcdsaChannelSigner, T: Deref, F: Deref, L: Deref> chain::Confirm for (ChannelMonitor<Signer>, T, F, L)
where
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
(13, spendable_txids_confirmed, vec_type),
});
- let mut secp_ctx = Secp256k1::new();
- secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
-
Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl {
latest_update_id,
commitment_transaction_number_obscure_factor,
best_block,
counterparty_node_id,
-
- secp_ctx,
})))
}
}
fn test_prune_preimages() {
let secp_ctx = Secp256k1::new();
let logger = Arc::new(TestLogger::new());
- let broadcaster = Arc::new(TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new()), blocks: Arc::new(Mutex::new(Vec::new()))});
+ let broadcaster = Arc::new(TestBroadcaster {
+ txn_broadcasted: Mutex::new(Vec::new()),
+ blocks: Arc::new(Mutex::new(Vec::new()))
+ });
let fee_estimator = TestFeeEstimator { sat_per_kw: Mutex::new(253) };
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
// Prune with one old state and a holder commitment tx holding a few overlaps with the
// old state.
let shutdown_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
- let best_block = BestBlock::from_genesis(Network::Testnet);
+ let best_block = BestBlock::from_network(Network::Testnet);
let monitor = ChannelMonitor::new(Secp256k1::new(), keys,
Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &Script::new(),
(OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),