+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
//! The logic to monitor for on-chain transactions and create the relevant claim responses lives
//! here.
//!
}
impl_writeable!(HTLCUpdate, 0, { payment_hash, payment_preimage, source });
-/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
-/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
-/// events to it, while also taking any add/update_monitor events and passing them to some remote
-/// server(s).
-///
-/// In general, you must always have at least one local copy in memory, which must never fail to
-/// update (as it is responsible for broadcasting the latest state in case the channel is closed),
-/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails
-/// to update (eg out-of-memory or some other condition), you must immediately shut down without
-/// taking any further action such as writing the current state to disk. This should likely be
-/// accomplished via panic!() or abort().
-///
-/// Note that any updates to a channel's monitor *must* be applied to each instance of the
-/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If
-/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions
-/// which we have revoked, allowing our counterparty to claim all funds in the channel!
-///
-/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or
-/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather
-/// than calling these methods directly, the user should register implementors as listeners to the
-/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
-/// all registered listeners in one go.
-pub trait ManyChannelMonitor<ChanSigner: ChannelKeys>: Send + Sync {
- /// Adds a monitor for the given `funding_txo`.
- ///
- /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
- /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
- /// callbacks with the funding transaction, or any spends of it.
- ///
- /// Further, the implementer must also ensure that each output returned in
- /// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about
- /// any spends of any of the outputs.
- ///
- /// Any spends of outputs which should have been registered which aren't passed to
- /// ChannelMonitors via block_connected may result in FUNDS LOSS.
- fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
-
- /// Updates a monitor for the given `funding_txo`.
- ///
- /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
- /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
- /// callbacks with the funding transaction, or any spends of it.
- ///
- /// Further, the implementer must also ensure that each output returned in
- /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about
- /// any spends of any of the outputs.
- ///
- /// Any spends of outputs which should have been registered which aren't passed to
- /// ChannelMonitors via block_connected may result in FUNDS LOSS.
- fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>;
-
- /// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
- /// with success or failure.
- ///
- /// You should probably just call through to
- /// ChannelMonitor::get_and_clear_pending_htlcs_updated() for each ChannelMonitor and return
- /// the full list.
- fn get_and_clear_pending_htlcs_updated(&self) -> Vec<HTLCUpdate>;
-}
-
/// A simple implementation of a ManyChannelMonitor and ChainListener. Can be used to create a
/// watchtower or watch our own channels.
///
L::Target: Logger,
C::Target: ChainWatchInterface,
{
- fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) {
+ fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[usize]) {
let block_hash = header.bitcoin_hash();
{
let mut monitors = self.monitors.lock().unwrap();
hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
hash_map::Entry::Vacant(e) => e,
};
- log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(monitor.funding_info.0.to_channel_id()[..]));
- self.chain_monitor.install_watch_tx(&monitor.funding_info.0.txid, &monitor.funding_info.1);
- self.chain_monitor.install_watch_outpoint((monitor.funding_info.0.txid, monitor.funding_info.0.index as u32), &monitor.funding_info.1);
- for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
- for (idx, script) in outputs.iter().enumerate() {
- self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
+ {
+ let funding_txo = monitor.get_funding_txo();
+ log_trace!(self.logger, "Got new Channel Monitor for channel {}", log_bytes!(funding_txo.0.to_channel_id()[..]));
+ self.chain_monitor.install_watch_tx(&funding_txo.0.txid, &funding_txo.1);
+ self.chain_monitor.install_watch_outpoint((funding_txo.0.txid, funding_txo.0.index as u32), &funding_txo.1);
+ for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
+ for (idx, script) in outputs.iter().enumerate() {
+ self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
+ }
}
}
entry.insert(monitor);
}
}
-impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F, L, C>
+impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send> ManyChannelMonitor for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
+ type Keys = ChanSigner;
+
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
match self.add_monitor_by_key(funding_txo, monitor) {
Ok(_) => Ok(()),
b_htlc_key: PublicKey,
delayed_payment_key: PublicKey,
per_commitment_point: PublicKey,
- feerate_per_kw: u64,
+ feerate_per_kw: u32,
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
}
-/// Cache remote basepoint to compute any transaction on
-/// remote outputs, either justice or preimage/timeout transactions.
+/// We use this to track remote commitment transactions and htlcs outputs and
+/// use it to generate any justice or 2nd-stage preimage/timeout transactions.
#[derive(PartialEq)]
-struct RemoteTxCache {
+struct RemoteCommitmentTransaction {
remote_delayed_payment_base_key: PublicKey,
remote_htlc_base_key: PublicKey,
on_remote_tx_csv: u16,
per_htlc: HashMap<Txid, Vec<HTLCOutputInCommitment>>
}
+impl Writeable for RemoteCommitmentTransaction {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ self.remote_delayed_payment_base_key.write(w)?;
+ self.remote_htlc_base_key.write(w)?;
+ w.write_all(&byte_utils::be16_to_array(self.on_remote_tx_csv))?;
+ w.write_all(&byte_utils::be64_to_array(self.per_htlc.len() as u64))?;
+ for (ref txid, ref htlcs) in self.per_htlc.iter() {
+ w.write_all(&txid[..])?;
+ w.write_all(&byte_utils::be64_to_array(htlcs.len() as u64))?;
+ for &ref htlc in htlcs.iter() {
+ htlc.write(w)?;
+ }
+ }
+ Ok(())
+ }
+}
+impl Readable for RemoteCommitmentTransaction {
+ fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let remote_commitment_transaction = {
+ let remote_delayed_payment_base_key = Readable::read(r)?;
+ let remote_htlc_base_key = Readable::read(r)?;
+ let on_remote_tx_csv: u16 = Readable::read(r)?;
+ let per_htlc_len: u64 = Readable::read(r)?;
+ let mut per_htlc = HashMap::with_capacity(cmp::min(per_htlc_len as usize, MAX_ALLOC_SIZE / 64));
+ for _ in 0..per_htlc_len {
+ let txid: Txid = Readable::read(r)?;
+ let htlcs_count: u64 = Readable::read(r)?;
+ let mut htlcs = Vec::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / 32));
+ for _ in 0..htlcs_count {
+ let htlc = Readable::read(r)?;
+ htlcs.push(htlc);
+ }
+ if let Some(_) = per_htlc.insert(txid, htlcs) {
+ return Err(DecodeError::InvalidValue);
+ }
+ }
+ RemoteCommitmentTransaction {
+ remote_delayed_payment_base_key,
+ remote_htlc_base_key,
+ on_remote_tx_csv,
+ per_htlc,
+ }
+ };
+ Ok(remote_commitment_transaction)
+ }
+}
+
/// When ChannelMonitor discovers an onchain outpoint being a step of a channel and that it needs
/// to generate a tx to push channel state forward, we cache outpoint-solving tx material to build
/// a new bumped one in case of lenghty confirmation delay
current_remote_commitment_txid: Option<Txid>,
prev_remote_commitment_txid: Option<Txid>,
- remote_tx_cache: RemoteTxCache,
+ remote_tx_cache: RemoteCommitmentTransaction,
funding_redeemscript: Script,
channel_value_satoshis: u64,
// first is the idx of the first of the two revocation points
their_cur_revocation_points: Option<(u64, PublicKey, Option<PublicKey>)>,
- their_to_self_delay: u16,
+ on_local_tx_csv: u16,
commitment_secrets: CounterpartyCommitmentSecrets,
remote_claimable_outpoints: HashMap<Txid, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>,
secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
}
+/// Simple trait indicating ability to track a set of ChannelMonitors and multiplex events between
+/// them. Generally should be implemented by keeping a local SimpleManyChannelMonitor and passing
+/// events to it, while also taking any add/update_monitor events and passing them to some remote
+/// server(s).
+///
+/// In general, you must always have at least one local copy in memory, which must never fail to
+/// update (as it is responsible for broadcasting the latest state in case the channel is closed),
+/// and then persist it to various on-disk locations. If, for some reason, the in-memory copy fails
+/// to update (eg out-of-memory or some other condition), you must immediately shut down without
+/// taking any further action such as writing the current state to disk. This should likely be
+/// accomplished via panic!() or abort().
+///
+/// Note that any updates to a channel's monitor *must* be applied to each instance of the
+/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If
+/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions
+/// which we have revoked, allowing our counterparty to claim all funds in the channel!
+///
+/// User needs to notify implementors of ManyChannelMonitor when a new block is connected or
+/// disconnected using their `block_connected` and `block_disconnected` methods. However, rather
+/// than calling these methods directly, the user should register implementors as listeners to the
+/// BlockNotifier and call the BlockNotifier's `block_(dis)connected` methods, which will notify
+/// all registered listeners in one go.
+pub trait ManyChannelMonitor: Send + Sync {
+ /// The concrete type which signs for transactions and provides access to our channel public
+ /// keys.
+ type Keys: ChannelKeys;
+
+ /// Adds a monitor for the given `funding_txo`.
+ ///
+ /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
+ /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
+ /// callbacks with the funding transaction, or any spends of it.
+ ///
+ /// Further, the implementer must also ensure that each output returned in
+ /// monitor.get_outputs_to_watch() is registered to ensure that the provided monitor learns about
+ /// any spends of any of the outputs.
+ ///
+ /// Any spends of outputs which should have been registered which aren't passed to
+ /// ChannelMonitors via block_connected may result in FUNDS LOSS.
+ fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<Self::Keys>) -> Result<(), ChannelMonitorUpdateErr>;
+
+ /// Updates a monitor for the given `funding_txo`.
+ ///
+ /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
+ /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
+ /// callbacks with the funding transaction, or any spends of it.
+ ///
+ /// Further, the implementer must also ensure that each output returned in
+ /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about
+ /// any spends of any of the outputs.
+ ///
+ /// Any spends of outputs which should have been registered which aren't passed to
+ /// ChannelMonitors via block_connected may result in FUNDS LOSS.
+ fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>;
+
+ /// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
+ /// with success or failure.
+ ///
+ /// You should probably just call through to
+ /// ChannelMonitor::get_and_clear_pending_htlcs_updated() for each ChannelMonitor and return
+ /// the full list.
+ fn get_and_clear_pending_htlcs_updated(&self) -> Vec<HTLCUpdate>;
+}
+
#[cfg(any(test, feature = "fuzztarget"))]
/// Used only in testing and fuzztarget to check serialization roundtrips don't change the
/// underlying object
self.funding_redeemscript != other.funding_redeemscript ||
self.channel_value_satoshis != other.channel_value_satoshis ||
self.their_cur_revocation_points != other.their_cur_revocation_points ||
- self.their_to_self_delay != other.their_to_self_delay ||
+ self.on_local_tx_csv != other.on_local_tx_csv ||
self.commitment_secrets != other.commitment_secrets ||
self.remote_claimable_outpoints != other.remote_claimable_outpoints ||
self.remote_commitment_txn_on_chain != other.remote_commitment_txn_on_chain ||
self.current_remote_commitment_txid.write(writer)?;
self.prev_remote_commitment_txid.write(writer)?;
- self.remote_tx_cache.remote_delayed_payment_base_key.write(writer)?;
- self.remote_tx_cache.remote_htlc_base_key.write(writer)?;
- writer.write_all(&byte_utils::be16_to_array(self.remote_tx_cache.on_remote_tx_csv))?;
- writer.write_all(&byte_utils::be64_to_array(self.remote_tx_cache.per_htlc.len() as u64))?;
- for (ref txid, ref htlcs) in self.remote_tx_cache.per_htlc.iter() {
- writer.write_all(&txid[..])?;
- writer.write_all(&byte_utils::be64_to_array(htlcs.len() as u64))?;
- for &ref htlc in htlcs.iter() {
- htlc.write(writer)?;
- }
- }
+ self.remote_tx_cache.write(writer)?;
self.funding_redeemscript.write(writer)?;
self.channel_value_satoshis.write(writer)?;
},
}
- writer.write_all(&byte_utils::be16_to_array(self.their_to_self_delay))?;
+ writer.write_all(&byte_utils::be16_to_array(self.on_local_tx_csv))?;
self.commitment_secrets.write(writer)?;
writer.write_all(&$local_tx.delayed_payment_key.serialize())?;
writer.write_all(&$local_tx.per_commitment_point.serialize())?;
- writer.write_all(&byte_utils::be64_to_array($local_tx.feerate_per_kw))?;
+ writer.write_all(&byte_utils::be32_to_array($local_tx.feerate_per_kw))?;
writer.write_all(&byte_utils::be64_to_array($local_tx.htlc_outputs.len() as u64))?;
for &(ref htlc_output, ref sig, ref htlc_source) in $local_tx.htlc_outputs.iter() {
serialize_htlc_in_commitment!(htlc_output);
pub(super) fn new(keys: ChanSigner, shutdown_pubkey: &PublicKey,
on_remote_tx_csv: u16, destination_script: &Script, funding_info: (OutPoint, Script),
remote_htlc_base_key: &PublicKey, remote_delayed_payment_base_key: &PublicKey,
- their_to_self_delay: u16, funding_redeemscript: Script, channel_value_satoshis: u64,
+ on_local_tx_csv: u16, funding_redeemscript: Script, channel_value_satoshis: u64,
commitment_transaction_number_obscure_factor: u64,
initial_local_commitment_tx: LocalCommitmentTransaction) -> ChannelMonitor<ChanSigner> {
let payment_key_hash = WPubkeyHash::hash(&keys.pubkeys().payment_point.serialize());
let remote_payment_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_key_hash[..]).into_script();
- let remote_tx_cache = RemoteTxCache { remote_delayed_payment_base_key: *remote_delayed_payment_base_key, remote_htlc_base_key: *remote_htlc_base_key, on_remote_tx_csv, per_htlc: HashMap::new() };
+ let remote_tx_cache = RemoteCommitmentTransaction { remote_delayed_payment_base_key: *remote_delayed_payment_base_key, remote_htlc_base_key: *remote_htlc_base_key, on_remote_tx_csv, per_htlc: HashMap::new() };
- let mut onchain_tx_handler = OnchainTxHandler::new(destination_script.clone(), keys.clone(), their_to_self_delay);
+ let mut onchain_tx_handler = OnchainTxHandler::new(destination_script.clone(), keys.clone(), on_local_tx_csv);
let local_tx_sequence = initial_local_commitment_tx.unsigned_tx.input[0].sequence as u64;
let local_tx_locktime = initial_local_commitment_tx.unsigned_tx.lock_time as u64;
channel_value_satoshis: channel_value_satoshis,
their_cur_revocation_points: None,
- their_to_self_delay,
+ on_local_tx_csv,
commitment_secrets: CounterpartyCommitmentSecrets::new(),
remote_claimable_outpoints: HashMap::new(),
/// monitor watches for timeouts and may broadcast it if we approach such a timeout. Thus, it
/// is important that any clones of this channel monitor (including remote clones) by kept
/// up-to-date as our local commitment transaction is updated.
- /// Panics if set_their_to_self_delay has never been called.
+ /// Panics if set_on_local_tx_csv has never been called.
pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
if self.local_tx_signed {
return Err(MonitorUpdateError("A local commitment tx has already been signed, no new local commitment txn can be sent to our counterparty"));
}
/// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
- pub fn get_funding_txo(&self) -> OutPoint {
- self.funding_info.0
+ pub fn get_funding_txo(&self) -> &(OutPoint, Script) {
+ &self.funding_info
}
/// Gets a list of txids, with their output scripts (in the order they appear in the
self.remote_payment_script = {
// Note that the Network here is ignored as we immediately drop the address for the
// script_pubkey version
- let payment_hash160 = WPubkeyHash::hash(&PublicKey::from_secret_key(&self.secp_ctx, &self.keys.payment_key()).serialize());
+ let payment_hash160 = WPubkeyHash::hash(&self.keys.pubkeys().payment_point.serialize());
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script()
};
let mut claim_requests = Vec::with_capacity(local_tx.htlc_outputs.len());
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
- let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay, &local_tx.delayed_payment_key);
+ let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.on_local_tx_csv, &local_tx.delayed_payment_key);
let broadcasted_local_revokable_script = Some((redeemscript.to_v0_p2wsh(), local_tx.per_commitment_point.clone(), local_tx.revocation_key.clone()));
for &(ref htlc, _, _) in local_tx.htlc_outputs.iter() {
spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WSH {
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
per_commitment_point: broadcasted_local_revokable_script.1,
- to_self_delay: self.their_to_self_delay,
+ to_self_delay: self.on_local_tx_csv,
output: outp.clone(),
key_derivation_params: self.keys.key_derivation_params(),
remote_revocation_pubkey: broadcasted_local_revokable_script.2.clone(),
break;
}
} else if self.remote_payment_script == outp.script_pubkey {
- spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH {
+ spendable_output = Some(SpendableOutputDescriptor::StaticOutputRemotePayment {
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
output: outp.clone(),
key_derivation_params: self.keys.key_derivation_params(),
let current_remote_commitment_txid = Readable::read(reader)?;
let prev_remote_commitment_txid = Readable::read(reader)?;
- let remote_tx_cache = {
- let remote_delayed_payment_base_key = Readable::read(reader)?;
- let remote_htlc_base_key = Readable::read(reader)?;
- let on_remote_tx_csv: u16 = Readable::read(reader)?;
- let per_htlc_len: u64 = Readable::read(reader)?;
- let mut per_htlc = HashMap::with_capacity(cmp::min(per_htlc_len as usize, MAX_ALLOC_SIZE / 64));
- for _ in 0..per_htlc_len {
- let txid: Txid = Readable::read(reader)?;
- let htlcs_count: u64 = Readable::read(reader)?;
- let mut htlcs = Vec::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / 32));
- for _ in 0..htlcs_count {
- let htlc = Readable::read(reader)?;
- htlcs.push(htlc);
- }
- if let Some(_) = per_htlc.insert(txid, htlcs) {
- return Err(DecodeError::InvalidValue);
- }
- }
- RemoteTxCache {
- remote_delayed_payment_base_key,
- remote_htlc_base_key,
- on_remote_tx_csv,
- per_htlc,
- }
- };
+ let remote_tx_cache = Readable::read(reader)?;
let funding_redeemscript = Readable::read(reader)?;
let channel_value_satoshis = Readable::read(reader)?;
}
};
- let their_to_self_delay: u16 = Readable::read(reader)?;
+ let on_local_tx_csv: u16 = Readable::read(reader)?;
let commitment_secrets = Readable::read(reader)?;
let b_htlc_key = Readable::read(reader)?;
let delayed_payment_key = Readable::read(reader)?;
let per_commitment_point = Readable::read(reader)?;
- let feerate_per_kw: u64 = Readable::read(reader)?;
+ let feerate_per_kw: u32 = Readable::read(reader)?;
let htlcs_len: u64 = Readable::read(reader)?;
let mut htlcs = Vec::with_capacity(cmp::min(htlcs_len as usize, MAX_ALLOC_SIZE / 128));
channel_value_satoshis,
their_cur_revocation_points,
- their_to_self_delay,
+ on_local_tx_csv,
commitment_secrets,
remote_claimable_outpoints,
use util::test_utils::TestLogger;
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
use bitcoin::secp256k1::Secp256k1;
- use rand::{thread_rng,Rng};
use std::sync::Arc;
use chain::keysinterface::InMemoryChannelKeys;
let mut preimages = Vec::new();
{
- let mut rng = thread_rng();
- for _ in 0..20 {
- let mut preimage = PaymentPreimage([0; 32]);
- rng.fill_bytes(&mut preimage.0[..]);
+ for i in 0..20 {
+ let preimage = PaymentPreimage([i; 32]);
let hash = PaymentHash(Sha256::hash(&preimage.0[..]).into_inner());
preimages.push((preimage, hash));
}