diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/EngineConfig.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/EngineConfig.scala index 34f97131651..38177052c37 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/EngineConfig.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/EngineConfig.scala @@ -6,7 +6,6 @@ package engine import java.nio.file.Path import com.daml.lf.transaction.ContractKeyUniquenessMode -import com.daml.lf.transaction.ContractKeyUniquenessMode.ContractByKeyUniquenessMode /** The Engine configurations describes the versions of language and * transaction the engine is allowed to read and write together with @@ -32,7 +31,7 @@ final case class EngineConfig( packageValidation: Boolean = true, stackTraceMode: Boolean = false, profileDir: Option[Path] = None, - contractKeyUniqueness: ContractByKeyUniquenessMode = ContractKeyUniquenessMode.On, + contractKeyUniqueness: ContractKeyUniquenessMode = ContractKeyUniquenessMode.Strict, forbidV0ContractId: Boolean = false, requireSuffixedGlobalContractId: Boolean = false, limits: interpretation.Limits = interpretation.Limits.Lenient, diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala index 893ac4854f0..de346081a64 100644 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala +++ b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala @@ -268,7 +268,7 @@ class ContractKeySpec val uckEngine = new Engine( EngineConfig( allowedLanguageVersions = LV.DevVersions, - contractKeyUniqueness = ContractKeyUniquenessMode.On, + contractKeyUniqueness = ContractKeyUniquenessMode.Strict, forbidV0ContractId = true, requireSuffixedGlobalContractId = true, ) @@ -357,6 +357,12 @@ class ContractKeySpec val rollbackGlobalArchivedCreate = ("RollbackGlobalArchivedCreate", keyResultCid) + // regression tests for https://github.com/digital-asset/daml/issues/14171 + val rollbackExerciseCreateFetchByKey = + ("RollbackExerciseCreateFetchByKey", keyResultCid) + val rollbackExerciseCreateLookup = + ("RollbackExerciseCreateLookup", keyResultCid) + val allCases = Table( ("choice", "argument"), createOverwritesLocal, @@ -378,21 +384,41 @@ class ContractKeySpec rollbackGlobalArchiveUpdates, rollbackGlobalArchivedLookup, rollbackGlobalArchivedCreate, + rollbackExerciseCreateFetchByKey, + rollbackExerciseCreateLookup, + ) + + val nonUckFailures = Set( + "RollbackExerciseCreateLookup", + "RollbackExerciseCreateFetchByKey", ) val uckFailures = Set( - "CreateOverwritesLocal", "CreateOverwritesKnownGlobal", + "CreateOverwritesLocal", + "FetchDoesNotOverwriteGlobal", + "FetchDoesNotOverwriteLocal", + "GlobalArchiveOverwritesKnownGlobal1", + "GlobalArchiveOverwritesKnownGlobal2", + "GlobalArchiveOverwritesUnknownGlobal", "LocalArchiveOverwritesKnownGlobal", "RollbackCreateNonRollbackFetchByKey", - "RollbackFetchByKeyRollbackCreateNonRollbackFetchByKey", + "RollbackCreateNonRollbackGlobalArchive", "RollbackFetchByKeyNonRollbackCreate", + "RollbackFetchByKeyRollbackCreateNonRollbackFetchByKey", + "RollbackFetchNonRollbackCreate", + "RollbackGlobalArchiveNonRollbackCreate", + "RollbackGlobalArchiveUpdates", ) // TEST_EVIDENCE: Semantics: contract key behaviour (non-unique mode) "non-uck mode" in { forEvery(allCases) { case (name, arg) => - run(nonUckEngine, name, arg) shouldBe a[Right[_, _]] + if (nonUckFailures.contains(name)) { + run(nonUckEngine, name, arg) shouldBe a[Left[_, _]] + } else { + run(nonUckEngine, name, arg) shouldBe a[Right[_, _]] + } } } // TEST_EVIDENCE: Semantics: contract key behaviour (unique mode) diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala index 7d4087db954..dee0af46eeb 100644 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala +++ b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala @@ -2159,13 +2159,13 @@ class EngineTest ("LookupTwice", emptyArg, 1), ("LookupAfterCreate", emptyArg, 0), ("LookupAfterCreateArchive", emptyArg, 0), - ("LookupAfterFetch", cidArg, 1), - ("LookupAfterArchive", cidArg, 1), + ("LookupAfterFetch", cidArg, 0), + ("LookupAfterArchive", cidArg, 0), ("LookupAfterRollbackCreate", emptyArg, 0), ("LookupAfterRollbackLookup", emptyArg, 1), ("LookupAfterArchiveAfterRollbackLookup", cidArg, 1), ) - forAll(cases) { case (choice, argument, lookups) => + forEvery(cases) { case (choice, argument, lookups) => val command = ApiCommand.CreateAndExercise( tId, ValueRecord(None, ImmArray((None, ValueParty(party)))), diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala index f146bead4a0..e3f45725274 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala @@ -16,7 +16,6 @@ import com.daml.lf.speedy.SError._ import com.daml.lf.speedy.SExpr._ import com.daml.lf.speedy.SResult._ import com.daml.lf.speedy.SBuiltin.checkAborted -import com.daml.lf.transaction.ContractKeyUniquenessMode.ContractByKeyUniquenessMode import com.daml.lf.transaction.{ ContractKeyUniquenessMode, GlobalKey, @@ -855,7 +854,7 @@ private[lf] object Speedy { validating: Boolean = false, traceLog: TraceLog = newTraceLog, warningLog: WarningLog = newWarningLog, - contractKeyUniqueness: ContractByKeyUniquenessMode = ContractKeyUniquenessMode.On, + contractKeyUniqueness: ContractKeyUniquenessMode = ContractKeyUniquenessMode.Strict, commitLocation: Option[Location] = None, limits: interpretation.Limits = interpretation.Limits.Lenient, )(implicit loggingContext: LoggingContext): Machine = { diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/transaction/PartialTransaction.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/transaction/PartialTransaction.scala index d7148773ec5..4fa4076464e 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/transaction/PartialTransaction.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/transaction/PartialTransaction.scala @@ -7,10 +7,10 @@ package speedy import com.daml.lf.data.Ref.{ChoiceName, Location, Party, TypeConName} import com.daml.lf.data.{BackStack, ImmArray, Ref, Time} import com.daml.lf.ledger.{Authorize, FailedAuthorization} -import com.daml.lf.transaction.ContractKeyUniquenessMode.ContractByKeyUniquenessMode +import com.daml.lf.transaction.ContractKeyUniquenessMode import com.daml.lf.transaction.{ - GlobalKey, ContractStateMachine, + GlobalKey, Node, NodeId, SubmittedTransaction, @@ -172,7 +172,7 @@ private[lf] object PartialTransaction { } def initial( - contractKeyUniqueness: ContractByKeyUniquenessMode, + contractKeyUniqueness: ContractKeyUniquenessMode, submissionTime: Time.Timestamp, initialSeeds: InitialSeeding, committers: Set[Party], @@ -187,6 +187,15 @@ private[lf] object PartialTransaction { actionNodeLocations = BackStack.empty, ) + @throws[SError.SErrorCrash] + private def assertRightKey[X](where: String, either: Either[Tx.InconsistentContractKey, X]): X = + either match { + case Right(value) => + value + case Left(err) => + throw SError.SErrorCrash(where, s"inconsonstent contract key ${err.key}.") + } + type NodeSeeds = ImmArray[(NodeId, crypto.Hash)] sealed abstract class Result extends Product with Serializable @@ -398,10 +407,14 @@ private[speedy] case class PartialTransaction( normByKey(version, byKey), version, ) + val newContractState = assertRightKey( + NameOf.qualifiedNameOfCurrentFunc, + contractState.visitFetch(templateId, coid, key, byKey), + ) mustBeActive( NameOf.qualifiedNameOfCurrentFunc, coid, - insertLeafNode(node, version, optLocation), + insertLeafNode(node, version, optLocation, newContractState), ).noteAuthFails(nid, CheckAuthorization.authorizeFetch(optLocation, node), auth) } @@ -420,7 +433,15 @@ private[speedy] case class PartialTransaction( result, version, ) - insertLeafNode(node, version, optLocation) + val gkey = GlobalKey.assertBuild(templateId, key.key) + // This method is only called after we have already resolved the key in com.daml.lf.speedy.SBuiltin.SBUKeyBuiltin.execute + // so the current state's global key inputs must resolve the key. + val keyInput = contractState.globalKeyInputs(gkey) + val newContractState = assertRightKey( + NameOf.qualifiedNameOfCurrentFunc, + contractState.visitLookup(templateId, key.key, keyInput.toKeyMapping, result), + ) + insertLeafNode(node, version, optLocation, newContractState) .noteAuthFails(nid, CheckAuthorization.authorizeLookupByKey(optLocation, node), auth) } @@ -464,6 +485,12 @@ private[speedy] case class PartialTransaction( version = version, ) + // important: the semantics of Daml dictate that contracts are immediately + // inactive as soon as you exercise it. therefore, mark it as consumed now. + val newContractState = assertRightKey( + NameOf.qualifiedNameOfCurrentFunc, + contractState.visitExercise(nid, templateId, targetId, mbKey, byKey, consuming), + ) mustBeActive( NameOf.qualifiedNameOfCurrentFunc, targetId, @@ -472,9 +499,7 @@ private[speedy] case class PartialTransaction( nextNodeIdx = nextNodeIdx + 1, context = Context(ec), actionNodeSeeds = actionNodeSeeds :+ ec.actionNodeSeed, // must push before children - // important: the semantics of Daml dictate that contracts are immediately - // inactive as soon as you exercise it. therefore, mark it as consumed now. - contractState = contractState.visitExercise(nid, templateId, targetId, mbKey, consuming), + contractState = newContractState, ), ).noteAuthFails(nid, CheckAuthorization.authorizeExercise(optLocation, makeExNode(ec)), auth) } @@ -649,10 +674,11 @@ private[speedy] case class PartialTransaction( f /** Insert the given `LeafNode` under a fresh node-id, and return it */ - def insertLeafNode( + private[this] def insertLeafNode( node: Node.LeafOnlyAction, version: TxVersion, optLocation: Option[Location], + newContractState: ContractStateMachine[NodeId]#State, ): PartialTransaction = { val _ = version val nid = NodeId(nextNodeIdx) @@ -661,6 +687,7 @@ private[speedy] case class PartialTransaction( nextNodeIdx = nextNodeIdx + 1, context = context.addActionChild(nid, version), nodes = nodes.updated(nid, node), + contractState = newContractState, ) } diff --git a/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala b/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala index 8656457aec5..52e958c3c76 100644 --- a/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala +++ b/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala @@ -1314,7 +1314,6 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { msgs shouldBe Seq( "starts test", "maintainers", - "queries key", "choice controllers", "choice observers", "choice body", @@ -1338,7 +1337,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { ) inside(res) { case Success(Left(SErrorDamlException(IE.ContractKeyNotFound(gkey)))) => gkey.templateId shouldBe T - msgs shouldBe Seq("starts test", "maintainers", "queries key") + msgs shouldBe Seq("starts test", "maintainers") } } @@ -1378,7 +1377,6 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { msgs shouldBe Seq( "starts test", "maintainers", - "queries key", "choice controllers", "choice observers", ) @@ -2219,7 +2217,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { getKey = getKey, ) inside(res) { case Success(Right(_)) => - msgs shouldBe Seq("starts test", "maintainers", "queries key", "ends test") + msgs shouldBe Seq("starts test", "maintainers", "ends test") } } @@ -2238,7 +2236,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { ) inside(res) { case Success(Left(SErrorDamlException(IE.ContractKeyNotFound(key)))) => key.templateId shouldBe T - msgs shouldBe Seq("starts test", "maintainers", "queries key") + msgs shouldBe Seq("starts test", "maintainers") } } @@ -2255,7 +2253,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { getKey = getKey, ) inside(res) { case Success(Left(SErrorDamlException(IE.FailedAuthorization(_, _)))) => - msgs shouldBe Seq("starts test", "maintainers", "queries key") + msgs shouldBe Seq("starts test", "maintainers") } } } @@ -2712,7 +2710,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { getKey = getKey, ) inside(res) { case Success(Right(_)) => - msgs shouldBe Seq("starts test", "maintainers", "queries key", "ends test") + msgs shouldBe Seq("starts test", "maintainers", "ends test") } } @@ -2730,7 +2728,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { getKey = getKey, ) inside(res) { case Success(Right(_)) => - msgs shouldBe Seq("starts test", "maintainers", "queries key", "ends test") + msgs shouldBe Seq("starts test", "maintainers", "ends test") } } @@ -2747,7 +2745,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside { getKey = getKey, ) inside(res) { case Success(Left(SErrorDamlException(IE.FailedAuthorization(_, _)))) => - msgs shouldBe Seq("starts test", "maintainers", "queries key") + msgs shouldBe Seq("starts test", "maintainers") } } } diff --git a/daml-lf/tests/MultiKeys.daml b/daml-lf/tests/MultiKeys.daml index de998dab998..69635bf4f72 100644 --- a/daml-lf/tests/MultiKeys.daml +++ b/daml-lf/tests/MultiKeys.daml @@ -280,3 +280,27 @@ template KeyOperations E -> pure () create (Keyed p) pure () + + choice RollbackExerciseCreateFetchByKey: () + with cid : ContractId Keyed + controller p + do + try do + exercise cid Archive + create (Keyed p) + throw E + catch E -> pure () + fetchByKey @Keyed p + pure () + + choice RollbackExerciseCreateLookup: () + with cid : ContractId Keyed + controller p + do + try do + exercise cid Archive + create (Keyed p) + throw E + catch E -> pure () + result <- lookupByKey @Keyed p + result === Some cid diff --git a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/ContractStateMachine.scala b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/ContractStateMachine.scala index 45b93a52543..5fb790bb0d6 100644 --- a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/ContractStateMachine.scala +++ b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/ContractStateMachine.scala @@ -8,7 +8,7 @@ import com.daml.lf.data.Ref.{Identifier, TypeConName} import com.daml.lf.transaction.Node.KeyWithMaintainers import com.daml.lf.transaction.Transaction.{ DuplicateContractKey, - InconsistentKeys, + InconsistentContractKey, KeyCreate, KeyInput, KeyInputError, @@ -107,7 +107,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { /** Visit a create node */ def handleCreate(node: Node.Create): Either[KeyInputError, State] = - visitCreate(node.templateId, node.coid, node.key) + visitCreate(node.templateId, node.coid, node.key).left.map(Right(_)) private[lf] def visitCreate( templateId: TypeConName, @@ -177,14 +177,9 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { } } - def handleExercise(nid: Nid, exe: Node.Exercise): Either[KeyInputError, State] = { - for { - state <- - if (exe.byKey || !mode.byKeyOnly) - assertKeyMapping(exe.templateId, exe.targetCoid, exe.key) - else Right(this) - } yield state.visitExercise(nid, exe.templateId, exe.targetCoid, exe.key, exe.consuming) - } + def handleExercise(nid: Nid, exe: Node.Exercise): Either[KeyInputError, State] = + visitExercise(nid, exe.templateId, exe.targetCoid, exe.key, exe.byKey, exe.consuming).left + .map(Left(_)) /** Omits the key lookup that are done in [[com.daml.lf.speedy.Compiler.compileChoiceByKey]] for by-bey nodes, * which translates to a [[resolveKey]] below. @@ -195,35 +190,43 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { templateId: TypeConName, targetId: ContractId, mbKey: Option[KeyWithMaintainers], + byKey: Boolean, consuming: Boolean, - ): State = { - if (consuming) { - val consumedState = activeState.consume(targetId, nodeId) - val newActiveState = mbKey match { - case Some(kWithM) => - val gkey = GlobalKey(templateId, kWithM.key) - val keys = consumedState.keys - val updatedKeys = keys.updated(gkey, KeyInactive) + ): Either[InconsistentContractKey, State] = { + for { + state <- + if (byKey || !mode.byKeyOnly) + assertKeyMapping(templateId, targetId, mbKey) + else Right(this) + } yield { + if (consuming) { + val consumedState = state.activeState.consume(targetId, nodeId) + val newActiveState = mbKey match { + case Some(kWithM) => + val gkey = GlobalKey(templateId, kWithM.key) + val keys = consumedState.keys + val updatedKeys = keys.updated(gkey, KeyInactive) - // If the key was brought in scope before, we must update `keys` - // independently of whether this exercise is by-key because it affects later key lookups. - if (mode.byKeyOnly) { - keys.get(gkey).orElse(lookupActiveGlobalKeyInput(gkey)) match { - // An archive can only mark a key as inactive - // if it was brought into scope before. - case Some(KeyActive(cid)) if cid == targetId => - consumedState.copy(keys = updatedKeys) - // If the key was not in scope or mapped to a different cid, we don’t change keys. Instead we will do - // an activeness check when looking it up later. - case _ => consumedState + // If the key was brought in scope before, we must update `keys` + // independently of whether this exercise is by-key because it affects later key lookups. + if (mode.byKeyOnly) { + keys.get(gkey).orElse(state.lookupActiveGlobalKeyInput(gkey)) match { + // An archive can only mark a key as inactive + // if it was brought into scope before. + case Some(KeyActive(cid)) if cid == targetId => + consumedState.copy(keys = updatedKeys) + // If the key was not in scope or mapped to a different cid, we don’t change keys. Instead we will do + // an activeness check when looking it up later. + case _ => consumedState + } + } else { + consumedState.copy(keys = updatedKeys) } - } else { - consumedState.copy(keys = updatedKeys) - } - case None => consumedState - } - this.copy(activeState = newActiveState) - } else this + case None => consumedState + } + state.copy(activeState = newActiveState) + } else state + } } /** Must be used to handle lookups iff [[com.daml.lf.transaction.ContractKeyUniquenessMode.byKeyOnly]] is false @@ -232,7 +235,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { // If the key has not yet been resolved, we use the resolution from the lookup node, // but this only makes sense if `activeState.keys` is updated by every node and not only by by-key nodes. require(!mode.byKeyOnly, "This method can only be used if all key nodes are considered") - handleLookupWithInternal(lookup, lookup.result) + visitLookup(lookup.templateId, lookup.key.key, lookup.result, lookup.result).left.map(Left(_)) } /** Must be used to handle lookups iff [[com.daml.lf.transaction.ContractKeyUniquenessMode.byKeyOnly]] is true @@ -249,28 +252,28 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { def handleLookupWith( lookup: Node.LookupByKey, keyInput: Option[ContractId], - ): Either[KeyInputError, State] = { - require(mode.byKeyOnly, "This method can only be used if only byKey nodes are considered") - handleLookupWithInternal(lookup, keyInput) - } + ): Either[KeyInputError, State] = + visitLookup(lookup.templateId, lookup.key.key, keyInput, lookup.result).left.map(Left(_)) - private def handleLookupWithInternal( - lookup: Node.LookupByKey, + private[lf] def visitLookup( + templateId: TypeConName, + key: Value, keyInput: Option[ContractId], - ): Either[KeyInputError, State] = { - val gk = GlobalKey.assertBuild(lookup.templateId, lookup.key.key) + keyResolution: Option[ContractId], + ): Either[InconsistentContractKey, State] = { + val gk = GlobalKey.assertBuild(templateId, key) val (keyMapping, next) = resolveKey(gk) match { case Right(result) => result case Left(handle) => handle(keyInput) } Either.cond( - keyMapping == lookup.result, + keyMapping == keyResolution, next, - InconsistentKeys(gk), + InconsistentContractKey(gk), ) } - def resolveKey( + private[lf] def resolveKey( gkey: GlobalKey ): Either[Option[ContractId] => (KeyMapping, State), (KeyMapping, State)] = { val keys = activeState.keys @@ -315,17 +318,25 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { } } - def handleFetch(node: Node.Fetch): Either[KeyInputError, State] = { - if (node.byKey || !mode.byKeyOnly) { - assertKeyMapping(node.templateId, node.coid, node.key) - } else Right(this) - } + def handleFetch(node: Node.Fetch): Either[KeyInputError, State] = + visitFetch(node.templateId, node.coid, node.key, node.byKey).left.map(Left(_)) - private def assertKeyMapping( + private[lf] def visitFetch( + templateId: TypeConName, + contractId: ContractId, + key: Option[KeyWithMaintainers], + byKey: Boolean, + ): Either[InconsistentContractKey, State] = + if (byKey || !mode.byKeyOnly) + assertKeyMapping(templateId, contractId, key) + else + Right(this) + + private[this] def assertKeyMapping( templateId: Identifier, cid: Value.ContractId, optKey: Option[Node.KeyWithMaintainers], - ): Either[KeyInputError, State] = { + ): Either[InconsistentContractKey, State] = { optKey match { case None => Right(this) case Some(kWithM) => @@ -335,7 +346,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { case Left(handle) => handle(Some(cid)) } // Since keys is defined only where keyInputs is defined, we don't need to update keyInputs. - Either.cond(keyMapping == KeyActive(cid), next, InconsistentKeys(gk)) + Either.cond(keyMapping == KeyActive(cid), next, InconsistentContractKey(gk)) } } @@ -349,9 +360,8 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { /** To be called when interpretation enters a try block or iteration enters a Rollback node * Must be matched by [[endRollback]] or [[dropRollback]]. */ - def beginRollback(): State = { + def beginRollback(): State = this.copy(rollbackStack = activeState +: rollbackStack) - } /** To be called when interpretation does insert a Rollback node or iteration leaves a Rollback node. * Must be matched by a [[beginRollback]]. @@ -410,12 +420,12 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) { case (key, KeyCreate) if keyMappingFor(key).exists(_ != KeyInactive) && mode != ContractKeyUniquenessMode.Off => - DuplicateContractKey(key) + Right(DuplicateContractKey(key)) case (key, NegativeKeyLookup) if keyMappingFor(key).exists(_ != KeyInactive) => - InconsistentKeys(key) + Left(InconsistentContractKey(key)) case (key, Transaction.KeyActive(cid)) if keyMappingFor(key).exists(km => km != KeyActive(cid)) => - InconsistentKeys(key) + Left(InconsistentContractKey(key)) } .toLeft(()) } diff --git a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/Transaction.scala b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/Transaction.scala index 6fecee78577..91f216c743d 100644 --- a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/Transaction.scala +++ b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/transaction/Transaction.scala @@ -713,7 +713,6 @@ object Transaction { final case class DuplicateContractKey( key: GlobalKey ) extends TransactionError - with KeyInputError final case class AuthFailureDuringExecution( nid: NodeId, @@ -749,16 +748,14 @@ object Transaction { override def isActive: Boolean = true } - /** contractKeyInputs failed to produce an input due to an error for the given key. - */ - sealed trait KeyInputError extends Product with Serializable { - def key: GlobalKey - } - /** An exercise, fetch or lookupByKey failed because the mapping of key -> contract id * was inconsistent with earlier nodes (in execution order). */ - final case class InconsistentKeys(key: GlobalKey) extends KeyInputError + final case class InconsistentContractKey(key: GlobalKey) + + /** contractKeyInputs failed to produce an input due to an error for the given key. + */ + type KeyInputError = Either[InconsistentContractKey, DuplicateContractKey] sealed abstract class ChildrenRecursion object ChildrenRecursion { diff --git a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/ContractStateMachineSpec.scala b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/ContractStateMachineSpec.scala index e116ed3963c..5e22d8d5170 100644 --- a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/ContractStateMachineSpec.scala +++ b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/ContractStateMachineSpec.scala @@ -18,7 +18,7 @@ import com.daml.lf.transaction.Node.KeyWithMaintainers import com.daml.lf.transaction.Transaction.{ ChildrenRecursion, DuplicateContractKey, - InconsistentKeys, + InconsistentContractKey, KeyCreate, KeyInput, KeyInputError, @@ -134,6 +134,12 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive version = txVersion, ) + def inconsistentContractKey[X](key: GlobalKey): Left[KeyInputError, X] = + Left(Left(InconsistentContractKey(key))) + + def duplicateContractKey[X](key: GlobalKey): Left[KeyInputError, X] = + Left(Right(DuplicateContractKey(key))) + def createRbExLbkLbk: TestCase = { // [ Create c1 (key=k1), Rollback [ Exe c1 [ LBK k1 -> None ]], LBK k1 -> c1 ] val builder = TransactionBuilder() @@ -153,7 +159,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> expected, ContractKeyUniquenessMode.Off -> expected, ), ) @@ -188,7 +193,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> expected, ContractKeyUniquenessMode.Off -> expected, ), ) @@ -219,7 +223,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> expected, ContractKeyUniquenessMode.Off -> expected, ), ) @@ -252,7 +255,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> expected, ContractKeyUniquenessMode.Off -> expected, ), ) @@ -279,8 +281,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, resolver, Map( - ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), - ContractKeyUniquenessMode.On -> expected, + ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expected, ), ) @@ -304,10 +305,8 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> // TODO This is a bug in the contract key logic - Left(InconsistentKeys(gkey("key1"))), ContractKeyUniquenessMode.Off -> // TODO This is a bug in the contract key logic - Left(InconsistentKeys(gkey("key1"))), + inconsistentContractKey(gkey("key1")), ), ) @@ -334,8 +333,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive "DoubleCreate", tx, Map( - ContractKeyUniquenessMode.Strict -> Left(DuplicateContractKey(gkey("key1"))), - ContractKeyUniquenessMode.On -> Left(DuplicateContractKey(gkey("key1"))), + ContractKeyUniquenessMode.Strict -> duplicateContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expectedOff, ), ) @@ -357,8 +355,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive tx, Map(gkey("key1") -> KeyInactive), Map( - ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), - ContractKeyUniquenessMode.On -> expected, + ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expected, ), ) @@ -381,8 +378,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive "FetchByKey-then-Fetch", tx, Map( - ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), - ContractKeyUniquenessMode.On -> expected, + ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expected, ), ) @@ -405,8 +401,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive "Archive other contract with key", tx, Map( - ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), - ContractKeyUniquenessMode.On -> expected, + ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expected, ), ) @@ -428,8 +423,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive "CreateAfterRbExercise", tx, Map( - ContractKeyUniquenessMode.Strict -> Left(DuplicateContractKey(gkey("key1"))), - ContractKeyUniquenessMode.On -> expected, + ContractKeyUniquenessMode.Strict -> duplicateContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expected, ), ) @@ -437,7 +431,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive def differingCause1: TestCase = { // [ Create c1 (key = k1), ExeN c2 [ Create c3 (key = k1), LookupByKey k1 -> None ] ] - // In ContractKeyUniquenessMode.On and ContractKeyUniquenessMode.Strict, + // In ContractKeyUniquenessMode.Strict, // iterating over the ExeN subtree from an empty state fails with InconsistentKeys // but iterating over the whole transaction fails with DuplicateContractKey val builder = TransactionBuilder() @@ -446,21 +440,20 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive val _ = builder.add(mkCreate(3, "key1"), exerciseNid) val _ = builder.add(mkLookupByKey("key1", None), exerciseNid) val tx = builder.build() - val expected = Left(DuplicateContractKey(gkey("key1"))) + val expected = duplicateContractKey(gkey("key1")) TestCase( "differing cause 1", tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> expected, - ContractKeyUniquenessMode.Off -> Left(InconsistentKeys(gkey("key1"))), + ContractKeyUniquenessMode.Off -> inconsistentContractKey(gkey("key1")), ), ) } def differingCause2: TestCase = { // [ Create c1 (key = k1), ExeN c2 [ Create c3 (key = k2), Create c4 (key=k1), Create c5 (key = k2) ] - // In ContractKeyUniquenessMode.On and ContractKeyUniquenessMode.Strict, + // In ContractKeyUniquenessMode.Strict, // iterating over the ExeN subtree from an empty state fails with DuplicateContractKeys(k2) // while iterating over the whole transaction fails with DuplicateContractKeys(k1) val builder = TransactionBuilder() @@ -482,8 +475,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive "differing cause 2", tx, Map( - ContractKeyUniquenessMode.Strict -> Left(DuplicateContractKey(gkey("key1"))), - ContractKeyUniquenessMode.On -> Left(DuplicateContractKey(gkey("key1"))), + ContractKeyUniquenessMode.Strict -> duplicateContractKey(gkey("key1")), ContractKeyUniquenessMode.Off -> expectedOff, ), ) @@ -498,13 +490,12 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive val _ = builder.add(mkFetch(2, "key1", byKey = true), rollbackNid) val _ = builder.add(mkFetch(3, "key1", byKey = true), exerciseNid) val tx = builder.build() - val expected = Left(InconsistentKeys(gkey("key1"))) + val expected = inconsistentContractKey(gkey("key1")) TestCase( "inconsistent fetch-by-key", tx, Map( ContractKeyUniquenessMode.Strict -> expected, - ContractKeyUniquenessMode.On -> expected, ContractKeyUniquenessMode.Off -> expected, ), ) @@ -618,9 +609,11 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive for { next <- node match { case create: Node.Create => - state.visitCreate(create.templateId, create.coid, create.key) - case exercise: Node.Exercise => state.handleExercise((), exercise) - case fetch: Node.Fetch => state.handleFetch(fetch) + state.handleCreate(create) + case exercise: Node.Exercise => + state.handleExercise((), exercise) + case fetch: Node.Fetch => + state.handleFetch(fetch) case lookup: Node.LookupByKey => val gkey = GlobalKey.assertBuild(lookup.templateId, lookup.key.key) if (state.mode == ContractKeyUniquenessMode.Strict) diff --git a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala index ed239a5ada6..2c406c31751 100644 --- a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala +++ b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala @@ -482,7 +482,9 @@ class TransactionSpec val builder = TransactionBuilder() builder.add(create(cid("#0"))) builder.add(create(cid("#0"))) - builder.build().contractKeyInputs shouldBe Left(DuplicateContractKey(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Right(DuplicateContractKey(globalKey(cid("#0")))) + ) } "two creates do not conflict if interleaved with archive" in { val builder = TransactionBuilder() @@ -502,33 +504,43 @@ class TransactionSpec val builder = TransactionBuilder() builder.add(create(cid("#0"))) builder.add(lookup(cid("#0"), found = false)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Left(InconsistentContractKey(globalKey(cid("#0")))) + ) } "inconsistent lookups conflict" in { val builder = TransactionBuilder() builder.add(lookup(cid("#0"), found = true)) builder.add(lookup(cid("#0"), found = false)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Left(InconsistentContractKey(globalKey(cid("#0")))) + ) } "inconsistent lookups conflict across rollback" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) builder.add(lookup(cid("#0"), found = true), rollback) builder.add(lookup(cid("#0"), found = false)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Left(InconsistentContractKey(globalKey(cid("#0")))) + ) } "positive lookup conflicts with create" in { val builder = TransactionBuilder() builder.add(lookup(cid("#0"), found = true)) builder.add(create(cid("#0"))) - builder.build().contractKeyInputs shouldBe Left(DuplicateContractKey(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Right(DuplicateContractKey(globalKey(cid("#0")))) + ) } "positive lookup in rollback conflicts with create" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) builder.add(lookup(cid("#0"), found = true), rollback) builder.add(create(cid("#0"))) - builder.build().contractKeyInputs shouldBe Left(DuplicateContractKey(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Right(DuplicateContractKey(globalKey(cid("#0")))) + ) } "rolled back archive does not prevent conflict" in { val builder = TransactionBuilder() @@ -536,7 +548,9 @@ class TransactionSpec val rollback = builder.add(builder.rollback()) builder.add(exe(cid("#0"), consuming = true, byKey = true), rollback) builder.add(create(cid("#0"))) - builder.build().contractKeyInputs shouldBe Left(DuplicateContractKey(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Right(DuplicateContractKey(globalKey(cid("#0")))) + ) } "successful, inconsistent lookups conflict" in { val builder = TransactionBuilder() @@ -551,7 +565,11 @@ class TransactionSpec ) builder.add(builder.lookupByKey(create0, found = true)) builder.add(builder.lookupByKey(create1, found = true)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) + builder.build().contractKeyInputs shouldBe Left( + Left( + InconsistentContractKey(globalKey(cid("#0"))) + ) + ) } "first negative input wins" in { val builder = TransactionBuilder() diff --git a/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionImpl.scala b/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionImpl.scala index 5c1716140c0..a6e8ba65ada 100644 --- a/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionImpl.scala +++ b/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionImpl.scala @@ -56,9 +56,9 @@ private[validate] class PrepareSubmissionImpl(bridgeMetrics: BridgeMetrics)(impl private def invalidInputFromParticipantRejection(completionInfo: CompletionInfo)(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): LfTransaction.KeyInputError => Rejection = { - case LfTransaction.InconsistentKeys(key) => + case Left(LfTransaction.InconsistentContractKey(key)) => TransactionInternallyInconsistentKey(key, completionInfo) - case LfTransaction.DuplicateContractKey(key) => + case Right(LfTransaction.DuplicateContractKey(key)) => TransactionInternallyDuplicateKeys(key, completionInfo) } } diff --git a/security-evidence.md b/security-evidence.md index 0fbbf950790..970c6b289c3 100644 --- a/security-evidence.md +++ b/security-evidence.md @@ -75,9 +75,9 @@ - Evaluation order of create_interface with duplicate contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L744) - Evaluation order of create_interface with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L769) - Evaluation order of create_interface with failed precondition: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L694) -- Evaluation order of exercise by interface of a cached global contract that does not implement the interface.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1703) -- Evaluation order of exercise by interface of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1685) -- Evaluation order of exercise by interface of cached global contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1741) +- Evaluation order of exercise by interface of a cached global contract that does not implement the interface.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1701) +- Evaluation order of exercise by interface of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1683) +- Evaluation order of exercise by interface of cached global contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1739) - Evaluation order of exercise of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1140) - Evaluation order of exercise of a non-cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L937) - Evaluation order of exercise of a wrongly typed cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1004) @@ -89,98 +89,98 @@ - Evaluation order of exercise of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1040) - Evaluation order of exercise with argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1178) - Evaluation order of exercise with output exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1201) -- Evaluation order of exercise_by_key of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1435) +- Evaluation order of exercise_by_key of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1433) - Evaluation order of exercise_by_key of a non-cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1272) -- Evaluation order of exercise_by_key of a wrongly typed cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1345) -- Evaluation order of exercise_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1326) -- Evaluation order of exercise_by_key of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1415) -- Evaluation order of exercise_by_key of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1491) -- Evaluation order of exercise_by_key of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1364) -- Evaluation order of exercise_by_key with argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1506) -- Evaluation order of exercise_by_key with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1569) -- Evaluation order of exercise_by_key with result exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1530) -- Evaluation order of exercise_interface of a cached local contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1849) -- Evaluation order of exercise_interface of a non-cached global contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1633) -- Evaluation order of exercise_interface of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1789) -- Evaluation order of exercise_interface of an local contract not implementing the interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1808) -- Evaluation order of exercise_vy_key with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1555) -- Evaluation order of fetch of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2103) -- Evaluation order of fetch of a non-cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1924) -- Evaluation order of fetch of a wrongly typed cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1982) -- Evaluation order of fetch of a wrongly typed non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1909) -- Evaluation order of fetch of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1966) -- Evaluation order of fetch of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2051) -- Evaluation order of fetch of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2121) -- Evaluation order of fetch of an wrongly typed local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2068) -- Evaluation order of fetch of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2016) -- Evaluation order of fetch_by_key of a cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2245) -- Evaluation order of fetch_by_key of a local contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2299) -- Evaluation order of fetch_by_key of a non-cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2184) -- Evaluation order of fetch_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2226) -- Evaluation order of fetch_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2281) -- Evaluation order of fetch_by_key of an unknown contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2332) -- Evaluation order of fetch_by_key with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2362) -- Evaluation order of fetch_by_key with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2376) -- Evaluation order of fetch_by_key with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2348) -- Evaluation order of fetch_interface of a cached global contract not implementing the interface.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2492) -- Evaluation order of fetch_interface of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2616) -- Evaluation order of fetch_interface of a non-cached global contract that doesn't implement interface.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2416) -- Evaluation order of fetch_interface of a non-cached global contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2433) -- Evaluation order of fetch_interface of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2475) -- Evaluation order of fetch_interface of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2563) -- Evaluation order of fetch_interface of an local contract not implementing the interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2580) -- Evaluation order of fetch_interface of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2634) -- Evaluation order of fetch_interface of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2528) -- Evaluation order of lookup of a local contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1458) -- Evaluation order of lookup_by_key of a cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2737) -- Evaluation order of lookup_by_key of a local contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2806) -- Evaluation order of lookup_by_key of a local contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2790) -- Evaluation order of lookup_by_key of a non-cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2677) -- Evaluation order of lookup_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2719) -- Evaluation order of lookup_by_key of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2773) -- Evaluation order of lookup_by_key of an unknown contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2840) -- Evaluation order of lookup_by_key with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2870) -- Evaluation order of lookup_by_key with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2884) -- Evaluation order of lookup_by_key with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2856) +- Evaluation order of exercise_by_key of a wrongly typed cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1344) +- Evaluation order of exercise_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1325) +- Evaluation order of exercise_by_key of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1413) +- Evaluation order of exercise_by_key of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1489) +- Evaluation order of exercise_by_key of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1363) +- Evaluation order of exercise_by_key with argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1504) +- Evaluation order of exercise_by_key with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1567) +- Evaluation order of exercise_by_key with result exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1528) +- Evaluation order of exercise_interface of a cached local contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1847) +- Evaluation order of exercise_interface of a non-cached global contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1631) +- Evaluation order of exercise_interface of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1787) +- Evaluation order of exercise_interface of an local contract not implementing the interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1806) +- Evaluation order of exercise_vy_key with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1553) +- Evaluation order of fetch of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2101) +- Evaluation order of fetch of a non-cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1922) +- Evaluation order of fetch of a wrongly typed cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1980) +- Evaluation order of fetch of a wrongly typed non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1907) +- Evaluation order of fetch of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1964) +- Evaluation order of fetch of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2049) +- Evaluation order of fetch of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2119) +- Evaluation order of fetch of an wrongly typed local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2066) +- Evaluation order of fetch of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2014) +- Evaluation order of fetch_by_key of a cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2243) +- Evaluation order of fetch_by_key of a local contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2297) +- Evaluation order of fetch_by_key of a non-cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2182) +- Evaluation order of fetch_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2224) +- Evaluation order of fetch_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2279) +- Evaluation order of fetch_by_key of an unknown contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2330) +- Evaluation order of fetch_by_key with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2360) +- Evaluation order of fetch_by_key with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2374) +- Evaluation order of fetch_by_key with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2346) +- Evaluation order of fetch_interface of a cached global contract not implementing the interface.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2490) +- Evaluation order of fetch_interface of a cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2614) +- Evaluation order of fetch_interface of a non-cached global contract that doesn't implement interface.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2414) +- Evaluation order of fetch_interface of a non-cached global contract with failed authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2431) +- Evaluation order of fetch_interface of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2473) +- Evaluation order of fetch_interface of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2561) +- Evaluation order of fetch_interface of an local contract not implementing the interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2578) +- Evaluation order of fetch_interface of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2632) +- Evaluation order of fetch_interface of cached global contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2526) +- Evaluation order of lookup of a local contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1456) +- Evaluation order of lookup_by_key of a cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2735) +- Evaluation order of lookup_by_key of a local contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2804) +- Evaluation order of lookup_by_key of a local contract with failure authorization: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2788) +- Evaluation order of lookup_by_key of a non-cached global contract with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2675) +- Evaluation order of lookup_by_key of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2717) +- Evaluation order of lookup_by_key of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2771) +- Evaluation order of lookup_by_key of an unknown contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2838) +- Evaluation order of lookup_by_key with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2868) +- Evaluation order of lookup_by_key with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2882) +- Evaluation order of lookup_by_key with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2854) - Evaluation order of successful create: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L447) - Evaluation order of successful create_interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L670) -- Evaluation order of successful exercise by interface of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1589) +- Evaluation order of successful exercise by interface of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1587) - Evaluation order of successful exercise of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L964) - Evaluation order of successful exercise of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1060) - Evaluation order of successful exercise of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L897) - Evaluation order of successful exercise_by_key of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1300) -- Evaluation order of successful exercise_by_key of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1392) +- Evaluation order of successful exercise_by_key of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1390) - Evaluation order of successful exercise_by_key of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1230) -- Evaluation order of successful exercise_interface of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1661) -- Evaluation order of successful exercise_interface of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1766) -- Evaluation order of successful fetch of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1949) -- Evaluation order of successful fetch of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2036) -- Evaluation order of successful fetch of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1887) -- Evaluation order of successful fetch_by_key of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2209) -- Evaluation order of successful fetch_by_key of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2265) -- Evaluation order of successful fetch_by_key of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2140) -- Evaluation order of successful fetch_interface of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2458) -- Evaluation order of successful fetch_interface of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2548) -- Evaluation order of successful fetch_interface of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2394) -- Evaluation order of successful lookup_by_key of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2702) -- Evaluation order of successful lookup_by_key of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2757) -- Evaluation order of successful lookup_by_key of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2654) +- Evaluation order of successful exercise_interface of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1659) +- Evaluation order of successful exercise_interface of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1764) +- Evaluation order of successful fetch of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1947) +- Evaluation order of successful fetch of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2034) +- Evaluation order of successful fetch of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1885) +- Evaluation order of successful fetch_by_key of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2207) +- Evaluation order of successful fetch_by_key of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2263) +- Evaluation order of successful fetch_by_key of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2138) +- Evaluation order of successful fetch_interface of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2456) +- Evaluation order of successful fetch_interface of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2546) +- Evaluation order of successful fetch_interface of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2392) +- Evaluation order of successful lookup_by_key of a cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2700) +- Evaluation order of successful lookup_by_key of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2755) +- Evaluation order of successful lookup_by_key of a non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2652) - Evaluation order: Interface preconditions are evaluated in the order given by the implementation list.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L505) - Evaluation order: Interface preconditions are evaluated in the order given by the implementation list.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L728) - Evaluation order: Template precondition before interface preconditions.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L489) - Evaluation order: Template precondition before interface preconditions.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L712) - Exceptions, throw/catch.: [ExceptionTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/ExceptionTest.scala#L25) - Rollback creates cannot be exercise: [EngineTest.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala#L2001) -- This checks that type checking in exercise_interface is done after checking activeness.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1829) -- This checks that type checking is done after checking activeness.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1723) -- This checks that type checking is done after checking activeness.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2598) +- This checks that type checking in exercise_interface is done after checking activeness.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1827) +- This checks that type checking is done after checking activeness.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1721) +- This checks that type checking is done after checking activeness.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2596) - command submission timeout is applied: [FailureTests.scala](ledger-service/http-json/src/failurelib/scala/http/FailureTests.scala#L99) -- contract key behaviour (non-unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L392) -- contract key behaviour (unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L398) +- contract key behaviour (non-unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L414) +- contract key behaviour (unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L424) - contract keys must have a non-empty set of maintainers: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L221) - contract keys should be evaluated after ensure clause: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L188) - contract keys should be evaluated only when executing create: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L149) -- exercise_interface with a contract instance that does not implement the interface fails.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1615) +- exercise_interface with a contract instance that does not implement the interface fails.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1613) - fromStartupMode should not succeed for any input when the db connection is broken: [FailureTests.scala](ledger-service/http-json/src/failurelib/scala/http/FailureTests.scala#L436) - redirect to the configured callback URI after login: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L641) - restart trigger on initialization failure due to failed connection: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L457)