Skip to content

test(tbtc): multi-signer simulated integration test for reservation coordination - #4279

Draft
piotr-roslaniec wants to merge 3 commits into
m1/reservation-coordination-checklistfrom
m1/reservation-multisigner-integration-test
Draft

test(tbtc): multi-signer simulated integration test for reservation coordination#4279
piotr-roslaniec wants to merge 3 commits into
m1/reservation-coordination-checklistfrom
m1/reservation-multisigner-integration-test

Conversation

@piotr-roslaniec

Copy link
Copy Markdown
Collaborator

Summary

Implements implementation-plan.md Milestone 3's "multi-signer simulated
integration test" item - the last piece of the full M1 keep-core-readiness
implementation plan (M0 is an external release-coordination gate, not a code
task; M1's four rows and M2's test-coverage backfill are covered by
#4276,
#4277,
#4278, and a
separate M2 follow-up PR).

Stacked on m1/reservation-coordination-checklist
(#4278), tip
c8eb5419f.

Scope note (per explicit decision this session): Milestone 3 has two
items - this test, and a "testnet round with a forced liveness/stranding
drill" (~2 weeks, needs a live testnet deployment and real multi-operator
wall-clock timing). Only the former is code; the latter is tracked as an
agent-not-actionable item in the plan doc, unchanged by this PR.

Change

Scales TestCoordinationExecutor_Coordinate's existing 3-operator harness -
deterministic keypairs, real per-operator localChain fakes, a real shared
netlocal.BroadcastChannel, one goroutine per operator running
coordinationExecutor.coordinate concurrently - to ReservationAnchorProposal
and ReservationReanchorProposal:

  • TestCoordinationExecutor_Coordinate_ReservationAnchor
  • TestCoordinationExecutor_Coordinate_ReservationReanchor

This exercises the real leader/follower coordination round-trip (checklist
generation -> leader election -> broadcast -> follower validation ->
convergence) that no mocked pkg/tbtcpg unit test can cover, since those
call task.Run(request) directly and never go through
coordinationExecutor.coordinate. It also exercises #4277's protobuf
marshaling of both proposal types over a real wire round-trip, since every
follower unmarshals the leader's broadcast coordinationMessage.

Depends on #4278 (this branch's parent): before that fix,
ActionReservationAnchor/ActionReservationReanchor never appeared in
getActionsChecklist's output, so every operator's checklist search in
these tests fell through to NoopProposal and failed. Verified directly:
temporarily reverted #4278's checklist change, re-ran both new tests (both
failed with the expected NoopProposal mismatch), then restored it.

A bug found in this test's own harness

Both new tests initially shared one netlocal broadcast channel name.
getBroadcastChannel's registry is keyed by name and never releases old
channels, so under -race (which changed goroutine/channel-delivery timing
enough to surface it in ~every run), the reanchor test's follower sometimes
received a stale broadcast left over from the anchor test's leader - a
cross-test data race in the test harness itself, not in the production code
under test. Fixed by giving each test its own channel name; re-verified
stable across 10 repeated -race runs plus the full non-race and race
suites.

Testing

  • go test ./pkg/tbtc/...: 365/365 pass.
  • go test -race ./pkg/tbtc/...: clean, no data races, including
    -count=10 targeted at just the two new tests.
  • go build ./... && go test ./...: full repo, 49 packages, zero FAIL.
  • gofmt -l / go vet: clean.

Not in this PR

  • The testnet-round liveness/stranding drill (Milestone 3's other item) -
    operational, not code; tracked separately.
  • Milestone 2's test-coverage backfill - separate follow-up PR.

…oordination

Implementation-plan.md Milestone 3, 'multi-signer simulated
integration test' item (per user decision: build the test, leave the
testnet-drill item as an agent-not-actionable tracked item since it
needs live infra and calendar time, not code).

Scales TestCoordinationExecutor_Coordinate's existing 3-operator
harness - deterministic keypairs, real per-operator localChain fakes,
a real shared netlocal.BroadcastChannel, one goroutine per operator
running coordinationExecutor.coordinate concurrently - to
ReservationAnchorProposal and ReservationReanchorProposal. This
exercises the real leader/follower coordination round-trip
(checklist generation -> leader election -> broadcast -> follower
validation -> convergence) that no mocked pkg/tbtcpg unit test can
cover, since those call task.Run(request) directly and never go
through coordinationExecutor.coordinate. It also exercises PR
#4277's protobuf marshaling of both proposal types over a real wire
round-trip, since every follower unmarshals the leader's broadcast
coordinationMessage.

Depends on PR #4278 (this branch's parent): before that fix,
ActionReservationAnchor/ActionReservationReanchor never appeared in
getActionsChecklist's output, so every operator's checklist search in
these tests would fall through to NoopProposal and fail - confirmed
by temporarily reverting the checklist fix and re-running (both new
tests failed with the expected NoopProposal mismatch), then restoring
it.

Found and fixed one bug in this test's own harness during
verification: both new tests initially shared one netlocal broadcast
channel name. getBroadcastChannel's registry is keyed by name and
never releases old channels, so under -race (which changed
goroutine/channel-delivery timing enough to surface it in ~every
run), the reanchor test's follower sometimes received a stale
broadcast left over from the anchor test's leader. Fixed by giving
each test its own channel name; re-verified stable across 10
repeated -race runs plus the full non-race and race suites.

Testing:
- go test ./pkg/tbtc/...: 365/365 pass.
- go test -race ./pkg/tbtc/...: clean, no data races, including
  -count=10 on just the two new tests.
- go build ./... && go test ./...: full repo, 49 packages, zero FAIL.
- gofmt -l / go vet: clean.
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…ion-multisigner-integration-test

Auto-merged cleanly on coordination_test.go (this branch's own
additions - the multi-signer integration tests and their fixtures -
land purely after the base's content with zero line overlap), but the
merge exposed a real breakage in this branch's own new tests: both
TestCoordinationExecutor_Coordinate_ReservationAnchor and
_ReservationReanchor used coordinationBlock = 900, which predates
ReservationsActivationBlock (24559289) fixed on the base branch
(757c6d8). With the base's activation-block gate now in effect,
ActionReservationAnchor/ActionReservationReanchor never appear in the
checklist at block 900, so both tests' mock proposal generators fell
through to NoopProposal and failed.

Bumped both tests' coordinationBlock to 24559289+3511=24562800 (a
post-activation, 4th-coordination-window block, verified against the
same production getActionsChecklist this session already confirmed
correct on the base branch). Leader election is unaffected by this
change and stays at operator2: the coordination seed depends only on
the wallet public key hash and the injected safe-block hash - both
fixed regardless of which raw block number the test passes in - not on
the coordination block number itself. Corrected
newReservationCoordinationWallet's doc comment, which had claimed
leader election was tied to block 900 specifically.

Full repo: zero FAIL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant