Skip to content

Add datastore write API for ccip - #23600

Merged
AmrMohamedRezk merged 2 commits into
developfrom
CCIP-13348/datastore-write-api
Sep 2, 2026
Merged

Add datastore write API for ccip#23600
AmrMohamedRezk merged 2 commits into
developfrom
CCIP-13348/datastore-write-api

Conversation

@AmrMohamedRezk

@AmrMohamedRezk AmrMohamedRezk commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

CCIP-13348

Introduces the CCIP-owned datastore write API and guarded changeset-output merge path required for the AddressBook retirement. This establishes one consistent write model before converting individual changesets. Datastore keys are now caller-defined and validated before writes occur.

Requires

This is the base PR of the stack.

Supports


Stack created with GitHub Stacks CLIGive Feedback 💬

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T09:45:42.075332Z 1a44740 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

✅ No conflicts with other open PRs targeting develop

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1a4474056b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

finalCSOut.DataStore = ds
if finalCSOut.DataStore == nil {
finalCSOut.DataStore = singletons
} else if err := finalCSOut.DataStore.Merge(singletons.Seal()); err != nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Skip legacy refs already represented in the datastore

When a sub-changeset records an address using a semantic qualifier, its legacy address-book entry is also passed to PopulateDataStore, which creates another ref for the same contract using the synthetic address-type qualifier. Merging all of those refs unconditionally leaves two keys for the same chain/type/version/address, so lookups that omit a qualifier become ambiguous and the returned datastore no longer preserves the intended write model. Filter address-book-derived refs whose contract is already represented; the same unconditional merge appears in both Solana E2E variants.

Useful? React with 👍 / 👎.

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.

Last PR removes this completely. No need to address individually.

Comment on lines +444 to +445
for _, ref := range srcRefs {
if held, taken := heldBy[ref.Key().String()]; taken && !shared.AddressesEqual(ref.ChainSelector, held, ref.Address) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Exclude staged deletions from collision validation

When src stages a RemoteDelete, its memory store can retain the corresponding address record while tracking the key in DeletedRemoteKeys—the deletion test constructs exactly this shape. If an earlier sub-changeset has updated that key to a different address, this comparison rejects the later deletion as an address collision even though MemoryDataStore.Merge would delete the key and no source address would survive. Remove deletion-marked refs from collision checks (and environment publication) so valid ordered replacement/deletion sequences can be orchestrated.

Useful? React with 👍 / 👎.

@trunk-io

trunk-io Bot commented Sep 1, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

Comment on lines +352 to +357
// An address the environment already records under the same type and version is not
// re-saved: AddressBookMap.Save rejects a repeated address, and a changeset that registers
// contracts the environment already knows about is doing so legitimately. An address
// recorded under a *different* type and version is a genuine disagreement and is rejected
// here, before anything is merged.
for _, chainSelector := range sortedKeys(srcAddrs) {

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.

Is there a reason we can't re-use mergeAddressBookEntries here? The code seems almost identical

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.

mergeAddressBookEntries cannot be reused directly because it mutates an AddressBook, while this code is only planning and must not mutate env.ExistingAddresses. This loop also needs to collect new entries into p.envAddresses

Comment on lines +315 to +317
// planAddressBook stages the merged address book in a fresh book, so the destination is only
// replaced once the whole merge is known to be legal, and works out which entries the
// environment is still missing.

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.

Suggested change
// planAddressBook stages the merged address book in a fresh book, so the destination is only
// replaced once the whole merge is known to be legal, and works out which entries the
// environment is still missing.
// planAddressBook stages the merged address book in a fresh book, so the destination is only
// replaced once the whole merge is known to be legal, and works out which entries the
// environment is still missing.
// The merged book consists of addresses in dest, src, and env.ExistingAddresses

Comment on lines +420 to +421
"failed to merge data store: addresses %s and %s both claim %s; give them distinct qualifiers",
earlier.Address, ref.Address, key,

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 thought it was impossible to actually construct a datastore w/ two entries that have the exact same address, chain, and type and version w/out a differentiating qualifier.

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.

Yes but this check is for the same datastore key with different addresses

Comment on lines +473 to +475
// The environment is the state before this run, so a source ref taking over a key it holds
// is a redeploy superseding what was there, not a collision. It is recorded so the
// replacement is reported rather than silent.

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.

Is it always the case that we want to overwrite?

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.

overwriting is not unconditional. But source precedence is intentional only after conflict validation. The merge uses Upsert because it is applying the valid later state.

@AmrMohamedRezk
AmrMohamedRezk force-pushed the CCIP-13348/datastore-write-api branch 2 times, most recently from 8b12f73 to 5dffd2c Compare September 1, 2026 13:02
@AmrMohamedRezk
AmrMohamedRezk force-pushed the CCIP-13348/datastore-write-api branch from 5dffd2c to a25f320 Compare September 1, 2026 13:26
@AmrMohamedRezk
AmrMohamedRezk added this pull request to the merge queue Sep 2, 2026
Merged via the queue into develop with commit c788459 Sep 2, 2026
217 checks passed
@AmrMohamedRezk
AmrMohamedRezk deleted the CCIP-13348/datastore-write-api branch September 2, 2026 12:29
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