Skip to content

Commit 20851ff

Browse files
committed
Augment the chanmon fuzzer with async ops
Originally from Matt. This augments the channel monitor consistency tests with ops that disable and enable the signer to simulate asynchronous remote signing.
1 parent e8c95bb commit 20851ff

File tree

1 file changed

+136
-35
lines changed

1 file changed

+136
-35
lines changed

fuzz/src/chanmon_consistency.rs

+136-35
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use lightning::ln::script::ShutdownScript;
4646
use lightning::ln::functional_test_utils::*;
4747
use lightning::offers::invoice::UnsignedBolt12Invoice;
4848
use lightning::offers::invoice_request::UnsignedInvoiceRequest;
49-
use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState};
49+
use lightning::util::test_channel_signer::{TestChannelSigner, EnforcementState, ops};
5050
use lightning::util::errors::APIError;
5151
use lightning::util::logger::Logger;
5252
use lightning::util::config::UserConfig;
@@ -69,6 +69,7 @@ use std::sync::atomic;
6969
use std::io::Cursor;
7070
use bitcoin::bech32::u5;
7171

72+
const ASYNC_OPS: u32 = ops::GET_PER_COMMITMENT_POINT | ops::RELEASE_COMMITMENT_SECRET | ops::SIGN_COUNTERPARTY_COMMITMENT;
7273
const MAX_FEE: u32 = 10_000;
7374
struct FuzzEstimator {
7475
ret_val: atomic::AtomicU32,
@@ -168,10 +169,15 @@ impl chain::Watch<TestChannelSigner> for TestChainMonitor {
168169
}
169170
}
170171

172+
struct SignerState {
173+
enforcement: Arc<Mutex<EnforcementState>>,
174+
unavailable: Arc<Mutex<u32>>,
175+
}
176+
171177
struct KeyProvider {
172178
node_secret: SecretKey,
173179
rand_bytes_id: atomic::AtomicU32,
174-
enforcement_states: Mutex<HashMap<[u8;32], Arc<Mutex<EnforcementState>>>>,
180+
enforcement_states: Mutex<HashMap<[u8;32], SignerState>>,
175181
}
176182

177183
impl EntropySource for KeyProvider {
@@ -253,22 +259,19 @@ impl SignerProvider for KeyProvider {
253259
channel_keys_id,
254260
channel_keys_id,
255261
);
256-
let revoked_commitment = self.make_enforcement_state_cell(keys.commitment_seed);
257-
TestChannelSigner::new_with_revoked(keys, revoked_commitment, false)
262+
let mut revoked_commitments = self.enforcement_states.lock().unwrap();
263+
let new_state = revoked_commitments.entry(keys.commitment_seed)
264+
.or_insert(SignerState {
265+
enforcement: Arc::new(Mutex::new(EnforcementState::new())),
266+
unavailable: Arc::new(Mutex::new(0)),
267+
});
268+
let mut ret = TestChannelSigner::new_with_revoked(keys, Arc::clone(&new_state.enforcement), false);
269+
ret.unavailable = Arc::clone(&new_state.unavailable);
270+
ret
258271
}
259272

260-
fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, DecodeError> {
261-
let mut reader = std::io::Cursor::new(buffer);
262-
263-
let inner: InMemorySigner = ReadableArgs::read(&mut reader, self)?;
264-
let state = self.make_enforcement_state_cell(inner.commitment_seed);
265-
266-
Ok(TestChannelSigner {
267-
inner,
268-
state,
269-
disable_revocation_policy_check: false,
270-
unavailable: Arc::new(Mutex::new(0)),
271-
})
273+
fn read_chan_signer(&self, _buffer: &[u8]) -> Result<Self::Signer, DecodeError> {
274+
unreachable!();
272275
}
273276

274277
fn get_destination_script(&self) -> Result<Script, ()> {
@@ -286,17 +289,6 @@ impl SignerProvider for KeyProvider {
286289
}
287290
}
288291

289-
impl KeyProvider {
290-
fn make_enforcement_state_cell(&self, commitment_seed: [u8; 32]) -> Arc<Mutex<EnforcementState>> {
291-
let mut revoked_commitments = self.enforcement_states.lock().unwrap();
292-
if !revoked_commitments.contains_key(&commitment_seed) {
293-
revoked_commitments.insert(commitment_seed, Arc::new(Mutex::new(EnforcementState::new())));
294-
}
295-
let cell = revoked_commitments.get(&commitment_seed).unwrap();
296-
Arc::clone(cell)
297-
}
298-
}
299-
300292
#[inline]
301293
fn check_api_err(api_err: APIError, sendable_bounds_violated: bool) {
302294
match api_err {
@@ -799,7 +791,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
799791
for (idx, dest) in nodes.iter().enumerate() {
800792
if dest.get_our_node_id() == node_id {
801793
for update_add in update_add_htlcs.iter() {
802-
out.locked_write(format!("Delivering update_add_htlc to node {}.\n", idx).as_bytes());
794+
out.locked_write(format!("Delivering update_add_htlc to node {} from node {}.\n", idx, $node).as_bytes());
803795
if !$corrupt_forward {
804796
dest.handle_update_add_htlc(&nodes[$node].get_our_node_id(), update_add);
805797
} else {
@@ -814,19 +806,19 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
814806
}
815807
}
816808
for update_fulfill in update_fulfill_htlcs.iter() {
817-
out.locked_write(format!("Delivering update_fulfill_htlc to node {}.\n", idx).as_bytes());
809+
out.locked_write(format!("Delivering update_fulfill_htlc to node {} from node {}.\n", idx, $node).as_bytes());
818810
dest.handle_update_fulfill_htlc(&nodes[$node].get_our_node_id(), update_fulfill);
819811
}
820812
for update_fail in update_fail_htlcs.iter() {
821-
out.locked_write(format!("Delivering update_fail_htlc to node {}.\n", idx).as_bytes());
813+
out.locked_write(format!("Delivering update_fail_htlc to node {} from node {}.\n", idx, $node).as_bytes());
822814
dest.handle_update_fail_htlc(&nodes[$node].get_our_node_id(), update_fail);
823815
}
824816
for update_fail_malformed in update_fail_malformed_htlcs.iter() {
825-
out.locked_write(format!("Delivering update_fail_malformed_htlc to node {}.\n", idx).as_bytes());
817+
out.locked_write(format!("Delivering update_fail_malformed_htlc to node {} from node {}.\n", idx, $node).as_bytes());
826818
dest.handle_update_fail_malformed_htlc(&nodes[$node].get_our_node_id(), update_fail_malformed);
827819
}
828820
if let Some(msg) = update_fee {
829-
out.locked_write(format!("Delivering update_fee to node {}.\n", idx).as_bytes());
821+
out.locked_write(format!("Delivering update_fee to node {} from node {}.\n", idx, $node).as_bytes());
830822
dest.handle_update_fee(&nodes[$node].get_our_node_id(), &msg);
831823
}
832824
let processed_change = !update_add_htlcs.is_empty() || !update_fulfill_htlcs.is_empty() ||
@@ -843,7 +835,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
843835
} });
844836
break;
845837
}
846-
out.locked_write(format!("Delivering commitment_signed to node {}.\n", idx).as_bytes());
838+
out.locked_write(format!("Delivering commitment_signed to node {} from node {}.\n", idx, $node).as_bytes());
847839
dest.handle_commitment_signed(&nodes[$node].get_our_node_id(), &commitment_signed);
848840
break;
849841
}
@@ -852,15 +844,15 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
852844
events::MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => {
853845
for (idx, dest) in nodes.iter().enumerate() {
854846
if dest.get_our_node_id() == *node_id {
855-
out.locked_write(format!("Delivering revoke_and_ack to node {}.\n", idx).as_bytes());
847+
out.locked_write(format!("Delivering revoke_and_ack to node {} from node {}.\n", idx, $node).as_bytes());
856848
dest.handle_revoke_and_ack(&nodes[$node].get_our_node_id(), msg);
857849
}
858850
}
859851
},
860852
events::MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } => {
861853
for (idx, dest) in nodes.iter().enumerate() {
862854
if dest.get_our_node_id() == *node_id {
863-
out.locked_write(format!("Delivering channel_reestablish to node {}.\n", idx).as_bytes());
855+
out.locked_write(format!("Delivering channel_reestablish to node {} from node {}.\n", idx, $node).as_bytes());
864856
dest.handle_channel_reestablish(&nodes[$node].get_our_node_id(), msg);
865857
}
866858
}
@@ -1259,6 +1251,102 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
12591251
},
12601252
0x89 => { fee_est_c.ret_val.store(253, atomic::Ordering::Release); nodes[2].maybe_update_chan_fees(); },
12611253

1254+
0xa0 => {
1255+
let signer_states = keys_manager_a.enforcement_states.lock().unwrap();
1256+
assert_eq!(signer_states.len(), 1);
1257+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() = ASYNC_OPS;
1258+
}
1259+
0xa1 => {
1260+
let signer_states = keys_manager_a.enforcement_states.lock().unwrap();
1261+
assert_eq!(signer_states.len(), 1);
1262+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::GET_PER_COMMITMENT_POINT;
1263+
nodes[0].signer_unblocked(None);
1264+
}
1265+
0xa2 => {
1266+
let signer_states = keys_manager_a.enforcement_states.lock().unwrap();
1267+
assert_eq!(signer_states.len(), 1);
1268+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::RELEASE_COMMITMENT_SECRET;
1269+
nodes[0].signer_unblocked(None);
1270+
}
1271+
0xa3 => {
1272+
let signer_states = keys_manager_a.enforcement_states.lock().unwrap();
1273+
assert_eq!(signer_states.len(), 1);
1274+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::SIGN_COUNTERPARTY_COMMITMENT;
1275+
nodes[0].signer_unblocked(None);
1276+
}
1277+
1278+
0xa4 => {
1279+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1280+
assert_eq!(signer_states.len(), 2);
1281+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() = ASYNC_OPS;
1282+
}
1283+
0xa5 => {
1284+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1285+
assert_eq!(signer_states.len(), 2);
1286+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::GET_PER_COMMITMENT_POINT;
1287+
nodes[1].signer_unblocked(None);
1288+
}
1289+
0xa6 => {
1290+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1291+
assert_eq!(signer_states.len(), 2);
1292+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::RELEASE_COMMITMENT_SECRET;
1293+
nodes[1].signer_unblocked(None);
1294+
}
1295+
0xa7 => {
1296+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1297+
assert_eq!(signer_states.len(), 2);
1298+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::SIGN_COUNTERPARTY_COMMITMENT;
1299+
nodes[1].signer_unblocked(None);
1300+
}
1301+
1302+
0xa8 => {
1303+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1304+
assert_eq!(signer_states.len(), 2);
1305+
*signer_states.values().last().unwrap().unavailable.lock().unwrap() = ASYNC_OPS;
1306+
}
1307+
0xa9 => {
1308+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1309+
assert_eq!(signer_states.len(), 2);
1310+
*signer_states.values().last().unwrap().unavailable.lock().unwrap() &= !ops::GET_PER_COMMITMENT_POINT;
1311+
nodes[1].signer_unblocked(None);
1312+
}
1313+
0xaa => {
1314+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1315+
assert_eq!(signer_states.len(), 2);
1316+
*signer_states.values().last().unwrap().unavailable.lock().unwrap() &= !ops::RELEASE_COMMITMENT_SECRET;
1317+
nodes[1].signer_unblocked(None);
1318+
}
1319+
0xab => {
1320+
let signer_states = keys_manager_b.enforcement_states.lock().unwrap();
1321+
assert_eq!(signer_states.len(), 2);
1322+
*signer_states.values().last().unwrap().unavailable.lock().unwrap() &= !ops::SIGN_COUNTERPARTY_COMMITMENT;
1323+
nodes[1].signer_unblocked(None);
1324+
}
1325+
1326+
0xac => {
1327+
let signer_states = keys_manager_c.enforcement_states.lock().unwrap();
1328+
assert_eq!(signer_states.len(), 1);
1329+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() = ASYNC_OPS;
1330+
}
1331+
0xad => {
1332+
let signer_states = keys_manager_c.enforcement_states.lock().unwrap();
1333+
assert_eq!(signer_states.len(), 1);
1334+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::GET_PER_COMMITMENT_POINT;
1335+
nodes[2].signer_unblocked(None);
1336+
}
1337+
0xae => {
1338+
let signer_states = keys_manager_c.enforcement_states.lock().unwrap();
1339+
assert_eq!(signer_states.len(), 1);
1340+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::RELEASE_COMMITMENT_SECRET;
1341+
nodes[2].signer_unblocked(None);
1342+
}
1343+
0xaf => {
1344+
let signer_states = keys_manager_c.enforcement_states.lock().unwrap();
1345+
assert_eq!(signer_states.len(), 1);
1346+
*signer_states.values().next().unwrap().unavailable.lock().unwrap() &= !ops::SIGN_COUNTERPARTY_COMMITMENT;
1347+
nodes[2].signer_unblocked(None);
1348+
}
1349+
12621350
0xff => {
12631351
// Test that no channel is in a stuck state where neither party can send funds even
12641352
// after we resolve all pending events.
@@ -1268,6 +1356,19 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
12681356
*monitor_b.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateStatus::Completed;
12691357
*monitor_c.persister.update_ret.lock().unwrap() = ChannelMonitorUpdateStatus::Completed;
12701358

1359+
for signer_state in keys_manager_a.enforcement_states.lock().unwrap().values() {
1360+
*signer_state.unavailable.lock().unwrap() = 0;
1361+
}
1362+
for signer_state in keys_manager_b.enforcement_states.lock().unwrap().values() {
1363+
*signer_state.unavailable.lock().unwrap() = 0;
1364+
}
1365+
for signer_state in keys_manager_c.enforcement_states.lock().unwrap().values() {
1366+
*signer_state.unavailable.lock().unwrap() = 0;
1367+
}
1368+
nodes[0].signer_unblocked(None);
1369+
nodes[1].signer_unblocked(None);
1370+
nodes[2].signer_unblocked(None);
1371+
12711372
if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) {
12721373
monitor_a.chain_monitor.force_channel_monitor_updated(chan_1_funding, *id);
12731374
nodes[0].process_monitor_events();

0 commit comments

Comments
 (0)