Skip to content

Commit ade5c8f

Browse files
[main] Update 2025-05-06.23
Reference commit: d47e3ebf10
1 parent e07d5ed commit ade5c8f

File tree

249 files changed

+3753
-1636
lines changed

Some content is hidden

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

249 files changed

+3753
-1636
lines changed

UNRELEASED.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ 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-05-07 (Exclusive)
13+
- The VettedPackage validFrom and validUntil fields have been renamed to validFromInclusive and validFromExclusive.
14+
1215
## Until 2025-04-30 (Exclusive)
1316
- JSON API - fixed openapi documentation for maps: (`eventsById`,`filtersByParty`).
1417

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

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@ import "scalapb/scalapb.proto";
1212
* The PartyManagementService allows modifying party hosting on participants.
1313
*/
1414
service PartyManagementService {
15-
// Initiate adding a party already hosted on one or more non-local participants to the
16-
// local participant in the specified synchronizer.
17-
// Performs some checks synchronously and then starts the replication asynchronously.
15+
// Initiate adding a party already hosted on one or more source participants to this
16+
// target participant in the specified synchronizer.
17+
// Performs some checks synchronously and then starts the party addition asynchronously.
18+
//
19+
// Depends on the party authorizing the PartyToParticipant topology proposal at the
20+
// specified topology_serial prior or concurrently to this endpoint. On the other hand,
21+
// this target participant authorizes the topology proposal as part of this endpoint in
22+
// a specific, intermediate step, and therefore the target participant signature must not
23+
// already be in place prior to the call.
1824
rpc AddPartyAsync(AddPartyAsyncRequest) returns (AddPartyAsyncResponse);
1925

2026
// Status endpoint that given an add_party_request_id returns status information about progress,
2127
// completion, or errors of a previous call to AddPartyAsync on the source or target
2228
// participant.
2329
//
24-
// Note that the status reflects the state as perceived by the local participant and does not
25-
// imply the state of remote participants. The status on the target participant is more
30+
// Note that the status reflects the state as perceived by this participant and does not
31+
// imply the state of other participants. The status on the target participant is more
2632
// authoritative as the target participant drives the process of adding the party. For example
2733
// when the target participant status indicates "completed", the party has been added
2834
// successfully.
@@ -44,14 +50,13 @@ message AddPartyAsyncRequest {
4450
// The synchronizer in which to replicate the party
4551
// Required
4652
string synchronizer_id = 2;
47-
// Optionally, the source participant already hosting the party
48-
// Required if the party is already hosted on multiple participants.
53+
// A source participant already hosting the party
54+
// Required
4955
string source_participant_uid = 3;
50-
// Optionally, the topology serial number of this request (auto-determined if omitted)
51-
// NOTE: omitting the serial MAY end up overwriting previous mappings processed concurrently.
52-
// To avoid such cases, first read the PartyToParticipant state using the TopologyManagerReadService
53-
// and update the mappings accordingly, incrementing the serial by one and setting it explicitly.
54-
uint32 serial = 4;
56+
// The topology serial number of the PartyToParticipant topology transaction used to
57+
// add the party to this target participant.
58+
// Required
59+
uint32 topology_serial = 4;
5560
}
5661

5762
message AddPartyAsyncResponse {
@@ -76,45 +81,39 @@ message GetAddPartyStatusResponse {
7681
string synchronizer_id = 2;
7782
string source_participant_uid = 3;
7883
string target_participant_uid = 4;
84+
uint32 topology_serial = 5;
7985

8086
message Status {
8187
// The add-party request has been submitted by the target participant, or accepted by the
8288
// source participant.
83-
message ProposalProcessed {
84-
optional uint32 topology_serial = 1;
85-
}
89+
message ProposalProcessed {}
8690
// The add-party request has been observed as agreed to by all participants.
8791
message AgreementAccepted {
8892
string sequencer_uid = 1;
89-
optional uint32 topology_serial = 2;
9093
}
9194
// The PartyToParticipant topology transaction has been authorized by all party and
9295
// participant signers.
9396
message TopologyAuthorized {
9497
string sequencer_uid = 1;
95-
uint32 topology_serial = 2;
9698
// The timestamp at which the ACS snapshot for replication is taken.
97-
google.protobuf.Timestamp timestamp = 3;
99+
google.protobuf.Timestamp timestamp = 2;
98100
}
99-
// The local participant has connected to the sequencer channel for ACS replication.
101+
// This participant has connected to the sequencer channel for ACS replication.
100102
message ConnectionEstablished {
101103
string sequencer_uid = 1;
102-
uint32 topology_serial = 2;
103-
google.protobuf.Timestamp timestamp = 3;
104+
google.protobuf.Timestamp timestamp = 2;
104105
}
105-
// The local participant is ready for ACS replication or has started replicating the ACS.
106+
// This participant is ready for ACS replication or has started replicating the ACS.
106107
message ReplicatingAcs {
107108
string sequencer_uid = 1;
108-
uint32 topology_serial = 2;
109-
google.protobuf.Timestamp timestamp = 3;
110-
uint32 contracts_replicated = 4;
109+
google.protobuf.Timestamp timestamp = 2;
110+
uint32 contracts_replicated = 3;
111111
}
112-
// The local participant has completed its part of the ACS replication.
112+
// This participant has completed its part of the ACS replication.
113113
message Completed {
114114
string sequencer_uid = 1;
115-
uint32 topology_serial = 2;
116-
google.protobuf.Timestamp timestamp = 3;
117-
uint32 contracts_replicated = 4;
115+
google.protobuf.Timestamp timestamp = 2;
116+
uint32 contracts_replicated = 3;
118117
}
119118
// The add-party request has failed after the specified last successful status.
120119
message Error {
@@ -140,7 +139,7 @@ message GetAddPartyStatusResponse {
140139
}
141140
}
142141

143-
Status status = 5;
142+
Status status = 6;
144143
}
145144

146145
message ExportAcsTargetSynchronizer {

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,8 @@ object ParticipantAdminCommands {
469469
final case class AddPartyAsync(
470470
party: PartyId,
471471
synchronizerId: SynchronizerId,
472-
sourceParticipant: Option[ParticipantId],
473-
serial: Option[PositiveInt],
472+
sourceParticipant: ParticipantId,
473+
serial: PositiveInt,
474474
) extends GrpcAdminCommand[
475475
v30.AddPartyAsyncRequest,
476476
v30.AddPartyAsyncResponse,
@@ -486,8 +486,8 @@ object ParticipantAdminCommands {
486486
v30.AddPartyAsyncRequest(
487487
partyId = party.toProtoPrimitive,
488488
synchronizerId = synchronizerId.toProtoPrimitive,
489-
sourceParticipantUid = sourceParticipant.fold("")(_.uid.toProtoPrimitive),
490-
serial = serial.fold(0)(_.value),
489+
sourceParticipantUid = sourceParticipant.uid.toProtoPrimitive,
490+
topologySerial = serial.value,
491491
)
492492
)
493493

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,7 @@ import com.digitalasset.canton.topology.*
2020
import com.digitalasset.canton.topology.admin.grpc.{BaseQuery, TopologyStoreId}
2121
import com.digitalasset.canton.topology.admin.v30
2222
import com.digitalasset.canton.topology.admin.v30.*
23-
import com.digitalasset.canton.topology.admin.v30.AuthorizeRequest.Type.{
24-
Proposal,
25-
TransactionHashBytes,
26-
}
23+
import com.digitalasset.canton.topology.admin.v30.AuthorizeRequest.Type.{Proposal, TransactionHash}
2724
import com.digitalasset.canton.topology.admin.v30.IdentityInitializationServiceGrpc.IdentityInitializationServiceStub
2825
import com.digitalasset.canton.topology.admin.v30.TopologyAggregationServiceGrpc.TopologyAggregationServiceStub
2926
import com.digitalasset.canton.topology.admin.v30.TopologyManagerReadServiceGrpc.TopologyManagerReadServiceStub
@@ -915,7 +912,7 @@ object TopologyAdminCommands {
915912
}
916913

917914
final case class Authorize[M <: TopologyMapping: ClassTag](
918-
transactionHash: ByteString,
915+
transactionHash: String,
919916
mustFullyAuthorize: Boolean,
920917
signedBy: Seq[Fingerprint],
921918
store: TopologyStoreId,
@@ -928,7 +925,7 @@ object TopologyAdminCommands {
928925

929926
override protected def createRequest(): Either[String, AuthorizeRequest] = Right(
930927
AuthorizeRequest(
931-
TransactionHashBytes(transactionHash),
928+
TransactionHash(transactionHash),
932929
mustFullyAuthorize = mustFullyAuthorize,
933930
forceChanges = Seq.empty,
934931
signedBy = signedBy.map(_.toProtoPrimitive),

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

Lines changed: 24 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
package com.digitalasset.canton.admin.api.client.data
55

6-
import cats.syntax.traverse.*
76
import com.digitalasset.canton.ProtoDeserializationError
87
import com.digitalasset.canton.admin.participant.v30
98
import com.digitalasset.canton.config.RequireTypes.{NonNegativeInt, PositiveInt}
@@ -24,6 +23,7 @@ final case class AddPartyStatus(
2423
synchronizerId: SynchronizerId,
2524
sourceParticipantId: ParticipantId,
2625
targetParticipantId: ParticipantId,
26+
topologySerial: PositiveInt,
2727
status: AddPartyStatus.Status,
2828
)
2929

@@ -47,13 +47,18 @@ object AddPartyStatus {
4747
"target_participant_uid",
4848
)
4949
.map(ParticipantId(_))
50+
topologySerial <- ProtoConverter.parsePositiveInt(
51+
"topology_serial",
52+
proto.topologySerial,
53+
)
5054
statusP <- ProtoConverter.required("status", proto.status).map(_.status)
5155
status <- parseStatus(statusP)
5256
} yield AddPartyStatus(
5357
partyId,
5458
synchronizerId,
5559
sourceParticipantId,
5660
targetParticipantId,
61+
topologySerial,
5762
status,
5863
)
5964

@@ -62,64 +67,41 @@ object AddPartyStatus {
6267
): ParsingResult[Status] =
6368
statusP match {
6469
case v30.GetAddPartyStatusResponse.Status.Status.ProposalProcessed(status) =>
65-
for {
66-
topologySerialO <- status.topologySerial.traverse(
67-
ProtoConverter.parsePositiveInt("topology_serial", _)
68-
)
69-
} yield ProposalProcessed(topologySerialO)
70+
Right(ProposalProcessed)
7071
case v30.GetAddPartyStatusResponse.Status.Status.AgreementAccepted(status) =>
7172
for {
7273
sequencerId <- UniqueIdentifier
7374
.fromProtoPrimitive(status.sequencerUid, "sequencer_id")
7475
.map(SequencerId(_))
75-
topologySerialO <- status.topologySerial.traverse(
76-
ProtoConverter.parsePositiveInt("topology_serial", _)
77-
)
78-
} yield AgreementAccepted(sequencerId, topologySerialO)
76+
} yield AgreementAccepted(sequencerId)
7977
case v30.GetAddPartyStatusResponse.Status.Status.TopologyAuthorized(status) =>
8078
for {
81-
commonFields <- parseCommonFields(
82-
status.sequencerUid,
83-
status.topologySerial,
84-
status.timestamp,
85-
)
86-
(sequencerId, topologySerial, timestamp) = commonFields
87-
} yield TopologyAuthorized(sequencerId, topologySerial, timestamp)
79+
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
80+
(sequencerId, timestamp) = commonFields
81+
} yield TopologyAuthorized(sequencerId, timestamp)
8882
case v30.GetAddPartyStatusResponse.Status.Status.ConnectionEstablished(status) =>
8983
for {
90-
commonFields <- parseCommonFields(
91-
status.sequencerUid,
92-
status.topologySerial,
93-
status.timestamp,
94-
)
95-
(sequencerId, topologySerial, timestamp) = commonFields
96-
} yield ConnectionEstablished(sequencerId, topologySerial, timestamp)
84+
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
85+
(sequencerId, timestamp) = commonFields
86+
} yield ConnectionEstablished(sequencerId, timestamp)
9787
case v30.GetAddPartyStatusResponse.Status.Status.ReplicatingAcs(status) =>
9888
for {
99-
commonFields <- parseCommonFields(
100-
status.sequencerUid,
101-
status.topologySerial,
102-
status.timestamp,
103-
)
104-
(sequencerId, topologySerial, timestamp) = commonFields
89+
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
90+
(sequencerId, timestamp) = commonFields
10591
contractsReplicated <- ProtoConverter.parseNonNegativeInt(
10692
"contracts_replicated",
10793
status.contractsReplicated,
10894
)
109-
} yield ReplicatingAcs(sequencerId, topologySerial, timestamp, contractsReplicated)
95+
} yield ReplicatingAcs(sequencerId, timestamp, contractsReplicated)
11096
case v30.GetAddPartyStatusResponse.Status.Status.Completed(status) =>
11197
for {
112-
commonFields <- parseCommonFields(
113-
status.sequencerUid,
114-
status.topologySerial,
115-
status.timestamp,
116-
)
117-
(sequencerId, topologySerial, timestamp) = commonFields
98+
commonFields <- parseCommonFields(status.sequencerUid, status.timestamp)
99+
(sequencerId, timestamp) = commonFields
118100
contractsReplicated <- ProtoConverter.parseNonNegativeInt(
119101
"contracts_replicated",
120102
status.contractsReplicated,
121103
)
122-
} yield Completed(sequencerId, topologySerial, timestamp, contractsReplicated)
104+
} yield Completed(sequencerId, timestamp, contractsReplicated)
123105
case v30.GetAddPartyStatusResponse.Status.Status.Error(status) =>
124106
for {
125107
statusPriorToErrorP <- ProtoConverter.required(
@@ -147,40 +129,33 @@ object AddPartyStatus {
147129

148130
private def parseCommonFields(
149131
sequencerUidP: String,
150-
topologySerialP: Int,
151132
timestampPO: Option[protobuf.timestamp.Timestamp],
152-
): ParsingResult[(SequencerId, PositiveInt, CantonTimestamp)] = for {
133+
): ParsingResult[(SequencerId, CantonTimestamp)] = for {
153134
sequencerId <- UniqueIdentifier
154135
.fromProtoPrimitive(sequencerUidP, "sequencer_id")
155136
.map(SequencerId(_))
156-
topologySerial <- ProtoConverter.parsePositiveInt("topology_serial", topologySerialP)
157137
timestampP <- ProtoConverter.required("timestamp", timestampPO)
158138
timestamp <- CantonTimestamp.fromProtoTimestamp(timestampP)
159-
} yield (sequencerId, topologySerial, timestamp)
139+
} yield (sequencerId, timestamp)
160140

161141
sealed trait Status
162-
final case class ProposalProcessed(topologySerial: Option[PositiveInt]) extends Status
163-
final case class AgreementAccepted(sequencerId: SequencerId, topologySerial: Option[PositiveInt])
164-
extends Status
142+
final case object ProposalProcessed extends Status
143+
final case class AgreementAccepted(sequencerId: SequencerId) extends Status
165144
final case class TopologyAuthorized(
166145
sequencerId: SequencerId,
167-
topologySerial: PositiveInt,
168146
timestamp: CantonTimestamp,
169147
) extends Status
170148
final case class ConnectionEstablished(
171149
sequencerId: SequencerId,
172-
topologySerial: PositiveInt,
173150
timestamp: CantonTimestamp,
174151
) extends Status
175152
final case class ReplicatingAcs(
176153
sequencerId: SequencerId,
177-
topologySerial: PositiveInt,
178154
timestamp: CantonTimestamp,
179155
contractsReplicated: NonNegativeInt,
180156
) extends Status
181157
final case class Completed(
182158
sequencerId: SequencerId,
183-
topologySerial: PositiveInt,
184159
timestamp: CantonTimestamp,
185160
contractsReplicated: NonNegativeInt,
186161
) extends Status

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,8 +1951,7 @@ object CantonConfig {
19511951
.foldLeft(c) { case (subConfig, (key, obj)) =>
19521952
subConfig.withValue(key, goVal(key, obj))
19531953
}
1954-
go(config)
1955-
.resolve()
1954+
go(config.resolve()) // Resolve config _before_ redacting confidential fields
19561955
.root()
19571956
.get("canton")
19581957
.render(CantonConfig.defaultConfigRenderer)

community/app-base/src/main/scala/com/digitalasset/canton/console/ConsoleMacros.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,10 @@ trait ConsoleMacros extends NamedLogging with NoTracing {
285285
)
286286
)
287287

288-
val LfContractId.V1(discriminator, _) = contract.contractId
288+
val LfContractId.V1(discriminator, _) = contract.contractId match {
289+
case cid: LfContractId.V1 => cid
290+
case _ => sys.error("ContractId V2 are not supported")
291+
}
289292
val pureCrypto = participant.underlying
290293
.map(_.cryptoPureApi)
291294
.getOrElse(sys.error("where is my crypto?"))

community/app-base/src/main/scala/com/digitalasset/canton/console/InstanceReference.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ trait LocalInstanceReference extends InstanceReference with NoTracing {
347347
protected def startInstance(): Either[StartupError, Unit] =
348348
nodes.startAndWait(name)
349349
protected def stopInstance(): Either[ShutdownError, Unit] = nodes.stopAndWait(name)
350+
351+
/** We use [[com.digitalasset.canton.crypto.Crypto]] because it supports key administration
352+
* console commands that do not require the node to be connected to a synchronizer. It is
353+
* intended to be used exclusively by the admin API with a trusted operator.
354+
*/
350355
protected[canton] def crypto: Crypto
351356

352357
protected def runCommandIfRunning[Result](

community/app-base/src/main/scala/com/digitalasset/canton/console/commands/PartiesAdministration.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,8 @@ class ParticipantPartiesAdministrationGroup(
342342
def add_party_async(
343343
party: PartyId,
344344
synchronizerId: SynchronizerId,
345-
sourceParticipant: Option[ParticipantId],
346-
serial: Option[PositiveInt],
345+
sourceParticipant: ParticipantId,
346+
serial: PositiveInt,
347347
): String = check(FeatureFlag.Preview) {
348348
consoleEnvironment.run {
349349
reference.adminCommand(

community/app-base/src/main/scala/com/digitalasset/canton/console/commands/TopologyAdministration.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ class TopologyAdministrationGroup(
427427
consoleEnvironment.run {
428428
adminCommand(
429429
TopologyAdminCommands.Write.Authorize(
430-
txHash.hash.getCryptographicEvidence,
430+
txHash.hash.toHexString,
431431
mustFullyAuthorize = mustBeFullyAuthorized,
432432
signedBy = signedBy,
433433
store = store,

0 commit comments

Comments
 (0)