Skip to content

Commit 8129ede

Browse files
committed
Optionally disable all state-based policy checks in test signer
The signer we use in tests tracks the state of the channel and refuses to sign when the channel attempts an invalid state transition. In the next commit, however, we'll add an upgrade test which will fail these checks as the the state won't get copied from previous versions of LDK to this version. Thus, here, we add the ability to disable all state-based checks in the signer.
1 parent 50e1d15 commit 8129ede

File tree

4 files changed

+66
-40
lines changed

4 files changed

+66
-40
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ impl SignerProvider for KeyProvider {
382382
channel_keys_id,
383383
);
384384
let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed);
385-
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false)
385+
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false, false)
386386
}
387387

388388
fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::EcdsaSigner, DecodeError> {

fuzz/src/full_stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ impl SignerProvider for KeyProvider {
529529
let inner: InMemorySigner = ReadableArgs::read(&mut data, self)?;
530530
let state = Arc::new(Mutex::new(EnforcementState::new()));
531531

532-
Ok(TestChannelSigner::new_with_revoked(inner, state, false))
532+
Ok(TestChannelSigner::new_with_revoked(inner, state, false, false))
533533
}
534534

535535
fn get_destination_script(&self, _channel_keys_id: [u8; 32]) -> Result<ScriptBuf, ()> {

lightning/src/util/test_channel_signer.rs

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ pub struct TestChannelSigner {
7171
/// Channel state used for policy enforcement
7272
pub state: Arc<Mutex<EnforcementState>>,
7373
pub disable_revocation_policy_check: bool,
74+
pub disable_all_state_policy_checks: bool,
7475
}
7576

7677
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -124,6 +125,7 @@ impl TestChannelSigner {
124125
inner,
125126
state,
126127
disable_revocation_policy_check: false,
128+
disable_all_state_policy_checks: false,
127129
}
128130
}
129131

@@ -132,12 +134,11 @@ impl TestChannelSigner {
132134
/// Since there are multiple copies of this struct for each channel, some coordination is needed
133135
/// so that all copies are aware of enforcement state. A pointer to this state is provided
134136
/// here, usually by an implementation of KeysInterface.
135-
pub fn new_with_revoked(inner: InMemorySigner, state: Arc<Mutex<EnforcementState>>, disable_revocation_policy_check: bool) -> Self {
136-
Self {
137-
inner,
138-
state,
139-
disable_revocation_policy_check,
140-
}
137+
pub fn new_with_revoked(
138+
inner: InMemorySigner, state: Arc<Mutex<EnforcementState>>,
139+
disable_revocation_policy_check: bool, disable_all_state_policy_checks: bool,
140+
) -> Self {
141+
Self { inner, state, disable_revocation_policy_check, disable_all_state_policy_checks }
141142
}
142143

143144
pub fn channel_type_features(&self) -> &ChannelTypeFeatures { self.inner.channel_type_features().unwrap() }
@@ -177,19 +178,26 @@ impl ChannelSigner for TestChannelSigner {
177178
if !self.is_signer_available(SignerOp::ReleaseCommitmentSecret) {
178179
return Err(());
179180
}
180-
{
181-
let mut state = self.state.lock().unwrap();
181+
let mut state = self.state.lock().unwrap();
182+
if !self.disable_all_state_policy_checks {
182183
assert!(idx == state.last_holder_revoked_commitment || idx == state.last_holder_revoked_commitment - 1, "can only revoke the current or next unrevoked commitment - trying {}, last revoked {}", idx, state.last_holder_revoked_commitment);
183184
assert!(idx > state.last_holder_commitment, "cannot revoke the last holder commitment - attempted to revoke {} last commitment {}", idx, state.last_holder_commitment);
184-
state.last_holder_revoked_commitment = idx;
185185
}
186+
state.last_holder_revoked_commitment = idx;
186187
self.inner.release_commitment_secret(idx)
187188
}
188189

189190
fn validate_holder_commitment(&self, holder_tx: &HolderCommitmentTransaction, _outbound_htlc_preimages: Vec<PaymentPreimage>) -> Result<(), ()> {
190191
let mut state = self.state.lock().unwrap();
191192
let idx = holder_tx.commitment_number();
192-
assert!(idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1, "expecting to validate the current or next holder commitment - trying {}, current {}", idx, state.last_holder_commitment);
193+
if !self.disable_all_state_policy_checks {
194+
assert!(
195+
idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1,
196+
"expecting to validate the current or next holder commitment - trying {}, current {}",
197+
idx,
198+
state.last_holder_commitment
199+
);
200+
}
193201
state.last_holder_commitment = idx;
194202
Ok(())
195203
}
@@ -200,7 +208,9 @@ impl ChannelSigner for TestChannelSigner {
200208
return Err(());
201209
}
202210
let mut state = self.state.lock().unwrap();
203-
assert!(idx == state.last_counterparty_revoked_commitment || idx == state.last_counterparty_revoked_commitment - 1, "expecting to validate the current or next counterparty revocation - trying {}, current {}", idx, state.last_counterparty_revoked_commitment);
211+
if !self.disable_all_state_policy_checks {
212+
assert!(idx == state.last_counterparty_revoked_commitment || idx == state.last_counterparty_revoked_commitment - 1, "expecting to validate the current or next counterparty revocation - trying {}, current {}", idx, state.last_counterparty_revoked_commitment);
213+
}
204214
state.last_counterparty_revoked_commitment = idx;
205215
Ok(())
206216
}
@@ -218,22 +228,28 @@ impl EcdsaChannelSigner for TestChannelSigner {
218228
fn sign_counterparty_commitment(&self, commitment_tx: &CommitmentTransaction, inbound_htlc_preimages: Vec<PaymentPreimage>, outbound_htlc_preimages: Vec<PaymentPreimage>, secp_ctx: &Secp256k1<secp256k1::All>) -> Result<(Signature, Vec<Signature>), ()> {
219229
self.verify_counterparty_commitment_tx(commitment_tx, secp_ctx);
220230

221-
{
222-
#[cfg(test)]
223-
if !self.is_signer_available(SignerOp::SignCounterpartyCommitment) {
224-
return Err(());
225-
}
226-
let mut state = self.state.lock().unwrap();
227-
let actual_commitment_number = commitment_tx.commitment_number();
228-
let last_commitment_number = state.last_counterparty_commitment;
231+
#[cfg(test)]
232+
if !self.is_signer_available(SignerOp::SignCounterpartyCommitment) {
233+
return Err(());
234+
}
235+
let mut state = self.state.lock().unwrap();
236+
let actual_commitment_number = commitment_tx.commitment_number();
237+
let last_commitment_number = state.last_counterparty_commitment;
238+
if !self.disable_all_state_policy_checks {
229239
// These commitment numbers are backwards counting. We expect either the same as the previously encountered,
230240
// or the next one.
231241
assert!(last_commitment_number == actual_commitment_number || last_commitment_number - 1 == actual_commitment_number, "{} doesn't come after {}", actual_commitment_number, last_commitment_number);
232242
// Ensure that the counterparty doesn't get more than two broadcastable commitments -
233243
// the last and the one we are trying to sign
234-
assert!(actual_commitment_number >= state.last_counterparty_revoked_commitment - 2, "cannot sign a commitment if second to last wasn't revoked - signing {} revoked {}", actual_commitment_number, state.last_counterparty_revoked_commitment);
235-
state.last_counterparty_commitment = cmp::min(last_commitment_number, actual_commitment_number)
244+
assert!(
245+
actual_commitment_number >= state.last_counterparty_revoked_commitment - 2,
246+
"cannot sign a commitment if second to last wasn't revoked - signing {} revoked {}",
247+
actual_commitment_number,
248+
state.last_counterparty_revoked_commitment
249+
);
236250
}
251+
state.last_counterparty_commitment =
252+
cmp::min(last_commitment_number, actual_commitment_number);
237253

238254
Ok(self.inner.sign_counterparty_commitment(commitment_tx, inbound_htlc_preimages, outbound_htlc_preimages, secp_ctx).unwrap())
239255
}
@@ -244,12 +260,14 @@ impl EcdsaChannelSigner for TestChannelSigner {
244260
return Err(());
245261
}
246262
let trusted_tx = self.verify_holder_commitment_tx(commitment_tx, secp_ctx);
247-
let state = self.state.lock().unwrap();
248-
let commitment_number = trusted_tx.commitment_number();
249-
if state.last_holder_revoked_commitment - 1 != commitment_number && state.last_holder_revoked_commitment - 2 != commitment_number {
250-
if !self.disable_revocation_policy_check {
251-
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
252-
state.last_holder_revoked_commitment, commitment_number, self.inner.commitment_seed[0])
263+
if !self.disable_all_state_policy_checks {
264+
let state = self.state.lock().unwrap();
265+
let commitment_number = trusted_tx.commitment_number();
266+
if state.last_holder_revoked_commitment - 1 != commitment_number && state.last_holder_revoked_commitment - 2 != commitment_number {
267+
if !self.disable_revocation_policy_check {
268+
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
269+
state.last_holder_revoked_commitment, commitment_number, self.inner.commitment_seed[0])
270+
}
253271
}
254272
}
255273
Ok(self.inner.sign_holder_commitment(commitment_tx, secp_ctx).unwrap())
@@ -284,13 +302,15 @@ impl EcdsaChannelSigner for TestChannelSigner {
284302
if !self.is_signer_available(SignerOp::SignHolderHtlcTransaction) {
285303
return Err(());
286304
}
287-
let state = self.state.lock().unwrap();
288-
if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number &&
289-
state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number
290-
{
291-
if !self.disable_revocation_policy_check {
292-
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
293-
state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.commitment_seed[0])
305+
if !self.disable_all_state_policy_checks {
306+
let state = self.state.lock().unwrap();
307+
if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number &&
308+
state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number
309+
{
310+
if !self.disable_revocation_policy_check {
311+
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
312+
state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.commitment_seed[0])
313+
}
294314
}
295315
}
296316
assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input());

lightning/src/util/test_utils.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,8 @@ impl SignerProvider for OnlyReadsKeysInterface {
327327
Ok(TestChannelSigner::new_with_revoked(
328328
inner,
329329
state,
330-
false
330+
false,
331+
false,
331332
))
332333
}
333334

@@ -1263,7 +1264,8 @@ pub struct TestKeysInterface {
12631264
pub backing: sign::PhantomKeysManager,
12641265
pub override_random_bytes: Mutex<Option<[u8; 32]>>,
12651266
pub disable_revocation_policy_check: bool,
1266-
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
1267+
pub disable_all_state_policy_checks: bool,
1268+
enforcement_states: Mutex<HashMap<[u8; 32], Arc<Mutex<EnforcementState>>>>,
12671269
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
12681270
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
12691271
pub next_signer_disabled_ops: Mutex<HashSet<SignerOp>>,
@@ -1319,7 +1321,9 @@ impl SignerProvider for TestKeysInterface {
13191321
fn derive_channel_signer(&self, channel_value_satoshis: u64, channel_keys_id: [u8; 32]) -> TestChannelSigner {
13201322
let keys = self.backing.derive_channel_signer(channel_value_satoshis, channel_keys_id);
13211323
let state = self.make_enforcement_state_cell(keys.commitment_seed);
1322-
let signer = TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check);
1324+
let rev_checks = self.disable_revocation_policy_check;
1325+
let state_checks = self.disable_all_state_policy_checks;
1326+
let signer = TestChannelSigner::new_with_revoked(keys, state, rev_checks, state_checks);
13231327
#[cfg(test)]
13241328
if let Some(ops) = self.unavailable_signers_ops.lock().unwrap().get(&channel_keys_id) {
13251329
for &op in ops {
@@ -1342,7 +1346,8 @@ impl SignerProvider for TestKeysInterface {
13421346
Ok(TestChannelSigner::new_with_revoked(
13431347
inner,
13441348
state,
1345-
self.disable_revocation_policy_check
1349+
self.disable_revocation_policy_check,
1350+
self.disable_all_state_policy_checks,
13461351
))
13471352
}
13481353

@@ -1366,6 +1371,7 @@ impl TestKeysInterface {
13661371
backing: sign::PhantomKeysManager::new(seed, now.as_secs(), now.subsec_nanos(), seed),
13671372
override_random_bytes: Mutex::new(None),
13681373
disable_revocation_policy_check: false,
1374+
disable_all_state_policy_checks: false,
13691375
enforcement_states: Mutex::new(new_hash_map()),
13701376
expectations: Mutex::new(None),
13711377
unavailable_signers_ops: Mutex::new(new_hash_map()),

0 commit comments

Comments
 (0)