Add failing daml-test-file (#14176)

fix #14171

CHANGELOG_BEGIN

* [Bugfix] fix failing by-key ops after roll-backed archive and create
  See https://github.com/digital-asset/daml/issues/14171

CHANGELOG_END
This commit is contained in:
Moisés Ackerman 2022-06-15 22:00:04 +02:00 committed by GitHub
parent 90f0bf8ba0
commit 78cc57b243
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 308 additions and 217 deletions

View File

@ -6,7 +6,6 @@ package engine
import java.nio.file.Path import java.nio.file.Path
import com.daml.lf.transaction.ContractKeyUniquenessMode import com.daml.lf.transaction.ContractKeyUniquenessMode
import com.daml.lf.transaction.ContractKeyUniquenessMode.ContractByKeyUniquenessMode
/** The Engine configurations describes the versions of language and /** The Engine configurations describes the versions of language and
* transaction the engine is allowed to read and write together with * transaction the engine is allowed to read and write together with
@ -32,7 +31,7 @@ final case class EngineConfig(
packageValidation: Boolean = true, packageValidation: Boolean = true,
stackTraceMode: Boolean = false, stackTraceMode: Boolean = false,
profileDir: Option[Path] = None, profileDir: Option[Path] = None,
contractKeyUniqueness: ContractByKeyUniquenessMode = ContractKeyUniquenessMode.On, contractKeyUniqueness: ContractKeyUniquenessMode = ContractKeyUniquenessMode.Strict,
forbidV0ContractId: Boolean = false, forbidV0ContractId: Boolean = false,
requireSuffixedGlobalContractId: Boolean = false, requireSuffixedGlobalContractId: Boolean = false,
limits: interpretation.Limits = interpretation.Limits.Lenient, limits: interpretation.Limits = interpretation.Limits.Lenient,

View File

@ -268,7 +268,7 @@ class ContractKeySpec
val uckEngine = new Engine( val uckEngine = new Engine(
EngineConfig( EngineConfig(
allowedLanguageVersions = LV.DevVersions, allowedLanguageVersions = LV.DevVersions,
contractKeyUniqueness = ContractKeyUniquenessMode.On, contractKeyUniqueness = ContractKeyUniquenessMode.Strict,
forbidV0ContractId = true, forbidV0ContractId = true,
requireSuffixedGlobalContractId = true, requireSuffixedGlobalContractId = true,
) )
@ -357,6 +357,12 @@ class ContractKeySpec
val rollbackGlobalArchivedCreate = val rollbackGlobalArchivedCreate =
("RollbackGlobalArchivedCreate", keyResultCid) ("RollbackGlobalArchivedCreate", keyResultCid)
// regression tests for https://github.com/digital-asset/daml/issues/14171
val rollbackExerciseCreateFetchByKey =
("RollbackExerciseCreateFetchByKey", keyResultCid)
val rollbackExerciseCreateLookup =
("RollbackExerciseCreateLookup", keyResultCid)
val allCases = Table( val allCases = Table(
("choice", "argument"), ("choice", "argument"),
createOverwritesLocal, createOverwritesLocal,
@ -378,21 +384,41 @@ class ContractKeySpec
rollbackGlobalArchiveUpdates, rollbackGlobalArchiveUpdates,
rollbackGlobalArchivedLookup, rollbackGlobalArchivedLookup,
rollbackGlobalArchivedCreate, rollbackGlobalArchivedCreate,
rollbackExerciseCreateFetchByKey,
rollbackExerciseCreateLookup,
)
val nonUckFailures = Set(
"RollbackExerciseCreateLookup",
"RollbackExerciseCreateFetchByKey",
) )
val uckFailures = Set( val uckFailures = Set(
"CreateOverwritesLocal",
"CreateOverwritesKnownGlobal", "CreateOverwritesKnownGlobal",
"CreateOverwritesLocal",
"FetchDoesNotOverwriteGlobal",
"FetchDoesNotOverwriteLocal",
"GlobalArchiveOverwritesKnownGlobal1",
"GlobalArchiveOverwritesKnownGlobal2",
"GlobalArchiveOverwritesUnknownGlobal",
"LocalArchiveOverwritesKnownGlobal", "LocalArchiveOverwritesKnownGlobal",
"RollbackCreateNonRollbackFetchByKey", "RollbackCreateNonRollbackFetchByKey",
"RollbackFetchByKeyRollbackCreateNonRollbackFetchByKey", "RollbackCreateNonRollbackGlobalArchive",
"RollbackFetchByKeyNonRollbackCreate", "RollbackFetchByKeyNonRollbackCreate",
"RollbackFetchByKeyRollbackCreateNonRollbackFetchByKey",
"RollbackFetchNonRollbackCreate",
"RollbackGlobalArchiveNonRollbackCreate",
"RollbackGlobalArchiveUpdates",
) )
// TEST_EVIDENCE: Semantics: contract key behaviour (non-unique mode) // TEST_EVIDENCE: Semantics: contract key behaviour (non-unique mode)
"non-uck mode" in { "non-uck mode" in {
forEvery(allCases) { case (name, arg) => 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) // TEST_EVIDENCE: Semantics: contract key behaviour (unique mode)

View File

@ -2159,13 +2159,13 @@ class EngineTest
("LookupTwice", emptyArg, 1), ("LookupTwice", emptyArg, 1),
("LookupAfterCreate", emptyArg, 0), ("LookupAfterCreate", emptyArg, 0),
("LookupAfterCreateArchive", emptyArg, 0), ("LookupAfterCreateArchive", emptyArg, 0),
("LookupAfterFetch", cidArg, 1), ("LookupAfterFetch", cidArg, 0),
("LookupAfterArchive", cidArg, 1), ("LookupAfterArchive", cidArg, 0),
("LookupAfterRollbackCreate", emptyArg, 0), ("LookupAfterRollbackCreate", emptyArg, 0),
("LookupAfterRollbackLookup", emptyArg, 1), ("LookupAfterRollbackLookup", emptyArg, 1),
("LookupAfterArchiveAfterRollbackLookup", cidArg, 1), ("LookupAfterArchiveAfterRollbackLookup", cidArg, 1),
) )
forAll(cases) { case (choice, argument, lookups) => forEvery(cases) { case (choice, argument, lookups) =>
val command = ApiCommand.CreateAndExercise( val command = ApiCommand.CreateAndExercise(
tId, tId,
ValueRecord(None, ImmArray((None, ValueParty(party)))), ValueRecord(None, ImmArray((None, ValueParty(party)))),

View File

@ -16,7 +16,6 @@ import com.daml.lf.speedy.SError._
import com.daml.lf.speedy.SExpr._ import com.daml.lf.speedy.SExpr._
import com.daml.lf.speedy.SResult._ import com.daml.lf.speedy.SResult._
import com.daml.lf.speedy.SBuiltin.checkAborted import com.daml.lf.speedy.SBuiltin.checkAborted
import com.daml.lf.transaction.ContractKeyUniquenessMode.ContractByKeyUniquenessMode
import com.daml.lf.transaction.{ import com.daml.lf.transaction.{
ContractKeyUniquenessMode, ContractKeyUniquenessMode,
GlobalKey, GlobalKey,
@ -855,7 +854,7 @@ private[lf] object Speedy {
validating: Boolean = false, validating: Boolean = false,
traceLog: TraceLog = newTraceLog, traceLog: TraceLog = newTraceLog,
warningLog: WarningLog = newWarningLog, warningLog: WarningLog = newWarningLog,
contractKeyUniqueness: ContractByKeyUniquenessMode = ContractKeyUniquenessMode.On, contractKeyUniqueness: ContractKeyUniquenessMode = ContractKeyUniquenessMode.Strict,
commitLocation: Option[Location] = None, commitLocation: Option[Location] = None,
limits: interpretation.Limits = interpretation.Limits.Lenient, limits: interpretation.Limits = interpretation.Limits.Lenient,
)(implicit loggingContext: LoggingContext): Machine = { )(implicit loggingContext: LoggingContext): Machine = {

View File

@ -7,10 +7,10 @@ package speedy
import com.daml.lf.data.Ref.{ChoiceName, Location, Party, TypeConName} import com.daml.lf.data.Ref.{ChoiceName, Location, Party, TypeConName}
import com.daml.lf.data.{BackStack, ImmArray, Ref, Time} import com.daml.lf.data.{BackStack, ImmArray, Ref, Time}
import com.daml.lf.ledger.{Authorize, FailedAuthorization} 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.{ import com.daml.lf.transaction.{
GlobalKey,
ContractStateMachine, ContractStateMachine,
GlobalKey,
Node, Node,
NodeId, NodeId,
SubmittedTransaction, SubmittedTransaction,
@ -172,7 +172,7 @@ private[lf] object PartialTransaction {
} }
def initial( def initial(
contractKeyUniqueness: ContractByKeyUniquenessMode, contractKeyUniqueness: ContractKeyUniquenessMode,
submissionTime: Time.Timestamp, submissionTime: Time.Timestamp,
initialSeeds: InitialSeeding, initialSeeds: InitialSeeding,
committers: Set[Party], committers: Set[Party],
@ -187,6 +187,15 @@ private[lf] object PartialTransaction {
actionNodeLocations = BackStack.empty, 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)] type NodeSeeds = ImmArray[(NodeId, crypto.Hash)]
sealed abstract class Result extends Product with Serializable sealed abstract class Result extends Product with Serializable
@ -398,10 +407,14 @@ private[speedy] case class PartialTransaction(
normByKey(version, byKey), normByKey(version, byKey),
version, version,
) )
val newContractState = assertRightKey(
NameOf.qualifiedNameOfCurrentFunc,
contractState.visitFetch(templateId, coid, key, byKey),
)
mustBeActive( mustBeActive(
NameOf.qualifiedNameOfCurrentFunc, NameOf.qualifiedNameOfCurrentFunc,
coid, coid,
insertLeafNode(node, version, optLocation), insertLeafNode(node, version, optLocation, newContractState),
).noteAuthFails(nid, CheckAuthorization.authorizeFetch(optLocation, node), auth) ).noteAuthFails(nid, CheckAuthorization.authorizeFetch(optLocation, node), auth)
} }
@ -420,7 +433,15 @@ private[speedy] case class PartialTransaction(
result, result,
version, 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) .noteAuthFails(nid, CheckAuthorization.authorizeLookupByKey(optLocation, node), auth)
} }
@ -464,6 +485,12 @@ private[speedy] case class PartialTransaction(
version = version, 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( mustBeActive(
NameOf.qualifiedNameOfCurrentFunc, NameOf.qualifiedNameOfCurrentFunc,
targetId, targetId,
@ -472,9 +499,7 @@ private[speedy] case class PartialTransaction(
nextNodeIdx = nextNodeIdx + 1, nextNodeIdx = nextNodeIdx + 1,
context = Context(ec), context = Context(ec),
actionNodeSeeds = actionNodeSeeds :+ ec.actionNodeSeed, // must push before children actionNodeSeeds = actionNodeSeeds :+ ec.actionNodeSeed, // must push before children
// important: the semantics of Daml dictate that contracts are immediately contractState = newContractState,
// inactive as soon as you exercise it. therefore, mark it as consumed now.
contractState = contractState.visitExercise(nid, templateId, targetId, mbKey, consuming),
), ),
).noteAuthFails(nid, CheckAuthorization.authorizeExercise(optLocation, makeExNode(ec)), auth) ).noteAuthFails(nid, CheckAuthorization.authorizeExercise(optLocation, makeExNode(ec)), auth)
} }
@ -649,10 +674,11 @@ private[speedy] case class PartialTransaction(
f f
/** Insert the given `LeafNode` under a fresh node-id, and return it */ /** Insert the given `LeafNode` under a fresh node-id, and return it */
def insertLeafNode( private[this] def insertLeafNode(
node: Node.LeafOnlyAction, node: Node.LeafOnlyAction,
version: TxVersion, version: TxVersion,
optLocation: Option[Location], optLocation: Option[Location],
newContractState: ContractStateMachine[NodeId]#State,
): PartialTransaction = { ): PartialTransaction = {
val _ = version val _ = version
val nid = NodeId(nextNodeIdx) val nid = NodeId(nextNodeIdx)
@ -661,6 +687,7 @@ private[speedy] case class PartialTransaction(
nextNodeIdx = nextNodeIdx + 1, nextNodeIdx = nextNodeIdx + 1,
context = context.addActionChild(nid, version), context = context.addActionChild(nid, version),
nodes = nodes.updated(nid, node), nodes = nodes.updated(nid, node),
contractState = newContractState,
) )
} }

View File

@ -1314,7 +1314,6 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside {
msgs shouldBe Seq( msgs shouldBe Seq(
"starts test", "starts test",
"maintainers", "maintainers",
"queries key",
"choice controllers", "choice controllers",
"choice observers", "choice observers",
"choice body", "choice body",
@ -1338,7 +1337,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside {
) )
inside(res) { case Success(Left(SErrorDamlException(IE.ContractKeyNotFound(gkey)))) => inside(res) { case Success(Left(SErrorDamlException(IE.ContractKeyNotFound(gkey)))) =>
gkey.templateId shouldBe T 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( msgs shouldBe Seq(
"starts test", "starts test",
"maintainers", "maintainers",
"queries key",
"choice controllers", "choice controllers",
"choice observers", "choice observers",
) )
@ -2219,7 +2217,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside {
getKey = getKey, getKey = getKey,
) )
inside(res) { case Success(Right(_)) => 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)))) => inside(res) { case Success(Left(SErrorDamlException(IE.ContractKeyNotFound(key)))) =>
key.templateId shouldBe T 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, getKey = getKey,
) )
inside(res) { case Success(Left(SErrorDamlException(IE.FailedAuthorization(_, _)))) => 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, getKey = getKey,
) )
inside(res) { case Success(Right(_)) => 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, getKey = getKey,
) )
inside(res) { case Success(Right(_)) => 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, getKey = getKey,
) )
inside(res) { case Success(Left(SErrorDamlException(IE.FailedAuthorization(_, _)))) => inside(res) { case Success(Left(SErrorDamlException(IE.FailedAuthorization(_, _)))) =>
msgs shouldBe Seq("starts test", "maintainers", "queries key") msgs shouldBe Seq("starts test", "maintainers")
} }
} }
} }

View File

@ -280,3 +280,27 @@ template KeyOperations
E -> pure () E -> pure ()
create (Keyed p) create (Keyed p)
pure () 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

View File

@ -8,7 +8,7 @@ import com.daml.lf.data.Ref.{Identifier, TypeConName}
import com.daml.lf.transaction.Node.KeyWithMaintainers import com.daml.lf.transaction.Node.KeyWithMaintainers
import com.daml.lf.transaction.Transaction.{ import com.daml.lf.transaction.Transaction.{
DuplicateContractKey, DuplicateContractKey,
InconsistentKeys, InconsistentContractKey,
KeyCreate, KeyCreate,
KeyInput, KeyInput,
KeyInputError, KeyInputError,
@ -107,7 +107,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
/** Visit a create node */ /** Visit a create node */
def handleCreate(node: Node.Create): Either[KeyInputError, State] = 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( private[lf] def visitCreate(
templateId: TypeConName, templateId: TypeConName,
@ -177,14 +177,9 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
} }
} }
def handleExercise(nid: Nid, exe: Node.Exercise): Either[KeyInputError, State] = { def handleExercise(nid: Nid, exe: Node.Exercise): Either[KeyInputError, State] =
for { visitExercise(nid, exe.templateId, exe.targetCoid, exe.key, exe.byKey, exe.consuming).left
state <- .map(Left(_))
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)
}
/** Omits the key lookup that are done in [[com.daml.lf.speedy.Compiler.compileChoiceByKey]] for by-bey nodes, /** Omits the key lookup that are done in [[com.daml.lf.speedy.Compiler.compileChoiceByKey]] for by-bey nodes,
* which translates to a [[resolveKey]] below. * which translates to a [[resolveKey]] below.
@ -195,35 +190,43 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
templateId: TypeConName, templateId: TypeConName,
targetId: ContractId, targetId: ContractId,
mbKey: Option[KeyWithMaintainers], mbKey: Option[KeyWithMaintainers],
byKey: Boolean,
consuming: Boolean, consuming: Boolean,
): State = { ): Either[InconsistentContractKey, State] = {
if (consuming) { for {
val consumedState = activeState.consume(targetId, nodeId) state <-
val newActiveState = mbKey match { if (byKey || !mode.byKeyOnly)
case Some(kWithM) => assertKeyMapping(templateId, targetId, mbKey)
val gkey = GlobalKey(templateId, kWithM.key) else Right(this)
val keys = consumedState.keys } yield {
val updatedKeys = keys.updated(gkey, KeyInactive) 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` // 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. // independently of whether this exercise is by-key because it affects later key lookups.
if (mode.byKeyOnly) { if (mode.byKeyOnly) {
keys.get(gkey).orElse(lookupActiveGlobalKeyInput(gkey)) match { keys.get(gkey).orElse(state.lookupActiveGlobalKeyInput(gkey)) match {
// An archive can only mark a key as inactive // An archive can only mark a key as inactive
// if it was brought into scope before. // if it was brought into scope before.
case Some(KeyActive(cid)) if cid == targetId => case Some(KeyActive(cid)) if cid == targetId =>
consumedState.copy(keys = updatedKeys) consumedState.copy(keys = updatedKeys)
// If the key was not in scope or mapped to a different cid, we dont change keys. Instead we will do // If the key was not in scope or mapped to a different cid, we dont change keys. Instead we will do
// an activeness check when looking it up later. // an activeness check when looking it up later.
case _ => consumedState case _ => consumedState
}
} else {
consumedState.copy(keys = updatedKeys)
} }
} else { case None => consumedState
consumedState.copy(keys = updatedKeys) }
} state.copy(activeState = newActiveState)
case None => consumedState } else state
} }
this.copy(activeState = newActiveState)
} else this
} }
/** Must be used to handle lookups iff [[com.daml.lf.transaction.ContractKeyUniquenessMode.byKeyOnly]] is false /** 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, // 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. // 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") 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 /** 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( def handleLookupWith(
lookup: Node.LookupByKey, lookup: Node.LookupByKey,
keyInput: Option[ContractId], keyInput: Option[ContractId],
): Either[KeyInputError, State] = { ): Either[KeyInputError, State] =
require(mode.byKeyOnly, "This method can only be used if only byKey nodes are considered") visitLookup(lookup.templateId, lookup.key.key, keyInput, lookup.result).left.map(Left(_))
handleLookupWithInternal(lookup, keyInput)
}
private def handleLookupWithInternal( private[lf] def visitLookup(
lookup: Node.LookupByKey, templateId: TypeConName,
key: Value,
keyInput: Option[ContractId], keyInput: Option[ContractId],
): Either[KeyInputError, State] = { keyResolution: Option[ContractId],
val gk = GlobalKey.assertBuild(lookup.templateId, lookup.key.key) ): Either[InconsistentContractKey, State] = {
val gk = GlobalKey.assertBuild(templateId, key)
val (keyMapping, next) = resolveKey(gk) match { val (keyMapping, next) = resolveKey(gk) match {
case Right(result) => result case Right(result) => result
case Left(handle) => handle(keyInput) case Left(handle) => handle(keyInput)
} }
Either.cond( Either.cond(
keyMapping == lookup.result, keyMapping == keyResolution,
next, next,
InconsistentKeys(gk), InconsistentContractKey(gk),
) )
} }
def resolveKey( private[lf] def resolveKey(
gkey: GlobalKey gkey: GlobalKey
): Either[Option[ContractId] => (KeyMapping, State), (KeyMapping, State)] = { ): Either[Option[ContractId] => (KeyMapping, State), (KeyMapping, State)] = {
val keys = activeState.keys val keys = activeState.keys
@ -315,17 +318,25 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
} }
} }
def handleFetch(node: Node.Fetch): Either[KeyInputError, State] = { def handleFetch(node: Node.Fetch): Either[KeyInputError, State] =
if (node.byKey || !mode.byKeyOnly) { visitFetch(node.templateId, node.coid, node.key, node.byKey).left.map(Left(_))
assertKeyMapping(node.templateId, node.coid, node.key)
} else Right(this)
}
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, templateId: Identifier,
cid: Value.ContractId, cid: Value.ContractId,
optKey: Option[Node.KeyWithMaintainers], optKey: Option[Node.KeyWithMaintainers],
): Either[KeyInputError, State] = { ): Either[InconsistentContractKey, State] = {
optKey match { optKey match {
case None => Right(this) case None => Right(this)
case Some(kWithM) => case Some(kWithM) =>
@ -335,7 +346,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
case Left(handle) => handle(Some(cid)) case Left(handle) => handle(Some(cid))
} }
// Since keys is defined only where keyInputs is defined, we don't need to update keyInputs. // 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 /** To be called when interpretation enters a try block or iteration enters a Rollback node
* Must be matched by [[endRollback]] or [[dropRollback]]. * Must be matched by [[endRollback]] or [[dropRollback]].
*/ */
def beginRollback(): State = { def beginRollback(): State =
this.copy(rollbackStack = activeState +: rollbackStack) this.copy(rollbackStack = activeState +: rollbackStack)
}
/** To be called when interpretation does insert a Rollback node or iteration leaves a Rollback node. /** To be called when interpretation does insert a Rollback node or iteration leaves a Rollback node.
* Must be matched by a [[beginRollback]]. * Must be matched by a [[beginRollback]].
@ -410,12 +420,12 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
case (key, KeyCreate) case (key, KeyCreate)
if keyMappingFor(key).exists(_ != KeyInactive) && if keyMappingFor(key).exists(_ != KeyInactive) &&
mode != ContractKeyUniquenessMode.Off => mode != ContractKeyUniquenessMode.Off =>
DuplicateContractKey(key) Right(DuplicateContractKey(key))
case (key, NegativeKeyLookup) if keyMappingFor(key).exists(_ != KeyInactive) => case (key, NegativeKeyLookup) if keyMappingFor(key).exists(_ != KeyInactive) =>
InconsistentKeys(key) Left(InconsistentContractKey(key))
case (key, Transaction.KeyActive(cid)) case (key, Transaction.KeyActive(cid))
if keyMappingFor(key).exists(km => km != KeyActive(cid)) => if keyMappingFor(key).exists(km => km != KeyActive(cid)) =>
InconsistentKeys(key) Left(InconsistentContractKey(key))
} }
.toLeft(()) .toLeft(())
} }

View File

@ -713,7 +713,6 @@ object Transaction {
final case class DuplicateContractKey( final case class DuplicateContractKey(
key: GlobalKey key: GlobalKey
) extends TransactionError ) extends TransactionError
with KeyInputError
final case class AuthFailureDuringExecution( final case class AuthFailureDuringExecution(
nid: NodeId, nid: NodeId,
@ -749,16 +748,14 @@ object Transaction {
override def isActive: Boolean = true 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 /** An exercise, fetch or lookupByKey failed because the mapping of key -> contract id
* was inconsistent with earlier nodes (in execution order). * 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 sealed abstract class ChildrenRecursion
object ChildrenRecursion { object ChildrenRecursion {

View File

@ -18,7 +18,7 @@ import com.daml.lf.transaction.Node.KeyWithMaintainers
import com.daml.lf.transaction.Transaction.{ import com.daml.lf.transaction.Transaction.{
ChildrenRecursion, ChildrenRecursion,
DuplicateContractKey, DuplicateContractKey,
InconsistentKeys, InconsistentContractKey,
KeyCreate, KeyCreate,
KeyInput, KeyInput,
KeyInputError, KeyInputError,
@ -134,6 +134,12 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
version = txVersion, 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 = { def createRbExLbkLbk: TestCase = {
// [ Create c1 (key=k1), Rollback [ Exe c1 [ LBK k1 -> None ]], LBK k1 -> c1 ] // [ Create c1 (key=k1), Rollback [ Exe c1 [ LBK k1 -> None ]], LBK k1 -> c1 ]
val builder = TransactionBuilder() val builder = TransactionBuilder()
@ -153,7 +159,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, ContractKeyUniquenessMode.Strict -> expected,
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -188,7 +193,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, ContractKeyUniquenessMode.Strict -> expected,
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -219,7 +223,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, ContractKeyUniquenessMode.Strict -> expected,
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -252,7 +255,6 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, ContractKeyUniquenessMode.Strict -> expected,
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -279,8 +281,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
resolver, resolver,
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -304,10 +305,8 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, 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 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", "DoubleCreate",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(DuplicateContractKey(gkey("key1"))), ContractKeyUniquenessMode.Strict -> duplicateContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> Left(DuplicateContractKey(gkey("key1"))),
ContractKeyUniquenessMode.Off -> expectedOff, ContractKeyUniquenessMode.Off -> expectedOff,
), ),
) )
@ -357,8 +355,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
tx, tx,
Map(gkey("key1") -> KeyInactive), Map(gkey("key1") -> KeyInactive),
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -381,8 +378,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
"FetchByKey-then-Fetch", "FetchByKey-then-Fetch",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -405,8 +401,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
"Archive other contract with key", "Archive other contract with key",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(InconsistentKeys(gkey("key1"))), ContractKeyUniquenessMode.Strict -> inconsistentContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -428,8 +423,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
"CreateAfterRbExercise", "CreateAfterRbExercise",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(DuplicateContractKey(gkey("key1"))), ContractKeyUniquenessMode.Strict -> duplicateContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -437,7 +431,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
def differingCause1: TestCase = { def differingCause1: TestCase = {
// [ Create c1 (key = k1), ExeN c2 [ Create c3 (key = k1), LookupByKey k1 -> None ] ] // [ 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 // iterating over the ExeN subtree from an empty state fails with InconsistentKeys
// but iterating over the whole transaction fails with DuplicateContractKey // but iterating over the whole transaction fails with DuplicateContractKey
val builder = TransactionBuilder() 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(mkCreate(3, "key1"), exerciseNid)
val _ = builder.add(mkLookupByKey("key1", None), exerciseNid) val _ = builder.add(mkLookupByKey("key1", None), exerciseNid)
val tx = builder.build() val tx = builder.build()
val expected = Left(DuplicateContractKey(gkey("key1"))) val expected = duplicateContractKey(gkey("key1"))
TestCase( TestCase(
"differing cause 1", "differing cause 1",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, ContractKeyUniquenessMode.Strict -> expected,
ContractKeyUniquenessMode.On -> expected, ContractKeyUniquenessMode.Off -> inconsistentContractKey(gkey("key1")),
ContractKeyUniquenessMode.Off -> Left(InconsistentKeys(gkey("key1"))),
), ),
) )
} }
def differingCause2: TestCase = { def differingCause2: TestCase = {
// [ Create c1 (key = k1), ExeN c2 [ Create c3 (key = k2), Create c4 (key=k1), Create c5 (key = k2) ] // [ 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) // iterating over the ExeN subtree from an empty state fails with DuplicateContractKeys(k2)
// while iterating over the whole transaction fails with DuplicateContractKeys(k1) // while iterating over the whole transaction fails with DuplicateContractKeys(k1)
val builder = TransactionBuilder() val builder = TransactionBuilder()
@ -482,8 +475,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
"differing cause 2", "differing cause 2",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> Left(DuplicateContractKey(gkey("key1"))), ContractKeyUniquenessMode.Strict -> duplicateContractKey(gkey("key1")),
ContractKeyUniquenessMode.On -> Left(DuplicateContractKey(gkey("key1"))),
ContractKeyUniquenessMode.Off -> expectedOff, 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(2, "key1", byKey = true), rollbackNid)
val _ = builder.add(mkFetch(3, "key1", byKey = true), exerciseNid) val _ = builder.add(mkFetch(3, "key1", byKey = true), exerciseNid)
val tx = builder.build() val tx = builder.build()
val expected = Left(InconsistentKeys(gkey("key1"))) val expected = inconsistentContractKey(gkey("key1"))
TestCase( TestCase(
"inconsistent fetch-by-key", "inconsistent fetch-by-key",
tx, tx,
Map( Map(
ContractKeyUniquenessMode.Strict -> expected, ContractKeyUniquenessMode.Strict -> expected,
ContractKeyUniquenessMode.On -> expected,
ContractKeyUniquenessMode.Off -> expected, ContractKeyUniquenessMode.Off -> expected,
), ),
) )
@ -618,9 +609,11 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
for { for {
next <- node match { next <- node match {
case create: Node.Create => case create: Node.Create =>
state.visitCreate(create.templateId, create.coid, create.key) state.handleCreate(create)
case exercise: Node.Exercise => state.handleExercise((), exercise) case exercise: Node.Exercise =>
case fetch: Node.Fetch => state.handleFetch(fetch) state.handleExercise((), exercise)
case fetch: Node.Fetch =>
state.handleFetch(fetch)
case lookup: Node.LookupByKey => case lookup: Node.LookupByKey =>
val gkey = GlobalKey.assertBuild(lookup.templateId, lookup.key.key) val gkey = GlobalKey.assertBuild(lookup.templateId, lookup.key.key)
if (state.mode == ContractKeyUniquenessMode.Strict) if (state.mode == ContractKeyUniquenessMode.Strict)

View File

@ -482,7 +482,9 @@ class TransactionSpec
val builder = TransactionBuilder() val builder = TransactionBuilder()
builder.add(create(cid("#0"))) builder.add(create(cid("#0")))
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 { "two creates do not conflict if interleaved with archive" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
@ -502,33 +504,43 @@ class TransactionSpec
val builder = TransactionBuilder() val builder = TransactionBuilder()
builder.add(create(cid("#0"))) builder.add(create(cid("#0")))
builder.add(lookup(cid("#0"), found = false)) 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 { "inconsistent lookups conflict" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
builder.add(lookup(cid("#0"), found = true)) builder.add(lookup(cid("#0"), found = true))
builder.add(lookup(cid("#0"), found = false)) 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 { "inconsistent lookups conflict across rollback" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
val rollback = builder.add(builder.rollback()) val rollback = builder.add(builder.rollback())
builder.add(lookup(cid("#0"), found = true), rollback) builder.add(lookup(cid("#0"), found = true), rollback)
builder.add(lookup(cid("#0"), found = false)) 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 { "positive lookup conflicts with create" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
builder.add(lookup(cid("#0"), found = true)) builder.add(lookup(cid("#0"), found = true))
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"))))
)
} }
"positive lookup in rollback conflicts with create" in { "positive lookup in rollback conflicts with create" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
val rollback = builder.add(builder.rollback()) val rollback = builder.add(builder.rollback())
builder.add(lookup(cid("#0"), found = true), rollback) builder.add(lookup(cid("#0"), found = true), rollback)
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"))))
)
} }
"rolled back archive does not prevent conflict" in { "rolled back archive does not prevent conflict" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
@ -536,7 +548,9 @@ class TransactionSpec
val rollback = builder.add(builder.rollback()) val rollback = builder.add(builder.rollback())
builder.add(exe(cid("#0"), consuming = true, byKey = true), rollback) builder.add(exe(cid("#0"), consuming = true, byKey = true), rollback)
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"))))
)
} }
"successful, inconsistent lookups conflict" in { "successful, inconsistent lookups conflict" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()
@ -551,7 +565,11 @@ class TransactionSpec
) )
builder.add(builder.lookupByKey(create0, found = true)) builder.add(builder.lookupByKey(create0, found = true))
builder.add(builder.lookupByKey(create1, 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 { "first negative input wins" in {
val builder = TransactionBuilder() val builder = TransactionBuilder()

View File

@ -56,9 +56,9 @@ private[validate] class PrepareSubmissionImpl(bridgeMetrics: BridgeMetrics)(impl
private def invalidInputFromParticipantRejection(completionInfo: CompletionInfo)(implicit private def invalidInputFromParticipantRejection(completionInfo: CompletionInfo)(implicit
contextualizedErrorLogger: ContextualizedErrorLogger contextualizedErrorLogger: ContextualizedErrorLogger
): LfTransaction.KeyInputError => Rejection = { ): LfTransaction.KeyInputError => Rejection = {
case LfTransaction.InconsistentKeys(key) => case Left(LfTransaction.InconsistentContractKey(key)) =>
TransactionInternallyInconsistentKey(key, completionInfo) TransactionInternallyInconsistentKey(key, completionInfo)
case LfTransaction.DuplicateContractKey(key) => case Right(LfTransaction.DuplicateContractKey(key)) =>
TransactionInternallyDuplicateKeys(key, completionInfo) TransactionInternallyDuplicateKeys(key, completionInfo)
} }
} }

View File

@ -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 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 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 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 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#L1685) - 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#L1741) - 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 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 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) - 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 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 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 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 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 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#L1326) - 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#L1415) - 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#L1491) - 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#L1364) - 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#L1506) - 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#L1569) - 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#L1530) - 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#L1849) - 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#L1633) - 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#L1789) - 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#L1808) - 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#L1555) - 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#L2103) - 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#L1924) - 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#L1982) - 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#L1909) - 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#L1966) - 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#L2051) - 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#L2121) - 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#L2068) - 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#L2016) - 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#L2245) - 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#L2299) - 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#L2184) - 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#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#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#L2281) - 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#L2332) - 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#L2362) - 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#L2376) - 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#L2348) - 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#L2492) - 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#L2616) - 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#L2416) - 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#L2433) - 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#L2475) - 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#L2563) - 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#L2580) - 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#L2634) - 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#L2528) - 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#L1458) - 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#L2737) - 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#L2806) - 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#L2790) - 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#L2677) - 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#L2719) - 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#L2773) - 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#L2840) - 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#L2870) - 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#L2884) - 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#L2856) - 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: [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 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 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 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 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 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_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 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#L1766) - 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#L1949) - 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#L2036) - 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#L1887) - 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#L2209) - 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#L2265) - 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#L2140) - 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#L2458) - 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#L2548) - 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#L2394) - 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#L2702) - 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#L2757) - 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#L2654) - 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#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: 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#L489)
- Evaluation order: Template precondition before interface preconditions.: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L712) - 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) - 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) - 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 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#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#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#L2598) - 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) - 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 (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#L398) - 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 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 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) - 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) - 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) - 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) - 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)