/// state. Thus, needs its own method as sign_holder_commitment may enforce that we only ever
/// get called once.
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
- fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
+ fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
/// Create a signature for the given input in a transaction spending an HTLC or commitment
/// transaction output when our counterparty broadcasts an old state.
fn sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
- let sig = commitment_tx.trust().built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
- let channel_parameters = self.get_channel_parameters();
let trusted_tx = commitment_tx.trust();
+ let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
+ let channel_parameters = self.get_channel_parameters();
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
Ok((sig, htlc_sigs))
}
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
- fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
- let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
- Ok(commitment_tx.trust().built_transaction().sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
+ let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
+ let trusted_tx = commitment_tx.trust();
+ let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
+ let channel_parameters = self.get_channel_parameters();
+ let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
+ Ok((sig, htlc_sigs))
}
fn sign_justice_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
// Get the EnforcingChannelKeys for each channel, which will be used to (1) get the keys
// needed to sign the new commitment tx and (2) sign the new commitment tx.
- let (local_revocation_basepoint, local_htlc_basepoint, local_secret, local_secret2) = {
+ let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point) = {
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
let chan_keys = local_chan.get_keys();
let pubkeys = chan_keys.pubkeys();
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
- chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER), chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2))
+ chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER),
+ chan_keys.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx))
};
- let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_secret1) = {
+ let (remote_delayed_payment_basepoint, remote_htlc_basepoint,remote_point) = {
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
let chan_keys = remote_chan.get_keys();
let pubkeys = chan_keys.pubkeys();
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
- chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1))
+ chan_keys.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx))
};
// Assemble the set of keys we can use for signatures for our commitment_signed message.
- let commitment_secret = SecretKey::from_slice(&remote_secret1).unwrap();
- let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &commitment_secret);
- let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, &remote_delayed_payment_basepoint,
+ let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint).unwrap();
// Build the remote commitment transaction so we can sign it, and then later use the
let _ = nodes[1].node.get_and_clear_pending_msg_events();
// Send the RAA to nodes[1].
- let per_commitment_secret = local_secret;
- let next_secret = SecretKey::from_slice(&local_secret2).unwrap();
- let next_per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &next_secret);
- let raa_msg = msgs::RevokeAndACK{ channel_id: chan.2, per_commitment_secret, next_per_commitment_point};
+ let raa_msg = msgs::RevokeAndACK {
+ channel_id: chan.2,
+ per_commitment_secret: local_secret,
+ next_per_commitment_point: next_local_point
+ };
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &raa_msg);
let events = nodes[1].node.get_and_clear_pending_msg_events();
let fee_estimator: test_utils::TestFeeEstimator;
let persister: test_utils::TestPersister;
let new_chain_monitor: test_utils::TestChainMonitor;
- let keys_manager: test_utils::TestKeysInterface;
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
logger = test_utils::TestLogger::new();
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
persister = test_utils::TestPersister::new();
- keys_manager = test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet);
- new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, &keys_manager);
+ let keys_manager = &chanmon_cfgs[0].keys_manager;
+ new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
nodes[0].chain_monitor = &new_chain_monitor;
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(
- &mut chan_0_monitor_read, &keys_manager).unwrap();
+ &mut chan_0_monitor_read, keys_manager).unwrap();
assert!(chan_0_monitor_read.is_empty());
let mut nodes_0_read = &nodes_0_serialized[..];
channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor);
<(BlockHash, ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: config,
- keys_manager: &keys_manager,
+ keys_manager,
fee_estimator: &fee_estimator,
chain_monitor: nodes[0].chain_monitor,
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
let persister: test_utils::TestPersister;
let logger: test_utils::TestLogger;
let new_chain_monitor: test_utils::TestChainMonitor;
- let keys_manager: test_utils::TestKeysInterface;
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let push_msat = 10001;
let a_flags = InitFeatures::known();
let b_flags = InitFeatures::known();
- let node_a = nodes.pop().unwrap();
- let node_b = nodes.pop().unwrap();
+ let node_a = nodes.remove(0);
+ let node_b = nodes.remove(0);
node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None).unwrap();
node_b.node.handle_open_channel(&node_a.node.get_our_node_id(), a_flags, &get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id()));
node_a.node.handle_accept_channel(&node_b.node.get_our_node_id(), b_flags, &get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id()));
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
logger = test_utils::TestLogger::new();
persister = test_utils::TestPersister::new();
- keys_manager = test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet);
- new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, &keys_manager);
+ let keys_manager = &chanmon_cfgs[0].keys_manager;
+ new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
nodes[0].chain_monitor = &new_chain_monitor;
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(
- &mut chan_0_monitor_read, &keys_manager).unwrap();
+ &mut chan_0_monitor_read, keys_manager).unwrap();
assert!(chan_0_monitor_read.is_empty());
let mut nodes_0_read = &nodes_0_serialized[..];
channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor);
<(BlockHash, ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: config,
- keys_manager: &keys_manager,
+ keys_manager,
fee_estimator: &fee_estimator,
chain_monitor: nodes[0].chain_monitor,
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
let fee_estimator: test_utils::TestFeeEstimator;
let persister: test_utils::TestPersister;
let new_chain_monitor: test_utils::TestChainMonitor;
- let keys_manager: &test_utils::TestKeysInterface;
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
logger = test_utils::TestLogger::new();
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
persister = test_utils::TestPersister::new();
- keys_manager = &chanmon_cfgs[0].keys_manager;
+ let keys_manager = &chanmon_cfgs[0].keys_manager;
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
nodes[0].chain_monitor = &new_chain_monitor;
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
let fee_estimator: test_utils::TestFeeEstimator;
let persister: test_utils::TestPersister;
let new_chain_monitor: test_utils::TestChainMonitor;
- let keys_manager: &test_utils::TestKeysInterface;
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
logger = test_utils::TestLogger::new();
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
persister = test_utils::TestPersister::new();
- keys_manager = &chanmon_cfgs[0].keys_manager;
+ let keys_manager = &chanmon_cfgs[0].keys_manager;
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
nodes[0].chain_monitor = &new_chain_monitor;
fn test_data_loss_protect() {
// We want to be sure that :
// * we don't broadcast our Local Commitment Tx in case of fallen behind
+ // (but this is not quite true - we broadcast during Drop because chanmon is out of sync with chanmgr)
// * we close channel in case of detecting other being fallen behind
// * we are able to claim our own outputs thanks to to_remote being static
+ // TODO: this test is incomplete and the data_loss_protect implementation is incomplete - see issue #775
let persister;
let logger;
let fee_estimator;
let mut guard = nodes[0].node.channel_state.lock().unwrap();
let keys = &guard.by_id.get_mut(&channel_id).unwrap().holder_keys;
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
+ let per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER);
+ // Must revoke without gaps
+ keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1);
let next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(),
&SecretKey::from_slice(&keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
- let per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER);
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(),
&msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point });
use std::io::Error;
use ln::msgs::DecodeError;
+/// Initial value for revoked commitment downward counter
+pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48;
+
/// An implementation of ChannelKeys that enforces some policy checks.
///
/// Eventually we will probably want to expose a variant of this which would essentially
#[derive(Clone)]
pub struct EnforcingChannelKeys {
pub inner: InMemoryChannelKeys,
- last_commitment_number: Arc<Mutex<Option<u64>>>,
+ pub(crate) last_commitment_number: Arc<Mutex<Option<u64>>>,
+ pub(crate) revoked_commitment: Arc<Mutex<u64>>,
}
impl EnforcingChannelKeys {
Self {
inner,
last_commitment_number: Arc::new(Mutex::new(None)),
+ revoked_commitment: Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER))
+ }
+ }
+
+ pub fn new_with_revoked(inner: InMemoryChannelKeys, revoked_commitment: Arc<Mutex<u64>>) -> Self {
+ Self {
+ inner,
+ last_commitment_number: Arc::new(Mutex::new(None)),
+ revoked_commitment
}
}
}
}
fn release_commitment_secret(&self, idx: u64) -> [u8; 32] {
- // TODO: enforce the ChannelKeys contract - error here if we already signed this commitment
+ println!("XXX revoke {} for {}", idx, self.inner.commitment_seed[0]);
+
+ {
+ let mut revoked = self.revoked_commitment.lock().unwrap();
+ assert!(idx == *revoked || idx == *revoked - 1, "can only revoke the current or next unrevoked commitment - trying {}, revoked {}", idx, *revoked);
+ *revoked = idx;
+ }
self.inner.release_commitment_secret(idx)
}
let commitment_txid = trusted_tx.txid();
let holder_csv = self.inner.counterparty_selected_contest_delay();
+ let revoked = self.revoked_commitment.lock().unwrap();
+ let commitment_number = trusted_tx.commitment_number();
+ println!("XXX sign {} for {}", commitment_number, self.inner.commitment_seed[0]);
+ if *revoked - 1 != commitment_number && *revoked - 2 != commitment_number {
+ println!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
+ *revoked, commitment_number, self.inner.commitment_seed[0]);
+ return Err(());
+ }
+
for (this_htlc, sig) in trusted_tx.htlcs().iter().zip(&commitment_tx.counterparty_htlc_sigs) {
assert!(this_htlc.transaction_output_index.is_some());
let keys = trusted_tx.keys();
}
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
- fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
- Ok(self.inner.unsafe_sign_holder_commitment(commitment_tx, secp_ctx).unwrap())
+ fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
+ Ok(self.inner.unsafe_sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap())
}
fn sign_justice_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
impl Readable for EnforcingChannelKeys {
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
- let inner = Readable::read(reader)?;
+ let inner: InMemoryChannelKeys = Readable::read(reader)?;
let last_commitment_number = Readable::read(reader)?;
Ok(EnforcingChannelKeys {
inner,
- last_commitment_number: Arc::new(Mutex::new(last_commitment_number))
+ last_commitment_number: Arc::new(Mutex::new(last_commitment_number)),
+ revoked_commitment: Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER)),
})
}
}
use ln::features::{ChannelFeatures, InitFeatures};
use ln::msgs;
use ln::msgs::OptionalField;
-use util::enforcing_trait_impls::EnforcingChannelKeys;
+use util::enforcing_trait_impls::{EnforcingChannelKeys, INITIAL_REVOKED_COMMITMENT_NUMBER};
use util::events;
use util::logger::{Logger, Level, Record};
use util::ser::{Readable, ReadableArgs, Writer, Writeable};
use regex;
use std::time::Duration;
-use std::sync::Mutex;
+use std::sync::{Mutex, Arc};
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use std::{cmp, mem};
use std::collections::{HashMap, HashSet};
backing: keysinterface::KeysManager,
pub override_session_priv: Mutex<Option<[u8; 32]>>,
pub override_channel_id_priv: Mutex<Option<[u8; 32]>>,
+ revoked_commitments: Mutex<HashMap<[u8;32], Arc<Mutex<u64>>>>,
}
impl keysinterface::KeysInterface for TestKeysInterface {
fn get_destination_script(&self) -> Script { self.backing.get_destination_script() }
fn get_shutdown_pubkey(&self) -> PublicKey { self.backing.get_shutdown_pubkey() }
fn get_channel_keys(&self, inbound: bool, channel_value_satoshis: u64) -> EnforcingChannelKeys {
- EnforcingChannelKeys::new(self.backing.get_channel_keys(inbound, channel_value_satoshis))
+ let keys = self.backing.get_channel_keys(inbound, channel_value_satoshis);
+ let revoked_commitment = self.make_revoked_commitment_cell(keys.commitment_seed);
+ EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment)
}
fn get_secure_random_bytes(&self) -> [u8; 32] {
self.backing.get_secure_random_bytes()
}
- fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::ChanKeySigner, msgs::DecodeError> {
- EnforcingChannelKeys::read(&mut std::io::Cursor::new(reader))
+ fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::ChanKeySigner, msgs::DecodeError> {
+ let mut reader = std::io::Cursor::new(buffer);
+
+ let inner: InMemoryChannelKeys = Readable::read(&mut reader)?;
+ let revoked_commitment = self.make_revoked_commitment_cell(inner.commitment_seed);
+
+ let last_commitment_number = Readable::read(&mut reader)?;
+
+ Ok(EnforcingChannelKeys {
+ inner,
+ last_commitment_number: Arc::new(Mutex::new(last_commitment_number)),
+ revoked_commitment,
+ })
}
}
+
impl TestKeysInterface {
pub fn new(seed: &[u8; 32], network: Network) -> Self {
let now = Duration::from_secs(genesis_block(network).header.time as u64);
backing: keysinterface::KeysManager::new(seed, network, now.as_secs(), now.subsec_nanos()),
override_session_priv: Mutex::new(None),
override_channel_id_priv: Mutex::new(None),
+ revoked_commitments: Mutex::new(HashMap::new()),
}
}
pub fn derive_channel_keys(&self, channel_value_satoshis: u64, user_id_1: u64, user_id_2: u64) -> EnforcingChannelKeys {
- EnforcingChannelKeys::new(self.backing.derive_channel_keys(channel_value_satoshis, user_id_1, user_id_2))
+ let keys = self.backing.derive_channel_keys(channel_value_satoshis, user_id_1, user_id_2);
+ let revoked_commitment = self.make_revoked_commitment_cell(keys.commitment_seed);
+ EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment)
+ }
+
+ fn make_revoked_commitment_cell(&self, commitment_seed: [u8; 32]) -> Arc<Mutex<u64>> {
+ let mut revoked_commitments = self.revoked_commitments.lock().unwrap();
+ if !revoked_commitments.contains_key(&commitment_seed) {
+ revoked_commitments.insert(commitment_seed, Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER)));
+ }
+ let cell = revoked_commitments.get(&commitment_seed).unwrap();
+ Arc::clone(cell)
}
}