mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
Add by_interface field in Create, Fetch, & Exercise transaction nodes. (#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
This commit is contained in:
parent
7d68e05f7f
commit
cbc3c8c686
@ -37,6 +37,7 @@ class AuthorizationSpec extends AnyFreeSpec with Matchers with Inside {
|
||||
observers = Seq("Carl"),
|
||||
key = Some(Value.ValueUnit),
|
||||
maintainers = maintainers,
|
||||
byInterface = None,
|
||||
)
|
||||
|
||||
"create" - {
|
||||
|
@ -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)
|
||||
@ -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)
|
||||
|
@ -1104,6 +1104,7 @@ class EngineTest
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
) =>
|
||||
coid shouldBe originalCoid
|
||||
consuming shouldBe true
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
@ -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)) =>
|
||||
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
@ -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
|
||||
@ -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
|
||||
|
@ -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,
|
||||
@ -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, _)
|
||||
@ -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 =
|
||||
@ -420,6 +424,7 @@ private[speedy] case class PartialTransaction(
|
||||
signatories,
|
||||
stakeholders,
|
||||
key,
|
||||
byInterface,
|
||||
version,
|
||||
)
|
||||
val nid = NodeId(nextNodeIdx)
|
||||
@ -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)
|
||||
@ -509,6 +515,7 @@ private[speedy] case class PartialTransaction(
|
||||
stakeholders,
|
||||
key,
|
||||
normByKey(version, byKey),
|
||||
byInterface,
|
||||
version,
|
||||
)
|
||||
mustBeActive(
|
||||
@ -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 =
|
||||
@ -571,6 +579,7 @@ private[speedy] case class PartialTransaction(
|
||||
nodeId = nid,
|
||||
parent = context,
|
||||
byKey = byKey,
|
||||
byInterface = byInterface,
|
||||
)
|
||||
|
||||
mustBeActive(
|
||||
@ -663,6 +672,7 @@ private[speedy] case class PartialTransaction(
|
||||
exerciseResult = None,
|
||||
key = ec.contractKey,
|
||||
byKey = normByKey(version, ec.byKey),
|
||||
byInterface = ec.byInterface,
|
||||
version = version,
|
||||
)
|
||||
}
|
||||
|
@ -301,6 +301,7 @@ object NormalizeRollbackSpec {
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
key = None,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
@ -324,6 +325,7 @@ object NormalizeRollbackSpec {
|
||||
exerciseResult = None,
|
||||
key = None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
Set(party),
|
||||
Set.empty,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
._2
|
||||
|
||||
@ -70,6 +71,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
choiceObservers = Set.empty,
|
||||
mbKey = None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
chosenValue = Value.ValueUnit,
|
||||
)
|
||||
|
||||
|
@ -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,
|
||||
@ -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,
|
||||
@ -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),
|
||||
)
|
||||
}
|
||||
@ -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,
|
||||
@ -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),
|
||||
)
|
||||
|
||||
@ -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,
|
||||
@ -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),
|
||||
)
|
||||
|
||||
|
@ -316,6 +316,7 @@ object ValueGenerators {
|
||||
signatories,
|
||||
stakeholders,
|
||||
key,
|
||||
None, // TODO https://github.com/digital-asset/daml/issues/10915
|
||||
version,
|
||||
)
|
||||
}
|
||||
@ -343,6 +344,7 @@ object ValueGenerators {
|
||||
stakeholders,
|
||||
key,
|
||||
byKey,
|
||||
None, // TODO https://github.com/digital-asset/daml/issues/10915
|
||||
version,
|
||||
)
|
||||
}
|
||||
@ -399,6 +401,7 @@ object ValueGenerators {
|
||||
exerciseResult,
|
||||
key,
|
||||
byKey,
|
||||
None, // TODO https://github.com/digital-asset/daml/issues/10915
|
||||
version,
|
||||
)
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
@ -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 {
|
||||
|
@ -56,6 +56,8 @@ object Node {
|
||||
|
||||
def byKey: Boolean
|
||||
|
||||
def byInterface: Option[TypeConName]
|
||||
|
||||
protected def versionValue[Cid2 >: ContractId](v: Value): VersionedValue =
|
||||
VersionedValue(version, v)
|
||||
}
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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)
|
||||
|
@ -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
|
||||
@ -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))
|
||||
|
@ -277,11 +277,16 @@ object TransactionCoder {
|
||||
|
||||
node match {
|
||||
|
||||
case nc @ Node.Create(_, _, _, _, _, _, _, _) =>
|
||||
case nc @ Node.Create(_, _, _, _, _, _, _, _, _) =>
|
||||
val builder = TransactionOuterClass.NodeCreate.newBuilder()
|
||||
nc.stakeholders.foreach(builder.addStakeholders)
|
||||
nc.signatories.foreach(builder.addSignatories)
|
||||
discard(builder.setContractIdStruct(encodeCid.encode(nc.coid)))
|
||||
if (nodeVersion >= TransactionVersion.minInterfaces) {
|
||||
nc.byInterface.foreach(iface =>
|
||||
builder.setByInterface(ValueCoder.encodeIdentifier(iface))
|
||||
)
|
||||
}
|
||||
for {
|
||||
_ <-
|
||||
if (nodeVersion < TransactionVersion.minNoVersionValue) {
|
||||
@ -309,7 +314,7 @@ object TransactionCoder {
|
||||
)
|
||||
} yield nodeBuilder.setCreate(builder).build()
|
||||
|
||||
case nf @ Node.Fetch(_, _, _, _, _, _, _, _) =>
|
||||
case nf @ Node.Fetch(_, _, _, _, _, _, _, _, _) =>
|
||||
val builder = TransactionOuterClass.NodeFetch.newBuilder()
|
||||
discard(builder.setTemplateId(ValueCoder.encodeIdentifier(nf.templateId)))
|
||||
nf.stakeholders.foreach(builder.addStakeholders)
|
||||
@ -319,6 +324,11 @@ object TransactionCoder {
|
||||
discard(builder.setByKey(nf.byKey))
|
||||
}
|
||||
nf.actingParties.foreach(builder.addActors)
|
||||
if (nodeVersion >= TransactionVersion.minInterfaces) {
|
||||
nf.byInterface.foreach(iface =>
|
||||
builder.setByInterface(ValueCoder.encodeIdentifier(iface))
|
||||
)
|
||||
}
|
||||
for {
|
||||
_ <- encodeAndSetContractKey(
|
||||
encodeCid,
|
||||
@ -328,7 +338,7 @@ object TransactionCoder {
|
||||
)
|
||||
} yield nodeBuilder.setFetch(builder).build()
|
||||
|
||||
case ne @ Node.Exercise(_, _, _, _, _, _, _, _, _, _, _, _, _, _) =>
|
||||
case ne @ Node.Exercise(_, _, _, _, _, _, _, _, _, _, _, _, _, _, _) =>
|
||||
val builder = TransactionOuterClass.NodeExercise.newBuilder()
|
||||
discard(
|
||||
builder
|
||||
@ -345,6 +355,11 @@ object TransactionCoder {
|
||||
if (nodeVersion >= TransactionVersion.minByKey) {
|
||||
discard(builder.setByKey(ne.byKey))
|
||||
}
|
||||
if (nodeVersion >= TransactionVersion.minInterfaces) {
|
||||
ne.byInterface.foreach(iface =>
|
||||
builder.setByInterface(ValueCoder.encodeIdentifier(iface))
|
||||
)
|
||||
}
|
||||
for {
|
||||
_ <- Either.cond(
|
||||
test = ne.version >= TransactionVersion.minChoiceObservers ||
|
||||
@ -515,6 +530,12 @@ object TransactionCoder {
|
||||
nodeVersion,
|
||||
protoCreate.getKeyWithMaintainers,
|
||||
)
|
||||
byInterface <-
|
||||
if (nodeVersion >= TransactionVersion.minInterfaces && protoCreate.hasByInterface) {
|
||||
ValueCoder.decodeIdentifier(protoCreate.getByInterface).map(Some(_))
|
||||
} else {
|
||||
Right(None)
|
||||
}
|
||||
} yield ni -> Node.Create(
|
||||
c,
|
||||
ci.template,
|
||||
@ -523,6 +544,7 @@ object TransactionCoder {
|
||||
signatories,
|
||||
stakeholders,
|
||||
key,
|
||||
byInterface,
|
||||
nodeVersion,
|
||||
)
|
||||
case NodeTypeCase.FETCH =>
|
||||
@ -543,6 +565,12 @@ object TransactionCoder {
|
||||
if (nodeVersion >= TransactionVersion.minByKey)
|
||||
protoFetch.getByKey
|
||||
else false
|
||||
byInterface <-
|
||||
if (nodeVersion >= TransactionVersion.minInterfaces && protoFetch.hasByInterface) {
|
||||
ValueCoder.decodeIdentifier(protoFetch.getByInterface).map(Some(_))
|
||||
} else {
|
||||
Right(None)
|
||||
}
|
||||
} yield ni -> Node.Fetch(
|
||||
coid = c,
|
||||
templateId = templateId,
|
||||
@ -551,6 +579,7 @@ object TransactionCoder {
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
byKey = byKey,
|
||||
byInterface = byInterface,
|
||||
version = nodeVersion,
|
||||
)
|
||||
|
||||
@ -600,6 +629,12 @@ object TransactionCoder {
|
||||
if (nodeVersion >= TransactionVersion.minByKey)
|
||||
protoExe.getByKey
|
||||
else false
|
||||
byInterface <-
|
||||
if (nodeVersion >= TransactionVersion.minInterfaces && protoExe.hasByInterface) {
|
||||
ValueCoder.decodeIdentifier(protoExe.getByInterface).map(Some(_))
|
||||
} else {
|
||||
Right(None)
|
||||
}
|
||||
} yield ni -> Node.Exercise(
|
||||
targetCoid = targetCoid,
|
||||
templateId = templateId,
|
||||
@ -614,6 +649,7 @@ object TransactionCoder {
|
||||
exerciseResult = rvOpt,
|
||||
key = keyWithMaintainers,
|
||||
byKey = byKey,
|
||||
byInterface = byInterface,
|
||||
version = nodeVersion,
|
||||
)
|
||||
case NodeTypeCase.LOOKUP_BY_KEY =>
|
||||
|
@ -49,6 +49,7 @@ object TransactionVersion {
|
||||
//nothing was added in V13, so there are no vals: "minSomething = V13"
|
||||
private[lf] val minExceptions = V14
|
||||
private[lf] val minByKey = V14
|
||||
private[lf] val minInterfaces = VDev
|
||||
|
||||
private[lf] val assignNodeVersion: LanguageVersion => TransactionVersion = {
|
||||
import LanguageVersion._
|
||||
|
@ -230,6 +230,7 @@ class TransactionCoderSpec
|
||||
signatories = Set(Party.assertFromString("alice")),
|
||||
stakeholders = Set(Party.assertFromString("alice"), Party.assertFromString("bob")),
|
||||
key = None,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
|
@ -679,6 +679,7 @@ object TransactionSpec {
|
||||
exerciseResult = if (hasExerciseResult) Some(V.ValueUnit) else None,
|
||||
key = None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
@ -691,6 +692,7 @@ object TransactionSpec {
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
key = None,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
|
@ -96,6 +96,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
signatories = samParties1,
|
||||
stakeholders = samParties2,
|
||||
key = key,
|
||||
byInterface = None, // TODO https://github.com/digital-asset/daml/issues/10915
|
||||
version = version,
|
||||
)
|
||||
|
||||
@ -112,6 +113,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
stakeholders = samParties3,
|
||||
key = key,
|
||||
byKey = samBool1,
|
||||
byInterface = None, // TODO https://github.com/digital-asset/daml/issues/10915
|
||||
version = version,
|
||||
)
|
||||
|
||||
@ -145,6 +147,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
exerciseResult = exerciseResult,
|
||||
key = key,
|
||||
byKey = samBool2,
|
||||
byInterface = None, // TODO https://github.com/digital-asset/daml/issues/10915
|
||||
version = version,
|
||||
)
|
||||
|
||||
|
@ -52,7 +52,7 @@ private[migration] class V10_1__Populate_Event_Data extends BaseJavaMigration {
|
||||
val txs = loadTransactions(conn)
|
||||
val data = txs.flatMap { case (txId, tx) =>
|
||||
tx.nodes.collect {
|
||||
case (nodeId, Node.Create(cid, _, _, _, signatories, stakeholders, _, _)) =>
|
||||
case (nodeId, Node.Create(cid, _, _, _, signatories, stakeholders, _, _, _)) =>
|
||||
(cid, EventId(txId, nodeId), signatories, stakeholders -- signatories)
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
signatories = Set(alice),
|
||||
stakeholders = Set(alice),
|
||||
key = None,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
)
|
||||
@ -53,6 +54,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(someContractKey(bob, "some key"), Set(bob))
|
||||
),
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
)
|
||||
@ -77,6 +79,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
)
|
||||
@ -91,6 +94,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
Node.KeyWithMaintainers(ValueParty(bob), Set(bob))
|
||||
),
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
),
|
||||
parentId = rootExercise,
|
||||
@ -112,6 +116,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
Node.KeyWithMaintainers(someContractKey(bob, "some key"), Set(bob))
|
||||
),
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
),
|
||||
parentId = rootExercise,
|
||||
@ -127,6 +132,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(someContractKey(bob, "some key"), Set(bob))
|
||||
),
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
),
|
||||
parentId = nestedExercise,
|
||||
|
@ -207,6 +207,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
|
||||
@ -228,6 +229,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = key,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
|
||||
@ -243,6 +245,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
stakeholders = Set(party),
|
||||
None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
|
||||
@ -384,6 +387,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
)
|
||||
@ -396,6 +400,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
stakeholders = Set(alice),
|
||||
None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
),
|
||||
exerciseId,
|
||||
@ -710,6 +715,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
signatories = Set(party),
|
||||
stakeholders = Set(party),
|
||||
key = Some(Node.KeyWithMaintainers(someContractKey(party, key), Set(party))),
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
)
|
||||
@ -750,6 +756,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
exerciseResult = Some(LfValue.ValueUnit),
|
||||
key = maybeKey.map(k => Node.KeyWithMaintainers(someContractKey(party, k), Set(party))),
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
)
|
||||
@ -810,6 +817,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
stakeholders = Set(party),
|
||||
None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = txVersion,
|
||||
)
|
||||
)
|
||||
|
@ -23,6 +23,7 @@ class ProjectionsSpec extends AnyWordSpec with Matchers {
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = None,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
@ -49,6 +50,7 @@ class ProjectionsSpec extends AnyWordSpec with Matchers {
|
||||
exerciseResult = None,
|
||||
key = None,
|
||||
byKey = false,
|
||||
byInterface = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
|
@ -1,32 +1,32 @@
|
||||
# Security tests, by category
|
||||
|
||||
## Authorization:
|
||||
- badly-authorized create is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L60)
|
||||
- badly-authorized exercise is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L158)
|
||||
- badly-authorized create is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L61)
|
||||
- badly-authorized exercise is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L159)
|
||||
- badly-authorized exercise/create (create is unauthorized) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L265)
|
||||
- badly-authorized exercise/create (exercise is unauthorized) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L233)
|
||||
- badly-authorized exercise/exercise (no implicit authority from outer exercise) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L324)
|
||||
- badly-authorized fetch is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L95)
|
||||
- badly-authorized lookup is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L117)
|
||||
- create with no signatories is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L50)
|
||||
- create with non-signatory maintainers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L72)
|
||||
- exercise with no controllers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L148)
|
||||
- well-authorized create is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L43)
|
||||
- well-authorized exercise is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L141)
|
||||
- badly-authorized fetch is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L96)
|
||||
- badly-authorized lookup is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L118)
|
||||
- create with no signatories is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L51)
|
||||
- create with non-signatory maintainers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L73)
|
||||
- exercise with no controllers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L149)
|
||||
- well-authorized create is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L44)
|
||||
- well-authorized exercise is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L142)
|
||||
- well-authorized exercise/create is accepted: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L211)
|
||||
- well-authorized exercise/exercise is accepted: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L367)
|
||||
- well-authorized fetch is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L89)
|
||||
- well-authorized lookup is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L111)
|
||||
- well-authorized fetch is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L90)
|
||||
- well-authorized lookup is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L112)
|
||||
|
||||
## Privacy:
|
||||
- ensure correct privacy for create node: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L32)
|
||||
- ensure correct privacy for exercise node (consuming): [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L43)
|
||||
- ensure correct privacy for exercise node (non-consuming): [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L62)
|
||||
- ensure correct privacy for exercise subtree: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L137)
|
||||
- ensure correct privacy for exercise subtree: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L139)
|
||||
- ensure correct privacy for fetch node: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L82)
|
||||
- ensure correct privacy for lookup-by-key node (found): [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L94)
|
||||
- ensure correct privacy for lookup-by-key node (not-found): [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L115)
|
||||
- ensure correct privacy for rollback subtree: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L199)
|
||||
- ensure correct privacy for lookup-by-key node (not-found): [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L116)
|
||||
- ensure correct privacy for rollback subtree: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L201)
|
||||
|
||||
## Semantics:
|
||||
- Exceptions, throw/catch.: [ExceptionTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/ExceptionTest.scala#L24)
|
||||
|
Loading…
Reference in New Issue
Block a user