mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 08:48:21 +03:00
clarify the role of party sets in various locations (#766)
* clarify role of party sets in various locations * use 1.dev for tests... ...so that we're sure we're testing the latest value / tx versions.
This commit is contained in:
parent
16ea1ceacd
commit
e8261f2fd9
@ -9,7 +9,7 @@ class EngineInfoTest extends WordSpec with Matchers {
|
||||
EngineInfo.getClass.getSimpleName should {
|
||||
"show supported LF, Transaction and Value versions" in {
|
||||
EngineInfo.show shouldBe
|
||||
"DAML LF Engine supports LF versions: 0, 0.dev, 1.0, 1.1, 1.2, 1.3, 1.dev; Transaction versions: 1, 2, 3, 4, 5; Value versions: 1, 2, 3, 4"
|
||||
"DAML LF Engine supports LF versions: 0, 0.dev, 1.0, 1.1, 1.2, 1.3, 1.dev; Transaction versions: 1, 2, 3, 4, 5, 6; Value versions: 1, 2, 3, 4"
|
||||
}
|
||||
|
||||
"toString returns the same value as show" in {
|
||||
|
@ -4,7 +4,7 @@
|
||||
DAML-LF Transaction Specification
|
||||
=================================
|
||||
|
||||
**version 5, 12 March 2019**
|
||||
**version 6, 29 April 2019**
|
||||
|
||||
This specification, in concert with the ``transaction.proto``
|
||||
machine-readable definition, defines a format for _transactions_, to be
|
||||
@ -155,6 +155,8 @@ This table lists every version of this specification in ascending order
|
||||
+--------------------+-----------------+
|
||||
| 5 | 2019-03-12 |
|
||||
+--------------------+-----------------+
|
||||
| 6 | 2019-04-29 |
|
||||
+--------------------+-----------------+
|
||||
|
||||
message Transaction
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
@ -300,6 +302,15 @@ As of version 1, these fields are included:
|
||||
Every element of ``stakeholders`` is a party identifier.
|
||||
``signatories`` must be a non-empty subset of ``stakeholders``.
|
||||
|
||||
.. note:: *This section is non-normative.*
|
||||
|
||||
The stakeholders of a contract are the signatories and the observers of
|
||||
said contract.
|
||||
|
||||
The signatories of a contract are specified in the DAML-LF definition of
|
||||
the template for said contract. Conceptually, they are the parties that
|
||||
agreed for that contract to be created.
|
||||
|
||||
*since version 3*
|
||||
|
||||
A new field is included:
|
||||
@ -314,6 +325,9 @@ A new field is included:
|
||||
* Its ``key`` must conform to the key definition for the ``template_id``
|
||||
in the ``contract_instance``.
|
||||
|
||||
The maintainers of a contract key are specified in the DAML-LF definition of
|
||||
the template for the contract.
|
||||
|
||||
*since version 4*
|
||||
|
||||
``contract_id`` must not be set, and this new field is required:
|
||||
@ -386,6 +400,12 @@ As of version 5, this new field is required to be non-empty:
|
||||
|
||||
Every element of ``actors`` is a party identifier.
|
||||
|
||||
.. note:: *This section is non-normative.*
|
||||
|
||||
Actors are specified explicitly by the user invoking fetching the
|
||||
contract -- or in other words, they are _not_ a property of the
|
||||
contract itself.
|
||||
|
||||
message NodeExercise
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -432,6 +452,17 @@ this choice.
|
||||
Every element of ``actors``, ``stakeholders``, ``signatories``, and
|
||||
``controllers`` is a party identifier.
|
||||
|
||||
.. note:: *This section is non-normative.*
|
||||
|
||||
The ``stakeholders`` and ``signatories`` field have the same meaning
|
||||
they have for ``NodeCreate``.
|
||||
|
||||
The ``actors`` field contains the parties that exercised the choice.
|
||||
The ``controllers`` field contains the parties that _can_ exercise
|
||||
the choice. Note that according to the ledger model these two fields
|
||||
_must_ be the same. For this reason the ``controllers`` field was
|
||||
removed in version 6 -- see *since version 6* below.
|
||||
|
||||
*since version 4*
|
||||
|
||||
``contract_id`` must not be set, and this new field is required:
|
||||
@ -449,6 +480,12 @@ If ``contract_id_struct``'s ``relative`` field is ``true``, then:
|
||||
3. ``signatories`` must have the same elements as the corresponding
|
||||
``NodeCreate``'s ``signatories`` field.
|
||||
|
||||
*since version 6*
|
||||
|
||||
The ``controllers`` field must be empty. Software needing to fill in
|
||||
data structures that demand both actors and controllers must use
|
||||
the ``actors`` field as the controllers.
|
||||
|
||||
message NodeLookupByKey
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
@ -306,7 +306,6 @@ object ValueGenerators {
|
||||
chosenValue <- versionedValueGen
|
||||
stakeholders <- genNonEmptyParties
|
||||
signatories <- genNonEmptyParties
|
||||
controllers <- genNonEmptyParties
|
||||
children <- Gen
|
||||
.listOf(Arbitrary.arbInt.arbitrary)
|
||||
.map(_.map(Transaction.NodeId.unsafeFromIndex))
|
||||
@ -322,7 +321,7 @@ object ValueGenerators {
|
||||
chosenValue,
|
||||
stakeholders,
|
||||
signatories,
|
||||
controllers,
|
||||
actingParties,
|
||||
children
|
||||
)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
// * 3: new node type NodeLookupByKey
|
||||
// * 4: string contract_id replaced globally by ContractId message
|
||||
// * 5: new field actors in NodeFetch
|
||||
// * 6: removal of controllers in exercise nodes
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
|
@ -81,6 +81,11 @@ object Node {
|
||||
chosenValue: Val,
|
||||
stakeholders: Set[Party],
|
||||
signatories: Set[Party],
|
||||
/** Note that here we have both actors and controllers because we use this
|
||||
* data structure _before_ we validate the transaction. However for every
|
||||
* valid transaction the actors must be the same as the controllers. This
|
||||
* is why we removed the controllers field in transaction version 6.
|
||||
*/
|
||||
controllers: Set[Party],
|
||||
children: ImmArray[Nid])
|
||||
extends GenNode[Nid, Cid, Val] {
|
||||
@ -95,7 +100,36 @@ object Node {
|
||||
)
|
||||
}
|
||||
|
||||
object NodeExercises extends WithTxValue3[NodeExercises]
|
||||
object NodeExercises extends WithTxValue3[NodeExercises] {
|
||||
|
||||
/** After interpretation authorization, it must be the case that
|
||||
* the controllers are the same as the acting parties. This
|
||||
* apply method enforces it.
|
||||
*/
|
||||
def apply[Nid, Cid, Val](
|
||||
targetCoid: Cid,
|
||||
templateId: Identifier,
|
||||
choiceId: ChoiceName,
|
||||
optLocation: Option[Location],
|
||||
consuming: Boolean,
|
||||
actingParties: Set[Party],
|
||||
chosenValue: Val,
|
||||
stakeholders: Set[Party],
|
||||
signatories: Set[Party],
|
||||
children: ImmArray[Nid]): NodeExercises[Nid, Cid, Val] =
|
||||
NodeExercises(
|
||||
targetCoid,
|
||||
templateId,
|
||||
choiceId,
|
||||
optLocation,
|
||||
consuming,
|
||||
actingParties,
|
||||
chosenValue,
|
||||
stakeholders,
|
||||
signatories,
|
||||
actingParties,
|
||||
children)
|
||||
}
|
||||
|
||||
final case class NodeLookupByKey[+Cid, +Val](
|
||||
templateId: Identifier,
|
||||
|
@ -99,7 +99,7 @@ object TransactionCoder {
|
||||
nodeId: Nid,
|
||||
node: GenNode[Nid, Cid, Val]): Either[EncodeError, TransactionOuterClass.Node] = {
|
||||
val nodeBuilder = TransactionOuterClass.Node.newBuilder().setNodeId(encodeNid(nodeId))
|
||||
import TransactionVersions.minKeyOrLookupByKey
|
||||
import TransactionVersions.{minKeyOrLookupByKey, minNoControllers}
|
||||
node match {
|
||||
case c: NodeCreate[Cid, Val] =>
|
||||
encodeContractInstance(encodeVal, c.coinst).flatMap { inst =>
|
||||
@ -151,7 +151,7 @@ object TransactionCoder {
|
||||
}
|
||||
|
||||
case e: NodeExercises[Nid, Cid, Val] =>
|
||||
encodeVal(e.chosenValue).map {
|
||||
encodeVal(e.chosenValue).flatMap {
|
||||
case (vversion, arg) =>
|
||||
val exBuilder =
|
||||
TransactionOuterClass.NodeExercise
|
||||
@ -165,11 +165,21 @@ object TransactionCoder {
|
||||
_.setContractIdStruct(_))
|
||||
.addAllActors(e.actingParties.map(_.underlyingString).asJava)
|
||||
.addAllChildren(e.children.map(encodeNid).toList.asJava)
|
||||
.addAllControllers(e.controllers.map(_.underlyingString).asJava)
|
||||
.addAllSignatories(e.signatories.map(_.underlyingString).asJava)
|
||||
.addAllStakeholders(e.stakeholders.map(_.underlyingString).asJava)
|
||||
|
||||
nodeBuilder.setExercise(exBuilder).build()
|
||||
if (transactionVersion precedes minNoControllers) {
|
||||
if (e.controllers == e.actingParties) {
|
||||
exBuilder.addAllControllers(e.controllers.map(_.underlyingString).asJava)
|
||||
Right(nodeBuilder.setExercise(exBuilder).build())
|
||||
} else {
|
||||
Left(EncodeError(
|
||||
s"As of version $transactionVersion, the controllers and actingParties of an exercise node _must_ be the same, but I got ${e.controllers} as controllers and ${e.actingParties} as actingParties."))
|
||||
}
|
||||
} else {
|
||||
Right(nodeBuilder.setExercise(exBuilder).build())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case nlbk: NodeLookupByKey[Cid, Val] =>
|
||||
@ -221,7 +231,7 @@ object TransactionCoder {
|
||||
protoNode: TransactionOuterClass.Node): Either[DecodeError, (Nid, GenNode[Nid, Cid, Val])] = {
|
||||
val nodeId = decodeNid(protoNode.getNodeId)
|
||||
|
||||
import TransactionVersions.minKeyOrLookupByKey
|
||||
import TransactionVersions.{minKeyOrLookupByKey, minNoControllers}
|
||||
protoNode.getNodeTypeCase match {
|
||||
case NodeTypeCase.CREATE =>
|
||||
for {
|
||||
@ -274,10 +284,19 @@ object TransactionCoder {
|
||||
children <- childrenOrError
|
||||
cv <- decodeVal(protoExe.getChosenValue)
|
||||
templateId <- ValueCoder.decodeIdentifier(protoExe.getTemplateId)
|
||||
controllers <- toPartySet(protoExe.getControllersList)
|
||||
actingParties <- toPartySet(protoExe.getActorsList)
|
||||
encodedControllers <- toPartySet(protoExe.getControllersList)
|
||||
controllers <- if (!(txVersion precedes minNoControllers)) {
|
||||
if (encodedControllers.isEmpty) {
|
||||
Right(actingParties)
|
||||
} else {
|
||||
Left(DecodeError(s"As of version $txVersion, exercise controllers must be empty."))
|
||||
}
|
||||
} else {
|
||||
Right(encodedControllers)
|
||||
}
|
||||
signatories <- toPartySet(protoExe.getSignatoriesList)
|
||||
stakeholders <- toPartySet(protoExe.getStakeholdersList)
|
||||
actingParties <- toPartySet(protoExe.getActorsList)
|
||||
} yield
|
||||
(
|
||||
ni,
|
||||
|
@ -15,12 +15,13 @@ final case class TransactionVersion(protoValue: String)
|
||||
*/
|
||||
object TransactionVersions
|
||||
extends LfVersions(
|
||||
maxVersion = TransactionVersion("5"),
|
||||
previousVersions = List("1", "2", "3", "4") map TransactionVersion)(_.protoValue) {
|
||||
maxVersion = TransactionVersion("6"),
|
||||
previousVersions = List("1", "2", "3", "4", "5") map TransactionVersion)(_.protoValue) {
|
||||
|
||||
private[this] val minVersion = TransactionVersion("1")
|
||||
private[transaction] val minKeyOrLookupByKey = TransactionVersion("3")
|
||||
private[transaction] val minFetchActors = TransactionVersion("5")
|
||||
private[transaction] val minNoControllers = TransactionVersion("6")
|
||||
|
||||
def assignVersion(a: GenTransaction[_, _, _ <: VersionedValue[_]]): TransactionVersion = {
|
||||
require(a != null)
|
||||
|
@ -48,6 +48,7 @@ private[lf] object VersionTimeline {
|
||||
This(That(TransactionVersion("5"))),
|
||||
That(LanguageVersion(LMV.V1, "2")),
|
||||
Both(This(ValueVersion("4")), LanguageVersion(LMV.V1, "3")),
|
||||
This(That(TransactionVersion("6"))),
|
||||
That(LanguageVersion(LMV.V1, Dev)),
|
||||
// add new versions above this line
|
||||
// do *not* backfill to make more Boths, because such would
|
||||
|
@ -11,9 +11,24 @@ import "com/digitalasset/ledger/api/v1/value.proto";
|
||||
option java_outer_classname = "EventOuterClass";
|
||||
option java_package = "com.digitalasset.ledger.api.v1";
|
||||
|
||||
// An event on the ledger can either be the creation or the archiving of a contract, or the exercise of a choice on a contract.
|
||||
// The ``GetTransactionTrees`` response will only contain create and exercise events.
|
||||
// Archive events correspond to consuming exercise events.
|
||||
// An event on the ledger can either be the creation or the archiving of
|
||||
// a contract, or the exercise of a choice on a contract.
|
||||
//
|
||||
// The ``GetTransactionTrees`` response will only contain create and
|
||||
// exercise events. Archive events correspond to consuming exercise
|
||||
// events.
|
||||
//
|
||||
// In the transaction service the events are restricted to the events
|
||||
// visible for the parties specified in the transaction filter. Each
|
||||
// event message type below contains a ``witness_parties`` field which
|
||||
// indicates the subset of the requested parties that can see the event
|
||||
// in question.
|
||||
//
|
||||
// However, note that transaction _trees_ might contain events with
|
||||
// _no_ witness parties, which were included simply because they were
|
||||
// children of events which have witnesses. On the other hand, on
|
||||
// the flat transaction stream you'll only receive events that have
|
||||
// witnesses.
|
||||
message Event {
|
||||
oneof event {
|
||||
CreatedEvent created = 1;
|
||||
@ -41,7 +56,11 @@ message CreatedEvent {
|
||||
// Required
|
||||
Record create_arguments = 4;
|
||||
|
||||
// The parties that are notified of this event.
|
||||
// The parties that are notified of this event. For `CreatedEvent`s,
|
||||
// these are the intersection of the stakeholders of the contract in
|
||||
// question and the parties specified in the `TransactionFilter`. The
|
||||
// stakeholders are the union of the signatories and the observers of
|
||||
// the contract.
|
||||
// Required
|
||||
repeated string witness_parties = 5;
|
||||
}
|
||||
@ -61,7 +80,11 @@ message ArchivedEvent {
|
||||
// Required
|
||||
Identifier template_id = 3;
|
||||
|
||||
// The parties that are notified of this event.
|
||||
// The parties that are notified of this event. For `ArchivedEvent`s,
|
||||
// these are the intersection of the stakeholders of the contract in
|
||||
// question and the parties specified in the `TransactionFilter`. The
|
||||
// stakeholders are the union of the signatories and the observers of
|
||||
// the contract.
|
||||
// Required
|
||||
repeated string witness_parties = 4;
|
||||
}
|
||||
@ -101,9 +124,21 @@ message ExercisedEvent {
|
||||
// Required
|
||||
bool consuming = 8;
|
||||
|
||||
// field ID 9 deprecated
|
||||
reserved 9; // removed field
|
||||
|
||||
// The parties that are notified of this event.
|
||||
// The parties that are notified of this event. The witnesses of an exercise
|
||||
// node will depend on whether the exercise was consuming or not.
|
||||
//
|
||||
// If consuming, the witnesses are the union of the stakeholders and
|
||||
// the actors.
|
||||
//
|
||||
// If not consuming, the witnesses are the union of the signatories and
|
||||
// the actors. Note that the actors might not necessarily be observers
|
||||
// and thus signatories. This is the case when the controllers of a
|
||||
// choice are specified using "flexible controllers", using the
|
||||
// `choice ... controller` syntax, and said controllers are not
|
||||
// explicitly marked as observers.
|
||||
//
|
||||
// Required
|
||||
repeated string witness_parties = 10;
|
||||
|
||||
|
@ -118,7 +118,7 @@ genrule(
|
||||
daml_compile(
|
||||
name = "Test",
|
||||
main_src = "src/test/resources/damls/Test.daml",
|
||||
target = "1.3",
|
||||
target = "1.dev",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
|
@ -368,7 +368,10 @@ private class PostgresLedgerDao(
|
||||
"recorded_at" -> recordedAt,
|
||||
"transaction" -> transactionSerializer
|
||||
.serialiseTransaction(transaction)
|
||||
.getOrElse(sys.error(s"failed to serialise transaction! trId: ${transactionId}"))
|
||||
.fold(
|
||||
e => sys.error(s"failed to serialise transaction! trId: ${transactionId}: $e"),
|
||||
identity
|
||||
)
|
||||
)
|
||||
.execute()
|
||||
|
||||
|
@ -323,7 +323,6 @@ class PostgresDaoSpec
|
||||
VersionedValue(ValueVersions.acceptedVersions.head, ValueText("some choice value")),
|
||||
Set(SimpleString.assertFromString("Alice"), SimpleString.assertFromString("Bob")),
|
||||
Set(SimpleString.assertFromString("Alice"), SimpleString.assertFromString("Bob")),
|
||||
Set(SimpleString.assertFromString("Alice"), SimpleString.assertFromString("Bob")),
|
||||
ImmArray.empty
|
||||
)),
|
||||
ImmArray(s"event$id"),
|
||||
|
Loading…
Reference in New Issue
Block a user