feat(canton): integrate Canton support#613
Conversation
There was a problem hiding this comment.
Pull request overview
Integrates Canton (Daml-based) chain support into MCMS by adding a new sdk/canton package implementing the Encoder/Inspector/Executor/Configurer/Timelock interfaces against the chainlink-canton bindings, wiring Canton into the factory, validation, chain selectors, and chain-wrapper builders, and adding an e2e test suite plus task entry.
Changes:
- New
sdk/cantonpackage: Merkle hashing matching the DamlCrypto.damllayout, MCMS/timelock SetConfig/SetRoot/Execute/Schedule/Cancel/Bypass, InstanceAddress→contract-ID resolver, and metadata inference for timelock proposal conversion. - Wire Canton into shared infrastructure:
factory.go,validation.go,types/chain_selector.go,timelock_proposal.go(Canton-onlyEnsureChainMetadatastep),chainwrappers/*(newCantonChainaccessor + mock),go.moddeps + replace directives. - New
e2e/tests/cantonsuite (configurer, inspector, timelock proposal/cancel/bypass, set-root/execute) ande2e:cantontask.
Reviewed changes
Copilot reviewed 38 out of 40 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| validation.go | Adds Canton case to validateChainMetadata (per-tx validator not wired). |
| types/chain_selector.go | Adds FamilyCanton to supported families. |
| timelock_proposal.go | Adds Canton-only EnsureChainMetadata step during Convert. |
| factory.go | Registers Canton encoder and OperationID. |
| go.mod | Adds Canton/Daml deps and replace directives. |
| taskfiles/test/Taskfile.yml | Adds e2e:canton task. |
| sdk/canton/chain_metadata.go | Defines TimelockRole, AdditionalFieldsMetadata, and NewChainMetadata. |
| sdk/canton/chain_metadata_infer.go | Infers metadata using hard-coded instance ID candidates and default chain id 1. |
| sdk/canton/chain_metadata_infer_test.go | Unit test for inference happy path. |
| sdk/canton/encoder.go | Merkle leaf hashing with domain separators and length prefixes. |
| sdk/canton/configurer.go | SetConfig against MCMS contract; sets Hash to a literal "tx.Digest". |
| sdk/canton/inspector.go | Reads config/op count/root/root metadata; converts MultisigConfig to types.Config. |
| sdk/canton/inspector_test.go | E2E-tagged unit tests for toConfig hierarchy. |
| sdk/canton/executor.go | ExecuteOperation/SetRoot; manual map-based metadata parsing; value receivers; dead PadLeft32. |
| sdk/canton/timelock_converter.go | Schedule/Bypass/Cancel encoding and OperationID. |
| sdk/canton/timelock_crypto.go | HashTimelockOpId matching Daml hashing. |
| sdk/canton/timelock_executor.go | ExecuteScheduledBatch submission. |
| sdk/canton/timelock_inspector.go | Read-only choices (IsOperation*, GetMinDelay) and role getters. |
| sdk/canton/resolver.go | Resolves InstanceAddress hex to active contract ID. |
| sdk/canton/helpers.go | Template ID parsing/formatting and constants. |
| chainwrappers/chainaccessor.go | Adds CantonChain(selector) and fixes a Sui alias. |
| chainwrappers/mocks/chain_accessor.go | Generated CantonChain mock. |
| chainwrappers/converters.go | Canton converter case. |
| chainwrappers/inspectors.go | Canton inspector case + cantonRole helper. |
| chainwrappers/executors.go | Canton executor case (requires *cantonsdk.Encoder). |
| chainwrappers/timelock_executors.go | Canton timelock executor case. |
| e2e/tests/setup.go | Adds CantonChain config and CantonBlockchain to shared setup. |
| e2e/tests/runner_test.go | Registers TestCantonSuite. |
| e2e/config.canton.toml | Canton e2e config. |
| e2e/tests/canton/* | New e2e suites; timelock_cancel.go contains a non-compiling salt expression. |
Files not reviewed (1)
- chainwrappers/mocks/chain_accessor.go: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| }, nil | ||
| } | ||
|
|
||
| func (e Executor) ExecuteOperation( |
gustavogama-cll
left a comment
There was a problem hiding this comment.
Submitting a few thoughts after a shallow initial pass because I think there is one request (the last comment) that might require a bigger refactoring.
| // Build exercise command using generated bindings | ||
| mcmsContract := mcmscore.MCMS{} | ||
| exerciseCmd := mcmsContract.SetConfig(mcmsContractID, input) | ||
|
|
||
| // Parse template ID | ||
| packageID, moduleName, entityName, err := parseTemplateIDFromString(mcmsContract.GetTemplateID()) | ||
| if err != nil { | ||
| return types.TransactionResult{}, fmt.Errorf("failed to parse template ID: %w", err) | ||
| } | ||
|
|
||
| // Convert input to choice argument | ||
| choiceArgument := ledger.MapToValue(input) | ||
|
|
||
| commandID := uuid.Must(uuid.NewUUID()).String() | ||
| submitResp, err := c.client.SubmitAndWaitForTransaction(ctx, &apiv2.SubmitAndWaitForTransactionRequest{ | ||
| Commands: &apiv2.Commands{ | ||
| WorkflowId: "mcms-set-config", | ||
| CommandId: commandID, | ||
| ActAs: []string{c.mcmsParties[0]}, | ||
| ReadAs: c.mcmsParties, | ||
| Commands: []*apiv2.Command{{ | ||
| Command: &apiv2.Command_Exercise{ | ||
| Exercise: &apiv2.ExerciseCommand{ | ||
| TemplateId: &apiv2.Identifier{ | ||
| PackageId: packageID, | ||
| ModuleName: moduleName, | ||
| EntityName: entityName, | ||
| }, | ||
| ContractId: exerciseCmd.ContractID, | ||
| Choice: exerciseCmd.Choice, | ||
| ChoiceArgument: choiceArgument, | ||
| }, | ||
| }, | ||
| }}, | ||
| }, | ||
| }) |
gustavogama-cll
left a comment
There was a problem hiding this comment.
Need to take a break and will resume later. As a general comment, I find the test coverage pretty lacking. According to Sonarqube we're at ~9%. We have the e2e tests, which are definitely important but I do feel like there's a lot of missing unit tests which would help us maintain and validate the scenarios that deviate from the happy paths.
gustavogama-cll
left a comment
There was a problem hiding this comment.
another quick round, will resume later
Squash of canton-main for signed commit history. Original branch preserved as canton-main-backup-20260604.
|
🤖 I have created a release *beep* *boop* --- ## [0.46.0](v0.45.1...v0.46.0) (2026-06-05) ### Features * **canton:** integrate Canton support ([#613](#613)) ([d1e8d62](d1e8d62)) ### Bug Fixes * replace sender to timelock address during error decoding ([#775](#775)) ([7da8a8e](7da8a8e)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: app-token-issuer-ops-platform[bot] <275822481+app-token-issuer-ops-platform[bot]@users.noreply.github.com>


This pull request adds support for the Canton blockchain.