Digital Asset Daml Release Notes

Release of Daml 2.10.1

Written by Curtis Hrischuk | Jun 2, 2025 3:56:14 PM

Summary

This is a maintenance release that addresses several issues.

What’s New

Package compatibility upload check for 1.15 packages is enhanced

As part of Smart Contract Upgrade feature, when a DAR/package is uploaded to a participant node, Canton checks the upgrade compatibility against the DARs already present in a participant's DAR/package stores. Together with the invariant that all active contracts must have their creation package in the store; this ensures that the stakeholder participants of a contract will only vet packages that are compatible with the creation package of the contract.  

However, it was discovered that there was a gap in the upload checks: For an LF 1.17 package with a data dependency on a LF 1.15 package, the compatibility check at upload compares neither the package IDs nor the contents of the referenced LF 1.15 packages, only the package names, the package versions, and the module names and identifiers matter.  If this occurred, command submission would fail with INVALID_ARGUMENT or the Daml model execution may behave unexpectedly..  

If you have been mixing LF 1.15 and LF 1.17 packages then please perform the following step before upgrading to 2.10.1: verify that the package store of each of your participants does not contain invalid upgrades by running the following script in a Canton console connected to the respective participant. remote_participant.ledger_api.packages.check_upgrade_validity

where remote_participant is a reference to a remote Canton participant on version 2.10.0. If you encounter any errors, contact Digital Asset support.  Then upgrade to 2.10.1.

Daml packages compatibility check on Ledger API start-up

On ledger-API start-up, the Daml package store of the participant node is checked for upgrade compatibility for all persisted packages. On compatibility check failure, the participant is shut down with an error message. To disable the check (not recommended), set canton.participants.participant.parameters.unsafe-disable-upgrade-validation=true.

JWT Tokens in Admin API

User authorization is extended to all service types for participant nodes in 2.10 for the Canton Admin API.

The user is able to configure authorization on the Admin API of the participant node in a manner similar to what is currently possible on the Ledger API. However, it is necessary to specify explicitly which users are allowed in and which grpc services are accessible to them. An example configuration for both Ledger and Admin API looks like this:

canton {
  participants {
    participant {
      ledger-api {
        port = 5001
        auth-services = [{
          type = jwt-rs-256-jwks
          url = "https://target.audience.url/jwks.json"
          target-audience = "https://rewrite.target.audience.url"
        }]
      }

      admin-api {
        port = 5002
        auth-services = [{
          type = jwt-rs-256-jwks
          url = "https://target.audience.url/jwks.json"
          target-audience = "https://rewrite.target.audience.url"
          users = [{
            user-id = alice
            allowed-services = [{
              "admin.v0.ParticipantRepairService",
              "connection.v30.ApiInfoService",
              "v1alpha.ServerReflection",
            }]
          }]
        }]
      }
    }
  }
}

While the users appearing in the sub claims of the JWT tokens on the Ledger API always have to be present in the participant’s user database, no such requirement exists for the Admin API. The user in the authorization service config can be an arbitrary choice of the participant’s operator. This user also needs to be configured in the associated IDP system issuing the JWT tokens.

The configuration can contain a definition of either the target audience or the target scope depending on the specific preference of the client organization. If none is given, the JWT tokens minted by the IDP must specify daml_ledger_api as their scope claim.

Independent of the specific service that the operator wants to expose, it is a good practice to also give access rights to the ServerReflection service. Some tools such as grpcurl or postman need to hit that service to construct their requests. 

The changes are backwards compatible

LF 1.17 templates cannot implement LF 1.15 interfaces.

It is now enforced that the execution of choices from LF 1.15 interfaces within LF 1.17 templates is not allowed. Maintaining two versions of a template within the same model leads to inconsistency: LF 1.17 templates support seamless upgrades, whereas LF 1.15 templates do not, requiring an offline migration to fully upgrade the model.  This is now enforced by:

  • The compiler prevents Daml models from implementing an LF 1.15 interface within an LF 1.17 template.
  • Participants can still load these models if they were compiled with SDK 2.10.0. However:
    • A warning is issued at load time, if those models contain an LF 1.17 template implementing an LF 1.15 interface.
    • Any attempt to execute a choice on an LF 1.15 interface within an LF 1.17 template (compiled with SDK 2.10.0) will trigger a runtime error during submission.

These changes preserve backward compatibility, while preventing the participant from crashing.


Please note that this does require recompiling the LV 1.15 interfaces to LF 1.17. 

Minor Improvements

  • The daml values representing parties received over the Ledger API can be validated in a stricter manner. When the canton.participants.<participant>.ledger-api.command-service.stricter-party-validation parameter is turned on, the parties must adhere to a format containing the hint and the fingerprint separated by a double colon: <party-hint>::<fingerprint>. The change affects the values embedded in the commands supplied to the Submit* calls to the CommandSubmissionService and the CommandService.
  • Added configuration 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
  • canton.participants.participant.parameters.disable-upgrade-validation is renamed and has an additional guard condition to avoid mistakenly enabling it.  It is renamed to unsafe-disable-upgrade-validation.  It is only enabled if it is set in conjunction with canton.parameters.non-standard-config = yes

Bugfixes


Confidential configuration fields were logged in plain text when using specific configuration syntax or CLI flags

If the logConfigWithDefaults config parameter is set to false (which is the default), the config rendering logic fails to redact some confidential information (e.g DB credentials) when config substitution is used in combination with a config element override.

Suppose we have the following configuration file:

canton.conf

_storage {
  password = confidential
}
canton {
  storage = ${_storage}
}

Now the confidential config element is changed via another config file:

override.conf

canton.storage.password = confidential2

and then:

canton -c canton.conf -c override.conf

This exposes the confidential password field in the log file.

Alternatively the config element can be changed as well via the CLI:

canton -c canton.conf -C "canton.storage.password=confidential2"

In both cases the password field was not redacted and it now is.

RepairService contract import discards re-computed contract keys in the repaired contract

The repair service re-computes contract metadata when adding new contracts. However, instead of repairing the contract with the re-computed keys, it re-uses the keys from the input contract. Combined with a gap in the console macros which do not propagate contract keys during ACS export, migrating contracts with keys in that way can result in an inconsistency between the ACS and contract key store, which could cause the participant to halt when attempting to fetch a contract by key.  This has been fixed.

Zombie IDE processes

Multiple IDE instances may start processes that create a package database while a multi-build is running. These simultaneous operations can lead to collisions, corrupting the package database. Running a daml build  while interacting with a daml studio can sometimes collide when creating/updating the package-database, leading to corruption.  The workaround was to close the IDE, kill all damlc processes, and then run daml clean --all followed by daml build --all.

Smart Contract Upgrade runtime error details are hidden by the IDE

The IDE does not show the error details when a runtime error occurs during the upgrade process. 

This is because the IDE does not propagate the error details from the Canton server to the client.

Compiler emits a misleading warning about changed precondition

The compiler performs best-effort checks to verify that the expressions defining the ensure clause, signatories, observers, or the key of a template remain unchanged between templates in an upgrade relationship. If a change is detected, a warning is emitted. However, if the precondition expression calls a utility package—such as the standard library—a warning may be erroneously triggered.

IDE does not close daml processes when closed

An incompatibility between the latest version of VS Code and the VS Code client library we are using causes the Daml process to remain open improperly on Windows and Mac, preventing it from closing as expected.

PQS pruning avoids deadlocks

Pruning for the Participant Query Store (PQS) no longer uses any DDL commands, which were causing readers to encounter deadlocks whilst pruning was running.

Download and Installation 

The Daml 2.10.1 SDK has been released. You can install it using the command: daml install 2.10.1.

The table below lists how you can download Daml Enterprise or individual components.

Daml Enterprise v2.10.1

Component

File download

Container Image

SDK

Linux
macOS
Windows

NA

Canton for Daml Enterprise

Standalone JAR file

digitalasset-docker.jfrog.io/canton-enterprise:2.10.1

Daml Finance

GitHub Page

NA

HTTP JSON API Service

Standalone JAR file

digitalasset-docker.jfrog.io/http-json:2.10.1

Trigger Service

Standalone JAR file

digitalasset-docker.jfrog.io/trigger-service:2.10.1

OAuth 2.0 middleware (Open-Source)

GitHub Page

digitalasset-docker.jfrog.io/oauth2-middleware:2.10.1

Participant Query Store

Standalone JAR file

digitalasset-docker.jfrog.io/participant-query-store:0.5.5

Daml Shell

Standalone JAR file

digitalasset-docker.jfrog.io/daml-shell:0.1.6

Trigger Runner

Standalone JAR file

digitalasset-docker.jfrog.io/trigger-runner:2.10.1

Daml Script

Standalone JAR file

digitalasset-docker.jfrog.io/daml-script:2.10.1

 

If you are using Oracle JVM and testing security provider signatures, note that the Canton JAR file embeds the Bouncy Castle provider as a dependency. To enable the JVM to verify the signature, put the bcprov JAR on the classpath before the Canton standalone JAR. For example:

java -cp bcprov-jdk15on-1.70.jar:canton-with-drivers-2.10.1-all.jar com.digitalasset.canton.CantonEnterpriseApp

Note: These Docker images are designed to be suitable for production use, with minimal size and attack surface. Minimal images can sometimes make debugging difficult (e.g. no shell in the containers). For convenience, we provide “debug” versions of each of the above images, which you can access by appending “-debug” to the image tag (e.g. digitalasset-docker.jfrog.io/http-json:2.10.1-debug).