Skip to content

Commit 3b08fea

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 5f247a6 commit 3b08fea

File tree

4 files changed

+59
-42
lines changed

4 files changed

+59
-42
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ impl SignerProvider for KeyProvider {
380380
);
381381
let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed);
382382
let keys = DynSigner::new(keys);
383-
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false)
383+
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false, false)
384384
}
385385

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

fuzz/src/full_stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ impl SignerProvider for KeyProvider {
465465
f = key;
466466
let signer = InMemorySigner::new(&secp_ctx, a, b, c, d, e, f, keys_id, keys_id);
467467

468-
TestChannelSigner::new_with_revoked(DynSigner::new(signer), state, false)
468+
TestChannelSigner::new_with_revoked(DynSigner::new(signer), state, false, false)
469469
}
470470

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

lightning/src/util/test_channel_signer.rs

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ pub struct TestChannelSigner {
7474
/// Channel state used for policy enforcement
7575
pub state: Arc<Mutex<EnforcementState>>,
7676
pub disable_revocation_policy_check: bool,
77+
pub disable_all_state_policy_checks: bool,
7778
}
7879

7980
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -123,7 +124,12 @@ impl TestChannelSigner {
123124
/// Construct an TestChannelSigner
124125
pub fn new(inner: DynSigner) -> Self {
125126
let state = Arc::new(Mutex::new(EnforcementState::new()));
126-
Self { inner, state, disable_revocation_policy_check: false }
127+
Self {
128+
inner,
129+
state,
130+
disable_revocation_policy_check: false,
131+
disable_all_state_policy_checks: false,
132+
}
127133
}
128134

129135
/// Construct an TestChannelSigner with externally managed storage
@@ -133,9 +139,9 @@ impl TestChannelSigner {
133139
/// here, usually by an implementation of KeysInterface.
134140
pub fn new_with_revoked(
135141
inner: DynSigner, state: Arc<Mutex<EnforcementState>>,
136-
disable_revocation_policy_check: bool,
142+
disable_revocation_policy_check: bool, disable_all_state_policy_checks: bool,
137143
) -> Self {
138-
Self { inner, state, disable_revocation_policy_check }
144+
Self { inner, state, disable_revocation_policy_check, disable_all_state_policy_checks }
139145
}
140146

141147
#[cfg(any(test, feature = "_test_utils"))]
@@ -175,12 +181,12 @@ impl ChannelSigner for TestChannelSigner {
175181
if !self.is_signer_available(SignerOp::ReleaseCommitmentSecret) {
176182
return Err(());
177183
}
178-
{
179-
let mut state = self.state.lock().unwrap();
184+
let mut state = self.state.lock().unwrap();
185+
if !self.disable_all_state_policy_checks {
180186
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);
181187
assert!(idx > state.last_holder_commitment, "cannot revoke the last holder commitment - attempted to revoke {} last commitment {}", idx, state.last_holder_commitment);
182-
state.last_holder_revoked_commitment = idx;
183188
}
189+
state.last_holder_revoked_commitment = idx;
184190
self.inner.release_commitment_secret(idx)
185191
}
186192

@@ -190,12 +196,14 @@ impl ChannelSigner for TestChannelSigner {
190196
) -> Result<(), ()> {
191197
let mut state = self.state.lock().unwrap();
192198
let idx = holder_tx.commitment_number();
193-
assert!(
194-
idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1,
195-
"expecting to validate the current or next holder commitment - trying {}, current {}",
196-
idx,
197-
state.last_holder_commitment
198-
);
199+
if !self.disable_all_state_policy_checks {
200+
assert!(
201+
idx == state.last_holder_commitment || idx == state.last_holder_commitment - 1,
202+
"expecting to validate the current or next holder commitment - trying {}, current {}",
203+
idx,
204+
state.last_holder_commitment
205+
);
206+
}
199207
state.last_holder_commitment = idx;
200208
Ok(())
201209
}
@@ -206,7 +214,9 @@ impl ChannelSigner for TestChannelSigner {
206214
return Err(());
207215
}
208216
let mut state = self.state.lock().unwrap();
209-
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);
217+
if !self.disable_all_state_policy_checks {
218+
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);
219+
}
210220
state.last_counterparty_revoked_commitment = idx;
211221
Ok(())
212222
}
@@ -230,14 +240,14 @@ impl EcdsaChannelSigner for TestChannelSigner {
230240
) -> Result<(Signature, Vec<Signature>), ()> {
231241
self.verify_counterparty_commitment_tx(channel_parameters, commitment_tx, secp_ctx);
232242

233-
{
234-
#[cfg(test)]
235-
if !self.is_signer_available(SignerOp::SignCounterpartyCommitment) {
236-
return Err(());
237-
}
238-
let mut state = self.state.lock().unwrap();
239-
let actual_commitment_number = commitment_tx.commitment_number();
240-
let last_commitment_number = state.last_counterparty_commitment;
243+
#[cfg(test)]
244+
if !self.is_signer_available(SignerOp::SignCounterpartyCommitment) {
245+
return Err(());
246+
}
247+
let mut state = self.state.lock().unwrap();
248+
let actual_commitment_number = commitment_tx.commitment_number();
249+
let last_commitment_number = state.last_counterparty_commitment;
250+
if !self.disable_all_state_policy_checks {
241251
// These commitment numbers are backwards counting. We expect either the same as the previously encountered,
242252
// or the next one.
243253
assert!(
@@ -255,9 +265,9 @@ impl EcdsaChannelSigner for TestChannelSigner {
255265
actual_commitment_number,
256266
state.last_counterparty_revoked_commitment
257267
);
258-
state.last_counterparty_commitment =
259-
cmp::min(last_commitment_number, actual_commitment_number)
260268
}
269+
state.last_counterparty_commitment =
270+
cmp::min(last_commitment_number, actual_commitment_number);
261271

262272
Ok(self
263273
.inner
@@ -281,14 +291,16 @@ impl EcdsaChannelSigner for TestChannelSigner {
281291
}
282292
let trusted_tx =
283293
self.verify_holder_commitment_tx(channel_parameters, commitment_tx, secp_ctx);
284-
let state = self.state.lock().unwrap();
285-
let commitment_number = trusted_tx.commitment_number();
286-
if state.last_holder_revoked_commitment - 1 != commitment_number
287-
&& state.last_holder_revoked_commitment - 2 != commitment_number
288-
{
289-
if !self.disable_revocation_policy_check {
290-
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
291-
state.last_holder_revoked_commitment, commitment_number, self.inner.channel_keys_id()[0])
294+
if !self.disable_all_state_policy_checks {
295+
let state = self.state.lock().unwrap();
296+
let commitment_number = trusted_tx.commitment_number();
297+
if state.last_holder_revoked_commitment - 1 != commitment_number
298+
&& state.last_holder_revoked_commitment - 2 != commitment_number
299+
{
300+
if !self.disable_revocation_policy_check {
301+
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
302+
state.last_holder_revoked_commitment, commitment_number, self.inner.channel_keys_id()[0])
303+
}
292304
}
293305
}
294306
Ok(self.inner.sign_holder_commitment(channel_parameters, commitment_tx, secp_ctx).unwrap())
@@ -356,13 +368,15 @@ impl EcdsaChannelSigner for TestChannelSigner {
356368
if !self.is_signer_available(SignerOp::SignHolderHtlcTransaction) {
357369
return Err(());
358370
}
359-
let state = self.state.lock().unwrap();
360-
if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number
361-
&& state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number
362-
{
363-
if !self.disable_revocation_policy_check {
364-
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
365-
state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.channel_keys_id()[0])
371+
if !self.disable_all_state_policy_checks {
372+
let state = self.state.lock().unwrap();
373+
if state.last_holder_revoked_commitment - 1 != htlc_descriptor.per_commitment_number
374+
&& state.last_holder_revoked_commitment - 2 != htlc_descriptor.per_commitment_number
375+
{
376+
if !self.disable_revocation_policy_check {
377+
panic!("can only sign the next two unrevoked commitment numbers, revoked={} vs requested={} for {}",
378+
state.last_holder_revoked_commitment, htlc_descriptor.per_commitment_number, self.inner.channel_keys_id()[0])
379+
}
366380
}
367381
}
368382
assert_eq!(htlc_tx.input[input], htlc_descriptor.unsigned_tx_input());

lightning/src/util/test_utils.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,7 @@ pub struct TestKeysInterface {
15311531
pub backing: DynKeysInterface,
15321532
pub override_random_bytes: Mutex<Option<[u8; 32]>>,
15331533
pub disable_revocation_policy_check: bool,
1534+
pub disable_all_state_policy_checks: bool,
15341535
enforcement_states: Mutex<HashMap<[u8; 32], Arc<Mutex<EnforcementState>>>>,
15351536
expectations: Mutex<Option<VecDeque<OnGetShutdownScriptpubkey>>>,
15361537
pub unavailable_signers_ops: Mutex<HashMap<[u8; 32], HashSet<SignerOp>>>,
@@ -1599,8 +1600,9 @@ impl SignerProvider for TestKeysInterface {
15991600
fn derive_channel_signer(&self, channel_keys_id: [u8; 32]) -> TestChannelSigner {
16001601
let keys = self.backing.derive_channel_signer(channel_keys_id);
16011602
let state = self.make_enforcement_state_cell(keys.channel_keys_id());
1602-
let signer =
1603-
TestChannelSigner::new_with_revoked(keys, state, self.disable_revocation_policy_check);
1603+
let rev_checks = self.disable_revocation_policy_check;
1604+
let state_checks = self.disable_all_state_policy_checks;
1605+
let signer = TestChannelSigner::new_with_revoked(keys, state, rev_checks, state_checks);
16041606
#[cfg(test)]
16051607
if let Some(ops) = self.unavailable_signers_ops.lock().unwrap().get(&channel_keys_id) {
16061608
for &op in ops {
@@ -1668,6 +1670,7 @@ impl TestKeysInterface {
16681670
backing: DynKeysInterface::new(backing),
16691671
override_random_bytes: Mutex::new(None),
16701672
disable_revocation_policy_check: false,
1673+
disable_all_state_policy_checks: false,
16711674
enforcement_states: Mutex::new(new_hash_map()),
16721675
expectations: Mutex::new(None),
16731676
unavailable_signers_ops: Mutex::new(new_hash_map()),

0 commit comments

Comments
 (0)