Release of Daml 2.9.1

Summary

Release 2.9.1 brings a wide range of improvements to Daml Enterprise. Note that 2.9.1 is the first external release for the 2.9.x minor release line; 2.9.0 was an internal release only.

Key Enhancements

Release 2.9.1 brings a wide range of improvements to Daml Enterprise:

  • The Participant Query Store (PQS) has several major enhancements including new features and optimizations: Selective ledger redaction; read API enhancements; performance optimizations; Windows for development; background JST token refresh; the ability to keep alive interactions for network load balancer support, and more.

  • Daml Shell is a new feature. It is a terminal-based application for querying a Daml ledger that uses a PQS datastore. It is intended for a production environment.

  • Moderate or large development developer efficiency is increased from improvements to the multi-package build feature and IDE.

  • Additional enhancements and bug fixes are described below too.

Beta features are fully supported, and we seek further customer validation before promoting these features to GA status. Two important new Beta features are now available for (select) customers upon request.

  • Smart Contract Upgrades (SCU): Fixing application bugs or extending Daml models is now possible without downtime or breaking Daml clients. This feature also eliminates the need to hardcode package IDs which increases developer efficiency. To use SCU, customers must upgrade to Daml-LF-1.16 and adjust their deployment model (see below).

  • KMS Drivers: A Key Management System (KMS) or Hardware Security Module (HSM) allows Canton private keys to reside securely inside a KMS or HSM. This feature is an extension point to allow integration of a range of KMSs and HSMs by implementation of a plugin.

If you have an interest in using these features, please contact your account manager, CX representative, or DA support (support@digitalasset.com).

Impact and Migration

Daml Enterprise 2.9.1 includes preparation for the Long Term Support (LTS) release. There is a new Canton protocol version (PV=6), a new Daml LF version (LF 1.16), and some items have been deprecated. 

The default latest stable protocol version in this release is 5 and it now needs to be set explicitly.   A new protocol version 6 is available and requires enabling Canton Beta features as described in the docs. Protocol versions 3 and 4 have been removed since the Daml Enterprise releases they were part of are no longer supported.  

As mentioned above, you must now set the protocol version explicitly. In prior releases, the domain protocol version was set to the latest protocol version by default. Unfortunately, this implicit selection can lead to the behavior of long running production environments to diverge from short lived test environments, so it is now an explicit parameter that needs to be set. To specify the protocol version for a domain:

myDomain {
  init.domain-parameters.protocol-version = 5
}

Specifying for a domain manager is:

domainManager {
 init.domain-parameters.protocol-version = 5
}

You can read more about protocol versions in the docs. If you are unsure which protocol version to pick, use the latest one supported by your binary (see docs).

Please ensure all your environments use the same protocol version: you should not use one protocol version in your test environment and another one in production.

If a protocol version is not provided, then an error message like this will be logged:

ERROR c.d.c.CantonEnterpriseApp$ - CONFIG_VALIDATION_ERROR(8,0): Failed to validate the configuration due to: Protocol version is not defined for domain `mydomain`. Define protocol version at key `init.domain-parameters.protocol-version` …

Daml-LF versions 1.14, 1.15, and 1.16 are available. LF 1.15 is the default Daml compiler setting. LF 1.16 status is Beta.   

The compatibility matrix is:

  • PV5 is compatible with LF 1.14 and LF 1.15.

  • PV6 is compatible with LF 1.14, LF 1.15, and LF 1.16.

As mentioned above, PV3 and PV4 have been removed.

Canton no longer allows packages with the same name and version to be uploaded when using LF 1.16 since this would break the new Smart Contract Upgrade feature by allowing incompatible DARs. Instead, the version must be updated in the daml.yaml file. 

The PQS schema has some changes that were made to fix read performance issues. This may require some updates to your code if you are using a PQS version earlier than 2.8.4.

The JSON API no longer supports partially qualified template IDs,(i.e.  simply ``<module>:<entity>``).

Daml 2.9 no longer officially supports some old versions of runtime dependencies since they have fallen out of support themselves: 

  • Java 11 is no longer supported. Java 17 is the supported LTS version for the foreseeable future.

  • PostgreSQL 10 is no longer supported. PostgreSQL 12 is the oldest recommended version.

What’s New

Participant Query Store (PQS) Major Enhancements

Background

The term Operational Data Store (ODS) usually refers to a database that mirrors the ledger and allows for efficient querying. The Participant Query Store (PQS) is a participant node’s ODS. It stores contract creation, contract archival, and exercise information in a PostgreSQL database using a JSONB column format. The PostgreSQL database is queried over JDBC.

Details

The list of new features and enhancements for PQS are briefly described below.  Please refer to the documentation for more details.

Data privacy and other regulations require the ability to forget data which is supported by the new selective ledger redaction feature for PQS.  PQS is expected to maintain archived data for many years, so a pruning window approach of data aging out (e.g., a monthly pruning schedule) may not apply. “Selective Ledger Redaction” enables a PQS admin (or delegate) to redact contract information from a PQS. The redaction user needs privilege levels of SELECT and UPDATE.

A new read API addition allows general timestamping of events (creation, creates, exercises, archives). The following PostgreSQL functions now return the columns created_effective_at and archived_effective_at: creates, archives, active, and lookup_contract. The following functions now return the column exercised_effective_at for exercises and lookup_exercises

PQS has added a stored procedure to easily create indexes on contract data (create_index_for_contract) which require the privilege level of either: CREATE, or SUPERUSER.

Prior releases optimized the write path of PQS and this release has added read performance optimization. This required schema changes that were updated in 2.8.4. This has resulted in some columns being added for read API results and some names being adjusted for consistent terminology. There are some query adjustments needed and they are listed in the “Impact and Migration” section below.

There are two areas where PQS has increased consistency with the ledger. First, stakeholder information is available (signatories and observers) in preference to witnesses. Secondly, PQS has improved how it handles Daml interfaces by providing a consistent view across all templates that implement a given interface. This fixed some bugs around interface handling that were raised by clients.

There were also several network related enhancements. Some network load balancers require keep-alive messages to maintain open sockets and a keep-alive is now provided for JDBC and gRPC connections with a default keep-alive period of 40 seconds. The network connectivity is more resilient because it will retry the connection up to a maximum retry count or maximum retry time limit. PQS now performs a background JWT token refresh and reopens the event stream when it detects an UNAUTHENTICATED(ACCESS_TOKEN_EXPIRED) error code from the ledger API.

PQS can be used for Windows development, in addition to Linux and macOS. Also, if API authorization during development is disabled then PQS will ignore non-local parties from the participant node it is part of.

Lastly, there have been requests to be able to use a relational schema approach instead of dealing with JSONB in designing queries. Docs.daml.com documentation has been added on how to leverage PostgreSQL features to accomplish this.

Impact and Migration

There are two PQS feature updates that have some migration implications: a schema update and support for the smart contract upgrade feature.

As mentioned, some schema updates were made in version 2.8.4. When using the Read API table functions, the following changes are required to interpret the returned result sets. All other columns remain unchanged, but new columns have been added to improve consistency and provide additional information:

 

creates('TemplateName')

Pre 2.8.4

Post 2.8.4

tx

created_at_ix

offset

created_at_offset

pk

create_event_pk



archives('TemplateName')

Pre 2.8.4

Post 2.8.4

tx

archive_at_ix

offset

archive_at_offset

pk

archive_event_pk

contract_creation_offset

created_at_offset



exercises('TemplateName:ChoiceName')

Pre 2.8.4

Post 2.8.4

tx

exercised_at_ix

offset

exercised_at_offset

pk

exercise_event_pk

Some additional notes about the schema:

  • Users should not directly interact with table schema but should use the provided read APIs.

  • The table structures have changed - and can change in the future. We now utilize table partitioning for performance and functionality reasons. You will notice several partitions underneath the __contracts table, instead of a large number of template-specific tables.

PQS now supports the highly sought after feature of using package-name (specified in daml.yaml) instead of the more cumbersome package-id, which is required to support smart contract upgrades. When specifying a template/interface/choice name, simply substitute any package-id with the package-name (e.g. now "register:DA.Register:Token") instead of the prior "deadbeefpackageidhex:DA.Register:Token" format. This applies to template filters and SQL queries (eg. via the active() function). These functions will always return all versions of a given identifier. Qualified name can be:

  • fully qualified, e.g. <package-name>:<module-path>:<template-name>

  • partially qualified, e.g. <module-path>:<template-name>

Qualified names cannot be ambiguous.

The read API now returns the package-name, package-id, and package-version for each contract instance, making it easy for users to determine and inspect different versions over time. To reconstruct the old experience (should you need to) of querying one specific version, simply use a filter predicate in the SQL. eg. SELECT * FROM active('mypackage:My.App:MyTemplate') WHERE package_id = 'deadbeefpackageidhex'.

Daml Shell GA

Background

Daml shell is a terminal-based application that you can use to inspect a Daml ledger by connecting to a live PQS datastore using JDBC. It can examine the current and historical states of the ledger at specific offsets to query ledger events, transactions and contracts in a user-friendly manner. For example, it can be used to trace a contract back to the exercise that created it. 

Details

The Daml Shell CLI includes extensive help via the help command; each command has its own detailed help support. Some of the actions that Daml Shell supports are:

  • Find a specific contract and display it. For example, if you have a contract-id, Daml Shell allows you to inspect the corresponding contract using the contract command.

  • Find all events related to a transaction ID. A transaction is displayed as a series of ledger events (creates, archives, and exercises). 

  • Auto-completion for identifiers such as names and ID's.

  • List active, or historical events for a template using the FQN as an argument.

  • Apply query and filter facilities to commands to manage the output.

  • Use several comparison operators.

  • Perform bounded searches, for instance by specifying a minimum and maximum offset value to search within.

  • Use the diff command to highlight the delta between two contract-ids for the same template.

  • Find specific contracts by querying using a ‘where’ clause that searches the payload fields.

  • Export queried data to a CSV file so that external tools can perform sophisticated search, filtering, query summarization, etc.

  • Pass the result set from a query to an external shell command (e.g., jq, grep, awk) for very flexible filtering.

A performance baseline has shown that Daml Shell is well-suited for production scale environments of millions of contracts. It also supports Windows for development.

Impact and Migration

This is a purely additive change. 

Multi-package build and IDE enhancements

Background

Daml Enterprise 2.8.0 introduced the multi-package build feature. There are extensions in this release that further increase developer efficiency for multi-package applications. 

Details

Environment variable interpolation is added for daml.yaml and multi-package.yaml files.  It uses simple, familiar syntax, including familiar escape mechanisms, and supports the usual mid-string placement. This allows environment variable references to be replaced with their definitions from the calling shell’s environment, throwing an exception if a variable does not exist. So fields like sdk-version can be specified purely by an envrc shell file or similar, and it allows for directories holding DARs to be stored as absolute paths in a variable. The environment variables are case sensitive. For example “SDK_VERSION” and “sdk_version” are valid and different environment variables.

The IDE now supports working with multiple packages at once, using the new Multi-Package support in the IDE, which can be enabled in the VSCode extension settings. When enabled, it will now correctly unpack data-dependencies, and allow for Go to definition to jump between packages in your project, even from within unpacked dependencies and across different SDK versions. For dependencies of different SDK versions, it will prompt you to install the relevant SDK, to ensure the code intelligence is correct.  The Multi-Package build features are Beta and need to be enabled.

Known limitations

If the Daml assistant is an old version, the assistant won’t know how to resolve environment variables, and will subsequently fail with a parse error. A newer version of the Daml assistant must be explicitly installed and activated to handle environment variables before using them in daml.yaml.

Impact and Migration

The Multi-Package IDE support needs to be enabled by showing VSCode's settings (<ctrl> + <comma>),  finding the "Daml:  Multi Package IDE Support", and enabling it.

This feature is purely additive and backwards compatible. 

Daml Language Updates and Deprecations

Background

The Daml language evolves and occasionally features will transition to the status “deprecated.” Here are the features that are deprecated in this release and will be removed at a later date:

  • Deprecate BigNumeric. The recommended migration is to Numeric.round and similar functionality.

  • The Template ‘agreement text’ is deprecated.

  • TextMap is deprecated. The recommended alternative is Map

  • fromListWith is deprecated. Instead, use either fromListWithL or fromListWithR.

A runtime difference between Java 11 and 17 for timestamp parsing was identified and is now consistent across Java versions.

Smart Contract Upgrading (Beta)

Background

The feature allows Daml models (packages in DAR files) to be updated on Canton transparently, provided some guidelines in making the changes are followed. For example, you can fix an application bug by uploading the DAR of the fixed package. This is a Beta feature that requires LF 1.16 & Canton Protocol versions 6. Please contact your account manager or DA support for access to the documentation.

Details

This feature is well-suited for developing and rolling out incremental template changes. There are guidelines to ensure upgrade compatibility between DAR files. The compatibility is checked at compile time, DAR upload time, and runtime. This is to ensure data backwards upgrade compatibility and forwards compatibility (subject to the guidelines being followed) so that DARs can be safely upgraded to new versions. It also prevents unexpected data loss at clients if a runtime downgrade occurs (e.g., a client is using template version 1.0.0 while the participant node has the newer version 1.1.0). 

A general guideline is that additive application changes are allowed but items cannot be removed. A summary of the allowed changes in templates are:

  • A template can add new Optional fields at the end of the list of fields;

  • A record datatype can add new Optional fields at the end of the list of fields, and a variant/enum datatype can add new constructors at the end;

  • The ensure predicate can be changed and it is reevaluated at interpretation;

  • A choice signature can be changed by adding optional parameters at the end;

  • The controller of a choice can be changed;

  • The observer of a choice can be changed

  • The body of a choice can be changed;

  • A new choice can be added to a template;

  • The implementation of an interface instance can be changed;

  • A new interface instance can be added to a template.

Please consult the documentation for more information.

A change is that the package name now associates a series of DAR versions where the newest version is the default version to use. The package name and version (e.g., “version: 1.1.0”) are specified in the daml.yaml file. Package name is now part of the Fully Qualified Name instead of the package ID. Internally, the package ID is still available and used at run time where the package name and version are resolved to a package ID. This allows backwards compatibility. So, there is flexibility where the package ID can still be specified (prior approach) or the package name can be used (new approach). A side effect is that the package name provides a namespace scope where modules, templates, and data belong to the namespace of a package. 

To prevent unexpected behavior, this feature enforces that a DAR being uploaded to a participant node has a unique package name and version. This closes a loophole where the PN allowed uploading multiple DARs with the same package name and version. For backward compatibility, this restriction only applies for packages compiled with LF >= 1.16. If LF < 1.15 is used, there can be several packages with the same name and version but this should be corrected as it will not be supported further.

Compilation support for smart contract upgrade is enabled by adding two fields to the daml.yaml:

  • typecheck-upgrades: true

  • upgrades: <path to dar files of prior versions>

For additional type checking, use the ‘dry-run’ option which simulates the checks a PN will run during the upload step. The format of the command is “daml ledger upload-dar --dry-run” which can be included as part of a CI/CD process.

The JSON API server is compatible with the smart contract upgrade feature by:

  • Supporting package names for commands and queries;

  • Allowing use of an optional packageIdSelectionPreference field to specify a preferred package ID to use;

  • Requiring either a package ID or package name to be present to disambiguate the partially-qualified form of template/interface ids.

Previously JSON API had supported partially qualified template IDs, (i.e.  simply ``<module>:<entity>``) as an interactive convenience which fails if   there is more than one package with matching template names. Since partially qualified template IDs were not supported for production use and do not work with smart  contract upgrades, it is now unavailable.

The Java and TypeScript codegen allow the use of package name and package ID. 

The PQS support for this feature is documented in the “Impact and Migration” subsection of the heading “Participant Query Store (PQS) Major Enhancements”.

Known limitations

Compile time compatibility checking in the IDE is not reflected directly in the IDE (Daml Studio). 

Impact and Migration

This feature is currently Beta and is not enabled by default. There are three steps that are required to enable this feature:

1. Compile the Daml model(s) into LF 1.16 (LF 1.15 is the default). When using the daml build command to compile a Daml project, make sure the LF-version is set to 1.16. To do this, set this field in the daml.yaml

build-options:
     - --target=1.16

Additionally, we recommend to use the following fields to enable compile time checking of upgrades.

typecheck-upgrades: true
upgrades: <path to dar files of prior versions>

2. The Canton protocol version needs to be set to 6. The default version is 5. See here for information about the parameter protocolVersion for domain parameter configuration.   Also, remember to enable Canton Beta features as described in the docs.


3. Domain migration. For existing systems, the protocol version change requires a domain migration that is discussed in “Change the Canton Protocol Version.” 


This feature is not compatible with some deprecated coding patterns which may require some code changes. 

  1. Retroactive interface instances are not supported, as they are no longer required: new interface implementations can be added post-hoc via a smart contract upgrade of the template that then includes the implementation of the new interface as part of its definition

  2. Using divulged contracts during interpretation, which is deprecated since Daml 1.14, does not work with upgrades.

  3. Interface definitions are not upgradable by SCU.  So, to allow upgrading of templates,  move co-mingled interfaces into a different package that can be referenced by all current and future versions of the template.

Please refer to the documentation for more details.

KMS Drivers (Beta)

Background

A Key Management System (KMS) or Hardware Security Module (HSM) allows Canton to perform cryptographic operations where the private key resides securely inside the KMS/HSM. The KMS Drivers feature allows customers to integrate Canton with their KMS or HSM through a plugin approach. This is a Beta feature so please contact your account manager or DA support for access to the documentation.

Details

AWS KMS and Google Cloud KMS are directly supported. To broaden the support of other KMSs and HSMs, a plugin approach (called KMS Drivers) for custom integrations can now be used. A plugin needs to be implemented that includes a driver and a factory. The driver implements a set of APIs. A factory implementation instantiates the driver at run-time. 

Known limitations

The driver and factory implementation needs to be written in Scala.

Impact and Migration

This feature is purely additive and backwards compatible. 

Training and Certification 

The first of four courses in our new Technical Solution Architect Certification Path is released. The course offers an introduction to Daml architecture that will help users analyze the motivation to build a Daml solution and evaluate the suitability of Daml and Canton technologies for their specific business use cases. The course can be taken on our LMS platform, and the other three courses in the certification path will be available in June / July.

Additional Enhancements and Updates

Explicit Contract Disclosure is promoted to General Availability

Daml Script now supports Explicit Contract Disclosure. Explicit Contract Disclosure is now promoted to General Availability.

EventsByX is promoted to General Availability

The following two gRPC APIs are promoted to General Availability.

  • Retrieve contract events by contract ID via the GetEventsByContractId request.

  • Retrieve contract events by contract key via the GetEventsByContractKey request.

Deprecate Daml Navigator

The Daml Navigator is deprecated. It will work for Daml 2.9, and function as usual. However, there is no explicit support for smart contract upgrade. Daml Shell is recommended going forward. 

Pagination for Parties on the Ledger API

Pagination for party listing is now supported on the ledger API to avoid overwhelming a client. The ListKnownParties method on the PartyManagementService now takes two additional parameters. The new page_size field determines the maximum number of results to be returned by the server. The new page_token field on the other hand is a continuation token that signals to the server to fetch the next page containing the results. Each ListKnownPartiesResponse response contains a page of parties and a next_page_token field that can be used to populate the page_token field for a subsequent request. When the last page is reached, the next_page_token is empty. The parties on each page are sorted in ascending order according to their ids. The pages themselves are sorted as well.

Canton View Performance Optimization

To achieve sub-transaction privacy, a submitting participant node breaks up a transaction into multiple views depending on the involved informees of the transaction. Previously the view construction was based on the number of Daml parties which could result in a high view count that could pose scaling challenges. It has changed so that it is based on the number of participants that host those parties. This leads to a reduction of views and scaling improvements for transactions and topologies where many parties are hosted by a smaller set of participants. This optimization is only available for protocol version 6 (PV=6).

Another performance optimization was to reduce the number of expensive asymmetric encryption/decryption operations. In PV=6, Canton will generate session keys to encrypt the views per set of recipients and reuse the session keys for a short configurable time (default is 10 seconds). 

Pruned Offset Notification

Client applications keeping a permanent subscription on the flat transaction and the transaction tree streams can be notified about the pruning operations as they happen. In order to receive these notifications a client must open a tailing subscription (i.e. specify LEDGER_END in the end field) and set the send_pruned_offsets to true in the request record. Every time the participant is pruned a flat-transaction/transaction-tree stream will emit a special GetTransactionsResponse or GetTransactionTreesResponse message respectively that will contain just a pruned_offset and no other data.

To verify whether a participant supports this new functionality, applications can inspect the GetLedgerApiVersionResponse returned by the version service to check for presence of features.experimental.pruned_offsets.supported flag.

Daml SDK Installers are More Resilient

In some cases the Daml SDK installers and Daml Assistant would not succeed and they are now more resilient. Also, the Daml SDK installers (.exe, .sh, .bat) no longer require access to the internet during installation.

JWT Token Grace Period

When a token used in the ledger API request stream expires, the stream is terminated. This normally happens several minutes or hours after the stream initiation. Users can now configure a grace period that will protract the stream termination beyond the token expiry:

canton.participants.participant1.parameters.ledger-api-server-parameters.token-expiry-grace-period-for-streams=600.seconds.

The grace period can be any non-negative duration where both the value and the units must be defined e.g. "600.seconds" or "10.minutes". When the parameter is omitted, the grace period defaults to zero. When the configured value is Inf the stream is never terminated.

A return code of ABORTED(ACCESS_TOKEN_EXPIRED) is returned when a JWT token expires. This replaces the previous, more generic return code of PERMISSION_DENIED(PERMISSION_DENIED).

Security and Bug Fixes

The following bugs were fixed in 2.8 patch releases and are mentioned here for completeness. Any additional bugs that are fixed in the 2.9.1 release are also included.

Canton

Daml enterprise now supports replicating a party from one participant node to another for migration or to have multiple participants hosting the same party. The party replication documentation has the details.

We have improved the background journal cleaning to reduce database load by using smaller transactions to clean up the journal.

The metrics for the executor services have been removed since they were not actively used and could have a negative performance impact under high load.

We have reworked the reference configuration example examples/03_advanced_configuration. The updated example contains the full configuration which can be customized by removing unneeded parts. The installation documentation has been updated accordingly.

Several software dependencies have been updated to prevent security vulnerabilities. They are: Logback (v1.4.14), Amqp (v5.18), netty (v4.1.100), and GRPC (v1.60).

It was uncovered that an AWS RDS failover would not retry if there was a read-only transaction exception. This has been fixed and a test added to prevent regressions.

Added a timeout and retry to a topology request. This allows the topology request to succeed in the event that the message was not received. 

Avoid generating log entries when configuring HA-sequencer pruning. The ``sequencer.health.status`` command can now be used to identify the sequencer that accepts administrative changes.

A bug was fixed in memory resource management so that infinite loops are terminated based on a timer.

When the in-memory blocks exceed 5000, an unexpected shutdown could occur which stops further block processing by the sequencer and HyperLedger Fabric integration. This occurs in a rare situation where the driver is catching up after being stopped and the Fabric Ledger size has increased greatly while it was stopped. The workaround when this occurred was to restart the sequencer. This workaround is no longer needed because this has been fixed.

Pruning is no longer blocked if a domain is inactive.

The repair service didn’t properly communicate removal of contract keys for a contract that was purged and it now does.

Resolved a memory leak in the metrics associated with the gRPC statistics.

Enterprise HA sequencers now expose the admin status.  HA sequencers only allow one of the sequencers to make administrative changes such as configuring the pruning schedule. Now the sequencer node admin status identifies the admin sequencer via the health status as described at https://docs.daml.com/canton/usermanual/pruning.html .

Enhancements and updates to the Canton console are:

  • The party migration macros have been improved to be more intuitive and safer to use.

  • The new repair method participant.repair.purge_deactivated_domain allows removing data from the deactivated domain after a hard domain migration.

  • Repair method participant.repair.add to add contracts is also available on remote nodes.

  • Repair method participant.repair.migrate_domain features a force flag. When set true it forces a domain migration ignoring in-flight transactions. See the upgrading manual for details.

  • A new connect method connect_single to connect a participant to a domain using a single sequencer connection.

The metrics for the executor services have been removed since they were not actively used and could have a negative performance impact under high load.  This includes:

  • daml.executor.runtime.completed

  • daml.executor.runtime.duration

  • daml.executor.runtime.idle

  • daml.executor.runtime.running

  • daml.executor.runtime.submitted

  • daml_executor_pool_size

  • daml_executor_pool_core

  • daml_executor_pool_max

  • daml_executor_pool_largest

  • daml_executor_threads_active

  • daml_executor_threads_running

  • daml_executor_tasks_queued

  • daml_executor_tasks_executing_queued

  • daml_executor_tasks_stolen

  • daml_executor_tasks_submitted

  • daml_executor_tasks_completed

  • daml_executor_tasks_queue_remaining

Daml SDK

The multiple DAR build feature could fail to properly parse daml.yaml files that contained only the parameters `sdk-version` and `build-options`, mistakenly treating them as full packages and trying to build them.

A recent VSCode update changed to using case-insensitive extension names which impacted the `daml studio –replace=always` command. Daml Assistant now deals with the case-insensitive extension names properly. 

The package multi-build feature has had two bugs fixed. First, package multi-build no longer ignores DARs listed under dependencies in the daml.yaml. Secondly, the daml build --all top level build order now matches the multi-package.yaml.

The Daml SDK installers (.exe, .sh, .bat) no longer require access to the internet during installation.

JSON API Server

Fixed a rare race condition where the JSON API could return archived contracts on the very first query of a new (to the JSON API) party.

PQS

As a precautionary measure, a starting PQS will detect an issue and exit if multiple concurrent PQS processes try to address the same PostgreSQL database. Note that only a single PQS instance should write to a database. This can only happen in an unsupported situation where a PQS is not shut down, a PQS is misconfigured, etc. 

Fix for a race condition that could cause foreign-key duplicate errors on startup if the PQS was shut down under a sustained, very high ledger event throughput velocity.

Correct a PostgreSQL issue where it was possible to see multiple (ie. inconsistent - advancing) latest offsets, on a rapidly advancing ledger, rather than the snapshot isolation that users would expect.

The gRPC channel buffers memory footprint has been reduced for scenarios with a ledger that exclusively has very large transactions (e.g., > 1 MByte per transaction) on it.

Trigger Service

For the Trigger Service, AllInDar actually means "all templates known to the trigger service" which was confusing to users. So, to avoid confusion, AllInDar has been deprecated in favor of AllTemplates.

Download and Installation 

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

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

Daml Enterprise v2.9.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.9.1

Daml Finance

GitHub Page

NA

HTTP JSON API Service

Standalone JAR file

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

Trigger Service

Standalone JAR file

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

OAuth 2.0 middleware (Open-Source)

GitHub Page

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

Participant Query Store

Standalone JAR file

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

Daml Shell

Standalone JAR file

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

Trigger Runner

Standalone JAR file

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

Daml Script

Standalone JAR file

digitalasset-docker.jfrog.io/daml-script:2.9.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.9.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.9.1-debug).