Skip to content

Commit

Permalink
Update participant state v2 interfaces (digital-asset#1800)
Browse files Browse the repository at this point in the history
Moves party allocation to its own WriteService trait (similar to package upload).

Changes uploadDar to uploadPackages, so that the write service does not depend on the DAR file format.

Adds or improves many comments.
  • Loading branch information
rautenrieth-da authored Jun 27, 2019
1 parent d24366f commit 77d9162
Show file tree
Hide file tree
Showing 17 changed files with 281 additions and 157 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,16 @@ message PackageDetails {
string package_id = 1;

// Size of the package in bytes.
// The size of the package is given by the size of the ``daml_lf``
// ArchivePayload. See further details in ``daml_lf.proto``.
// Required
uint64 package_size = 2;

// Indicates since when the package is known to the backing participant.
// Required
google.protobuf.Timestamp known_since = 3;

// Descrioption provided by the backing participant descnribing where
// Description provided by the backing participant describing where
// it got the package from.
// Optional
string source_description = 4;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ trait ErrorFactories {
def unimplemented(description: String): StatusRuntimeException =
grpcError(Status.UNIMPLEMENTED.withDescription(description))

def permissionDenied(description: String): StatusRuntimeException =
grpcError(Status.PERMISSION_DENIED.withDescription(description))

def grpcError(status: Status) = new ApiException(status)

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,19 @@ package object v2 {

final case class LedgerConfiguration(minTTL: Duration, maxTTL: Duration)

/** DAML-LF package details */
final case class PackageDetails(size: Long, knownSince: Instant, sourceDescription: String)
/** Meta-data of a DAML-LF package
*
* @param size : The size of the archive payload, in bytes.
*
* @param knownSince : Indicates since when the package is known to
* the backing participant.
*
* @param sourceDescription : Optional description provided by the backing
* participant describing where it got the package from.
*
*/
final case class PackageDetails(
size: Long,
knownSince: Instant,
sourceDescription: Option[String])
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,30 @@ package com.daml.ledger.participant.state.v2

import com.digitalasset.ledger.api.domain.PartyDetails

sealed abstract class PartyAllocationResult extends Product with Serializable
sealed abstract class PartyAllocationResult extends Product with Serializable {
def description: String
}

object PartyAllocationResult {

/** The party was successfully allocated */
final case class Ok(result: PartyDetails) extends PartyAllocationResult

/** Synchronous party allocation is not supported */
final case object NotSupported extends PartyAllocationResult
final case class Ok(result: PartyDetails) extends PartyAllocationResult {
override def description: String = "Party successfully allocated"
}

/** The requested party name already exists */
final case object AlreadyExists extends PartyAllocationResult
final case object AlreadyExists extends PartyAllocationResult {
override def description: String = "Party already exists"
}

/** The requested party name is not valid */
final case object InvalidName extends PartyAllocationResult
final case class InvalidName(details: String) extends PartyAllocationResult {
override def description: String = "Party name is invalid: " + details
}

/** The participant was not authorized to submit the allocation request */
final case object ParticipantNotAuthorized extends PartyAllocationResult {
override def description: String = "Participant is not authorized to allocate a party"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,29 @@ object Update {
s"Configuration changed to: $newConfiguration"
}

/** Signal that a party is hosted at this participant.
/** Signal that a party is hosted at a participant.
*
* As explained in the note on [[ReadService.stateUpdates]], the
* state updates are only expected to signal all updates pertaining
* to data affecting the parties hosted at the participant.
* @param party
* The newly allocated party identifier.
*
* @param displayName
* The user readable description of the party. May not be unique.
*
* @param participantId
* The participant that this party was added to.
*
* @param recordTime
* The ledger-provided timestamp at which the party was allocated.
*
*/
final case class PartyAddedToParticipant(party: Party) extends Update {
override def description: String = s"Add party '$party' to participant"
final case class PartyAddedToParticipant(
party: Party,
displayName: String,
participantId: String,
recordTime: Timestamp)
extends Update {
override def description: String =
s"Add party '$party' to participant"
}

/** Signal the uploading of a package that is publicly visible.
Expand All @@ -58,6 +72,22 @@ object Update {
* extension where we plan to support per-party package visibility
* https://github.com/digital-asset/daml/issues/311.
*
*
* @param archives
* The list of DAML-LF packages that were uploaded.
*
* @param sourceDescription
* A description of the packages, provided by the administrator as part of
* the upload.
*
* @param participantId
* The participant through which the packages were uploaded. This field
* is informative, and can be used by applications to display information
* about the origin of the packages.
*
* @param recordTime
* The ledger-provided timestamp at which the packages were uploaded.
*
*/
final case class PublicPackagesUploaded(
archives: List[DamlLf.Archive],
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.ledger.participant.state.v2

sealed abstract class UploadPackagesResult extends Product with Serializable {
def description: String
}

object UploadPackagesResult {

/** The package was successfully uploaded */
final case object Ok extends UploadPackagesResult {
override def description: String = "Packages successfully uploaded"
}

/** One of the uploaded packages is not valid */
final case class InvalidPackage(reason: String) extends UploadPackagesResult {
override def description: String = "Uploaded packages were invalid: " + reason
}

/** The participant was not authorized to submit the upload request */
final case object ParticipantNotAuthorized extends UploadPackagesResult {
override def description: String = "Participant is not authorized to upload packages"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ package com.daml.ledger.participant.state.v2

import java.util.concurrent.CompletionStage

import com.digitalasset.daml_lf.DamlLf.Archive

/** An interface for uploading packages via a participant. */
trait WritePackagesService {

/** Upload a collection of DAML-LF packages to the ledger.
Expand All @@ -21,18 +24,25 @@ trait WritePackagesService {
* message. See the comments on [[ReadService.stateUpdates]] and [[Update]] for
* further details.
*
* @param payload : DAML-LF packages to be uploaded to the ledger.
* @param sourceDescription : the description of the packages provided by the
* participant implementation.
* Note: we accept [[Archive]]s rather than parsed packages, because we want
* to be able to get the byte size of each individual ArchivePayload, which
* is information that the read / index service need to provide. Moreover
* this information should be consistent with the payload that the
* [[com.digitalasset.ledger.api.v1.package_service.GetPackageResponse]]
* contains. If we were to consume packages we'd have to re-encode them to
* provide the size, and the size might potentially be different from the
* original size, which would be quite confusing.
*
* @param sourceDescription : Description provided by the backing participant
* describing where it got the package from, e.g., when, where, or by whom
* the packages were uploaded.
*
* @param payload : DAML-LF archives to be uploaded to the ledger.
*
* @return an async result of a SubmissionResult
* @return an async result of a [[UploadPackagesResult]]
*/
// NOTE(FM): we accept dars rather than a list of archives because we want
// to be able to get the byte size of each individual ArchivePayload, which is
// information that the read / index service need to provide. Moreover this
// information should be consistent with the payload that the
// `GetPackageResponse` contains. If we were to consume archives we'd have
// to re-encode them to provide the size, and the size might potentially be
// different from the original size, which would be quite confusing.
def uploadDar(sourceDescription: String, payload: Array[Byte]): CompletionStage[UploadDarResult]
def uploadPackages(
payload: List[Archive],
sourceDescription: Option[String]
): CompletionStage[UploadPackagesResult]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright (c) 2019 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package com.daml.ledger.participant.state.v2

import java.util.concurrent.CompletionStage

/** An interface for on-boarding parties via a participant. */
trait WritePartyService {

/**
* Adds a new party to the set managed by the ledger.
*
* Caller specifies a party identifier suggestion, the actual identifier
* allocated might be different and is implementation specific.
*
* In particular, a ledger may:
* - Disregard the given hint and choose a completely new party identifier
* - Construct a new unique identifier from the given hint, e.g., by appending a UUID
* - Use the given hint as is, and reject the call if such a party already exists
*
* The result of the party allocation is communicated synchronously.
* TODO: consider also providing an asynchronous response in a similar
* manner as it is done for transaction submission. It is possible that
* in some implementations, party allocation will fail due to authorization etc.
*
* Successful party allocations will result in a [[Update.PartyAddedToParticipant]]
* message. See the comments on [[ReadService.stateUpdates]] and [[Update]] for
* further details.
*
* @param hint : A party identifier suggestion
*
* @param displayName : A human readable name of the new party
*
* @return an async result of a PartyAllocationResult
*/
def allocateParty(
hint: Option[String],
displayName: Option[String]
): CompletionStage[PartyAllocationResult]
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import java.util.concurrent.CompletionStage
* plans to make this functionality uniformly available: see the roadmap for
* progress information https://github.com/digital-asset/daml/issues/121.
*
* As of now there are two methods for changing the state of a DAML ledger:
* - submitting a transaction using [[WriteService!.submitTransaction]].
* - allocating a new party using [[WriteService!.allocateParty]]
* As of now there are three methods for changing the state of a DAML ledger:
* - submitting a transaction using [[WriteService!.submitTransaction]]
* - allocating a new party using [[WritePartyService!.allocateParty]]
* - uploading a new package using [[WritePackagesService!.uploadPackages]]
*
*/
trait WriteService extends WritePackagesService {
trait WriteService extends WritePackagesService with WritePartyService {

/** Submit a transaction for acceptance to the ledger.
*
Expand Down Expand Up @@ -95,25 +96,4 @@ trait WriteService extends WritePackagesService {
submitterInfo: SubmitterInfo,
transactionMeta: TransactionMeta,
transaction: SubmittedTransaction): CompletionStage[SubmissionResult]

/**
* Adds a new party to the set managed by the ledger.
*
* Caller specifies a party identifier suggestion, the actual identifier
* allocated might be different and is implementation specific.
*
* In particular, a ledger may:
* - Disregard the given hint and choose a completely new party identifier
* - Construct a new unique identifier from the given hint, e.g., by appending a UUID
* - Use the given hint as is, and reject the call if such a party already exists
*
* @param hint A party identifier suggestion
* @param displayName A human readable name of the new party
*
* @return an async result of a PartyAllocationResult
*/
def allocateParty(
hint: Option[String],
displayName: Option[String]
): CompletionStage[PartyAllocationResult]
}
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ object ApiServices {
}

val apiPartyManagementService =
ApiPartyManagementService.createApiService(partyManagementService, writeService)
ApiPartyManagementService
.createApiService(partyManagementService, writeService)

val apiPackageManagementService =
ApiPackageManagementService.createApiService(indexService, writeService)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class SandboxServer(actorSystemName: String, config: => SandboxConfig) extends A
// TODO is it sensible to have all the initial packages to be known
// since the epoch?
for (file <- config.damlPackages) {
packageStore.putDarFile(Instant.EPOCH, "", file) match {
packageStore.putDarFile(Instant.EPOCH, None, file) match {
case Right(details @ _) => ()
case Left(err) => sys.error(s"Could not load package $file: $err")
}
Expand Down
Loading

0 comments on commit 77d9162

Please sign in to comment.