Skip to content

Commit 1f7d051

Browse files
[main] Update 2025-07-22.23 (#357)
Reference commit: dd9a41a943
1 parent 49bf06a commit 1f7d051

File tree

576 files changed

+11063
-6107
lines changed

Some content is hidden

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

576 files changed

+11063
-6107
lines changed

UNRELEASED.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,38 @@ schedule, i.e. if you add an entry effective at or after the first
99
header, prepend the new date header that corresponds to the
1010
Wednesday after your change.
1111

12+
## until 2025-07-23 (Exclusive)
13+
- OTLP trace export configuration has been extended with several new parameters allowing connection to OTLP servers,
14+
which require more elaborate set-up:
15+
- `trustCollectionPath` should point to a valid CA certificate file. When selected a TLS connection
16+
is created instead of an open-text one.
17+
- `additionalHeaders` allows specifying key-value pairs that are added to the HTTP2 headers on all trace exporting
18+
calls to the OTLP server.
19+
- `timeout` sets the maximum time to wait for the collector to process an exported batch of spans.
20+
If unset, defaults to 10s.
21+
- `connectTimeout` sets the maximum time to wait for new connections to be established. If unset, defaults to 10s.
22+
- Bugfix: Corrected HTTP method for the JSON Ledger API endpoint `interactive-submission/preferred-packages` from GET to POST.
23+
- GetConnectedSynchronizers command now can be accessed either with ReadAs or Admin or IDP admin permissions. As a
24+
result, the proto command also now has an identityProviderId field.
25+
26+
## until 2025-07-16 (Exclusive)
27+
- **Breaking** The `ledger_api.parties.allocate` console command expect the SynchronizerId as an `Option[SynchhronizerId]` instead of a `String`.
28+
- **Breaking** The `synchronizers.id_of` console command returns now the `SynchronizerId` instead of a `PhysicalSynchronizerId`. Another command `synchronizers.physical_id_of` has been added to return the `PhysicalSynchronizerId`.
29+
30+
- The package dependency resolver, which is used in various topology state checks and transaction processing is improved as follows:
31+
- The underlying cache is now configurable via `canton.parameters.general.caching.package-dependency-cache`.
32+
By default, the cache is size-bounded at 10000 entries and a 15-minutes expiry-after-access eviction policy.
33+
- The parallelism of the DB package fetch loader used in the package dependency cache
34+
is bounded by the `canton.parameters.general.batching.parallelism` config parameter, which defaults to 8.
35+
- **Breaking** Renamed mediator scan to mediator inspection for both the commands and the admin API service. Renamed the inspection service gRPC of the participant into ParticipantInspectionService to differentiate from the mediator one.
36+
37+
## Until 2025-07-09 (Exclusive)
38+
- Sequencer API endpoint `SequencerService.SubscribeV2` has been renamed to `SequencerService.Subscribe`.
39+
- The limit in the config option `canton.sequencers.sequencer.parameters.sequencer-api-limits` has been renamed accordingly:
40+
`"com.digitalasset.canton.sequencer.api.v30.SequencerService/Subscribe" : 1000`
41+
42+
43+
1244
## Until 2025-07-09 (Exclusive)
1345

1446
- Added new limits for the number of open streams. This allows to limit the number of

base/daml-jwt/src/main/scala/com/daml/jwt/JwtDecoder.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ object JwtDecoder {
1717

1818
def decode(jwt: Jwt): Error \/ DecodedJwt[String] =
1919
\/.attempt(com.auth0.jwt.JWT.decode(jwt.value))(e => Error(Symbol("decode"), e.getMessage))
20+
// TODO (i26199)- possible place to add expiration time check
2021
.map(a => DecodedJwt(header = a.getHeader, payload = a.getPayload))
2122
.flatMap(base64Decode)
2223

base/daml-jwt/src/main/scala/com/daml/jwt/JwtVerifier.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class JwtVerifier(val verifier: com.auth0.jwt.interfaces.JWTVerifier) extends Jw
2222
// The auth0 library verification already fails if the token has expired,
2323
// but we still need to do manual expiration checks in ongoing streams
2424
\/.attempt(verifier.verify(jwt.value))(e => Error(Symbol("verify"), e.getMessage))
25+
// TODO (i26199)- possible place to add expiration time check
2526
.map(a => DecodedJwt(header = a.getHeader, payload = a.getPayload))
2627
.flatMap(base64Decode)
2728

community/admin-api/src/main/protobuf/com/digitalasset/canton/admin/participant/v30/inspection_service.proto renamed to community/admin-api/src/main/protobuf/com/digitalasset/canton/admin/participant/v30/participant_inspection_service.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import "scalapb/scalapb.proto";
1616
* This contains only a subset of the ParticipantInspection commands that can run over the admin-api instead of requiring
1717
* direct access to the participant node instance.
1818
*/
19-
service InspectionService {
19+
service ParticipantInspectionService {
2020
// Look up the ledger offset corresponding to the timestamp, specifically the largest offset such that no later
2121
// offset corresponds to a later timestamp than the specified one.
2222
rpc LookupOffsetByTime(LookupOffsetByTimeRequest) returns (LookupOffsetByTimeResponse);

community/admin-api/src/main/protobuf/com/digitalasset/canton/admin/participant/v30/party_management_service.proto

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,12 @@ message GetAddPartyStatusResponse {
132132
string error_message = 1;
133133
Status status_prior_to_error = 2;
134134
}
135+
// The participant has disconnected from the sequencer channel used for ACS replication.
136+
message Disconnected {
137+
string disconnect_message = 1;
138+
// Prior status is one of ConnectionEstablished or ReplicatingAcs.
139+
Status status_prior_to_disconnect = 2;
140+
}
135141

136142
oneof status {
137143
// Party Replication Daml admin workflow proposal and agreement handling
@@ -148,6 +154,9 @@ message GetAddPartyStatusResponse {
148154

149155
// Error indicating that party replication has failed.
150156
Error error = 7;
157+
158+
// Conditions that party replication is attempting to recover from.
159+
Disconnected disconnected = 8;
151160
}
152161
}
153162

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ object LedgerApiCommands {
205205
partyIdHint: String,
206206
annotations: Map[String, String],
207207
identityProviderId: String,
208-
synchronizerId: String,
208+
synchronizerId: Option[SynchronizerId],
209209
userId: String,
210210
) extends BaseCommand[AllocatePartyRequest, AllocatePartyResponse, PartyDetails] {
211211
override protected def createRequest(): Either[String, AllocatePartyRequest] =
@@ -214,7 +214,7 @@ object LedgerApiCommands {
214214
partyIdHint = partyIdHint,
215215
localMetadata = Some(ObjectMeta(resourceVersion = "", annotations = annotations)),
216216
identityProviderId = identityProviderId,
217-
synchronizerId = synchronizerId,
217+
synchronizerId = synchronizerId.map(_.toProtoPrimitive).getOrElse(""),
218218
userId = userId,
219219
)
220220
)
@@ -1850,7 +1850,13 @@ object LedgerApiCommands {
18501850
] {
18511851

18521852
override protected def createRequest(): Either[String, GetConnectedSynchronizersRequest] =
1853-
Right(GetConnectedSynchronizersRequest(partyId.toString, participantId = ""))
1853+
Right(
1854+
GetConnectedSynchronizersRequest(
1855+
partyId.toString,
1856+
participantId = "",
1857+
identityProviderId = "",
1858+
)
1859+
)
18541860

18551861
override protected def submitRequest(
18561862
service: StateServiceStub,

community/app-base/src/main/scala/com/digitalasset/canton/admin/api/client/commands/MediatorScanCommands.scala renamed to community/app-base/src/main/scala/com/digitalasset/canton/admin/api/client/commands/MediatorInspectionCommands.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ import com.digitalasset.canton.mediator.admin.v30
1313
import io.grpc.ManagedChannel
1414
import io.grpc.stub.StreamObserver
1515

16-
object MediatorScanCommands {
16+
object MediatorInspectionCommands {
1717
abstract class BaseScanCommand[Req, Res, Ret] extends GrpcAdminCommand[Req, Res, Ret] {
18-
override type Svc = v30.MediatorScanServiceGrpc.MediatorScanServiceStub
18+
override type Svc = v30.MediatorInspectionServiceGrpc.MediatorInspectionServiceStub
1919

2020
override def createService(
2121
channel: ManagedChannel
22-
): v30.MediatorScanServiceGrpc.MediatorScanServiceStub =
23-
v30.MediatorScanServiceGrpc.stub(channel)
22+
): v30.MediatorInspectionServiceGrpc.MediatorInspectionServiceStub =
23+
v30.MediatorInspectionServiceGrpc.stub(channel)
2424

2525
// command will potentially take a long time
2626
override def timeoutType: TimeoutType = DefaultUnboundedTimeout

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

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import com.digitalasset.canton.admin.api.client.data.{
2323
}
2424
import com.digitalasset.canton.admin.participant.v30
2525
import com.digitalasset.canton.admin.participant.v30.EnterpriseParticipantReplicationServiceGrpc.EnterpriseParticipantReplicationServiceStub
26-
import com.digitalasset.canton.admin.participant.v30.InspectionServiceGrpc.InspectionServiceStub
2726
import com.digitalasset.canton.admin.participant.v30.PackageServiceGrpc.PackageServiceStub
27+
import com.digitalasset.canton.admin.participant.v30.ParticipantInspectionServiceGrpc.ParticipantInspectionServiceStub
2828
import com.digitalasset.canton.admin.participant.v30.ParticipantRepairServiceGrpc.ParticipantRepairServiceStub
2929
import com.digitalasset.canton.admin.participant.v30.ParticipantStatusServiceGrpc.ParticipantStatusServiceStub
3030
import com.digitalasset.canton.admin.participant.v30.PartyManagementServiceGrpc.PartyManagementServiceStub
@@ -1475,10 +1475,10 @@ object ParticipantAdminCommands {
14751475
object Inspection {
14761476

14771477
abstract class Base[Req, Res, Ret] extends GrpcAdminCommand[Req, Res, Ret] {
1478-
override type Svc = InspectionServiceStub
1478+
override type Svc = ParticipantInspectionServiceStub
14791479

1480-
override def createService(channel: ManagedChannel): InspectionServiceStub =
1481-
v30.InspectionServiceGrpc.stub(channel)
1480+
override def createService(channel: ManagedChannel): ParticipantInspectionServiceStub =
1481+
v30.ParticipantInspectionServiceGrpc.stub(channel)
14821482
}
14831483

14841484
final case class LookupOffsetByTime(ts: Timestamp)
@@ -1490,7 +1490,7 @@ object ParticipantAdminCommands {
14901490
override protected def createRequest() = Right(v30.LookupOffsetByTimeRequest(Some(ts)))
14911491

14921492
override protected def submitRequest(
1493-
service: InspectionServiceStub,
1493+
service: ParticipantInspectionServiceStub,
14941494
request: v30.LookupOffsetByTimeRequest,
14951495
): Future[v30.LookupOffsetByTimeResponse] =
14961496
service.lookupOffsetByTime(request)
@@ -1523,7 +1523,7 @@ object ParticipantAdminCommands {
15231523
)
15241524

15251525
override protected def submitRequest(
1526-
service: InspectionServiceStub,
1526+
service: ParticipantInspectionServiceStub,
15271527
request: v30.OpenCommitmentRequest,
15281528
): Future[CancellableContext] = {
15291529
val context = Context.current().withCancellation()
@@ -1562,7 +1562,7 @@ object ParticipantAdminCommands {
15621562
)
15631563

15641564
override protected def submitRequest(
1565-
service: InspectionServiceStub,
1565+
service: ParticipantInspectionServiceStub,
15661566
request: v30.InspectCommitmentContractsRequest,
15671567
): Future[CancellableContext] = {
15681568
val context = Context.current().withCancellation()
@@ -1610,7 +1610,7 @@ object ParticipantAdminCommands {
16101610
)
16111611

16121612
override protected def submitRequest(
1613-
service: InspectionServiceStub,
1613+
service: ParticipantInspectionServiceStub,
16141614
request: v30.LookupReceivedAcsCommitmentsRequest,
16151615
): Future[v30.LookupReceivedAcsCommitmentsResponse] =
16161616
service.lookupReceivedAcsCommitments(request)
@@ -1734,7 +1734,7 @@ object ParticipantAdminCommands {
17341734
)
17351735

17361736
override protected def submitRequest(
1737-
service: InspectionServiceStub,
1737+
service: ParticipantInspectionServiceStub,
17381738
request: v30.LookupSentAcsCommitmentsRequest,
17391739
): Future[v30.LookupSentAcsCommitmentsResponse] =
17401740
service.lookupSentAcsCommitments(request)
@@ -1806,7 +1806,7 @@ object ParticipantAdminCommands {
18061806
)
18071807

18081808
override protected def submitRequest(
1809-
service: InspectionServiceStub,
1809+
service: ParticipantInspectionServiceStub,
18101810
request: v30.SetConfigForSlowCounterParticipantsRequest,
18111811
): Future[v30.SetConfigForSlowCounterParticipantsResponse] =
18121812
service.setConfigForSlowCounterParticipants(request)
@@ -1821,15 +1821,15 @@ object ParticipantAdminCommands {
18211821
distinguishedParticipants: Seq[ParticipantId],
18221822
thresholdDistinguished: NonNegativeInt,
18231823
thresholdDefault: NonNegativeInt,
1824-
participantsMetrics: Seq[ParticipantId],
1824+
individuallyMonitored: Seq[ParticipantId],
18251825
) {
18261826
def toProtoV30: v30.SlowCounterParticipantSynchronizerConfig =
18271827
v30.SlowCounterParticipantSynchronizerConfig(
18281828
synchronizerIds.map(_.toProtoPrimitive),
18291829
distinguishedParticipants.map(_.toProtoPrimitive),
18301830
thresholdDistinguished.value.toLong,
18311831
thresholdDefault.value.toLong,
1832-
participantsMetrics.map(_.toProtoPrimitive),
1832+
individuallyMonitored.map(_.toProtoPrimitive),
18331833
)
18341834
}
18351835

@@ -1870,7 +1870,7 @@ object ParticipantAdminCommands {
18701870
)
18711871

18721872
override protected def submitRequest(
1873-
service: InspectionServiceStub,
1873+
service: ParticipantInspectionServiceStub,
18741874
request: v30.GetConfigForSlowCounterParticipantsRequest,
18751875
): Future[v30.GetConfigForSlowCounterParticipantsResponse] =
18761876
service.getConfigForSlowCounterParticipants(request)
@@ -1907,7 +1907,7 @@ object ParticipantAdminCommands {
19071907
)
19081908

19091909
override protected def submitRequest(
1910-
service: InspectionServiceStub,
1910+
service: ParticipantInspectionServiceStub,
19111911
request: v30.GetIntervalsBehindForCounterParticipantsRequest,
19121912
): Future[v30.GetIntervalsBehindForCounterParticipantsResponse] =
19131913
service.getIntervalsBehindForCounterParticipants(request)
@@ -1949,7 +1949,7 @@ object ParticipantAdminCommands {
19491949
Right(v30.CountInFlightRequest(synchronizerId.toProtoPrimitive))
19501950

19511951
override protected def submitRequest(
1952-
service: InspectionServiceStub,
1952+
service: ParticipantInspectionServiceStub,
19531953
request: v30.CountInFlightRequest,
19541954
): Future[v30.CountInFlightResponse] =
19551955
service.countInFlight(request)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import com.digitalasset.canton.synchronizer.sequencer.block.bftordering.admin.Se
2424
endpointIdToProto,
2525
endpointToProto,
2626
}
27-
import com.digitalasset.canton.synchronizer.sequencer.block.bftordering.bindings.p2p.grpc.GrpcNetworking.P2PEndpoint
27+
import com.digitalasset.canton.synchronizer.sequencer.block.bftordering.bindings.p2p.grpc.P2PGrpcNetworking.P2PEndpoint
2828
import io.grpc.ManagedChannel
2929

3030
import scala.concurrent.Future

community/app-base/src/main/scala/com/digitalasset/canton/admin/api/client/data/AddPartyStatus.scala

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,23 @@ object AddPartyStatus {
6464

6565
private def parseStatus(
6666
statusP: v30.GetAddPartyStatusResponse.Status.Status
67-
): ParsingResult[Status] =
67+
): ParsingResult[Status] = {
68+
def parseConnectedStatus(status: v30.GetAddPartyStatusResponse.Status.ConnectionEstablished) =
69+
for {
70+
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
71+
(sequencerId, timestamp) = commonFields
72+
} yield ConnectionEstablished(sequencerId, timestamp)
73+
74+
def parseReplicatingStatus(status: v30.GetAddPartyStatusResponse.Status.ReplicatingAcs) =
75+
for {
76+
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
77+
(sequencerId, timestamp) = commonFields
78+
contractsReplicated <- ProtoConverter.parseNonNegativeInt(
79+
"contracts_replicated",
80+
status.contractsReplicated,
81+
)
82+
} yield ReplicatingAcs(sequencerId, timestamp, contractsReplicated)
83+
6884
statusP match {
6985
case v30.GetAddPartyStatusResponse.Status.Status.ProposalProcessed(_) =>
7086
Right(ProposalProcessed)
@@ -80,19 +96,9 @@ object AddPartyStatus {
8096
(sequencerId, timestamp) = commonFields
8197
} yield TopologyAuthorized(sequencerId, timestamp)
8298
case v30.GetAddPartyStatusResponse.Status.Status.ConnectionEstablished(status) =>
83-
for {
84-
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
85-
(sequencerId, timestamp) = commonFields
86-
} yield ConnectionEstablished(sequencerId, timestamp)
99+
parseConnectedStatus(status)
87100
case v30.GetAddPartyStatusResponse.Status.Status.ReplicatingAcs(status) =>
88-
for {
89-
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
90-
(sequencerId, timestamp) = commonFields
91-
contractsReplicated <- ProtoConverter.parseNonNegativeInt(
92-
"contracts_replicated",
93-
status.contractsReplicated,
94-
)
95-
} yield ReplicatingAcs(sequencerId, timestamp, contractsReplicated)
101+
parseReplicatingStatus(status)
96102
case v30.GetAddPartyStatusResponse.Status.Status.Completed(status) =>
97103
for {
98104
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
@@ -123,9 +129,31 @@ object AddPartyStatus {
123129
}
124130
statusPriorToError <- parseStatus(validStatusPriorToError)
125131
} yield Error(status.errorMessage, statusPriorToError)
132+
case v30.GetAddPartyStatusResponse.Status.Status.Disconnected(status) =>
133+
for {
134+
statusPriorToDisconnectP <- ProtoConverter.required(
135+
"status_prior_to_disconnect",
136+
status.statusPriorToDisconnect,
137+
)
138+
// Enforce constraint on prior status to disconnected.
139+
statusPriorToDisconnect <- statusPriorToDisconnectP.status match {
140+
case v30.GetAddPartyStatusResponse.Status.Status.ConnectionEstablished(status) =>
141+
parseConnectedStatus(status)
142+
case v30.GetAddPartyStatusResponse.Status.Status.ReplicatingAcs(status) =>
143+
parseReplicatingStatus(status)
144+
case invalidStatus =>
145+
Left[ProtoDeserializationError, ActivelyReplicatingStatus](
146+
ProtoDeserializationError.InvariantViolation(
147+
"status_prior_to_disconnect",
148+
s"Invalid value ${invalidStatus.getClass.getSimpleName}",
149+
)
150+
)
151+
}
152+
} yield Disconnected(status.disconnectMessage, statusPriorToDisconnect)
126153
case v30.GetAddPartyStatusResponse.Status.Status.Empty =>
127154
Left(ProtoDeserializationError.FieldNotSet("status"))
128155
}
156+
}
129157

130158
private def parseCommonFields(
131159
sequencerUidP: String,
@@ -145,15 +173,16 @@ object AddPartyStatus {
145173
sequencerId: SequencerId,
146174
timestamp: CantonTimestamp,
147175
) extends Status
176+
sealed trait ActivelyReplicatingStatus extends Status
148177
final case class ConnectionEstablished(
149178
sequencerId: SequencerId,
150179
timestamp: CantonTimestamp,
151-
) extends Status
180+
) extends ActivelyReplicatingStatus
152181
final case class ReplicatingAcs(
153182
sequencerId: SequencerId,
154183
timestamp: CantonTimestamp,
155184
contractsReplicated: NonNegativeInt,
156-
) extends Status
185+
) extends ActivelyReplicatingStatus
157186
final case class Completed(
158187
sequencerId: SequencerId,
159188
timestamp: CantonTimestamp,
@@ -163,4 +192,8 @@ object AddPartyStatus {
163192
error: String,
164193
statusPriorToError: Status,
165194
) extends Status
195+
final case class Disconnected(
196+
message: String,
197+
statusPriorToDisconnect: ActivelyReplicatingStatus,
198+
) extends Status
166199
}

0 commit comments

Comments
 (0)