Repository navigation
feat: look up a synchronizer registration by contract id - #68
Open
haikoschol wants to merge 4 commits into
Open
haikoschol wants to merge 4 commits into
haikoschol wants to merge 4 commits into
Conversation
Offboard and set-parameters votes pin a RegisteredSynchronizer by contract id, which is all their payload carries. Scan now serves an active registration by contract id, and the SV app forwards it, so the SV UI can show what such a vote targets, flag one whose registration was archived, and let an SV offboard the second of two duplicate registrations, which the lookup by synchronizer id does not reach. Empty means archived: offboarded, or replaced by a parameters change. Signed-off-by: Haiko Schol <haiko@chainsafe.io>
The SV app forwarded the lookup to Scan. The DSO party signs every RegisteredSynchronizer, so the SV app's own DSO store can hold them: ingest them there and look the contract up locally, which avoids a BFT call across all scans for an SV-local read and the dependency on Scan being reachable. Nothing else uses the Scan endpoint added for this, so it is removed again, along with its client chain, console method and integration-test assertion. The SV endpoint keeps its path and response schema, now defined in sv-internal.yaml. Signed-off-by: Haiko Schol <haiko@chainsafe.io>
moritzkiefer-da
approved these changes
Oct 2, 2026
moritzkiefer-da
left a comment
There was a problem hiding this comment.
thx while you're at it can you acutally change the one from #59 as well, I missed the scan indirection there.
…re [ci] The SV app forwarded the lookup by synchronizer id, which the SV UI uses to reject a duplicate registration, to Scan. The SV app's DSO store now ingests every RegisteredSynchronizer, so look it up there instead: an SV-local read no longer needs a BFT call across all scans or a reachable Scan. The lookup filters on a new dso_acs_store.registered_synchronizer_id column, populated at ingestion, the way Scan serves the same query: V077 adds the column and SqlIndexInitializationTrigger adds the concurrent index. order by contract_id keeps the answer deterministic when an id is registered twice, which the ledger does not prevent. Scan keeps its endpoint: the validator, the wallet and the scan proxy still use it. The SV endpoint keeps its path and response shape, now defined in sv-internal.yaml. Signed-off-by: Haiko Schol <haiko@chainsafe.io>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of ChainSafe/canton-extending-mainnet#128. The SV UI that uses this endpoint is #67, which is stacked on this PR.
Summary
The offboard (
SRARC_ArchiveSynchronizerRegistration) and set-parameters (SRARC_SetSynchronizerGovernanceParameters) votes pin aRegisteredSynchronizerby contract id, and that is all their payload carries. The only registration lookup was by synchronizer id. This PR adds a lookup by contract id to the SV app, which the SV UI in #67 uses to:Once the SV app holds the registrations, the existing lookup by synchronizer id (added in #59 for the register form's duplicate check) no longer needs to go through Scan either, so this PR serves both lookups from the SV app's own store.
It does not change Daml.
Changes
SvDsoStoreingestsRegisteredSynchronizer. The DSO party signs every registration, so the SV app's own DSO store can hold them.GET /v0/admin/sv/synchronizers/registrations/by-contract-id/{contract_id}(lookupSynchronizerRegistrationByContractId) from that store. It returns the registration only while its contract is active; an empty answer means the registration was archived (offboarded, or replaced by a parameters change).GET /v0/admin/sv/synchronizers/{synchronizer_id}/registration(lookupSynchronizerRegistration) is served from the same store instead of being forwarded to Scan. If an id is registered twice, which the ledger does not prevent, it returns the lowest contract id, as Scan does. Path and response shape are unchanged; the response schema is now defined insv-internal.yamlinstead of referencingscan.yaml, so the SV UI needs no change.V077__dso_acs_store_registered_synchronizer.sqladds a nullableregistered_synchronizer_id textcolumn todso_acs_store, filled at ingestion, for the lookup by synchronizer id.SqlIndexInitializationTriggercreates the matching partial indexdso_acs_store_sid_mid_pn_tid_rsidconcurrently. This mirrors how Scan indexes the same query (V076 +scan_acs_store_sid_mid_pn_tid_rsid). The lookup by contract id needs no index column.An earlier revision forwarded the contract-id lookup to a new Scan endpoint. That endpoint is removed again (see review). Scan keeps its lookup by synchronizer id, which the validator, the wallet and the scan proxy still use; this PR does not change Scan.
Testing
DbSvDsoStoreTest: aRegisteredSynchronizeris found by contract id and by synchronizer id among other registrations, is found by neither once archived, an unknown synchronizer id finds nothing, and a synchronizer id registered twice always resolves to the lowest contract id.SqlIndexInitializationTriggerStoreTestexpects the new index.register-synchronizer-form.test.tsxpasses unchanged.apps-sv,apps-scan,apps-commonandapps-app(incl. test sources) compile and passscalafmtCheck.Note for deployment
Adding a template to the DSO store's ingestion filter does not re-ingest contracts created before the upgrade: the store descriptor does not cover the filter. An SV app that upgrades to this change only sees registrations created afterwards; earlier ones stay missing until the DSO store is reset via
dsoAcsStoreDescriptorUserVersion. This now also affects the register form's duplicate check, which would not flag an id registered before the upgrade. That is harmless if this ships no later than the first release with registrations, which is the 0.10.0 Daml cut.The migration needs no backfill, because
dso_acs_storeheld noRegisteredSynchronizerrows before this PR. The column is nullable, so adding it does not rewrite the table, and the index is built concurrently after startup.