Skip to content

Commit

Permalink
Add by_interface field in Create, Fetch, & Exercise transaction nodes. (
Browse files Browse the repository at this point in the history
#11576)

* Add by_interface field in tx nodes.

This PR adds an optional `by_interface` field in the Create, Fetch,
and Exercise nodes, as part of #10915. It also updates TransactionCoder
to support these fields.

Setting these fields (in the LF interpreter) is left to a separate PR.

changelog_begin
changelog_end

* update security-evidence.md

* Add version checks in TransactionCoder
  • Loading branch information
sofiafaro-da authored Nov 8, 2021
1 parent 7d68e05 commit cbc3c8c
Show file tree
Hide file tree
Showing 23 changed files with 136 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class AuthorizationSpec extends AnyFreeSpec with Matchers with Inside {
observers = Seq("Carl"),
key = Some(Value.ValueUnit),
maintainers = maintainers,
byInterface = None,
)

"create" - {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class BlindingSpec extends AnyFreeSpec with Matchers {
observers = Seq("Carl"),
key = Some(ValueRecord(None, ImmArray.empty)),
maintainers = Seq("Alice"),
byInterface = None,
)
val lookup = builder.lookupByKey(create, true)
val nodeId = builder.add(lookup)
Expand All @@ -124,6 +125,7 @@ class BlindingSpec extends AnyFreeSpec with Matchers {
observers = Seq("Carl"),
key = Some(ValueRecord(None, ImmArray.empty)),
maintainers = Seq("Alice"),
byInterface = None,
)
val lookup = builder.lookupByKey(create, false)
val nodeId = builder.add(lookup)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1104,6 +1104,7 @@ class EngineTest
_,
_,
_,
_,
) =>
coid shouldBe originalCoid
consuming shouldBe true
Expand Down Expand Up @@ -1190,7 +1191,7 @@ class EngineTest

def actFetchActors(n: Node): Set[Party] = {
n match {
case Node.Fetch(_, _, actingParties, _, _, _, _, _) => actingParties
case Node.Fetch(_, _, actingParties, _, _, _, _, _, _) => actingParties
case _ => Set()
}
}
Expand Down Expand Up @@ -1576,7 +1577,7 @@ class EngineTest
)

tx.transaction.nodes.values.headOption match {
case Some(Node.Fetch(_, _, _, _, _, key, _, _)) =>
case Some(Node.Fetch(_, _, _, _, _, key, _, _, _)) =>
key match {
// just test that the maintainers match here, getting the key out is a bit hairier
case Some(Node.KeyWithMaintainers(_, maintainers)) =>
Expand Down Expand Up @@ -1800,7 +1801,7 @@ class EngineTest
val stx = suffix(tx)

val ImmArray(_, exeNode1) = tx.transaction.roots
val Node.Exercise(_, _, _, _, _, _, _, _, _, children, _, _, _, _) =
val Node.Exercise(_, _, _, _, _, _, _, _, _, children, _, _, _, _, _) =
tx.transaction.nodes(exeNode1)
val nids = children.toSeq.take(2).toImmArray

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ object ScenarioLedger {
}
processNodes(mbNewCache2, idsToProcess)

case Node.Fetch(referencedCoid, templateId @ _, _, _, _, _, _, _) =>
case Node.Fetch(referencedCoid, templateId @ _, _, _, _, _, _, _, _) =>
val newCacheP =
newCache.updateLedgerNodeInfo(referencedCoid)(info =>
info.copy(referencedBy = info.referencedBy + eventId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,7 @@ private[lf] object SBuiltin {
signatories = sigs,
stakeholders = sigs union obs,
key = mbKey,
byInterface = None, // TODO https://github.com/digital-asset/daml/issues/10915
)

machine.addLocalContract(coid, templateId, createArg, sigs, obs, mbKey)
Expand Down Expand Up @@ -1007,6 +1008,7 @@ private[lf] object SBuiltin {
mbKey = mbKey,
byKey = byKey,
chosenValue = chosenValue,
byInterface = None, // TODO https://github.com/digital-asset/daml/issues/10915
)
checkAborted(onLedger.ptx)
machine.returnValue = SUnit
Expand Down Expand Up @@ -1217,6 +1219,7 @@ private[lf] object SBuiltin {
stakeholders,
key,
byKey,
None, // TODO https://github.com/digital-asset/daml/issues/10915
)
checkAborted(onLedger.ptx)
machine.returnValue = SUnit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ private[lf] object PartialTransaction {
* @param parent The context in which the exercises is
* happening.
* @param byKey True if the exercise is done "by key"
* @param byInterface The interface through which this exercise
* was invoked, if any.
*/
final case class ExercisesContextInfo(
targetId: Value.ContractId,
Expand All @@ -151,6 +153,7 @@ private[lf] object PartialTransaction {
nodeId: NodeId,
parent: Context,
byKey: Boolean,
byInterface: Option[TypeConName],
) extends ContextInfo {
val actionNodeSeed = parent.nextActionChildSeed
val actionChildSeed = crypto.Hash.deriveNodeSeed(actionNodeSeed, _)
Expand Down Expand Up @@ -406,6 +409,7 @@ private[speedy] case class PartialTransaction(
signatories: Set[Party],
stakeholders: Set[Party],
key: Option[Node.KeyWithMaintainers[Value]],
byInterface: Option[TypeConName],
): (Value.ContractId, PartialTransaction) = {
val actionNodeSeed = context.nextActionChildSeed
val discriminator =
Expand All @@ -420,6 +424,7 @@ private[speedy] case class PartialTransaction(
signatories,
stakeholders,
key,
byInterface,
version,
)
val nid = NodeId(nextNodeIdx)
Expand Down Expand Up @@ -498,6 +503,7 @@ private[speedy] case class PartialTransaction(
stakeholders: Set[Party],
key: Option[Node.KeyWithMaintainers[Value]],
byKey: Boolean,
byInterface: Option[TypeConName],
): PartialTransaction = {
val nid = NodeId(nextNodeIdx)
val version = packageToTransactionVersion(templateId.packageId)
Expand All @@ -509,6 +515,7 @@ private[speedy] case class PartialTransaction(
stakeholders,
key,
normByKey(version, byKey),
byInterface,
version,
)
mustBeActive(
Expand Down Expand Up @@ -554,6 +561,7 @@ private[speedy] case class PartialTransaction(
mbKey: Option[Node.KeyWithMaintainers[Value]],
byKey: Boolean,
chosenValue: Value,
byInterface: Option[TypeConName],
): PartialTransaction = {
val nid = NodeId(nextNodeIdx)
val ec =
Expand All @@ -571,6 +579,7 @@ private[speedy] case class PartialTransaction(
nodeId = nid,
parent = context,
byKey = byKey,
byInterface = byInterface,
)

mustBeActive(
Expand Down Expand Up @@ -663,6 +672,7 @@ private[speedy] case class PartialTransaction(
exerciseResult = None,
key = ec.contractKey,
byKey = normByKey(version, ec.byKey),
byInterface = ec.byInterface,
version = version,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ object NormalizeRollbackSpec {
signatories = Set.empty,
stakeholders = Set.empty,
key = None,
byInterface = None,
version = TransactionVersion.minVersion,
)

Expand All @@ -324,6 +325,7 @@ object NormalizeRollbackSpec {
exerciseResult = None,
key = None,
byKey = false,
byInterface = None,
version = TransactionVersion.minVersion,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
Set(party),
Set.empty,
None,
None,
)
._2

Expand All @@ -70,6 +71,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
choiceObservers = Set.empty,
mbKey = None,
byKey = false,
byInterface = None,
chosenValue = Value.ValueUnit,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
signatories: Set[Ref.Party],
observers: Set[Ref.Party],
key: Option[Value] = None,
byInterface: Option[Ref.Identifier] = None,
): Node.Create =
create(id, templateId, argument, signatories, observers, key, signatories)
create(id, templateId, argument, signatories, observers, key, signatories, byInterface)

def create(
id: ContractId,
Expand All @@ -95,6 +96,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
observers: Set[Ref.Party],
key: Option[Value],
maintainers: Set[Ref.Party],
byInterface: Option[Ref.Identifier],
): Node.Create = {
Node.Create(
coid = id,
Expand All @@ -104,6 +106,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
signatories = signatories,
stakeholders = signatories | observers,
key = key.map(Node.KeyWithMaintainers(_, maintainers)),
byInterface = byInterface,
version = pkgTxVersion(templateId.packageId),
)
}
Expand All @@ -117,6 +120,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
result: Option[Value] = None,
choiceObservers: Set[Ref.Party] = Set.empty,
byKey: Boolean = true,
byInterface: Option[Ref.Identifier] = None,
): Node.Exercise =
Node.Exercise(
choiceObservers = choiceObservers,
Expand All @@ -132,6 +136,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
exerciseResult = result,
key = contract.key,
byKey = byKey,
byInterface = byInterface,
version = pkgTxVersion(contract.templateId.packageId),
)

Expand All @@ -144,7 +149,11 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
): Node.Exercise =
exercise(contract, choice, consuming, actingParties, argument, byKey = true)

def fetch(contract: Node.Create, byKey: Boolean = false): Node.Fetch =
def fetch(
contract: Node.Create,
byKey: Boolean = false,
byInterface: Option[Ref.Identifier] = None,
): Node.Fetch =
Node.Fetch(
coid = contract.coid,
templateId = contract.templateId,
Expand All @@ -153,6 +162,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
stakeholders = contract.stakeholders,
key = contract.key,
byKey = byKey,
byInterface = byInterface,
version = pkgTxVersion(contract.templateId.packageId),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ object ValueGenerators {
signatories,
stakeholders,
key,
None, // TODO https://github.com/digital-asset/daml/issues/10915
version,
)
}
Expand Down Expand Up @@ -343,6 +344,7 @@ object ValueGenerators {
stakeholders,
key,
byKey,
None, // TODO https://github.com/digital-asset/daml/issues/10915
version,
)
}
Expand Down Expand Up @@ -399,6 +401,7 @@ object ValueGenerators {
exerciseResult,
key,
byKey,
None, // TODO https://github.com/digital-asset/daml/issues/10915
version,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
// * 12 -- drop value version in profit of node version
// * 13 -- no change w.r.t. 12
// * 14 -- add rollback nodes
// add byKey flag to fetch and exercise node
// add by_key flag to fetch and exercise node
// * dev -- special staging area for the next version to be released
// add by_interface to fetch and exercise node
syntax = "proto3";

package com.daml.lf.transaction;
Expand Down Expand Up @@ -72,6 +73,7 @@ message NodeCreate {
repeated string signatories = 4;
KeyWithMaintainers key_with_maintainers = 5;
com.daml.lf.value.ContractId contract_id_struct = 6;
optional com.daml.lf.value.Identifier by_interface = 10; // *since version dev*
}

message NodeFetch {
Expand All @@ -83,7 +85,8 @@ message NodeFetch {
reserved 5; // was value_version
com.daml.lf.value.ContractId contract_id_struct = 6;
KeyWithMaintainers key_with_maintainers = 8;
bool byKey = 9; // *since version 1.14*
bool by_key = 9; // *since version 1.14*
optional com.daml.lf.value.Identifier by_interface = 10; // *since version dev*
}

message NodeExercise {
Expand All @@ -108,7 +111,8 @@ message NodeExercise {
reserved 13; // was contract_key
KeyWithMaintainers key_with_maintainers = 14; // optional
repeated string observers = 15; // *since version 11*
bool byKey = 18; // *since version 14*
bool by_key = 18; // *since version 14*
optional com.daml.lf.value.Identifier by_interface = 19; // *since version dev*
}

message NodeLookupByKey {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ object Node {

def byKey: Boolean

def byInterface: Option[TypeConName]

protected def versionValue[Cid2 >: ContractId](v: Value): VersionedValue =
VersionedValue(version, v)
}
Expand All @@ -82,6 +84,7 @@ object Node {
signatories: Set[Party],
stakeholders: Set[Party],
key: Option[KeyWithMaintainers[Value]],
override val byInterface: Option[TypeConName],
// For the sake of consistency between types with a version field, keep this field the last.
override val version: TransactionVersion,
) extends LeafOnlyAction
Expand Down Expand Up @@ -121,6 +124,7 @@ object Node {
stakeholders: Set[Party],
key: Option[KeyWithMaintainers[Value]],
override val byKey: Boolean, // invariant (!byKey || exerciseResult.isDefined)
override val byInterface: Option[TypeConName],
// For the sake of consistency between types with a version field, keep this field the last.
override val version: TransactionVersion,
) extends LeafOnlyAction
Expand Down Expand Up @@ -160,6 +164,7 @@ object Node {
exerciseResult: Option[Value],
key: Option[KeyWithMaintainers[Value]],
override val byKey: Boolean, // invariant (!byKey || exerciseResult.isDefined)
override val byInterface: Option[TypeConName],
// For the sake of consistency between types with a version field, keep this field the last.
override val version: TransactionVersion,
) extends Action
Expand Down Expand Up @@ -210,6 +215,7 @@ object Node {
override def keyMaintainers: Set[Party] = key.maintainers
override def hasResult: Boolean = result.isDefined
override def byKey: Boolean = true
override def byInterface: Option[TypeConName] = None

override private[lf] def updateVersion(version: TransactionVersion): Node.LookupByKey =
copy(version = version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,9 @@ sealed abstract class HasTxNodes {
*/
final def inputContracts[Cid2 >: ContractId]: Set[Cid2] =
fold(Set.empty[Cid2]) {
case (acc, (_, Node.Exercise(coid, _, _, _, _, _, _, _, _, _, _, _, _, _))) =>
case (acc, (_, Node.Exercise(coid, _, _, _, _, _, _, _, _, _, _, _, _, _, _))) =>
acc + coid
case (acc, (_, Node.Fetch(coid, _, _, _, _, _, _, _))) =>
case (acc, (_, Node.Fetch(coid, _, _, _, _, _, _, _, _))) =>
acc + coid
case (acc, (_, Node.LookupByKey(_, _, Some(coid), _))) =>
acc + coid
Expand Down Expand Up @@ -763,13 +763,13 @@ object GenTransaction {

tx.fold(State(Set.empty, Set.empty)) { case (state, (_, node)) =>
node match {
case Node.Create(_, tmplId, _, _, _, _, Some(key), _) =>
case Node.Create(_, tmplId, _, _, _, _, Some(key), _, _) =>
state.created(globalKey(tmplId, key.key))
case Node.Exercise(_, tmplId, _, true, _, _, _, _, _, _, _, Some(key), _, _) =>
case Node.Exercise(_, tmplId, _, true, _, _, _, _, _, _, _, Some(key), _, _, _) =>
state.consumed(globalKey(tmplId, key.key))
case Node.Exercise(_, tmplId, _, false, _, _, _, _, _, _, _, Some(key), _, _) =>
case Node.Exercise(_, tmplId, _, false, _, _, _, _, _, _, _, Some(key), _, _, _) =>
state.referenced(globalKey(tmplId, key.key))
case Node.Fetch(_, tmplId, _, _, _, Some(key), _, _) =>
case Node.Fetch(_, tmplId, _, _, _, Some(key), _, _, _) =>
state.referenced(globalKey(tmplId, key.key))
case Node.LookupByKey(tmplId, key, Some(_), _) =>
state.referenced(globalKey(tmplId, key.key))
Expand Down
Loading

0 comments on commit cbc3c8c

Please sign in to comment.