Skip to content

node(svm): regression tests for SVM watcher - #4924

Open
johnsaigle wants to merge 24 commits into
wormhole-foundation:mainfrom
johnsaigle:feat-svm-watcher-regression-tests
Open

johnsaigle wants to merge 24 commits into
wormhole-foundation:mainfrom
johnsaigle:feat-svm-watcher-regression-tests

Conversation

@johnsaigle

@johnsaigle johnsaigle commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Adds regression tests for the Solana (SVM) watcher. #4931 is the EVM counterpart.

What the tests check

TestReplayGeneratedBundles replays 355 recorded transactions: 235 synthetic cases and 120 from mainnet. Each transaction runs through four watcher paths. The fixtures name them reobservation, observation, polling and account. The test compares the digest that each path emits for guardians to sign with a baseline in testdata/.

The baseline records what the watcher does today for these inputs. It does not prove that the watcher is correct, and it does not cover transactions outside this set. A change to the baseline needs a careful review of the diff.

The testgen package generates the synthetic data and fetches the mainnet data. testgen/README.md describes how to regenerate the fixtures.

Production code changes

The watcher logic is the same as on main. The PR makes two mechanical edits in client.go and reobserve.go. Most of the changed lines only move code that is already there.

  • The solanaRPCClient interface replaces *rpc.Client. Tests supply a mock. The interface lists only methods that the watcher already calls.
  • The goroutine bodies become named methods, the pattern that EVM Watcher Divergence Tests #4931 uses for the EVM watcher. Where the watcher used an inline body, it now starts a named method. The methods are runDataPump, runWatcher, runSlotFetcher, runRetryFetchBlock, runDelayedFetchBlock, runInitialFetchMessageAccount and runRetryFetchMessageAccount. Each body keeps its code. The moved code keeps the channelcheck edits from main.

The PR leaves shim.go, tx_for_addr.go, the Solana transaction v1 code (#4961) and the borsh code (#4892) untouched.

Tests of the moved code

watcher_loops_test.go tests runWatcher and runDataPump with a mock RPC client and a local websocket server.

The runWatcher tests cover a stop on cancel, the slot update on each tick, and a bad observation request. They also cover a GetSlot error and a full error channel. The runDataPump tests check that messages arrive. They also check that the pump stops on cancel when its consumer has gone.

Two tests guard the channelcheck edits from main: the full error channel test and the stuck consumer test. Each one fails if the old plain channel send returns.

Checks

  • The 355 replay bundles also pass against the unmodified main logic with only the interface change. A scratch worktree confirmed this, so the baseline does not depend on the moved code.
  • make lint and go test -race pass for the Solana packages.
  • The CodeQL rules from codeql/ return no results for the Solana watcher.

Not covered

  • The tests use real timers. No test runs the retry paths, which wait 5 seconds between attempts.
  • The mock RPC client never fails on purpose. It has no timeouts or partial responses.
  • The tests use no random or adversarial inputs, and they do not explore goroutine interleavings.
  • testgen live needs a network RPC. CI does not run it.

johnsaigle and others added 21 commits November 4, 2026 13:57
Fix compile errors after the rebase onto main.

- Serialize test data with gagliardetto/binary. Main removed near/borsh-go.
- Write the message account with the current layout: VaaTime and VaaSignatureAccount replace MessageStatus, Gap and EmitterAuthority.
- Remove the pm_reliable_not_finalized case. It depended on the removed MessageStatus and Gap fields.
- Use rpc.CompiledInstruction for inner instructions and *big.Int for RentEpoch, as in the solana-go version on main.
- Run the transaction v1 lookup table test against the RPC client mock.
- Add testgen to the spellcheck dictionary and reword one README sentence.
@johnsaigle
johnsaigle force-pushed the feat-svm-watcher-regression-tests branch from 76b1003 to f447165 Compare November 4, 2026 19:05
Fix the alerts that CodeQL raised on this pull request.

- `solana-message-account-validation`: buildMessagePublicationFromAccountData takes raw account bytes. It creates the MessageAccountData with NewMessageAccountData and rejects the error before parsing. A new test covers the rejection.
- `solana-require-successful-transaction-meta`: testgen live collection calls validateTransactionMeta and rejects the error before it parses the transaction or reads metadata. Helpers now receive the validated fields.
- `canonical-vaa-address-parsing`: testgen converts the emitter with vaa.BytesToAddress. This replaces a local copy helper.

Run the three rules against a fresh database of the Solana watcher. They report no results.
Remove TestFigureOutTestData from the EVM watcher tests. The test computes two hashes for one Solana message. It does not test EVM code, and the Solana replay tests already cover the digests.
Restore the watcher logic from main wherever the regression tests do not need a change. The replay tests pass against the unmodified main logic plus the RPC interface.

- Remove `observations.go` and the shim PostMessage parse reorder. No test uses them, and they changed the order of the shim checks.
- Take `shim.go`, `shim_test.go`, `tx_for_addr.go` and `client_test.go` from main again.
- Remove `routines.go`. The run loops and retry bodies stay as named methods in `client.go`, next to the code that starts them. Each body moved without a change.
- Add tests for `runWatcher` and `runDataPump`. The tests check that the loops stop on cancel and record the slot on each tick. They also check a bad observation request, a full error channel, and a consumer that stops reading.
@johnsaigle johnsaigle changed the title node(svm): VAA injectivity regression tests for SVM watcher node(svm): regression tests for SVM watcher Nov 5, 2026
@johnsaigle
johnsaigle marked this pull request as ready for review November 6, 2026 21:24

This branch has not been deployed

No deployments
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.

3 participants