Skip to content

Vault: include-invalid pending items and relaxed GetSecrets consensus - #22736

Merged
russell-stern merged 53 commits into
developfrom
validate_observations
Aug 11, 2026
Merged

Vault: include-invalid pending items and relaxed GetSecrets consensus#22736
russell-stern merged 53 commits into
developfrom
validate_observations

Conversation

@russell-stern

@russell-stern russell-stern commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Updates the vault to require a prefix of the pending queue to validate observations. We also guarantee that at least 1 request can be processed before reaching quorum for state transition. Part of this is relaxing get secrets consensus in state transition to be 2f+1 observations seeing the request but only at least f+1 shares need to be contributed.

All changes are gated behind feature flags

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

I see you updated files related to core. Please run make gocs in the root directory to add a changeset as well as in the text include at least one of the following tags:

  • #added For any new functionality added.
  • #breaking_change For any functionality that requires manual action for the node to boot.
  • #bugfix For bug fixes.
  • #changed For any change to the existing functionality.
  • #db_update For any feature that introduces updates to database schema.
  • #deprecation_notice For any upcoming deprecation functionality.
  • #internal For changesets that need to be excluded from the final changelog.
  • #nops For any feature that is NOP facing and needs to be in the official Release Notes for the release.
  • #removed For any functionality/config that is removed.
  • #updated For any functionality that is updated.
  • #wip For any change that is not ready yet and external communication about it should be held off till it is feature complete.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

✅ No conflicts with other open PRs targeting develop

@russell-stern
russell-stern marked this pull request as ready for review June 3, 2026 20:59
@russell-stern
russell-stern requested review from a team as code owners June 3, 2026 20:59
@trunk-io

trunk-io Bot commented Jun 3, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

return gateAllows(ctx, r.lggr, r.cfg.VaultOptimizationsEnabled, "VaultOptimizationsEnabled")
}

func (r *ReportingPlugin) ciphertextlessObservationsEnabled(ctx context.Context) bool {

@cedric-cordenier cedric-cordenier Jun 4, 2026

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.

Nit: worth inlining IMO -- I don't think you gain much by abstracting this out

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.

We have this practice with all our gates, the one liner is long so this make it easier to read when you put the gate directly into an if

Result: &vaultcommon.SecretResponse_Data{
Data: &vaultcommon.SecretData{
EncryptedValue: hex.EncodeToString(secret.EncryptedSecret),
EncryptedValue: encryptedValueForGetSecretsObservation(r.ciphertextlessObservationsEnabled(ctx), secret.EncryptedSecret),

@cedric-cordenier cedric-cordenier Jun 4, 2026

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.

I do wonder if this has some weird error modes and I think we should ask research to take a look.

One possibility that springs to mind: we generate the shares during Observation, but then a request in the same batch updates the secret. If this is processed before the get request in StateTransition, the shares will effectively be for an outdated version of the ciphertext.

It might be safer to hash the ciphertext so that we can effectively "pin" the shares to a particular ciphertext to avoid issues like this.

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.

There's a caching system in StateTransition now so you always get the ciphertext that was present at the start of the round even if that same secret is updated before you get it

}
continue
}
resp.GetData().EncryptedValue = hex.EncodeToString(stored.EncryptedSecret)

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.

You shouldn't use a getter when writing; this will initialize a nil Data if it doesn't exist which may lead to unexpected results. You're guarding against that above, so you can just use resp.Data.EncryptedValue = foo

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.

It doesn't allow me to access resp.Data directly

@russell-stern
russell-stern force-pushed the validate_observations branch from e9091b8 to 3192138 Compare June 13, 2026 00:31
@russell-stern
russell-stern force-pushed the validate_observations branch from 59d3763 to 97fde95 Compare July 2, 2026 20:16
@russell-stern
russell-stern requested review from a team as code owners July 2, 2026 20:46
@russell-stern

Copy link
Copy Markdown
Contributor Author

/vault-audit

@app-token-issuer-foundations

app-token-issuer-foundations Bot commented Jul 20, 2026

Copy link
Copy Markdown

Vault audit complete for 49396931 — no blocking findings.

📋 View the full report and findings — private tracking issue, visible to chainlink team members only. Resolve blocking findings there with /resolved <FINDING-ID> <reason>.

// StateTransition-only and are intentionally not checked here.
func (r *ReportingPlugin) validateContribution(
ctx context.Context,
_ ReadKVStore,

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.

Nit: I would remove this if it's not needed

@@ -0,0 +1,297 @@
package vault

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.

General style nit that I don't think we need to address at this stage: there are a lot of small functions that we're calling into and the implementation of each is pretty trivial and could be inlined.

return false
}
// The pending queue must never be purged with fewer than 2f+1 stall
// signals, regardless of the configured stall threshold.

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.

@russell-stern I'm not sure I understand this -- it looks like the pendingQueueStallTracker simply counts the amount of time the current node has seen the same sequence number, and we are applying a minimum of 2F+1 as a threshold to it. That threshold is usually applied by counting the number of observations across the nodes, which we're not doing here 🤔

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.

This threshold is for how many times we can see the same sequence number before the node says "we're stuck". There's an attack vector if the threshold is ever set <= 2f so this is guaranteeing that we can never configure the vault with a small threshold

@russell-stern russell-stern added the build-publish Build and Publish image to SDLC label Aug 11, 2026
@cl-sonarqube-production

Copy link
Copy Markdown

@russell-stern
russell-stern added this pull request to the merge queue Aug 11, 2026
Merged via the queue into develop with commit 4dce437 Aug 11, 2026
298 of 301 checks passed
@russell-stern
russell-stern deleted the validate_observations branch August 11, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build-publish Build and Publish image to SDLC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants