Skip to content

common: keystore and jd client support, use keystore and jd in verifier standalone mode#643

Open
makramkd wants to merge 19 commits intomainfrom
mk/jd-client
Open

common: keystore and jd client support, use keystore and jd in verifier standalone mode#643
makramkd wants to merge 19 commits intomainfrom
mk/jd-client

Conversation

@makramkd
Copy link
Collaborator

@makramkd makramkd commented Feb 6, 2026

Apologies in advance for the big PR: open to suggestions on breaking this up into smaller pieces.

This PR:

  • Switches the standalone verifier to use the standalone keystore (from chainlink-common) instead of relying on a supplied private key from the environment.
  • Switches the standalone verifier to get its config from JD instead of reading it from a volume.

Reasoning:

  • We can't use private keys supplied by environment variables because they could be generated with potentially crappy entropy or could be compromised already out of the box. The safest approach to take here is similar to what the CL node keystore does, which is ensure that the required keys exist.
  • When we switch to a "create keys on startup" flow, we run into issues when trying to configure the verifier easily in devenv and in prod. This is because the process is chicken and egg - we need the verifier's public key in order to configure the contracts, and we then tell the verifier to use that public key to sign messages. Therefore, we unify the approach of standalone and CL node to both use JD here. This aligns with the long term goal that we had prior which is to use JD to push chain configs. In fact, this PR pushes both chain configs AND the committee verifier config.

Note that this is not expected to be the end-game for JD usage - the aim is to serve as a starting point in order to iterate on. Since standalone mode is currently not being used in production, we should be able to move fast on this.

Control Flow

Can put this somewhere in the repo, I suspect all JD-driven services will have the same flow. We tried to implement the minimum required flow in order to support the following things:

  • New config pushed (e.g., new chains in the TOML)
  • The verifier shuts down/restarts - uses cached job (similar to CL node)
sequenceDiagram
    participant V as Verifier
    participant DB as PostgreSQL
    participant HTTP as HTTP Server
    participant JD as Job Distributor
    participant LM as Lifecycle Manager
    participant DE as DevEnv

    Note over V: Phase 1: INIT
    V->>DB: Run migrations
    V->>DB: Generate/load signing key (ECDSA_S256)
    V->>DB: Generate/load CSA key (Ed25519)

    Note over V: Phase 2: READY
    V->>HTTP: Start HTTP server (background)
    HTTP-->>HTTP: GET /info, /health available
    V->>LM: Create Manager with JobRunner

    Note over LM: Lifecycle Manager Startup
    LM->>DB: Check for cached job
    
    alt Cached job exists
        LM->>LM: State = Running
        LM->>V: StartJob(cachedSpec)
        V->>V: Start coordinator
    else No cached job
        LM->>LM: State = WaitingForJob
    end

    LM->>JD: Connect via WSRPC (background)
    LM-->>LM: Listen for proposals/deletions

    Note over DE: DevEnv Flow
    DE->>HTTP: GET /info (get signing addr + CSA pubkey)
    DE->>JD: RegisterNode(name, csaPubKey)
    DE->>DE: Deploy contracts with signing address
    DE->>JD: ProposeJob(nodeId, tomlConfig)

    Note over LM: Handle Job Proposal
    JD->>LM: ProposeJob(id, version, spec)
    
    alt Already running a job
        LM->>V: StopJob()
        V->>V: Stop coordinator
    end
    
    LM->>V: StartJob(spec)
    V->>V: Parse TOML, start coordinator
    LM->>DB: SaveJob(id, version, spec)
    LM->>JD: ApproveJob(id, version)
    LM->>LM: State = Running

    Note over LM: Handle Delete Job
    JD->>LM: DeleteJob(id)
    
    alt Job ID matches current
        LM->>V: StopJob()
        V->>V: Stop coordinator
        LM->>DB: DeleteJob()
        LM->>LM: State = WaitingForJob
        LM-->>LM: Wait for new proposal
    end

    Note over LM: Handle Revoke (ignored)
    JD->>LM: RevokeJob(id)
    LM->>LM: Auto-approve, ignore

    Note over V: Shutdown
    V->>LM: Context cancelled / SIGTERM
    LM->>LM: Shutdown()
    
    alt Running a job
        LM->>V: StopJob()
        V->>V: Stop coordinator
    end
    
    LM->>JD: Close WSRPC connection
    V->>HTTP: Graceful shutdown
Loading

@github-actions
Copy link

github-actions bot commented Feb 6, 2026

Code coverage report:

Package main mk/jd-client diff
github.com/smartcontractkit/chainlink-ccv/aggregator 48.41% 48.41% +0.00%
github.com/smartcontractkit/chainlink-ccv/cmd 0.00% 0.00% +0.00%
github.com/smartcontractkit/chainlink-ccv/committee 100.00% 100.00% +0.00%
github.com/smartcontractkit/chainlink-ccv/common 0.00% 46.08% +46.08%
github.com/smartcontractkit/chainlink-ccv/executor 39.36% 39.42% +0.06%
github.com/smartcontractkit/chainlink-ccv/indexer 37.11% 37.16% +0.05%
github.com/smartcontractkit/chainlink-ccv/integration 37.02% 37.02% +0.00%
github.com/smartcontractkit/chainlink-ccv/pkg 100.00% 100.00% +0.00%
github.com/smartcontractkit/chainlink-ccv/pricer 15.70% 15.70% +0.00%
github.com/smartcontractkit/chainlink-ccv/protocol 63.07% 63.07% +0.00%
github.com/smartcontractkit/chainlink-ccv/verifier 54.90% 56.62% +1.72%

@makramkd makramkd marked this pull request as ready for review February 6, 2026 17:31
@makramkd makramkd requested review from a team and skudasov as code owners February 6, 2026 17:32
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