Draft
Conversation
Implements the Canton chain integration following the existing plugin architecture (Solana/Ethereum/Hydration pattern). Canton supports the bidirectional sign flow only (Canton → EVM → Canton). - Add Chain::Canton to primitives with all match arms - Add derive_epsilon_canton KDF function with golden tests - Add Canton indexer module with JWT ES256 auth, WebSocket streaming (/v2/updates, daml.ws.auth subprotocol), EIP-712 request ID computation, RLP encoding, and DER signature encoding - Add Canton variants to SignBidirectionalEvent (15 arms), RespondBidirectionalEvent (5 arms), SignatureRespondedEvent (3 arms) - Add per-chain respond serialization format (ABI for Canton, Borsh for Solana/Hydration) - Wire CantonClient into RPC executor with try_publish_canton - Wire CantonArgs into CLI with stream startup - Thread canton_operators/canton_requester through BidirectionalTx for the full bidirectional round-trip
Add stream-only and full-cluster Canton integration tests following the Solana/Ethereum patterns. Introduce a shared `canton-types` crate with typed Rust structs for the Canton JSON Ledger API v2 and Daml contract payloads, replacing hand-crafted json!() and Value parsing in both the MPC node indexer and integration tests. - Add `canton-types` workspace crate (ledger_api + contracts modules) - Add `CantonSandbox` test harness with JWT auth, party/user setup - Add 6 stream-only tests and 1 full-cluster bidirectional test - Wire Canton into ClusterSpawner/Cluster (follows Solana pattern) - Migrate indexer_canton to typed deserialization (net -120 lines) - Fix JWT scope claim (add scope: "daml_ledger_api") - Fix predecessor_id derivation (use pre-computed sender field)
Start sandbox with auth enabled (-c auth.conf) but without --dar. Upload DAR via POST /v2/packages with admin JWT after readiness. This follows the cn-quickstart pattern and ensures Canton validates all JWT tokens end-to-end during integration tests.
Add .github/workflows/canton.yml that installs dpm + Java 21, builds the MPC node, and runs Canton stream tests with --ignored flag. Check in the pre-built daml-vault DAR as a test fixture to avoid building the canton-mpc-poc dependency chain in CI.
Replace canton_operators, canton_requester, canton_sender Option fields on BidirectionalTx/RespondBidirectionalTx with a single ChainContext enum. Canton's epsilon() now uses the original sender string stored in ChainContext::Canton instead of the lossy keccak256 round-trip. Remove unused PendingDepositPayload and predecessor_id() from canton-types.
- Switch to TRANSACTION_SHAPE_LEDGER_EFFECTS (Canton 3.4+) - Add ExercisedEvent verification (SignBidirectional on pinned Signer template) - Add nonce replay prevention via consuming ExercisedEvent on SigningNonce - Replace manual DER with k256 to_der/from_der, fix 50% parity corruption - Add resolve_signature_recovery_id via ecrecover against derived public key - Replace manual RLP with alloy TxEip1559::encode_for_signing - Fix serialized_transaction() returning empty vec for Canton - Add stall watchdog (60s) and connect timeout (30s) on WebSocket - Cache EncodingKey (parse PEM once, not per JWT) - Use deterministic entropy via keccak256(request_id) - Pin signer contract/template IDs via CLI args - Verify sig_network matches node party_id - Add template constants with module boundary enforcement - Add Canton to startup log, fix checkpoint test interval - Propagate channel send errors, remove dead code - Add MAX_SECP256K1_SCALAR to mpc-primitives
- Use fresh DAR from canton-mpc-poc (matches current Signer/Vault split) - Fix nonce exhaustion in concurrent tests (update nonce_cid after each request) - Replace invalid dummy DER signature with valid k256-parseable one (r=1, s=1)
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.
Summary
Key decisions
canton:globalas synthetic CAIP-2 ID (Canton has no registered namespace in ChainAgnostic)senderfield on SignBidirectionalEvent is the pre-computed predecessorId from the Vault contractcanton_operators/canton_requesterthreaded through BidirectionalTx for full round-tripFiles
chain-signatures/node/src/indexer_canton/mod.rs(1026 lines)What's NOT included
canton:globalchain ID (separate PR to canton-mpc-poc)