Skip to content

Commit a5869b9

Browse files
committed
Revocation enforcement in signer
We want to make sure that we don't sign revoked transactions. Given that ChannelKeys are not singletons and revocation enforcement is stateful, we need to store the revocation state in KeysInterface.
1 parent 2cbb835 commit a5869b9

File tree

5 files changed

+107
-47
lines changed

5 files changed

+107
-47
lines changed

lightning/src/chain/keysinterface.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ pub trait ChannelKeys : Send+Clone + Writeable {
254254
/// state. Thus, needs its own method as sign_holder_commitment may enforce that we only ever
255255
/// get called once.
256256
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
257-
fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
257+
fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
258258

259259
/// Create a signature for the given input in a transaction spending an HTLC or commitment
260260
/// transaction output when our counterparty broadcasts an old state.
@@ -499,18 +499,22 @@ impl ChannelKeys for InMemoryChannelKeys {
499499
fn sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
500500
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
501501
let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
502-
let sig = commitment_tx.trust().built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
503-
let channel_parameters = self.get_channel_parameters();
504502
let trusted_tx = commitment_tx.trust();
503+
let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
504+
let channel_parameters = self.get_channel_parameters();
505505
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
506506
Ok((sig, htlc_sigs))
507507
}
508508

509509
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
510-
fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
510+
fn unsafe_sign_holder_commitment_and_htlcs<T: secp256k1::Signing + secp256k1::Verification>(&self, commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
511511
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
512-
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
513-
Ok(commitment_tx.trust().built_transaction().sign(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
512+
let funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &self.counterparty_pubkeys().funding_pubkey);
513+
let trusted_tx = commitment_tx.trust();
514+
let sig = trusted_tx.built_transaction().sign(&self.funding_key, &funding_redeemscript, self.channel_value_satoshis, secp_ctx);
515+
let channel_parameters = self.get_channel_parameters();
516+
let htlc_sigs = trusted_tx.get_htlc_sigs(&self.htlc_base_key, &channel_parameters.as_holder_broadcastable(), secp_ctx)?;
517+
Ok((sig, htlc_sigs))
514518
}
515519

516520
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, ()> {

lightning/src/ln/functional_tests.rs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1616,27 +1616,26 @@ fn test_fee_spike_violation_fails_htlc() {
16161616

16171617
// Get the EnforcingChannelKeys for each channel, which will be used to (1) get the keys
16181618
// needed to sign the new commitment tx and (2) sign the new commitment tx.
1619-
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, local_secret2) = {
1619+
let (local_revocation_basepoint, local_htlc_basepoint, local_secret, next_local_point) = {
16201620
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
16211621
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
16221622
let chan_keys = local_chan.get_keys();
16231623
let pubkeys = chan_keys.pubkeys();
16241624
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
1625-
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER), chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2))
1625+
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER),
1626+
chan_keys.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 2, &secp_ctx))
16261627
};
1627-
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_secret1) = {
1628+
let (remote_delayed_payment_basepoint, remote_htlc_basepoint,remote_point) = {
16281629
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
16291630
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
16301631
let chan_keys = remote_chan.get_keys();
16311632
let pubkeys = chan_keys.pubkeys();
16321633
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
1633-
chan_keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1))
1634+
chan_keys.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx))
16341635
};
16351636

16361637
// Assemble the set of keys we can use for signatures for our commitment_signed message.
1637-
let commitment_secret = SecretKey::from_slice(&remote_secret1).unwrap();
1638-
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &commitment_secret);
1639-
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &per_commitment_point, &remote_delayed_payment_basepoint,
1638+
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
16401639
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint).unwrap();
16411640

16421641
// Build the remote commitment transaction so we can sign it, and then later use the
@@ -1680,10 +1679,11 @@ fn test_fee_spike_violation_fails_htlc() {
16801679
let _ = nodes[1].node.get_and_clear_pending_msg_events();
16811680

16821681
// Send the RAA to nodes[1].
1683-
let per_commitment_secret = local_secret;
1684-
let next_secret = SecretKey::from_slice(&local_secret2).unwrap();
1685-
let next_per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &next_secret);
1686-
let raa_msg = msgs::RevokeAndACK{ channel_id: chan.2, per_commitment_secret, next_per_commitment_point};
1682+
let raa_msg = msgs::RevokeAndACK {
1683+
channel_id: chan.2,
1684+
per_commitment_secret: local_secret,
1685+
next_per_commitment_point: next_local_point
1686+
};
16871687
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &raa_msg);
16881688

16891689
let events = nodes[1].node.get_and_clear_pending_msg_events();
@@ -4269,7 +4269,6 @@ fn test_no_txn_manager_serialize_deserialize() {
42694269
let fee_estimator: test_utils::TestFeeEstimator;
42704270
let persister: test_utils::TestPersister;
42714271
let new_chain_monitor: test_utils::TestChainMonitor;
4272-
let keys_manager: test_utils::TestKeysInterface;
42734272
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
42744273
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
42754274

@@ -4284,12 +4283,12 @@ fn test_no_txn_manager_serialize_deserialize() {
42844283
logger = test_utils::TestLogger::new();
42854284
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
42864285
persister = test_utils::TestPersister::new();
4287-
keys_manager = test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet);
4288-
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, &keys_manager);
4286+
let keys_manager = &chanmon_cfgs[0].keys_manager;
4287+
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
42894288
nodes[0].chain_monitor = &new_chain_monitor;
42904289
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
42914290
let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(
4292-
&mut chan_0_monitor_read, &keys_manager).unwrap();
4291+
&mut chan_0_monitor_read, keys_manager).unwrap();
42934292
assert!(chan_0_monitor_read.is_empty());
42944293

42954294
let mut nodes_0_read = &nodes_0_serialized[..];
@@ -4299,7 +4298,7 @@ fn test_no_txn_manager_serialize_deserialize() {
42994298
channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor);
43004299
<(BlockHash, ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
43014300
default_config: config,
4302-
keys_manager: &keys_manager,
4301+
keys_manager,
43034302
fee_estimator: &fee_estimator,
43044303
chain_monitor: nodes[0].chain_monitor,
43054304
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
@@ -4346,7 +4345,6 @@ fn test_manager_serialize_deserialize_events() {
43464345
let persister: test_utils::TestPersister;
43474346
let logger: test_utils::TestLogger;
43484347
let new_chain_monitor: test_utils::TestChainMonitor;
4349-
let keys_manager: test_utils::TestKeysInterface;
43504348
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
43514349
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
43524350

@@ -4355,8 +4353,8 @@ fn test_manager_serialize_deserialize_events() {
43554353
let push_msat = 10001;
43564354
let a_flags = InitFeatures::known();
43574355
let b_flags = InitFeatures::known();
4358-
let node_a = nodes.pop().unwrap();
4359-
let node_b = nodes.pop().unwrap();
4356+
let node_a = nodes.remove(0);
4357+
let node_b = nodes.remove(0);
43604358
node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None).unwrap();
43614359
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()));
43624360
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()));
@@ -4394,12 +4392,12 @@ fn test_manager_serialize_deserialize_events() {
43944392
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
43954393
logger = test_utils::TestLogger::new();
43964394
persister = test_utils::TestPersister::new();
4397-
keys_manager = test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet);
4398-
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, &keys_manager);
4395+
let keys_manager = &chanmon_cfgs[0].keys_manager;
4396+
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
43994397
nodes[0].chain_monitor = &new_chain_monitor;
44004398
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
44014399
let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor<EnforcingChannelKeys>)>::read(
4402-
&mut chan_0_monitor_read, &keys_manager).unwrap();
4400+
&mut chan_0_monitor_read, keys_manager).unwrap();
44034401
assert!(chan_0_monitor_read.is_empty());
44044402

44054403
let mut nodes_0_read = &nodes_0_serialized[..];
@@ -4409,7 +4407,7 @@ fn test_manager_serialize_deserialize_events() {
44094407
channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor);
44104408
<(BlockHash, ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
44114409
default_config: config,
4412-
keys_manager: &keys_manager,
4410+
keys_manager,
44134411
fee_estimator: &fee_estimator,
44144412
chain_monitor: nodes[0].chain_monitor,
44154413
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
@@ -4470,7 +4468,6 @@ fn test_simple_manager_serialize_deserialize() {
44704468
let fee_estimator: test_utils::TestFeeEstimator;
44714469
let persister: test_utils::TestPersister;
44724470
let new_chain_monitor: test_utils::TestChainMonitor;
4473-
let keys_manager: &test_utils::TestKeysInterface;
44744471
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
44754472
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
44764473
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
@@ -4487,7 +4484,7 @@ fn test_simple_manager_serialize_deserialize() {
44874484
logger = test_utils::TestLogger::new();
44884485
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
44894486
persister = test_utils::TestPersister::new();
4490-
keys_manager = &chanmon_cfgs[0].keys_manager;
4487+
let keys_manager = &chanmon_cfgs[0].keys_manager;
44914488
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
44924489
nodes[0].chain_monitor = &new_chain_monitor;
44934490
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
@@ -4532,7 +4529,6 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
45324529
let fee_estimator: test_utils::TestFeeEstimator;
45334530
let persister: test_utils::TestPersister;
45344531
let new_chain_monitor: test_utils::TestChainMonitor;
4535-
let keys_manager: &test_utils::TestKeysInterface;
45364532
let nodes_0_deserialized: ChannelManager<EnforcingChannelKeys, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
45374533
let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
45384534
create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
@@ -4568,7 +4564,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
45684564
logger = test_utils::TestLogger::new();
45694565
fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 };
45704566
persister = test_utils::TestPersister::new();
4571-
keys_manager = &chanmon_cfgs[0].keys_manager;
4567+
let keys_manager = &chanmon_cfgs[0].keys_manager;
45724568
new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), &logger, &fee_estimator, &persister, keys_manager);
45734569
nodes[0].chain_monitor = &new_chain_monitor;
45744570

@@ -7374,8 +7370,10 @@ fn test_user_configurable_csv_delay() {
73747370
fn test_data_loss_protect() {
73757371
// We want to be sure that :
73767372
// * we don't broadcast our Local Commitment Tx in case of fallen behind
7373+
// (but this is not quite true - we broadcast during Drop because chanmon is out of sync with chanmgr)
73777374
// * we close channel in case of detecting other being fallen behind
73787375
// * we are able to claim our own outputs thanks to to_remote being static
7376+
// TODO: this test is incomplete and the data_loss_protect implementation is incomplete - see issue #775
73797377
let persister;
73807378
let logger;
73817379
let fee_estimator;
@@ -8084,9 +8082,11 @@ fn test_counterparty_raa_skip_no_crash() {
80848082
let mut guard = nodes[0].node.channel_state.lock().unwrap();
80858083
let keys = &guard.by_id.get_mut(&channel_id).unwrap().holder_keys;
80868084
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
8085+
let per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER);
8086+
// Must revoke without gaps
8087+
keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 1);
80878088
let next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(),
80888089
&SecretKey::from_slice(&keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
8089-
let per_commitment_secret = keys.release_commitment_secret(INITIAL_COMMITMENT_NUMBER);
80908090

80918091
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(),
80928092
&msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point });

lightning/src/ln/onchaintx.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
953953

954954
#[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
955955
pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction {
956-
let (sig, htlc_sigs) = self.key_storage.sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment");
956+
let (sig, htlc_sigs) = self.key_storage.unsafe_sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment");
957957
self.holder_htlc_sigs = Some(Self::extract_holder_sigs(&self.holder_commitment, htlc_sigs));
958958
self.holder_commitment.add_holder_sig(funding_redeemscript, sig)
959959
}

0 commit comments

Comments
 (0)