Skip to content

feat(devenv/tcapi): bound persistent-network event scans, add delivery-only Run mode#1221

Merged
jadepark-dev merged 12 commits into
mainfrom
jade/tcapi-persistent-env-support
Jul 3, 2026
Merged

feat(devenv/tcapi): bound persistent-network event scans, add delivery-only Run mode#1221
jadepark-dev merged 12 commits into
mainfrom
jade/tcapi-persistent-env-support

Conversation

@jadepark-dev

@jadepark-dev jadepark-dev commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Description

Two independent devenv/tcapi changes needed to run e2e tests against persistent staging chains instead of only local devenv:

  1. build/devenv/evm: the event poller's first eth_getLogs scan 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, mirroring verifier/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.

  2. Presence-based offchain assertions. ccv.Lib's plural getters AllAggregators/AllIndexers now 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 helper tcapi.SetupOffchainClients wires the aggregator/indexer clients when configured and returns nil clients when not, and basic.Run/token_transfer.Run gate their aggregator/indexer assertions on client presence (AssertMessage already skips stages for nil clients).

Testing

  • Local (env-phased-out.toml): TestSolana2EVM and TestEVM2Solana (all subtests, including the 4 TokenTransfer pool combinations and ArbMessaging) pass; endpoints are configured, so offchain assertions run as before.
  • Unit: table-driven tests for the Lib getter absence/error contract and for SetupOffchainClients (present / absent / broken).
  • Staging (env-private-staging.toml, Sepolia <-> Solana devnet): the presence path correctly detects no offchain endpoints and runs on-chain-only

Requires

Checklist

  • Breaking changes documented in changelog (see changelog directory)
  • Cross link related PRs (in this or other repositories)
  • just lint fix - no new lint errors
  • just generate - mocks and protobufs are up to date

jadepark-dev and others added 9 commits July 1, 2026 16:11
- 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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept as an independent constant rather than importing sourcereader.DefaultMaxBlockRange to avoid a devenv>verifier package dependency

@jadepark-dev jadepark-dev marked this pull request as ready for review July 2, 2026 21:31
@jadepark-dev jadepark-dev requested a review from a team as a code owner July 2, 2026 21:31
Copilot AI review requested due to automatic review settings July 2, 2026 21:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.OnchainAssertionOnly to 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.

Comment thread build/devenv/evm/event_poller_test.go
Comment on lines +114 to +120
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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Code coverage report:

Package main jade/tcapi-persistent-env-support Diff
github.com/smartcontractkit/chainlink-ccv/aggregator 49.55% 49.54% -0.01%
github.com/smartcontractkit/chainlink-ccv/bootstrap 55.13% 55.13% +0.00%
github.com/smartcontractkit/chainlink-ccv/cli 65.13% 65.13% +0.00%
github.com/smartcontractkit/chainlink-ccv/cmd 13.55% 13.55% +0.00%
github.com/smartcontractkit/chainlink-ccv/common 52.79% 52.79% +0.00%
github.com/smartcontractkit/chainlink-ccv/executor 46.47% 46.47% +0.00%
github.com/smartcontractkit/chainlink-ccv/indexer 35.47% 35.47% +0.00%
github.com/smartcontractkit/chainlink-ccv/integration 46.16% 46.25% +0.09%
github.com/smartcontractkit/chainlink-ccv/pkg 100.00% 100.00% +0.00%
github.com/smartcontractkit/chainlink-ccv/pricer 0.00% 0.00% +0.00%
github.com/smartcontractkit/chainlink-ccv/protocol 63.06% 63.06% +0.00%
github.com/smartcontractkit/chainlink-ccv/verifier 35.17% 35.18% +0.01%
Total 46.80% 46.90% +0.10%

@jadepark-dev jadepark-dev requested a review from makramkd July 3, 2026 14:08
@jadepark-dev jadepark-dev enabled auto-merge July 3, 2026 14:25
@jadepark-dev jadepark-dev added this pull request to the merge queue Jul 3, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 3, 2026
@jadepark-dev jadepark-dev added this pull request to the merge queue Jul 3, 2026
Merged via the queue into main with commit 60f7260 Jul 3, 2026
36 of 37 checks passed
@jadepark-dev jadepark-dev deleted the jade/tcapi-persistent-env-support branch July 3, 2026 14:48
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.

4 participants