The Canton 3.4 release notes for Splice 0.5.0 are provided below. The CIP-0089 has the motivation for the release. The high-level structure of the release notes are:
The content here is focussed on Canton updates. For Splice related changes, please refer to the Splice Release Notes.
The new release of Canton 3.4 has several goals:
Although much of the discussion is about the Canton Network or Splice, many of the improvements will be relevant to application developers for private synchronizer or multi-synchronizer applications. However, deploying private synchronizer or multi-synchronizer applications to production is recommended for a future Canton release.
There are two types of application updates discussed in this blog post.
For easier navigation, the changes are called out in a separate subsections and the links are below:
As a result of ongoing security audits, several default configuration values have changed for increased security out of the box. Of course, it is possible to revert these values to the 3.3 value through a configuration parameter.
Creating a contract by interface no longer computes the interface view. Thus if the computation of the view throws an error then it is no longer thrown when creating a contract by interface. This aligns the behavior of the create_interface builtin with that of fetch_interface, exercise_interface, and to_interface.
unsafeFromInterface is marked as deprecated and throws an error during interpretation.
To ensure consistency between the Ledger API and Daml models, the computation of an interface view now checks that the view is serializable (i.e. does not contain non-serializable types and is not too deeply nested). If the view is not serializable then an error is thrown.
The evaluation order of foldr has been changed to match the evaluation order one would observe if foldr was defined with this daml function rather than as a primitive:
foldr f z [] = z
foldr f z (x::xs) = f x (foldr f z xs)
This change only affects usages of foldr in which f throws an error after being partially applied to its first argument.
fromHex now returns None for inputs that do not generate valid UTF-8 strings. This ensures that fromHex x == Some y implies toHex y == x.
Fixed a Daml Studio issue whereby some SCU errors were previously reported as <missing error details> in the transaction view.
Fixed an issue with Daml Studio and daml test in which queryInterface @I did not return contracts upgraded with an instance of the I interface.
Fixed a smart contract upgrade error message in the compiler in which the package IDs of the upgraded package and its upgrade were flipped.
The deprecated @daml/ledger and @daml/react typescript libraries are no longer distributed with Canton 3.4.
The deprecated com.daml/bindings-rxjava library is no longer distributed with Canton 3.4.
You can expect the existing .dar files of applications to continue to work given that the above changes affect corner cases of the language runtime. We recommend migrating Daml code that requires changes by first recompiling it using the 3.4 Daml SDK and rolling out the new .dar files using Smart Contract Upgrading.
Digital Asset Package Manager (dpm) is a new command-line tool that does a lot of useful things for developing dApps with the Canton SDK. Using dpm, you have a tool for your local environment to: build the dApp, generate Java and Typescript code for Daml classes, test local deployment with sandbox, and use PQS and daml shell.
From version 3.4.x onwards, dpm is the preferred CLI tool for a local development experience. If you start a new project on 3.4, or migrate your 3.3 daml project to 3.4, we recommend using dpm. Currently, dpm does not support Canton 3.3 projects. A summary of dpm's features are listed here.
As a result of the introduction of dpm, the Daml Assistant (daml) is deprecated as of version 3.4, but still can be used to work with 3.3 and 3.4 daml projects. If you will be running your 3.3 project as is, and will migrate to 3.4 at a later date, you can continue to use Daml Assistant.
Here is a comparison of dpm with the daml which can help in migrating to dpm. In general, the command set is 1-1.
Further details available from:
The TypeScript codegen has been changed to produce interface definitions that use package names rather than package IDs. The following definition:
exports.Token = damlTypes.assembleInterface(
'41d34898b0a96f443eef3fa59e0ca61465caa5e1c2ca24ecb8e7de5e1ba611f5:Main:Token',
function () { return exports.EmptyInterfaceView; },
{
becomes:
exports.Token = damlTypes.assembleInterface(
'#tokens:Main:Token',
function () { return exports.EmptyInterfaceView; },
{
Please refer to the section Identifier Addressing by-package-name for more details.
There were several changes to UpgradeErrorType:
allocatePartyWithHint and allocatePartyWithHintOn are deprecated and replaced with allocatePartyByHint : PartyIdHint -> Script Party and allocatePartyByHintOn : PartyIdHint -> ParticipantName -> Script Party to reflect the removal of party display names in Canton.
Introduced tryFailureStatus : (HasCallStack => Script a) -> Script (Either FailureStatus a) which allows daml-script tests to observe and act on failures raised during command interpretation.
The Canton 3.4 release also introduces Early Access (Alpha) Daml language support for verifying cryptographic signatures. Thereby making it easier to build Daml workflows that bridge between Canton Network and other blockchains. These cryptographic primitives are useful for building bridges or wrapping tokens.
The daml compiler now provides a consistent flag syntax for disabling warnings and errors and promoting warnings to errors. See the documentation.
The JSON Ledger API v2 was introduced in Canton 3.3 and is the supported JSON Ledger API version going forward. The JSON Ledger API v1 was deprecated in Canton 3.3 and is removed in this release. The migration details for v1 are available in "HTTP JSON API Migration to V2 guide". Please note @daml/ledger was for JSON Ledger API v1 so it will no longer work. The rest of this document is about changes to JSON Ledger API v2 since Canton 3.3.
The JSON Ledger API configuration was simplified. Now the address, port, portFile, pathPrefix, as well as requestTimeout are set directly using the config parameter http-ledger-api like so:
canton.participants.<participant>.http-ledger-api.port=5555
instead of
canton.participants.<participant>.http-ledger-api.server.port=5555
The old configuration paths continue to be supported in 3.4.0, so this is backwards compatible.
The user can now self-administer using new LAPI endpoints. Using the LAPI, a user can now:
The existing endpoints are deprecated but preserved for backwards compatibility.
The users can self-allocate parties only if the number of parties listed in the user’s rights does not exceed the value defined in a configuration parameter:
canton.participants.<participant-id>.ledger-api.party-management-service.max-self-allocated-parties = <N>
To be able to allocate their own party, the participant needs a configuration change because the default is a user cannot allocate any parties (default value of 0).
The GetConnectedSynchronizers command now can be accessed either with ReadAs, Admin or IDPAdmin permissions. As a result, the gRPC command also now has an optional identityProviderId field.
The HTTP connection timeout is configurable in the JSON Ledger API via canton.participants.<participant-id>.http-ledger-api.server.request-timeout=<duration>. Configure this value to allow more complex Ledger API requests to complete (e.g. /state/active-contracts). The default value is 20 seconds.
A configuration parameter has been added for the size of the inbound metadata on the Ledger API. Changing this value allows the server to accept larger JWT tokens. canton.participants.participant.ledger-api.max-inbound-metadata-size=10240
The gRPC Admin API IDP configuration service has changed. Authorization of the calls made by the IDP Admins has been tightened. It is no longer possible for them to grant rights to parties which are in other IDPs or in no IDP. This effectively enforces keeping the IDP Admins within their respective IDP scope. Participant Admins can still grant the rights that cross the IDP box boundaries e.g. a User in "IDP A" can be given a right to a party authorized by "IDP B".
NOTE: Below is a set of default configuration changes for the Canton participant node itself. For backwards compatibility, the Canton Network validator sets these values to be the same as the Splice 0.4.x release so there is no impact to a validator.
The default security configuration of the APIs has been tightened. The maximum token lifetime accepted by the Ledger API (gRPC and JSON) and Admin API has been reduced. This change requires using tokens with an exp field set which was not required before. Tokens which have time to live longer than 5 minutes will not be accepted by default. However, this default value can be changed through:
canton.participants.<participant>.ledger-api.max-token-lifetime=10.minutes
and
canton.participants.<participant>.admin-api.max-token-lifetime=10.minutes
This default timeout can be turned off completely by those who use simplified authorization (for instance utilizing HMAC) by doing:
canton.participants.<participant>.ledger-api.max-token-lifetime=Inf
Correspondingly, the JWKS cache expiration has been reduced to a default of 5 minutes. A JWKS key will be evicted from the cache after that time and the participant will access the JWKS address again to pull the fresh keys. You can modify this behavior by setting
canton.participants.<participant>.ledger-api.jwks-cache-config.cache-expiration=10.minutes
and
canton.participants.<participant>.admin-api.jwks-cache-config.cache-expiration=10.minutes
By default, the Canton Admin Tokens no longer entitle the bearer to operate as a ParticipantAdmin nor to ActAs any party. This behavior can be altered by setting
canton.participants.<participant>.ledger-api.admin-token-config.act-as-any-party-claim=true
and
canton.participants.<participant>.ledger-api.admin-token-config.admin-claim=true
The key for configuration-stored, fixed admin tokens has changed. Previously, the setting of the admin token string was possible through Ledger API or Admin API configuration like so:
canton.participants.<participant-id>.ledger-api.admin-token="<your-token>"
or
canton.participants.<participant-id>.admin-api.admin-token="<your-token>"
Now, it is set through canton.participants.<participant-id>.ledger-api.admin-token-config.fixed-admin-token="<your-token>"
or
canton.participants.<participant-id>.admin-api.admin-token-config.fixed-admin-token="<your-token>"
Other parameters of the admin token can also be set through the AdminTokenConfig configuration as seen below:
canton {
participants {
<participant-id> {
ledger-api {
admin-token-config {
fixed-admin-token = <your-token>
admin-token-duration = 30.minutes
act-as-any-party-claim = true
admin-claim = true
}
}
}
}
}
The fixedAdminToken acts as the adminToken did in Canton 3.3 where it defines a token that is valid throughout the entire canton process lifespan. It is only meant for testing purposes and should not be used in production.
Other admin-tokens will be generated and rotated periodically for internal usage (e.g. in the console). They are invisible from the outside. Each admin-token of these is valid for the defined adminTokenDuration. The half of the token duration is used as the rotation interval, after which a new admin-token is generated (if needed) and used. The default value for the token duration is 5 minutes.
Setting the actAsAnyPartyClaim to true allows usage of the admin-token to authorize acting-as and reading-as any party in the participant. Similarly, setting the adminClaim to true allows usage of the admin-token to authorize any admin level operation in the participant. Setting these parameters to true is consistent with the past system behavior. The default values have been changed to false in the 3.4 release to increase default system security. So, the admin-token by default is only strong enough to issue pings.
gRPC and JSON API payloads for create events (create arguments, interface views, etc.) are now rendered using the normal form of the types defined in CreatedEvent.representative_package_id. This should be transparent on the returned values, with the exception of the record-ids in Ledger API verbose rendering (verbose = true) which now effectively reflect the representative package id as well.
A DAR is said to be self-consistent if the set of packages it contains is exactly the same as the set of packages used or imported by its main package. UploadDarFile now generates an error for DARs compiled in 3.4 that are not self-consistent, and emits a warning for older DARS that are not self-consistent. The error for newly compiled DARs can be downgraded to a warning by setting the enableStrictDarValidation config flag to false.
UploadDarFile now rejects packages that contain unknown protocol buffer fields. This change does not affect DARs generated with damlc.
The legacy gRPC Ledger API method CommandService.SubmitAndWaitForTransactionTree has been removed. Note that the JSON API version of this request /v2/commands/submit-and-wait-for-transaction-tree continues to be supported in 3.4 (marked as deprecated), but will be removed in 3.5.
The following legacy gRPC Ledger API methods in the UpdateService have been removed:
The JSON versions of the removed UpdateService requests continue to be supported in 3.4 (marked as deprecated), but will be removed in 3.5.
The configuration for the removed Ledger API transaction tree stream related methods have been removed as well
canton.participants.<participant>.ledger-api.index-service.transaction-tree-streams.*
The SubscribeTrees and SubscribeFlat Ledger API commands were removed. The SubscribeUpdates should be used instead.
The SubmitAndWaitTransactionTree Ledger API command was removed. The SubmitAndWaitTransaction should be used instead.
The GetTransactionById and GetTransactionByOffset Ledger API commands were removed. The GetUpdateById should be used instead.
The legacy gRPC Ledger API message TransactionFilter has been removed. As a consequence, the filter field has been dropped from the top level GetUpdatesRequest and GetActiveContractsRequest messages.
Likewise, the verbose field has been dropped from the top level GetUpdatesRequest and GetActiveContractsRequest messages. As before, the verbosity can be controlled through the EventFormat message. Its effect has been changed:
The JSON versions of the above gRPC messages continue to be supported in their old format. They will be removed in 3.5. This affects:
These JSON API enum types are now encoded as strings:
Corrected the HTTP verb for the JSON Ledger API endpoint interactive-submission/preferred-packages from GET to POST.
Removed the deprecated requesting_parties field from the GetEventsByContractIdRequest message in the Ledger API. Clients should use the event_format field instead, as described in "HTTP JSON API Migration to V2 guide".
A default value is provided for the transaction_format field inside of SubmitAndWaitForTransactionRequest. You can now omit this field in both gRPC and JSON requests, and get behavior consistent with the 3.2 version of Canton. This means you will receive a flat transaction with event visibility dictated by all act_as and read_as parties.
DisclosedContract.template_id and DisclosedContract.contract_id for Ledger API commands are not required anymore. When provided, the fields are used for validation of the analogous fields in the encoded created event blob.
The non-verbose mode of the Ledger API no longer renders trailing None fields in contracts and records. This only affects contracts created with a version of Canton strictly older than 3.3 as Canton 3.3 contracts are stripped of their trailing None fields already. Since clients of Canton 3.3 had to handle missing trailing Nones already, we do not expect this change to cause any disruption.
The INTERPRETATION_UPGRADE_ERROR_DOWNGRADE_DROP_DEFINED_FIELD and INTERPRETATION_UPGRADE_ERROR_DOWNGRADE_FAILED error codes no longer exist and have been replaced with the more general INTERPRETATION_UPGRADE_ERROR_TRANSLATION_FAILED error codes.
The metadata of the INTERPRETATION_UPGRADE_ERROR_VALIDATION_FAILED error now contains more information and its ordering has changed.
A new INTERPRETATION_UPGRADE_ERROR_AUTHENTICATION_FAILED error code has been added to denote contract ID authentication errors occurring during contract upgrading.
There have been some updates to the OpenAPI specification:
In Canton 3.3, Smart Contract Upgrade supported two formats for specifying interface and template identifiers to the Ledger API. They are:
The package-id reference format will not be supported in Splice 0.6.0 / Canton 3.5. Applications must switch to using the package-name reference format for all requests submitted to the Ledger API (commands and queries). A warning message will be logged if the package-id format is used, as the system internally converts it to the corresponding package-name format and resolves the query by package-name and not by package-id.
Externally signed transactions are an important feature, which has been improved in the following ways:
Refer to the API documentation for details.
Universal Event Streams were introduced in Canton 3.3 to allow a user to subscribe to ledger events and receive a complete view as a flat transaction stream or a transaction tree stream, while providing additional filtering and formatting capabilities. There are several enhancements:
There were several enhancements to the application Quick Start since the release of Canton 3.3. They are:
Canton 3.4 relaxes the need for a validator to upload the history of DARs of a dApp. Now, only the latest package version of a dApp needs to be loaded. Previously, when a dApp had multiple package versions the entire package version lineage needed to be uploaded to a validator.
This also simplifies importing an ACS for a new validator because there is no longer the need to load the entire version lineage of a package even if contracts in the ACS were originally created with older package versions. This reduces memory use on the validator.
Package unvetting is now a production-supported operation. When a package is discovered to be faulty or need to be deprecated for other reasons, the operation to "unvet" a package is now fully supported, such that this package can no longer be used on the ledger. Unvetting a package-id referenced by an active contract is not dangerous anymore provided there's another compatible package vetted (the same package-name but with a higher package-version than the unvetted package). If a package is mistakenly unvetted, it can be restored by simply re-vetting the package.
The package vetting and unvetting enhancements are:
The PackageManagementService.UpdateVettedPackages (JSON POST /v2/package-vetting) request is extended with the UPDATE_VETTED_PACKAGES_FORCE_FLAG_ALLOW_VET_INCOMPATIBLE_UPGRADES force flag to allow vetting packages that are upgrade incompatible. This should only be used in very rare cases where the upgrade check incorrectly fails and generally should not be used in combination with contracts already created in Canton 3.3.
PackageManagementService.UpdateVettedPackages request is extended with the UPDATE_VETTED_PACKAGES_FORCE_FLAG_ALLOW_UNVETTED_DEPENDENCIES force flag to allow vetting packages without vetting one or more of their dependencies.
Removed force flag FORCE_FLAG_ALLOW_UNVET_PACKAGE and topology manager error TOPOLOGY_DANGEROUS_VETTING_COMMAND_REQUIRES_FORCE_FLAG.
Removed force flag FORCE_FLAG_ALLOW_UNVET_PACKAGE_WITH_ACTIVE_CONTRACTS.
The VettedPackage validFrom and validUntil fields have been renamed to validFromInclusive and validFromExclusive.
The package upgrade validation is moved to vetting state change. Thus uploading an upgrade-incompatible DAR with vetting disabled is now possible. Related error codes changed:
Many improvements have been delivered to improve scale and performance, including more efficient processing in various components of the system, configure explicit rate limits to prevent overload, improve the ledger api indexing schema, and reduce the size of the topology state. Some of these changes were backported to Canton 3.3 and are currently operational. A summary of the improvements is:
The PartyToParticipant topology mapping has been enhanced to allow external parties to reference the protocol signing public keys and signing threshold they wish to use to authorize transactions. This effectively replaces the functionality provided by the PartyToKeyMapping, which is now deprecated.
Upgrades of participant permissions in the PartyToParticipant mapping now require the authorization of both the party and respective participant admin. For backwards compatibility, existing transactions in the genesis block do NOT require the authorization of participants for permission upgrades.
Additionally, when one of the signing keys in the PartyToParticipant is also the party’s namespace key, it can be used to “self-sign” the transaction, removing the need for a separate root NamespaceDelegation registering the party’s root namespace key, and thereby allowing a single topology transaction to onboard an external party.
There is now a configurable timeout when waiting to observe the submitted topology transactions. A warning is logged when the timeout occurs and the transaction dispatching will be retried. Additionally, the delay between retries of the topology dispatching loop has been made configurable.
participants.participant1.topology.topology-transaction-observation-timeout = 30s // default value
participants.participant1.topology.broadcast-retry-delay = 10s // default value
mediators.mediator1.topology.topology-transaction-observation-timeout = 30s // default value
mediators.mediator1.topology.broadcast-retry-delay = 10s // default value
sequencers.sequencer1.topology.topology-transaction-observation-timeout = 30s // default value
sequencers.sequencer1.topology.broadcast-retry-delay = 10s // default value
The topology message queue now supports backpressure. This means that topology requests will start to be rejected if the topology message queue is full. The size of the message queue can be configured via canton.<type>.<name>.topology.max-unsent-topology-queue-size = 100 (default).
The number of keys per node or external party are not restricted to a maximum of 20 keys.
The new party allocation endpoints above come with a copy/replace change for users of the gRPC InteractiveSubmissionService used in external signing workflows. The following protobuf messages have been refactored to a new common protobuf package so they can be re-used across different services. To consume these changes, re-generate any client code using the new protobuf definitions and update the package names accordingly in your application code.
The file and FQN changes are:
To avoid confusion, the field submission_time for interactive submissions is now called preparation_time. A similar change is that the dynamic domain parameter submission_time_record_time_tolerance is now called preparation_time_record_time_tolerance.
The error codes LOCAL_VERDICT_SUBMISSION_TIME_OUT_OF_BOUND and TOPOLOGY_INCREASE_OF_SUBMISSION_TIME_TOLERANCE are now called LOCAL_VERDICT_PREPARATION_TIME_OUT_OF_BOUND and TOPOLOGY_INCREASE_OF_PREPARATION_TIME_TOLERANCE. Correspondingly, the console commands set_submission_time_record_time_tolerance is now called set_preparation_time_record_time_tolerance.
The console commands for OwnerToKeyMapping (OTK) and PartyToKeyMapping (PTK) have been changed to accept the factory method parameters instead of OTK and PTK values directly.
Synchronizer owners are implicitly authorized to REMOVE any topology transaction on the synchronizer, even if they are not the "normal" authorizers. As a consequence, the unused topology mapping PurgeTopologyTransaction has been removed from the code base.
Committed NamespaceDelegation transactions with the Remove operations cannot be re-created with a Replace operation anymore.
Added a new, party replication focused ExportPartyAcs endpoint to party_management_service.proto. This endpoint finds the correct ledger offset (party activation on the target participant) and excludes active contracts from the export which have stakeholders that are already hosted on the target participant (contract duplication prevention).
Adds the capability to exclude contracts that have some stakeholders in ExportAcs and ImportAcs endpoints (participant_repair_service.proto).
The participant node Admin API PartyManagementService.ImportPartyAcs endpoint has the request enriched with:
The representative_package_id_override is introduced to allow overriding the original package id of the imported contracts. This allows the target participant to use a compatible alternative package for the contract without needing to upload original contract packages.
ParticipantRepairService.ExportAcsOld is deprecated.
ParticipantRepairService.ImportAcs is updated.
The ImportAcsRequest.contract_id_suffix_recomputation_mode is renamed to ImportAcsRequest.contract_import_mode and ContractIdSuffixRecomputationMode enum is renamed to ImportAcsRequest.ContractImportMode to better reflect its purpose. Upon import, contracts can be fully validated (including contract-id suffix recomputation).
The ExportAcs endpoint was moved from party_management_service.proto to participant_repair_service.proto. Note that endpoint does not return retriable error(s) since ACS export is defined by the ledger offset.
Removed contractSynchronizerRenames on ACS import legacy.
The GCP KMS driver now supports the Ed25519 scheme for signing.
Updated the KMS driver to support the Ed25519 scheme for signing and EciesHkdfHmacSha256Aes128Cbc for encryption. To enable this, the drivers must be recompiled.
Support for the ecies-hkdf-hmac-sha-256-aes-128-gcm encryption algorithm specification has been removed. Use ecies-hkdf-hmac-sha-256-aes-128-cbc instead.
The console command connect_local_bft now takes a list of SequencerReference instead of a NonEmpty[Map[SequencerAlias, SequencerReference]].
The console commands ledger_api.users.rights.grant and ledger_api.users.rights.revoke have been changed to return the complete state of current rights assigned to a user instead of the "delta" induced by the command.
The following canton console commands have been removed:
The following canton console commands have been added:
For more info on how to migrate follow the console commands migration guide.
New docker images for Canton nodes are now published to europe-docker.pkg.dev/da-images/public/docker and include:
Canton 3.4 introduces the preview feature, for testing purposes, of "logical synchronizer upgrades" (LSU), which reduces downtime and operational complexity for protocol version upgrades, as well as supporting data continuity for history across upgrades. This preview feature is for testing purposes only and should not be run in production (yet).
In order to support logical synchronizer upgrades, console commands and admin API endpoints now need to distinguish between logical and physical synchronizer ids:
message Synchronizer {
oneof kind {
string logical = 1;
string physical = 2;
}
}
Protobuf changes:
The OpenTelemetry (OTLP) trace export configuration has been extended with several new parameters allowing connection to OTLP servers, which require more elaborate set-up:
Enhancements were made towards supporting more than one synchronizer being connected to a validator. The following changes are backwards compatible since when a validator is connected to a single synchronizer (i.e., the Global Synchronizer). Console commands and API endpoints for allocating/enabling parties now take an optional synchronizer to specify the target synchronizer. The synchronizer ID parameter can be "omitted" or set to None, if the validator is connected to only one synchronizer. This means that party allocations must be done explicitly for each synchronizer, and that the participant must be connected to each synchronizer at the time of enabling the party.
If the synchronizer parameter is not specified and the participant is connected to multiple synchronizers, the request fails with the error PARTY_ALLOCATION_CANNOT_DETERMINE_SYNCHRONIZER. If the participant is not connected to any synchronizer, the request fails with the error PARTY_ALLOCATION_WITHOUT_CONNECTED_SYNCHRONIZER.
The authorized store can still be used to store PartyToParticipant topology transactions, but users are discouraged from doing so.
Changed the event format filter to use package name instead of package id for Canton 3.x.
Enhanced the support for divulgence in 3.4.
Added documentation about query optimization with expression indexes
Added JSON encoding feature flags