feat(devenv/tcapi): bound persistent-network event scans, add delivery-only Run mode#1221
Conversation
- Push OnchainSigningPubKey for every declared chain, not just the chain's own, so JD lane resolution can derive a signer address for a family the NOP never declared (e.g. a solana-only NOP signing into a canton-destination lane). - Reject Chains configs that mix chain families: a bootstrapper is built for exactly one family and shares one signing key across every declared chain, so a mixed list would silently push a mis-formatted key for whichever family loses out.
| // long-lived chain, so it neither scans from genesis nor exceeds the provider's | ||
| // getLogs range limit — in blocks, not wall-clock, since the target event is always | ||
| // recent. Mirrors verifier/pkg/sourcereader's DefaultMaxBlockRange. | ||
| const fallbackLookbackBlocks uint64 = 1500 |
There was a problem hiding this comment.
Kept as an independent constant rather than importing sourcereader.DefaultMaxBlockRange to avoid a devenv>verifier package dependency
There was a problem hiding this comment.
Pull request overview
This PR improves devenv e2e test reliability when attaching to long-lived/persistent chains by (a) preventing the EVM event poller from doing an unbounded initial eth_getLogs scan and (b) adding a “delivery-only” mode in tcapi runs that skips offchain aggregator/indexer assertions.
Changes:
- Bound the first EVM event poller scan using a fixed lookback window and make onRamp/offRamp pollers lazy to avoid unnecessary setup.
- Add
RunConfig.OnchainAssertionOnlyto allow tcapi test cases to skip aggregator/indexer wiring and assertions while still confirming on-chain send/exec. - Add unit coverage for the lookback start-block helper.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| build/devenv/tests/e2e/tcapi/types.go | Extends RunConfig with OnchainAssertionOnly and updates doc comment to reflect assertion scope. |
| build/devenv/tests/e2e/tcapi/token_transfer/v3.go | Conditionally wires aggregator/indexer clients and relaxes offchain assertion requirements when OnchainAssertionOnly is enabled. |
| build/devenv/tests/e2e/tcapi/basic/v3.go | Adds the same OnchainAssertionOnly behavior and factors aggregator/indexer setup into a helper. |
| build/devenv/evm/impl.go | Removes eager poller construction and introduces lazy poller creation via getOrCreate*Poller() paths. |
| build/devenv/evm/event_poller.go | Bounds the initial event scan with a fallback lookback start block. |
| build/devenv/evm/event_poller_test.go | Adds test coverage for the fallback lookback start-block helper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| aggregatorClients, err := tc.lib.AllAggregators() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get aggregator clients: %w", err) | ||
| } | ||
| aggregatorClient := aggregatorClients[common.DefaultCommitteeVerifierQualifier] | ||
| if tc.aggregatorQualifier != "" && tc.aggregatorQualifier != common.DefaultCommitteeVerifierQualifier { | ||
| if client, ok := aggregatorClients[tc.aggregatorQualifier]; ok { | ||
| aggregatorClient = client | ||
| var aggregatorClient *ccv.AggregatorClient | ||
| var indexerMonitor *ccv.IndexerMonitor | ||
| if !tc.args.Run.OnchainAssertionOnly { | ||
| var setupErr error | ||
| aggregatorClient, indexerMonitor, setupErr = setupAggregatorAndIndexer(tc.lib, tc.aggregatorQualifier) | ||
| if setupErr != nil { | ||
| return setupErr |
There was a problem hiding this comment.
question: I had a similar idea to make aggregator/indexer assertions optional on environments where this information may not be available - was wondering if we should gate this purely based on presence (i.e. len(aggregatorClients) == 0 means no aggregator assertions - or if aggregatorClient, ok returns nil, false, skip the assertion) vs. doing it via flag (OnchainAssertionOnly).
The main advantage I see to the presence-based approach is that you don't need to update the test code or write a new test in order to run it in different environments - but curious as to what your. thoughts are.
There was a problem hiding this comment.
Valid point, TestingContext.AssertMessage seems to be presence-based already, but iirc there was hard configuration validation. Maybe I can split that logic into absence vs. connection failure on lib construction. Let me explore a bit
|
Code coverage report:
|
Description
Two independent devenv/tcapi changes needed to run e2e tests against persistent staging chains instead of only local devenv:
build/devenv/evm: the event poller's firsteth_getLogsscan ran unbounded ([1, latest]), which blows up against a long-lived chain like Sepolia and exceeds RPC provider block-range limits. Bounds the first scan to the last 1500 blocks (fallbackLookbackBlocks, mirroringverifier/pkg/sourcereader.DefaultMaxBlockRange), since the target event is always recent when a waiter registers. Also makes onRamp/offRamp poller construction lazy, so a test only pays for the pollers it actually uses.Presence-based offchain assertions.
ccv.Lib's plural gettersAllAggregators/AllIndexersnow return an empty result with a nil error when the environment declares no aggregator/indexer endpoints, instead of erroring; the singular getters keep their original error contract. A shared helpertcapi.SetupOffchainClientswires the aggregator/indexer clients when configured and returns nil clients when not, andbasic.Run/token_transfer.Rungate their aggregator/indexer assertions on client presence (AssertMessagealready skips stages for nil clients).Testing
env-phased-out.toml):TestSolana2EVMandTestEVM2Solana(all subtests, including the 4 TokenTransfer pool combinations and ArbMessaging) pass; endpoints are configured, so offchain assertions run as before.Libgetter absence/error contract and forSetupOffchainClients(present / absent / broken).env-private-staging.toml, Sepolia <-> Solana devnet): the presence path correctly detects no offchain endpoints and runs on-chain-onlyRequires
Checklist
changelogdirectory)just lint fix- no new lint errorsjust generate- mocks and protobufs are up to date