From a34c97b3e2f53322a46bafed8b07db69d7e9bec8 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Thu, 17 Sep 2026 15:51:07 +0000 Subject: [PATCH] test(purgatory): choose same-second winners without nonce grinding The purgatory promotion regression searched up to 99,999 nonces for an event ID below a random baseline. A sufficiently low baseline could exhaust the search and fail without a product defect. Sign two candidates with distinct nonces and sort their IDs to assign winner and loser deterministically. Preserve their shared timestamp, declared Git state and losing-first submission order. Production promotion behavior is unchanged. Validation: the same-second purgatory integration test passes; workspace all-target Clippy and formatting pass. Assisted-by: GPT-6 --- tests/purgatory_sync.rs | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/tests/purgatory_sync.rs b/tests/purgatory_sync.rs index 28b8200..ca70605 100644 --- a/tests/purgatory_sync.rs +++ b/tests/purgatory_sync.rs @@ -39,7 +39,7 @@ use std::time::Duration; /// Build a state event with a nonce that changes its ID without changing its /// replaceable coordinate or declared repository state. -fn build_grinded_state_event( +fn build_nonce_state_event( keys: &Keys, identifier: &str, commit_hash: &str, @@ -66,7 +66,7 @@ fn build_grinded_state_event( ]) .custom_created_at(created_at) .finalize(keys) - .expect("build grinded state event") + .expect("build nonce-bearing state event") } /// Test that a git push triggers `process_newly_available_git_data` and @@ -181,29 +181,19 @@ async fn same_second_same_author_states_in_purgatory_keep_nip01_lowest_id() { let npub = keys.public_key().to_bech32().expect("encode public key"); let clone_url = format!("http://{}/{}/{}.git", relay.domain(), npub, identifier); let created_at = Timestamp::from_secs(Timestamp::now().as_secs() + 1); - let losing_state = build_grinded_state_event( - &keys, - identifier, - &commit_hash, - &clone_url, - relay.url(), - created_at, - 0, - ); - let winning_state = (1..100_000) - .map(|nonce| { - build_grinded_state_event( - &keys, - identifier, - &commit_hash, - &clone_url, - relay.url(), - created_at, - nonce, - ) - }) - .find(|candidate| candidate.id < losing_state.id) - .expect("nonce grinding must produce a lower NIP-01 event ID"); + let mut candidates = [0, 1].map(|nonce| { + build_nonce_state_event( + &keys, + identifier, + &commit_hash, + &clone_url, + relay.url(), + created_at, + nonce, + ) + }); + candidates.sort_by_key(|event| event.id); + let [winning_state, losing_state] = candidates; assert_eq!(losing_state.created_at, winning_state.created_at); assert!(winning_state.id < losing_state.id);