Skip to content

Commit f8e0405

Browse files
committed
Let some tests disable revocation policy check
When simulating a bad actor that broadcasts a revoked tx, the policy check would otherwise panic.
1 parent bd4345d commit f8e0405

File tree

4 files changed

+52
-23
lines changed

4 files changed

+52
-23
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl KeysInterface for KeyProvider {
182182
(0, 0),
183183
);
184184
let revoked_commitment = self.make_revoked_commitment_cell(keys.commitment_seed);
185-
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment)
185+
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment, false)
186186
}
187187

188188
fn get_secure_random_bytes(&self) -> [u8; 32] {
@@ -202,6 +202,7 @@ impl KeysInterface for KeyProvider {
202202
inner,
203203
last_commitment_number: Arc::new(Mutex::new(last_commitment_number)),
204204
revoked_commitment,
205+
disable_revocation_policy_check: false,
205206
})
206207
}
207208
}

lightning/src/ln/functional_tests.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,7 +2470,9 @@ fn test_justice_tx() {
24702470
bob_config.peer_channel_config_limits.force_announced_channel_preference = false;
24712471
bob_config.own_channel_config.our_to_self_delay = 6 * 24 * 3;
24722472
let user_cfgs = [Some(alice_config), Some(bob_config)];
2473-
let chanmon_cfgs = create_chanmon_cfgs(2);
2473+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
2474+
chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
2475+
chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
24742476
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
24752477
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &user_cfgs);
24762478
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -2600,7 +2602,8 @@ fn revoked_output_claim() {
26002602
#[test]
26012603
fn claim_htlc_outputs_shared_tx() {
26022604
// Node revoked old state, htlcs haven't time out yet, claim them in shared justice tx
2603-
let chanmon_cfgs = create_chanmon_cfgs(2);
2605+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
2606+
chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
26042607
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
26052608
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
26062609
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -2670,7 +2673,8 @@ fn claim_htlc_outputs_shared_tx() {
26702673
#[test]
26712674
fn claim_htlc_outputs_single_tx() {
26722675
// Node revoked old state, htlcs have timed out, claim each of them in separated justice tx
2673-
let chanmon_cfgs = create_chanmon_cfgs(2);
2676+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
2677+
chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
26742678
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
26752679
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
26762680
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -4993,7 +4997,8 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
49934997

49944998
#[test]
49954999
fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
4996-
let chanmon_cfgs = create_chanmon_cfgs(2);
5000+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
5001+
chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
49975002
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
49985003
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
49995004
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -5059,7 +5064,8 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
50595064

50605065
#[test]
50615066
fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
5062-
let chanmon_cfgs = create_chanmon_cfgs(2);
5067+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
5068+
chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
50635069
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
50645070
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
50655071
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -7040,7 +7046,8 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
70407046
// We can have at most two valid local commitment tx, so both cases must be covered, and both txs must be checked to get them all as
70417047
// HTLC could have been removed from lastest local commitment tx but still valid until we get remote RAA
70427048

7043-
let chanmon_cfgs = create_chanmon_cfgs(2);
7049+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
7050+
chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
70447051
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
70457052
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
70467053
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
@@ -7379,7 +7386,10 @@ fn test_data_loss_protect() {
73797386
let fee_estimator;
73807387
let tx_broadcaster;
73817388
let chain_source;
7382-
let chanmon_cfgs = create_chanmon_cfgs(2);
7389+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
7390+
// We broadcast during Drop because chanmon is out of sync with chanmgr, which would cause a panic
7391+
// during signing due to revoked tx
7392+
chanmon_cfgs[0].keys_manager.disable_revocation_policy_check = true;
73837393
let keys_manager = &chanmon_cfgs[0].keys_manager;
73847394
let monitor;
73857395
let node_state_0;
@@ -7699,7 +7709,8 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
76997709
// In case of penalty txn with too low feerates for getting into mempools, RBF-bump them to sure
77007710
// we're able to claim outputs on revoked HTLC transactions before timelocks expiration
77017711

7702-
let chanmon_cfgs = create_chanmon_cfgs(2);
7712+
let mut chanmon_cfgs = create_chanmon_cfgs(2);
7713+
chanmon_cfgs[1].keys_manager.disable_revocation_policy_check = true;
77037714
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
77047715
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
77057716
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);

lightning/src/util/enforcing_trait_impls.rs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,48 @@ use ln::msgs::DecodeError;
2727
/// Initial value for revoked commitment downward counter
2828
pub const INITIAL_REVOKED_COMMITMENT_NUMBER: u64 = 1 << 48;
2929

30-
/// An implementation of ChannelKeys that enforces some policy checks.
30+
/// An implementation of ChannelKeys that enforces some policy checks. The current checks
31+
/// are an incomplete set. They include:
32+
///
33+
/// - When signing, the holder transaction has not been revoked
34+
/// - When revoking, the holder transaction has not been signed
35+
/// - The remote commitment number is monotonic and without gaps
36+
/// - The pre-derived keys and pre-built transaction in CommitmentTransaction were correctly built
3137
///
3238
/// Eventually we will probably want to expose a variant of this which would essentially
3339
/// be what you'd want to run on a hardware wallet.
3440
#[derive(Clone)]
3541
pub struct EnforcingChannelKeys {
3642
pub inner: InMemoryChannelKeys,
43+
/// The last counterparty commitment number we signed, backwards counting
3744
pub last_commitment_number: Arc<Mutex<Option<u64>>>,
45+
/// The last holder commitment number we revoked, backwards counting
3846
pub revoked_commitment: Arc<Mutex<u64>>,
47+
pub disable_revocation_policy_check: bool,
3948
}
4049

4150
impl EnforcingChannelKeys {
51+
/// Construct an EnforcingChannelKeys
4252
pub fn new(inner: InMemoryChannelKeys) -> Self {
4353
Self {
4454
inner,
4555
last_commitment_number: Arc::new(Mutex::new(None)),
46-
revoked_commitment: Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER))
56+
revoked_commitment: Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER)),
57+
disable_revocation_policy_check: false
4758
}
4859
}
4960

50-
pub fn new_with_revoked(inner: InMemoryChannelKeys, revoked_commitment: Arc<Mutex<u64>>) -> Self {
61+
/// Construct an EnforcingChannelKeys with externally managed storage
62+
///
63+
/// Since there are multiple copies of this struct for each channel, some coordination is needed
64+
/// so that all copies are aware of revocations. A pointer to this state is provided here, usually
65+
/// by an implementation of KeysInterface.
66+
pub fn new_with_revoked(inner: InMemoryChannelKeys, revoked_commitment: Arc<Mutex<u64>>, disable_revocation_policy_check: bool) -> Self {
5167
Self {
5268
inner,
5369
last_commitment_number: Arc::new(Mutex::new(None)),
54-
revoked_commitment
70+
revoked_commitment,
71+
disable_revocation_policy_check
5572
}
5673
}
5774
}
@@ -62,8 +79,6 @@ impl ChannelKeys for EnforcingChannelKeys {
6279
}
6380

6481
fn release_commitment_secret(&self, idx: u64) -> [u8; 32] {
65-
println!("XXX revoke {} for {}", idx, self.inner.commitment_seed[0]);
66-
6782
{
6883
let mut revoked = self.revoked_commitment.lock().unwrap();
6984
assert!(idx == *revoked || idx == *revoked - 1, "can only revoke the current or next unrevoked commitment - trying {}, revoked {}", idx, *revoked);
@@ -98,11 +113,11 @@ impl ChannelKeys for EnforcingChannelKeys {
98113

99114
let revoked = self.revoked_commitment.lock().unwrap();
100115
let commitment_number = trusted_tx.commitment_number();
101-
println!("XXX sign {} for {}", commitment_number, self.inner.commitment_seed[0]);
102116
if *revoked - 1 != commitment_number && *revoked - 2 != commitment_number {
103-
println!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
104-
*revoked, commitment_number, self.inner.commitment_seed[0]);
105-
return Err(());
117+
if !self.disable_revocation_policy_check {
118+
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
119+
*revoked, commitment_number, self.inner.commitment_seed[0])
120+
}
106121
}
107122

108123
for (this_htlc, sig) in trusted_tx.htlcs().iter().zip(&commitment_tx.counterparty_htlc_sigs) {
@@ -116,8 +131,6 @@ impl ChannelKeys for EnforcingChannelKeys {
116131
secp_ctx.verify(&sighash, sig, &keys.countersignatory_htlc_key).unwrap();
117132
}
118133

119-
// TODO: enforce the ChannelKeys contract - error if this commitment was already revoked
120-
// TODO: need the commitment number
121134
Ok(self.inner.sign_holder_commitment_and_htlcs(commitment_tx, secp_ctx).unwrap())
122135
}
123136

@@ -165,6 +178,7 @@ impl Readable for EnforcingChannelKeys {
165178
inner,
166179
last_commitment_number: Arc::new(Mutex::new(last_commitment_number)),
167180
revoked_commitment: Arc::new(Mutex::new(INITIAL_REVOKED_COMMITMENT_NUMBER)),
181+
disable_revocation_policy_check: false,
168182
})
169183
}
170184
}

lightning/src/util/test_utils.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ pub struct TestKeysInterface {
422422
backing: keysinterface::KeysManager,
423423
pub override_session_priv: Mutex<Option<[u8; 32]>>,
424424
pub override_channel_id_priv: Mutex<Option<[u8; 32]>>,
425+
pub disable_revocation_policy_check: bool,
425426
revoked_commitments: Mutex<HashMap<[u8;32], Arc<Mutex<u64>>>>,
426427
}
427428

@@ -434,7 +435,7 @@ impl keysinterface::KeysInterface for TestKeysInterface {
434435
fn get_channel_keys(&self, inbound: bool, channel_value_satoshis: u64) -> EnforcingChannelKeys {
435436
let keys = self.backing.get_channel_keys(inbound, channel_value_satoshis);
436437
let revoked_commitment = self.make_revoked_commitment_cell(keys.commitment_seed);
437-
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment)
438+
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment, self.disable_revocation_policy_check)
438439
}
439440

440441
fn get_secure_random_bytes(&self) -> [u8; 32] {
@@ -464,6 +465,7 @@ impl keysinterface::KeysInterface for TestKeysInterface {
464465
inner,
465466
last_commitment_number: Arc::new(Mutex::new(last_commitment_number)),
466467
revoked_commitment,
468+
disable_revocation_policy_check: self.disable_revocation_policy_check,
467469
})
468470
}
469471
}
@@ -476,13 +478,14 @@ impl TestKeysInterface {
476478
backing: keysinterface::KeysManager::new(seed, network, now.as_secs(), now.subsec_nanos()),
477479
override_session_priv: Mutex::new(None),
478480
override_channel_id_priv: Mutex::new(None),
481+
disable_revocation_policy_check: false,
479482
revoked_commitments: Mutex::new(HashMap::new()),
480483
}
481484
}
482485
pub fn derive_channel_keys(&self, channel_value_satoshis: u64, user_id_1: u64, user_id_2: u64) -> EnforcingChannelKeys {
483486
let keys = self.backing.derive_channel_keys(channel_value_satoshis, user_id_1, user_id_2);
484487
let revoked_commitment = self.make_revoked_commitment_cell(keys.commitment_seed);
485-
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment)
488+
EnforcingChannelKeys::new_with_revoked(keys, revoked_commitment, self.disable_revocation_policy_check)
486489
}
487490

488491
fn make_revoked_commitment_cell(&self, commitment_seed: [u8; 32]) -> Arc<Mutex<u64>> {

0 commit comments

Comments
 (0)