Skip to content

Commit be5399b

Browse files
[main] Update 2026-01-20.22 (#427)
Reference commit: 6d8af8e330
1 parent 1cf2844 commit be5399b

File tree

962 files changed

+154557
-5897
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

962 files changed

+154557
-5897
lines changed

UNRELEASED.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,21 @@ Template for a bigger topic
1717

1818
#### Impact and Migration
1919

20+
- JSON Ledger API OpenAPI/AsyncAPI spec corrections
21+
- Fields not marked as required in the Ledger API `.proto` specification are now also optional in the OpenAPI/AsyncAPI specifications.
22+
If your client code is using code generated using previous versions of these specifications, it may not compile or function correctly with the new version. To migrate:
23+
- If you prefer not to update your code, continue using the previous specification versions as the JSON API server preserves backward compatibility.
24+
- If you want to use new endpoints, features or leverage the new less strict spec, migrate to the new OpenAPI/AsyncAPI specifications as follows:
25+
- Java clients: No changes are needed if you use the `OpenAPI Generator`. Otherwise, potentially optionality of fields should be handled appropriately for other code generators.
26+
- TypeScript clients: Update your code to handle optional fields, using the `!` or `??` operators as appropriate.
27+
- From Canton 3.5 onwards, OpenAPI/AsyncAPI specification files are suffixed with the Canton version (e.g., `openapi-3.5.0.yaml`).
28+
- Canton 3.5 is compatible with OpenAPI specification files from version 3.4.0 to 3.5.0 (inclusive).
29+
2030
### Minor Improvements
31+
- Changed the path for `crypto.kms.session-signing-keys` (deprecated) to `crypto.session-signing-keys` so that session signing key configuration is no longer directly tied to a KMS. However, session signing keys can still only be enabled when using a KMS provider or when running with `non-standard-config=true`.
2132
- Added a new configuration parameter for session signing keys, `toleranceShiftDuration`, and updated `cutOffDuration` to allow a zero duration.
2233
- Ledger JSON Api changes:
23-
- extra fields in JSON objects are no longer tolerated,
24-
- All JSON values are optional by default upon decoding (this is not reflected in the openapi spec yet, but written comments should reflect the optionality),
34+
- The Ledger JSON API server now enforces that only fields marked as required by the Ledger API OpenAPI/AsyncAPI specification are mandatory in request payloads.
2535
- ApiRequestLogger now also used by Ledger JSON Api. Changes:
2636
- Redundant Request TID removed from logs.
2737
- Additional CLI options added: `--log-access`, `--log-access-errors`...
@@ -49,6 +59,25 @@ For parties with signing keys both in `PartyToParticipant` and `PartyToKeyMappin
4959
```
5060
canton.monitoring.tracing.tracer.exporter.type=otlp
5161
```
62+
- On Ledger API interface subscriptions, the `CreatedEvent.interface_views` now returns the ID of the package containing
63+
the interface implementation that was used to compute the specific interface view as `InterfaceView.implementation_package_id`.
64+
- *BREAKING* The Postgres configuration of the indexer is separated from the Postgres configuration of the lapi server
65+
(`canton.participants.<participant>.ledger-api.postgres-data-source`).
66+
The new parameter `canton.participants.<participant>.parameters.ledger-api-server.indexer.postgres-data-source` should
67+
be used instead.
68+
- Added network timeout and client_connection_check_interval for db operations in the lapi server and indexer to avoid
69+
hanging connections for Postgres (see PostgresDataSourceConfig). The defaults are 60 seconds network timeout and
70+
5 seconds client_connection_check_interval for the lapi server, and 20 seconds network timeout and
71+
5 seconds client_connection_check_interval for the indexer. These values can be configured via the new configuration parameters
72+
`canton.participants.<participant>.ledger-api.postgres-data-source.network-timeout` for network timeout of the lapi
73+
server and `canton.participants.<participant>.parameters.ledger-api-server.indexer.postgres-data-source.client-connection-check-interval`
74+
for the client_connection_check_interval of the indexer.
75+
- We have changed the way that OffsetCheckpoints are populated to always generate at least one when an open-ended
76+
updates or completions stream is requested. An OffsetCheckpoint can have offset equal to the exclusive start for which
77+
the stream is requested. This ensures that checkpoints are visible even when there are no updates, and the stream was
78+
requested to begin exclusively from the ledger end.
79+
80+
* Additional metrics for the ACS commitment processor: `daml.participant.sync.commitments.last-incoming-received`, `daml.participant.sync.commitments.last-incoming-processed`, `daml.participant.sync.commitments.last-locally-completed`, and `daml.participant.sync.commitments.last-locally-checkpointed`.
5281

5382
### Preview Features
5483
- preview feature
@@ -120,3 +149,5 @@ Canton has been tested against the following versions of its dependencies:
120149
## update to GRPC 1.77.0
121150

122151
removes [CVE-2025-58057](https://github.com/advisories/GHSA-3p8m-j85q-pgmj) from security reports.
152+
153+

base/safe-proto/src/test/scala/com/daml/SafeProtoTest.scala

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,42 @@ import org.scalatest.Inside
88
import org.scalatest.matchers.should.Matchers
99
import org.scalatest.wordspec.AnyWordSpec
1010

11+
// The test is designed to need less than 1Gb of Heap
1112
class SafeProtoTest extends AnyWordSpec with Inside with Matchers {
1213

1314
private[this] def tuple(v: Value) =
1415
Value.newBuilder().setListValue(ListValue.newBuilder().addValues(v).addValues(v)).build()
1516

16-
private[this] val value0 = Value.newBuilder().setStringValue("a" * 1024 * 1024 * 1024).build()
17-
assert(value0.getSerializedSize > 0)
18-
private[this] val value1 = tuple(value0)
19-
assert(value1.getSerializedSize < 0)
20-
private[this] val value2 = tuple(value1)
21-
assert(value2.getSerializedSize >= 0)
17+
// We maximize structural sharing to limit the JVM heap memory usage.
18+
// This allows us to create objects that would serialize to massive sizes (e.g. > 512MB or 4GB)
19+
// without actually consuming that much RAM.
20+
private[this] lazy val values =
21+
LazyList.iterate(Value.newBuilder().setStringValue("a" * 1024).build())(tuple)
22+
23+
// values(19), and values(20) are technically serializable, but their serialization requires over 500 MB of memory.
24+
// We skip it to avoid excessive memory pressure on CI agents.
25+
private[this] val value18 = values(18) // serialization needs a bit more than 256MB
26+
assert(value18.getSerializedSize > 0)
27+
private[this] val value21 = values(21) // serialization would need a bit more than 2GB
28+
assert(value21.getSerializedSize < 0)
29+
private[this] val value22 = values(22) // serialization would need a bit more than 4GB
30+
assert(value22.getSerializedSize >= 0)
2231

2332
"toByteString" should {
2433

2534
"fail gracefully if the message to serialize exceeds 2GB" in {
26-
SafeProto.toByteString(value0) shouldBe a[Right[?, ?]]
27-
SafeProto.toByteString(value1) shouldBe a[Left[?, ?]]
28-
SafeProto.toByteString(value2) shouldBe a[Left[?, ?]]
35+
SafeProto.toByteString(value18) shouldBe a[Right[?, ?]]
36+
SafeProto.toByteString(value21) shouldBe a[Left[?, ?]]
37+
SafeProto.toByteString(value22) shouldBe a[Left[?, ?]]
2938
}
3039
}
3140

3241
"toByteArray" should {
3342

3443
"fail gracefully if the message to serialize exceeds 2GB" in {
35-
SafeProto.toByteArray(value0) shouldBe a[Right[?, ?]]
36-
SafeProto.toByteArray(value1) shouldBe a[Left[?, ?]]
37-
SafeProto.toByteArray(value2) shouldBe a[Left[?, ?]]
44+
SafeProto.toByteArray(value18) shouldBe a[Right[?, ?]]
45+
SafeProto.toByteArray(value21) shouldBe a[Left[?, ?]]
46+
SafeProto.toByteArray(value22) shouldBe a[Left[?, ?]]
3847
}
3948
}
4049

base/util-external/src/main/scala/com/digitalasset/canton/config/RequireTypes.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ object RequireTypes {
269269
lazy val one: PositiveInt = PositiveInt.tryCreate(1)
270270
lazy val two: PositiveInt = PositiveInt.tryCreate(2)
271271
lazy val three: PositiveInt = PositiveInt.tryCreate(3)
272+
lazy val four: PositiveInt = PositiveInt.tryCreate(4)
272273
lazy val MaxValue: PositiveInt = PositiveInt.tryCreate(Int.MaxValue)
273274
}
274275

base/util-external/src/main/scala/com/digitalasset/canton/util/Mutex.scala

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import java.util.concurrent.locks.ReentrantLock
1313
class Mutex {
1414
private val lock = new ReentrantLock()
1515

16-
@deprecated("use harmonize, not synchronize", since = "3.4")
17-
def synchronized[T](body: => T): T = sys.error("use harmonize to distinguish")
16+
@deprecated("use exclusive, not synchronize", since = "3.4")
17+
def synchronized[T](body: => T): T = sys.error("use exclusive to distinguish")
1818

1919
def exclusive[T](f: => T): T = {
2020
def runAndUnlock() =
@@ -33,7 +33,6 @@ class Mutex {
3333
}
3434
}
3535
}
36-
3736
}
3837

3938
object Mutex {

buf.work.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ directories:
77
- community/base/src/main/protobuf
88
- community/synchronizer/src/main/protobuf
99
- community/ledger-api-proto/src/main/protobuf
10-
- community/lib/ledger-api-value/target/protobuf_external
1110
- community/ledger/ledger-api-core/src/main/protobuf
1211
- community/lib/google-common-protos-scala/target/protobuf_external
1312
- community/participant/src/main/protobuf
13+
- community/daml-lf/snapshot/src/main/protobuf
14+
- community/daml-lf/archive/src/main/protobuf
15+
- community/daml-lf/transaction/src/main/protobuf
16+
- community/daml-lf/ledger-api-value/src/main/protobuf

community-build.sbt

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ lazy val `kms-driver-testing` = CommunityProjects.`kms-driver-testing`
4848
lazy val `kms-driver-testing-lib` = CommunityProjects.`kms-driver-testing-lib`
4949
lazy val `aws-kms-driver` = CommunityProjects.`aws-kms-driver`
5050
lazy val `mock-kms-driver` = CommunityProjects.`mock-kms-driver`
51+
lazy val `transcode-schema` = CommunityProjects.`transcode-schema`
52+
lazy val `transcode-daml-lf` = CommunityProjects.`transcode-daml-lf`
53+
lazy val `transcode-codec-json` = CommunityProjects.`transcode-codec-json`
54+
lazy val `transcode-codec-proto-java` = CommunityProjects.`transcode-codec-proto-java`
55+
lazy val `transcode-codec-proto-scala` = CommunityProjects.`transcode-codec-proto-scala`
56+
lazy val `transcode-daml-examples` = CommunityProjects.`transcode-daml-examples`
57+
lazy val `transcode-test-conformance` = CommunityProjects.`transcode-test-conformance`
58+
lazy val `transcode-test-utils` = CommunityProjects.`transcode-test-utils`
5159
lazy val `ledger-api-core` = CommunityProjects.`ledger-api-core`
5260
lazy val `ledger-json-api` = CommunityProjects.`ledger-json-api`
5361
lazy val `ledger-json-client` = CommunityProjects.`ledger-json-client`
@@ -76,9 +84,9 @@ lazy val `resources-pekko` = DamlProjects.`resources-pekko`
7684
lazy val `resources-grpc` = DamlProjects.`resources-grpc`
7785
lazy val `ledger-resources` = DamlProjects.`ledger-resources`
7886
lazy val `timer-utils` = DamlProjects.`timer-utils`
79-
lazy val `crypto` = DamlProjects.`crypto`
87+
lazy val crypto = DamlProjects.crypto
8088
lazy val `safe-proto` = DamlProjects.`safe-proto`
81-
lazy val `nameof` = DamlProjects.`nameof`
89+
lazy val nameof = DamlProjects.nameof
8290
lazy val `testing-utils` = DamlProjects.`testing-utils`
8391
lazy val `grpc-test-utils` = DamlProjects.`grpc-test-utils`
8492
lazy val `rs-grpc-testing-utils` = DamlProjects.`rs-grpc-testing-utils`
@@ -93,6 +101,23 @@ lazy val `executors` = DamlProjects.`executors`
93101
lazy val `observability-metrics` = DamlProjects.`observability-metrics`
94102
lazy val `observability-tracing` = DamlProjects.`observability-tracing`
95103
lazy val `observability-pekko-http-metrics` = DamlProjects.`observability-pekko-http-metrics`
104+
lazy val `daml-lf-data` = DamlProjects.`daml-lf-data`
105+
lazy val `daml-lf-repl` = DamlProjects.`daml-lf-repl`
106+
lazy val `daml-lf-ide-ledger` = DamlProjects.`daml-lf-ide-ledger`
107+
lazy val `daml-lf-language` = DamlProjects.`daml-lf-language`
108+
lazy val `daml-lf-transaction` = DamlProjects.`daml-lf-transaction`
109+
lazy val `daml-lf-archive` = DamlProjects.`daml-lf-archive`
110+
lazy val `daml-lf-stable-packages` = DamlProjects.`daml-lf-stable-packages`
111+
lazy val `daml-lf-validation` = DamlProjects.`daml-lf-validation`
112+
lazy val `daml-lf-snapshot-proto` = DamlProjects.`daml-lf-snapshot-proto`
113+
lazy val `daml-lf-snapshot` = DamlProjects.`daml-lf-snapshot`
114+
lazy val `daml-lf-interpreter` = DamlProjects.`daml-lf-interpreter`
115+
lazy val `daml-lf-engine` = DamlProjects.`daml-lf-engine`
116+
lazy val `daml-lf-parser` = DamlProjects.`daml-lf-parser`
117+
lazy val `daml-lf-encoder` = DamlProjects.`daml-lf-encoder`
118+
lazy val `daml-lf-archive-encoder` = DamlProjects.`daml-lf-archive-encoder`
119+
lazy val `daml-lf-api-type-signature` = DamlProjects.`daml-lf-api-type-signature`
120+
lazy val `daml-lf-tests` = DamlProjects.`daml-lf-tests`
96121

97122
lazy val root = (project in file("."))
98123
.disablePlugins(WartRemover)

community/app-base/src/main/scala/com/digitalasset/canton/admin/api/client/commands/SequencerBftAdminCommands.scala

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import com.digitalasset.canton.sequencer.admin.v30.{
1212
GetOrderingTopologyResponse,
1313
GetPeerNetworkStatusRequest,
1414
GetPeerNetworkStatusResponse,
15+
GetWriteReadinessRequest,
16+
GetWriteReadinessResponse,
1517
RemovePeerEndpointRequest,
1618
RemovePeerEndpointResponse,
1719
SequencerBftAdministrationServiceGrpc,
@@ -21,6 +23,7 @@ import com.digitalasset.canton.sequencer.admin.v30.{
2123
import com.digitalasset.canton.synchronizer.sequencer.block.bftordering.admin.SequencerBftAdminData.{
2224
OrderingTopology,
2325
PeerNetworkStatus,
26+
WriteReadiness,
2427
endpointIdToProto,
2528
endpointToProto,
2629
}
@@ -114,6 +117,28 @@ object SequencerBftAdminCommands {
114117
PeerNetworkStatus.fromProto(response)
115118
}
116119

120+
final case object GetWriteReadiness
121+
extends BaseSequencerBftAdministrationCommand[
122+
GetWriteReadinessRequest,
123+
GetWriteReadinessResponse,
124+
WriteReadiness,
125+
] {
126+
127+
override protected def createRequest(): Either[String, GetWriteReadinessRequest] =
128+
Right(GetWriteReadinessRequest())
129+
130+
override protected def submitRequest(
131+
service: SequencerBftAdministrationServiceStub,
132+
request: GetWriteReadinessRequest,
133+
): Future[GetWriteReadinessResponse] =
134+
service.getWriteReadiness(request)
135+
136+
override protected def handleResponse(
137+
response: GetWriteReadinessResponse
138+
): Either[String, WriteReadiness] =
139+
WriteReadiness.fromProto(response)
140+
}
141+
117142
final case class GetOrderingTopology()
118143
extends BaseSequencerBftAdministrationCommand[
119144
GetOrderingTopologyRequest,

community/app-base/src/main/scala/com/digitalasset/canton/admin/api/client/commands/TopologyAdminCommands.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -660,16 +660,15 @@ object TopologyAdminCommands {
660660
}
661661

662662
final case class LogicalUpgradeState(
663-
observer: StreamObserver[LogicalUpgradeStateResponse]
663+
store: Option[TopologyStoreId],
664+
observer: StreamObserver[LogicalUpgradeStateResponse],
664665
) extends BaseCommand[
665666
v30.LogicalUpgradeStateRequest,
666667
CancellableContext,
667668
CancellableContext,
668669
] {
669670
override protected def createRequest(): Either[String, v30.LogicalUpgradeStateRequest] =
670-
Right(
671-
v30.LogicalUpgradeStateRequest()
672-
)
671+
Right(v30.LogicalUpgradeStateRequest(store.map(_.toProtoV30)))
673672

674673
override protected def submitRequest(
675674
service: TopologyManagerReadServiceStub,

community/app-base/src/main/scala/com/digitalasset/canton/config/CantonConfig.scala

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ final case class CantonConfig(
454454
commitmentMismatchDebugging = participantParameters.commitmentMismatchDebugging,
455455
commitmentProcessorNrAcsChangesBehindToTriggerCatchUp =
456456
participantParameters.commitmentProcessorNrAcsChangesBehindToTriggerCatchUp,
457+
commitmentReduceParallelism = participantParameters.commitmentReduceParallelism,
457458
autoSyncProtocolFeatureFlags = participantParameters.autoSyncProtocolFeatureFlags,
458459
)
459460
}
@@ -750,8 +751,21 @@ object CantonConfig {
750751
deriveReader[KmsConfig.Driver]
751752
implicit val kmsConfigReader: ConfigReader[KmsConfig] =
752753
deriveReader[KmsConfig]
753-
implicit val cryptoReader: ConfigReader[CryptoConfig] =
754-
deriveReader[CryptoConfig]
754+
implicit val cryptoReader: ConfigReader[CryptoConfig] = {
755+
756+
implicit val deprecatedFields: DeprecatedFieldsFor[CryptoConfig] =
757+
new DeprecatedFieldsFor[CryptoConfig] {
758+
override def movedFields: List[DeprecatedConfigUtils.MovedConfigPath] = List(
759+
DeprecatedConfigUtils.MovedConfigPath(
760+
"kms.session-signing-keys",
761+
since = "3.5.0",
762+
to = Seq("session-signing-keys"),
763+
)
764+
)
765+
}
766+
767+
deriveReader[CryptoConfig].applyDeprecations
768+
}
755769
}
756770

757771
lazy implicit final val sequencerTestingInterceptorReader

0 commit comments

Comments
 (0)