mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-24 21:45:20 +00:00
Fix CI exit hang: sign reassembled public packets in FragmentationTests
Bisecting (base was 4/4 clean, branch 3/3 hung, reliably reproducible) pinned the parallel-suite exit hang to the public-message signature requirement (security fix #2), via FragmentationTests: reassemblyFromFragmentsDeliversPublicMessage and duplicateFragmentDoesNotBreakReassembly send fragments of an UNSIGNED public message and `await capture.waitForPublicMessages(...)`. With #2 the reassembled unsigned message is now (correctly) dropped, so didReceivePublicMessage never fires. The helper then trips a latent bug: on timeout it cancels the waiter task but never resumes its CheckedContinuation, so the throwing task group's teardown awaits a child that never completes and the whole test process hangs at exit (SIGKILL'd by CI). Base never hit it because the message always arrived in time. Fix matches the security model — real public broadcasts are signed: sign the reassembled packet with a NoiseEncryptionService and preseed the sender's signing key (same pattern as duplicatePacket_isDeduped), so #2 verifies and delivers it. Full parallel suite now exits cleanly 5/5 locally (branch was 3/3 hung before). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -21,9 +21,16 @@ struct FragmentationTests {
|
||||
let capture = CaptureDelegate()
|
||||
ble.delegate = capture
|
||||
|
||||
// Construct a big packet (3KB) from a remote sender (not our own ID)
|
||||
// Construct a big SIGNED public packet (3KB) from a remote sender. Public
|
||||
// messages must carry a valid signature, so the reassembled packet is
|
||||
// signed and the sender's signing key is preseeded into the registry.
|
||||
let signer = NoiseEncryptionService(keychain: MockKeychain())
|
||||
let signingKey = signer.getSigningPublicKeyData()
|
||||
let remoteShortID = PeerID(str: "1122334455667788")
|
||||
let original = makeLargePublicPacket(senderShortHex: remoteShortID, size: 3_000)
|
||||
let original = try #require(
|
||||
signer.signPacket(makeLargePublicPacket(senderShortHex: remoteShortID, size: 3_000)),
|
||||
"Failed to sign public packet"
|
||||
)
|
||||
|
||||
// Use a small fragment size to ensure multiple pieces
|
||||
let fragments = fragmentPacket(original, fragmentSize: 400)
|
||||
@@ -36,7 +43,7 @@ struct FragmentationTests {
|
||||
if i > 0 {
|
||||
try await Task.sleep(for: .milliseconds(5))
|
||||
}
|
||||
ble._test_handlePacket(fragment, fromPeerID: remoteShortID)
|
||||
ble._test_handlePacket(fragment, fromPeerID: remoteShortID, signingPublicKey: signingKey)
|
||||
}
|
||||
|
||||
// Wait for delegate callback with proper timeout
|
||||
@@ -52,8 +59,13 @@ struct FragmentationTests {
|
||||
let capture = CaptureDelegate()
|
||||
ble.delegate = capture
|
||||
|
||||
let signer = NoiseEncryptionService(keychain: MockKeychain())
|
||||
let signingKey = signer.getSigningPublicKeyData()
|
||||
let remoteShortID = PeerID(str: "A1B2C3D4E5F60708")
|
||||
let original = makeLargePublicPacket(senderShortHex: remoteShortID, size: 2048)
|
||||
let original = try #require(
|
||||
signer.signPacket(makeLargePublicPacket(senderShortHex: remoteShortID, size: 2048)),
|
||||
"Failed to sign public packet"
|
||||
)
|
||||
var frags = fragmentPacket(original, fragmentSize: 300)
|
||||
|
||||
// Duplicate one fragment
|
||||
@@ -66,7 +78,7 @@ struct FragmentationTests {
|
||||
if i > 0 {
|
||||
try await Task.sleep(for: .milliseconds(5))
|
||||
}
|
||||
ble._test_handlePacket(fragment, fromPeerID: remoteShortID)
|
||||
ble._test_handlePacket(fragment, fromPeerID: remoteShortID, signingPublicKey: signingKey)
|
||||
}
|
||||
|
||||
// Wait for delegate callback with proper timeout
|
||||
|
||||
Reference in New Issue
Block a user