Allow for the construction of shared GlobalKeys.

* Revert "Add SharedGlobalKey"

This reverts commit 6592cb7bd5.

* Adding shared flag to GlobalKey

* Remove shared flag from GlobalKey

* Support old and new grcp error parsing

* Add tests for hashContractKey
This commit is contained in:
Simon Maxen 2023-11-06 20:00:38 +00:00 committed by GitHub
parent f6d213a085
commit ae5e9feda9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
48 changed files with 636 additions and 786 deletions

View File

@ -4,6 +4,7 @@
package com.digitalasset.canton.protocol
import cats.syntax.either.*
import com.daml.lf.transaction.Util
import com.daml.lf.value.ValueCoder.{CidEncoder as LfDummyCidEncoder}
import com.daml.lf.value.{ValueCoder, ValueOuterClass}
import com.digitalasset.canton.serialization.ProtoConverter
@ -54,7 +55,7 @@ object GlobalKeySerialization {
)
globalKey <- LfGlobalKey
.build(templateId, versionedKey.unversioned)
.build(templateId, versionedKey.unversioned, false) // TODO should be Util.sharedKey(versionedKey.version)
.leftMap(err =>
ProtoDeserializationError.ValueDeserializationError("GlobalKey.key", err.toString)
)

View File

@ -3,19 +3,14 @@
package com.digitalasset.canton.platform.apiserver.execution
import com.daml.lf.command.{ApiCommands as LfCommands, DisclosedContract as LfDisclosedContract}
import com.daml.lf.command.{ApiCommands, DisclosedContract, LfCommands, LfDisclosedContract}
import com.daml.lf.crypto.Hash
import com.daml.lf.data.Ref.{Identifier, ParticipantId, Party}
import com.daml.lf.data.Time.Timestamp
import com.daml.lf.data.{Bytes, ImmArray, Ref, Time}
import com.daml.lf.engine.{Engine, ResultDone, ResultNeedUpgradeVerification}
import com.daml.lf.transaction.test.TransactionBuilder
import com.daml.lf.transaction.{
GlobalKeyWithMaintainers,
SubmittedTransaction,
Transaction,
Versioned,
}
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, SubmittedTransaction, Transaction, Util, Versioned}
import com.daml.lf.value.Value
import com.daml.lf.value.Value.{ContractInstance, ValueTrue}
import com.daml.logging.LoggingContext
@ -24,11 +19,7 @@ import com.digitalasset.canton.crypto.{CryptoPureApi, Salt, SaltSeed}
import com.digitalasset.canton.ledger.api.domain.{CommandId, Commands, LedgerId}
import com.digitalasset.canton.ledger.api.{DeduplicationPeriod, domain}
import com.digitalasset.canton.ledger.configuration.{Configuration, LedgerTimeModel}
import com.digitalasset.canton.ledger.participant.state.index.v2.{
ContractState,
ContractStore,
IndexPackagesService,
}
import com.digitalasset.canton.ledger.participant.state.index.v2.{ContractState, ContractStore, IndexPackagesService}
import com.digitalasset.canton.logging.LoggingContextWithTrace
import com.digitalasset.canton.metrics.Metrics
import com.digitalasset.canton.protocol.{DriverContractMetadata, LfContractId, LfTransactionVersion}
@ -145,9 +136,10 @@ class StoreBackedCommandExecutorSpec
"Upgrade Verification" should {
val stakeholderContractId: LfContractId = LfContractId.assertFromString("00" + "00" * 32 + "03")
val txVersion: LfTransactionVersion = LfTransactionVersion.maxVersion
val stakeholderContract = ContractState.Active(
contractInstance =
Versioned(LfTransactionVersion.maxVersion, ContractInstance(identifier, Value.ValueTrue)),
Versioned(txVersion, ContractInstance(identifier, Value.ValueTrue)),
ledgerEffectiveTime = Timestamp.now(),
stakeholders = Set(Ref.Party.assertFromString("unexpectedSig")),
signatories = Set(Ref.Party.assertFromString("unexpectedSig")),
@ -205,6 +197,7 @@ class StoreBackedCommandExecutorSpec
identifier,
someContractKey(signatory, "some key"),
Set(signatory),
shared = Util.sharedKey(txVersion),
)
),
resume = verdict => {

View File

@ -3,7 +3,7 @@
package com.digitalasset.canton.platform.store.dao
import com.daml.lf.transaction.GlobalKeyWithMaintainers
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Util}
import com.daml.lf.value.Value.{ValueText, VersionedContractInstance}
import com.digitalasset.canton.platform.store.interfaces.LedgerDaoContractsReader
import org.scalatest.flatspec.AsyncFlatSpec
@ -145,7 +145,7 @@ private[dao] trait JdbcLedgerDaoContractsSpec extends LoneElement with Inside wi
it should "present the contract key state at a specific event sequential id" in {
val aTextValue = ValueText(scala.util.Random.nextString(10))
val key = GlobalKeyWithMaintainers.assertBuild(someTemplateId, aTextValue, Set(alice, bob))
val key = GlobalKeyWithMaintainers.assertBuild(someTemplateId, aTextValue, Set(alice, bob), Util.sharedKey(txVersion))
for {
(_, tx) <- createAndStoreContract(

View File

@ -6,7 +6,7 @@ package com.digitalasset.canton.platform.store.dao
import com.daml.lf.data.Time.Timestamp
import com.daml.lf.data.{ImmArray, Ref}
import com.daml.lf.transaction.test.{TransactionBuilder, TreeTransactionBuilder}
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Node, TransactionVersion}
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Node, TransactionVersion, Util}
import com.daml.lf.value.Value.{ValueParty, VersionedContractInstance}
import com.digitalasset.canton.platform.store.entries.LedgerEntry
import org.scalatest.flatspec.AsyncFlatSpec
@ -14,7 +14,6 @@ import org.scalatest.matchers.should.Matchers
import org.scalatest.{Inside, LoneElement}
import java.util.UUID
import TreeTransactionBuilder.*
private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
@ -50,7 +49,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
stakeholders = Set(bob),
keyOpt = Some(
GlobalKeyWithMaintainers
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob))
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob), Util.sharedKey(txVersion))
),
version = TransactionVersion.minVersion,
)
@ -83,7 +82,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
signatories = Set(bob),
stakeholders = Set(bob),
keyOpt = Some(
GlobalKeyWithMaintainers.assertBuild(someTemplateId, ValueParty(bob), Set(bob))
GlobalKeyWithMaintainers.assertBuild(someTemplateId, ValueParty(bob), Set(bob), Util.sharedKey(txVersion))
),
byKey = false,
version = TransactionVersion.minVersion,
@ -105,7 +104,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
exerciseResult = Some(someChoiceResult),
keyOpt = Some(
GlobalKeyWithMaintainers
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob))
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob), Util.sharedKey(txVersion))
),
byKey = false,
version = TransactionVersion.minVersion,
@ -120,7 +119,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
stakeholders = Set(alice, bob),
keyOpt = Some(
GlobalKeyWithMaintainers
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob))
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob), Util.sharedKey(txVersion))
),
version = TransactionVersion.minVersion,
)

View File

@ -150,7 +150,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend with OptionVa
),
)
private[this] val txVersion = TransactionVersion.StableVersions.min
protected final val txVersion: TransactionVersion = TransactionVersion.StableVersions.min
private[this] def newBuilder(): NodeIdTransactionBuilder = new NodeIdTransactionBuilder
protected final val someContractInstance = ContractInstance(someTemplateId, someContractArgument)

View File

@ -229,6 +229,7 @@ object CommandExecutionErrors extends CommandExecutionErrorGroup {
Seq(
(ErrorResource.TemplateId, key.templateId.toString),
(ErrorResource.ContractKey, encodedKey),
(ErrorResource.SharedKey, GlobalKey.isShared(key).toString),
)
}
}
@ -430,6 +431,7 @@ object CommandExecutionErrors extends CommandExecutionErrorGroup {
Seq(
(ErrorResource.TemplateId, err.templateId.toString),
(ErrorResource.ContractKey, encodedKey),
(ErrorResource.SharedKey, err.shared.toString),
)
}
}

View File

@ -21,6 +21,7 @@ object ErrorResource {
ContractId,
ContractIds,
ContractKey,
SharedKey,
ContractKeyHash,
DalfPackage,
DevErrorType,
@ -48,6 +49,9 @@ object ErrorResource {
object ContractKey extends ErrorResource {
def asString: String = "CONTRACT_KEY"
}
object SharedKey extends ErrorResource {
def asString: String = "SHARED_KEY"
}
object ContractArg extends ErrorResource {
def asString: String = "CONTRACT_ARG"
}

View File

@ -191,7 +191,7 @@ final class Conversions(
.setTemplateId(convertIdentifier(tid))
.setKey(convertValue(key))
)
case FetchEmptyContractKeyMaintainers(tid, key) =>
case FetchEmptyContractKeyMaintainers(tid, key, _) =>
builder.setFetchEmptyContractKeyMaintainers(
proto.ScenarioError.FetchEmptyContractKeyMaintainers.newBuilder
.setTemplateId(convertIdentifier(tid))

View File

@ -126,7 +126,7 @@ final class ValueEnricher(
key: GlobalKeyWithMaintainers
): Result[GlobalKeyWithMaintainers] =
enrichContractKey(key.globalKey.templateId, key.globalKey.key).map(normalizedKey =>
key.copy(globalKey = GlobalKey.assertBuild(key.globalKey.templateId, normalizedKey))
key.copy(globalKey = GlobalKey.assertWithRenormalizedValue(key.globalKey, normalizedKey))
)
def enrichContractKey(

View File

@ -1,179 +0,0 @@
// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
package engine
package preprocessing
import com.daml.lf.data._
import com.daml.lf.language.Ast._
import com.daml.lf.speedy.{ArrayList, SValue}
import com.daml.lf.value.Value
import com.daml.lf.value.Value._
/** This translator is only intended for use where a SValue is needed for error reporting but
* only a Value is available. This can be the case for [[com.daml.lf.transaction.SharedGlobalKey]]
* where the package-id may not be available.
*
* TODO https://github.com/digital-asset/daml/issues/17646 - Once there are other ways to resolve missing package-ids,
* for example issue #17646, this will longer be necessary.
*/
object LossyValueTranslator {
private[preprocessing] val lossyConversionIdentifier: Ref.Identifier =
Ref.Identifier.assertFromString("Lossy:Conversion:Id")
private[preprocessing] val lossyConversionVariantRank: Int = -1
private[preprocessing] val lossyConversionFieldPrefix: String = "Lossy_Field_"
private final case class ValueTy(value: SValue, ty: Type)
@throws[Error.Preprocessing.Error]
def unsafeTranslate(lf: Value): (SValue, Type) = {
def vty(value: SValue, ty: Type): ValueTy = ValueTy(value, ty)
def bty(value: SValue, bt: BuiltinType): ValueTy = ValueTy(value, TBuiltin(bt))
def go(value0: Value, nesting: Int = 0): ValueTy = {
if (nesting > Value.MAXIMUM_NESTING) {
throw Error.Preprocessing.ValueNesting(lf)
} else {
val newNesting = nesting + 1
def typeError(msg: String = s"Unable to translate value: $value0") =
throw Error.Preprocessing.Internal("LossyTranslate", msg, None)
value0 match {
case ValueUnit => bty(SValue.SUnit, BTUnit)
case ValueBool(b) => bty(if (b) SValue.SValue.True else SValue.SValue.False, BTBool)
case ValueInt64(i) => bty(SValue.SInt64(i), BTInt64)
case ValueTimestamp(t) => bty(SValue.STimestamp(t), BTTimestamp)
case ValueDate(t) => bty(SValue.SDate(t), BTDate)
case ValueText(t) => bty(SValue.SText(t), BTText)
case ValueParty(p) => bty(SValue.SParty(p), BTParty)
case ValueContractId(c) =>
vty(
SValue.SContractId(c),
TApp(TBuiltin(BTContractId), TTyCon(lossyConversionIdentifier)),
)
case ValueNumeric(d) =>
Numeric.fromBigDecimal(TNat.Decimal.n, d) match {
case Right(value) =>
vty(SValue.SNumeric(value), TApp(TBuiltin(BTNumeric), TNat.Decimal))
case Left(message) => typeError(message)
}
case ValueOptional(mbValue) =>
mbValue match {
case None =>
vty(SValue.SValue.None, TBuiltin(BTOptional))
case Some(x) =>
val vt = go(x, newNesting)
vty(SValue.SOptional(Some(vt.value)), TApp(TBuiltin(BTOptional), vt.ty))
}
case ValueList(ls) =>
val list = ls.map(go(_, newNesting))
list.iterator.nextOption() match {
case None => vty(SValue.SValue.EmptyList, TBuiltin(BTList))
case Some(ref) => vty(SValue.SList(list.map(_.value)), TApp(TBuiltin(BTList), ref.ty))
}
case ValueTextMap(entries) =>
entries.iterator.nextOption() match {
case None =>
vty(SValue.SValue.EmptyTextMap, TBuiltin(BTTextMap))
case Some((_, refVal)) =>
val refTy = go(refVal, newNesting).ty
vty(
SValue.SMap(
isTextMap = true,
entries = entries.iterator.map { case (k, v) =>
SValue.SText(k) -> go(v, newNesting).value
},
),
TApp(TBuiltin(BTTextMap), refTy),
)
}
case ValueGenMap(entries) =>
entries.iterator.nextOption() match {
case None =>
vty(
SValue.SValue.EmptyGenMap,
TBuiltin(BTGenMap),
)
case Some((kr, vr)) =>
val refK = go(kr, newNesting).ty
val refV = go(vr, newNesting).ty
vty(
SValue.SMap(
isTextMap = false,
entries = entries.iterator.map { case (k, v) =>
go(k, newNesting).value -> go(v, newNesting).value
},
),
TApp(TApp(TBuiltin(BTGenMap), refK), refV),
)
}
case ValueVariant(mbId, constructorName, val0) =>
val vt = go(val0, newNesting)
// This cannot work in the general case as there is no way to derive all the types that
// are involved in the variant as we only observer one instance
vty(
SValue.SVariant(
mbId.getOrElse(lossyConversionIdentifier),
constructorName,
lossyConversionVariantRank,
vt.value,
),
TApp(TTyCon(lossyConversionIdentifier), vt.ty),
)
case ValueRecord(mTyCon, sourceElements) =>
val flatNames = sourceElements.iterator.flatMap(_._1).toList
val names = flatNames.length match {
case 0 =>
(1 to sourceElements.length).map(i =>
Ref.Name.assertFromString(s"$lossyConversionFieldPrefix$i")
)
case sourceElements.length => flatNames
case _ => typeError()
}
val vts = sourceElements.iterator.map(_._2).map(go(_, newNesting)).toList
val types = vts.map(_.ty).foldLeft[Type](TTyCon(lossyConversionIdentifier)) {
case (it, t) => TApp(it, t)
}
vty(
SValue.SRecord(
mTyCon.getOrElse(lossyConversionIdentifier),
ImmArray.from(names),
vts.map(_.value).to(ArrayList),
),
types,
)
case ValueEnum(mbId, constructor) =>
vty(
SValue.SEnum(
mbId.getOrElse(lossyConversionIdentifier),
constructor,
lossyConversionVariantRank,
),
TTyCon(lossyConversionIdentifier),
)
case _ => typeError()
}
}
}
val ValueTy(value, ty) = go(lf)
(value, ty)
}
}

View File

@ -10,7 +10,7 @@ import com.daml.lf.ledger.Authorize
import com.daml.lf.ledger.FailedAuthorization._
import com.daml.lf.speedy.DefaultAuthorizationChecker
import com.daml.lf.transaction.test.TestNodeBuilder.CreateKey
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Node}
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Node, Util}
import com.daml.lf.transaction.test.{TestIdFactory, TestNodeBuilder, TransactionBuilder}
import com.daml.lf.value.Value
import com.daml.lf.value.Value.ValueRecord
@ -33,7 +33,7 @@ class AuthorizationSpec extends AnyFreeSpec with Matchers with Inside with TestI
): Node.Create = {
val templateId = "M:T"
builder
val init = builder
.create(
id = newCid,
templateId = templateId,
@ -42,11 +42,17 @@ class AuthorizationSpec extends AnyFreeSpec with Matchers with Inside with TestI
observers = Seq("Carl"),
key = CreateKey.NoKey,
)
.copy(
// By default maintainers are added to signatories so do this to allow error case testing
keyOpt =
Some(GlobalKeyWithMaintainers.assertBuild(templateId, Value.ValueUnit, maintainers))
init.copy(
// By default maintainers are added to signatories so do this to allow error case testing
keyOpt = Some(
GlobalKeyWithMaintainers.assertBuild(
templateId,
Value.ValueUnit,
maintainers,
Util.sharedKey(init.version),
)
)
)
}
"create" - {

View File

@ -13,7 +13,12 @@ import com.daml.lf.language.Ast.Package
import com.daml.lf.language.LanguageMajorVersion
import com.daml.lf.speedy.InitialSeeding
import com.daml.lf.transaction.test.TransactionBuilder.assertAsVersionedContract
import com.daml.lf.transaction.{ContractKeyUniquenessMode, GlobalKey, GlobalKeyWithMaintainers}
import com.daml.lf.transaction.{
ContractKeyUniquenessMode,
GlobalKey,
GlobalKeyWithMaintainers,
Util,
}
import com.daml.lf.value.Value
import com.daml.lf.value.Value.{
ContractId,
@ -117,6 +122,7 @@ class ContractKeySpec(majorLanguageVersion: LanguageMajorVersion)
GlobalKey.assertBuild(
TypeConName(basicTestsPkgId, withKeyTemplate),
ValueRecord(None, ImmArray((None, ValueParty(alice)), (None, ValueInt64(42)))),
Util.sharedKey(basicTestsPkg.languageVersion),
)
->
toContractId("BasicTests:WithKey:1")

View File

@ -18,6 +18,7 @@ import com.daml.lf.transaction.{
Normalization,
ReplayMismatch,
SubmittedTransaction,
Util,
Validation,
VersionedTransaction,
Transaction => Tx,
@ -34,10 +35,10 @@ import com.daml.lf.crypto.Hash
import com.daml.lf.engine.Error.Interpretation
import com.daml.lf.engine.Error.Interpretation.DamlException
import com.daml.lf.language.{
LanguageVersion,
StablePackages,
LanguageMajorVersion,
LanguageVersion,
PackageInterface,
StablePackages,
}
import com.daml.lf.transaction.test.TransactionBuilder.assertAsVersionedContract
import com.daml.logging.LoggingContext
@ -398,6 +399,7 @@ class EngineTest(majorLanguageVersion: LanguageMajorVersion)
(Some[Ref.Name]("k"), ValueInt64(43)),
),
),
basicUseSharedKeys,
)
)
)
@ -657,6 +659,7 @@ class EngineTest(majorLanguageVersion: LanguageMajorVersion)
(Some[Ref.Name]("k"), ValueInt64(43)),
),
),
basicUseSharedKeys,
)
)
)
@ -704,6 +707,7 @@ class EngineTest(majorLanguageVersion: LanguageMajorVersion)
(Some[Ref.Name]("k"), ValueInt64(43)),
),
),
basicUseSharedKeys,
)
)
)
@ -759,7 +763,12 @@ class EngineTest(majorLanguageVersion: LanguageMajorVersion)
stakeholders = Set(alice),
keyOpt = Some(
GlobalKeyWithMaintainers
.assertBuild(usedDisclosedContract.templateId, usedContractKey, Set(alice))
.assertBuild(
usedDisclosedContract.templateId,
usedContractKey,
Set(alice),
basicUseSharedKeys,
)
),
agreementText = "",
version = transactionVersion,
@ -1606,8 +1615,10 @@ class EngineTest(majorLanguageVersion: LanguageMajorVersion)
arg = usedDisclosedContract.argument.toNormalizedValue(transactionVersion),
signatories = Set(alice),
stakeholders = Set(alice),
keyOpt =
Some(GlobalKeyWithMaintainers.assertBuild(templateId, usedContractKey, Set(alice))),
keyOpt = Some(
GlobalKeyWithMaintainers
.assertBuild(templateId, usedContractKey, Set(alice), basicUseSharedKeys)
),
agreementText = "",
version = transactionVersion,
)
@ -2419,6 +2430,8 @@ class EngineTestHelpers(majorLanguageVersion: LanguageMajorVersion) {
val basicTestsSignatures: PackageInterface =
language.PackageInterface(Map(basicTestsPkgId -> basicTestsPkg))
val basicUseSharedKeys: Boolean = Util.sharedKey(basicTestsPkg.languageVersion)
val party: Ref.IdString.Party = Party.assertFromString("Party")
val alice: Ref.IdString.Party = Party.assertFromString("Alice")
val bob: Ref.IdString.Party = Party.assertFromString("Bob")
@ -2476,6 +2489,7 @@ class EngineTestHelpers(majorLanguageVersion: LanguageMajorVersion) {
GlobalKey.assertBuild(
TypeConName(basicTestsPkgId, withKeyTemplate),
ValueRecord(None, ImmArray((None, ValueParty(alice)), (None, ValueInt64(42)))),
basicUseSharedKeys,
),
Set(alice),
)

View File

@ -1,162 +0,0 @@
// Copyright (c) 2023 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package com.daml.lf
package engine
package preprocessing
import com.daml.lf.data._
import com.daml.lf.engine.preprocessing.LossyValueTranslator.{
lossyConversionFieldPrefix,
lossyConversionIdentifier,
lossyConversionVariantRank,
unsafeTranslate,
}
import com.daml.lf.language.Ast.TTyCon
import com.daml.lf.language.Util._
import com.daml.lf.language.{Ast, LanguageMajorVersion}
import com.daml.lf.speedy.ArrayList
import com.daml.lf.speedy.SValue._
import com.daml.lf.testing.parser.ParserParameters
import com.daml.lf.value.Value
import com.daml.lf.value.Value._
import org.scalatest.Inside
import org.scalatest.matchers.should.Matchers
import org.scalatest.prop.TableDrivenPropertyChecks
import org.scalatest.wordspec.AnyWordSpec
import scala.util.{Failure, Success, Try}
class LossyValueTranslatorSpec()
extends AnyWordSpec
with Inside
with Matchers
with TableDrivenPropertyChecks {
import com.daml.lf.testing.parser.Implicits.SyntaxHelper
import com.daml.lf.transaction.test.TransactionBuilder.Implicits.{defaultPackageId => _, _}
private[this] implicit val parserParameters
: ParserParameters[LossyValueTranslatorSpec.this.type] =
ParserParameters.defaultFor(LanguageMajorVersion.V2)
private[this] implicit val defaultPackageId: Ref.PackageId =
parserParameters.defaultPackageId
private[this] val aCid =
ContractId.V1.assertBuild(
crypto.Hash.hashPrivateKey("a Contract ID"),
Bytes.assertFromString("00"),
)
"translateValue" should {
val testCases = Table[Ast.Type, Value, speedy.SValue](
("type", "value", "svalue"),
(TUnit, ValueUnit, SValue.Unit),
(TBool, ValueTrue, SValue.True),
(TInt64, ValueInt64(42), SInt64(42)),
(
TTimestamp,
ValueTimestamp(Time.Timestamp.assertFromString("1969-07-20T20:17:00Z")),
STimestamp(Time.Timestamp.assertFromString("1969-07-20T20:17:00Z")),
),
(
TDate,
ValueDate(Time.Date.assertFromString("1879-03-14")),
SDate(Time.Date.assertFromString("1879-03-14")),
),
(TText, ValueText("daml"), SText("daml")),
(
TNumeric(Ast.TNat(Decimal.scale)),
ValueNumeric(Numeric.assertFromString("10.")),
SNumeric(Numeric.assertFromString("10.0000000000")),
),
(TParty, ValueParty("Alice"), SParty("Alice")),
(
TContractId(TTyCon(lossyConversionIdentifier)),
ValueContractId(aCid),
SContractId(aCid),
),
(
TList(TText),
ValueList(FrontStack(ValueText("a"), ValueText("b"))),
SList(FrontStack(SText("a"), SText("b"))),
),
(
TTextMap(TBool),
ValueTextMap(SortedLookupList(Map("0" -> ValueTrue, "1" -> ValueFalse))),
SMap(true, Iterator(SText("0") -> SValue.True, SText("1") -> SValue.False)),
),
(
TGenMap(TInt64, TText),
ValueGenMap(ImmArray(ValueInt64(1) -> ValueText("1"), ValueInt64(42) -> ValueText("42"))),
SMap(false, Iterator(SInt64(1) -> SText("1"), SInt64(42) -> SText("42"))),
),
(TOptional(TText), ValueOptional(Some(ValueText("text"))), SOptional(Some(SText("text")))),
(
t"'Lossy':Conversion:Id Int64 Text Bool",
ValueRecord(
"",
ImmArray("x" -> ValueInt64(33), "y" -> ValueText("a"), "z" -> ValueBool(true)),
),
SRecord(
lossyConversionIdentifier,
ImmArray("x", "y", "z"),
ArrayList(SInt64(33), SText("a"), SBool(true)),
),
),
(
t"'Lossy':Conversion:Id Text",
ValueVariant("", "Right", ValueText("some test")),
SVariant(lossyConversionIdentifier, "Right", lossyConversionVariantRank, SText("some test")),
),
(
Ast.TTyCon(lossyConversionIdentifier),
ValueEnum("", "blue"),
SEnum(lossyConversionIdentifier, "blue", lossyConversionVariantRank),
),
(
Ast.TApp(Ast.TTyCon(lossyConversionIdentifier), Ast.TBuiltin(Ast.BTList)),
ValueRecord("", ImmArray("" -> ValueNil)),
SRecord(
lossyConversionIdentifier,
ImmArray(Ref.Name.assertFromString(s"${lossyConversionFieldPrefix}1")),
ArrayList(SValue.EmptyList),
),
),
)
"succeeds on well type values" in {
forAll(testCases) { (ty, value, sValue) =>
Try(
unsafeTranslate(value)
) shouldBe Success((sValue, ty))
}
}
"fails on too deep values" in {
def mkMyList(n: Int) =
Iterator.range(0, n).foldLeft[Value](ValueVariant("", "MyNil", ValueUnit)) { case (v, n) =>
ValueVariant(
"",
"MyCons",
ValueRecord("", ImmArray("" -> ValueInt64(n.toLong), "" -> v)),
)
}
val notTooBig = mkMyList(49)
val tooBig = mkMyList(50)
val failure = Failure(Error.Preprocessing.ValueNesting(tooBig))
Try(
unsafeTranslate(notTooBig)
) shouldBe a[Success[_]]
Try(
unsafeTranslate(tooBig)
) shouldBe failure
}
}
}

View File

@ -123,12 +123,13 @@ private[lf] object Pretty {
text("Update failed due to a contract key with an empty sey of maintainers when creating") &
prettyTypeConName(tid) & text("with") & prettyValue(true)(arg) /
text("The computed key is") & prettyValue(true)(key)
case FetchEmptyContractKeyMaintainers(tid, key) =>
case FetchEmptyContractKeyMaintainers(tid, key, sharedKey) =>
val sharedKeyText = if (sharedKey) "shared" else ""
text(
"Update failed due to a contract key with an empty sey of maintainers when fetching or looking up by key"
) &
prettyTypeConName(tid) /
text("The provided key is") & prettyValue(true)(key)
text(s"The provided $sharedKeyText key is") & prettyValue(true)(key)
case ContractNotFound(cid) =>
text("Update failed due to a unknown contract") & prettyContractId(cid)
case NonComparableValues =>

View File

@ -27,6 +27,7 @@ import com.daml.lf.transaction.{
GlobalKey,
GlobalKeyWithMaintainers,
TransactionVersion,
Util,
TransactionErrors => TxErr,
}
import com.daml.lf.value.{Value => V}
@ -1543,6 +1544,7 @@ private[lf] object SBuiltin {
IE.FetchEmptyContractKeyMaintainers(
cachedKey.templateId,
cachedKey.lfValue,
cachedKey.shared,
)
)
} else {
@ -2048,16 +2050,17 @@ private[lf] object SBuiltin {
private[this] def extractKey(
location: String,
version: TransactionVersion,
packageTxVersion: TransactionVersion,
templateId: Ref.TypeConName,
v: SValue,
): CachedKey =
v match {
case SStruct(_, vals) =>
val keyValue = vals.get(keyIdx)
val lfValue = keyValue.toNormalizedValue(version)
val lfValue = keyValue.toNormalizedValue(packageTxVersion)
val shared = Util.sharedKey(packageTxVersion)
val gkey = GlobalKey
.build(templateId, lfValue)
.build(templateId, lfValue, shared)
.getOrElse(
throw SErrorDamlException(IE.ContractIdInContractKey(keyValue.toUnnormalizedValue))
)
@ -2067,6 +2070,7 @@ private[lf] object SBuiltin {
extractParties(NameOf.qualifiedNameOfCurrentFunc, vals.get(maintainerIdx)),
),
keyValue,
shared,
)
case _ => throw SErrorCrash(location, s"Invalid key with maintainers: $v")
}

View File

@ -113,6 +113,7 @@ private[lf] object Speedy {
final case class CachedKey(
globalKeyWithMaintainers: GlobalKeyWithMaintainers,
key: SValue,
shared: Boolean,
) {
def globalKey: GlobalKey = globalKeyWithMaintainers.globalKey
def templateId: TypeConName = globalKey.templateId
@ -120,7 +121,7 @@ private[lf] object Speedy {
val lfValue: V = globalKey.key
def renormalizedGlobalKeyWithMaintainers(version: TxVersion) = {
globalKeyWithMaintainers.copy(
globalKey = GlobalKey.assertBuild(templateId, key.toNormalizedValue(version))
globalKey = GlobalKey.assertWithRenormalizedValue(globalKey, key.toNormalizedValue(version))
)
}
}

View File

@ -14,7 +14,7 @@ import com.daml.lf.speedy.SExpr.SExpr
import com.daml.lf.speedy.Speedy.ContractInfo
import com.daml.lf.testing.parser.Implicits.SyntaxHelper
import com.daml.lf.testing.parser.ParserParameters
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion}
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion, Util}
import com.daml.lf.value.Value
import com.daml.lf.value.Value.{ContractId, VersionedContractInstance}
import com.daml.lf.value.Value.ContractId.`Cid Order`
@ -115,13 +115,13 @@ class CompilerTest(majorLanguageVersion: LanguageMajorVersion)
"using a template with no key" should {
val templateId = Ref.Identifier.assertFromString("-pkgId-:Module:Record")
val disclosedContract1 = buildDisclosedContract(disclosedCid1, alice, templateId)
val disclosedContract1 = buildDisclosedContract(disclosedCid1, alice, templateId, version)
val versionedContract1 = VersionedContractInstance(
version,
templateId,
disclosedContract1.argument.toUnnormalizedValue,
)
val disclosedContract2 = buildDisclosedContract(disclosedCid2, alice, templateId)
val disclosedContract2 = buildDisclosedContract(disclosedCid2, alice, templateId, version)
val versionedContract2 = VersionedContractInstance(
version,
templateId,
@ -286,14 +286,14 @@ class CompilerTest(majorLanguageVersion: LanguageMajorVersion)
"using a template with a key" should {
val templateId = Ref.Identifier.assertFromString("-pkgId-:Module:RecordKey")
val disclosedContract1 =
buildDisclosedContract(disclosedCid1, alice, templateId, keyLabel = "test-label-1")
buildDisclosedContract(disclosedCid1, alice, templateId, version, keyLabel = "test-label-1")
val versionedContract1 = VersionedContractInstance(
version,
templateId,
disclosedContract1.argument.toUnnormalizedValue,
)
val disclosedContract2 =
buildDisclosedContract(disclosedCid2, alice, templateId, keyLabel = "test-label-2")
buildDisclosedContract(disclosedCid2, alice, templateId, version, keyLabel = "test-label-2")
val versionedContract2 = VersionedContractInstance(
version,
templateId,
@ -554,6 +554,7 @@ final class CompilerTestHelpers(majorLanguageVersion: LanguageMajorVersion) {
contractId: ContractId,
maintainer: Party,
templateId: Ref.Identifier,
version: TransactionVersion,
keyLabel: String = "",
): DisclosedContract = {
val withKey = keyLabel.nonEmpty
@ -572,7 +573,7 @@ final class CompilerTestHelpers(majorLanguageVersion: LanguageMajorVersion) {
if (withKey) {
Some(
GlobalKeyWithMaintainers(
GlobalKey.assertBuild(templateId, key.toUnnormalizedValue),
GlobalKey.assertBuild(templateId, key.toUnnormalizedValue, Util.sharedKey(version)),
Set(maintainer),
)
)

View File

@ -14,7 +14,7 @@ import com.daml.lf.speedy.SError._
import com.daml.lf.speedy.SExpr._
import com.daml.lf.speedy.SValue._
import com.daml.lf.testing.parser.Implicits.SyntaxHelper
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, TransactionVersion, Versioned}
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, TransactionVersion, Util, Versioned}
import com.daml.lf.ledger.FailedAuthorization
import com.daml.lf.ledger.FailedAuthorization.{
ExerciseMissingAuthorization,
@ -344,9 +344,11 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
),
)
private val testTxVersion: TransactionVersion = TransactionVersion.StableVersions.max
private[this] def buildContract(observer: Party): Versioned[Value.ContractInstance] =
Versioned(
TransactionVersion.StableVersions.max,
testTxVersion,
Value.ContractInstance(
T,
Value.ValueRecord(
@ -385,7 +387,7 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
private[this] val nonVisibleContract = buildContract(alice)
private[this] val helper = Versioned(
TransactionVersion.StableVersions.max,
testTxVersion,
Value.ContractInstance(
Helper,
ValueRecord(
@ -396,7 +398,7 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
)
private[this] val iface_contract = Versioned(
TransactionVersion.StableVersions.max,
testTxVersion,
Value.ContractInstance(
Human,
Value.ValueRecord(
@ -419,11 +421,16 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
private[this] val getHelper = Map(helperCId -> helper)
private[this] val getKey = Map(
GlobalKeyWithMaintainers.assertBuild(T, keyValue, Set(alice)) -> cId
GlobalKeyWithMaintainers.assertBuild(
T,
keyValue,
Set(alice),
Util.sharedKey(testTxVersion),
) -> cId
)
private[this] val dummyContract = Versioned(
TransactionVersion.StableVersions.max,
testTxVersion,
Value.ContractInstance(Dummy, ValueRecord(None, ImmArray(None -> ValueParty(alice)))),
)
private[this] val getWronglyTypedContract = Map(cId -> dummyContract)
@ -1676,7 +1683,9 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
Set(alice),
)
inside(res) {
case Success(Left(SErrorDamlException(IE.FetchEmptyContractKeyMaintainers(T, _)))) =>
case Success(
Left(SErrorDamlException(IE.FetchEmptyContractKeyMaintainers(T, _, _)))
) =>
msgs shouldBe Seq("starts test", "maintainers")
}
}
@ -2594,7 +2603,9 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
Set(alice),
)
inside(res) {
case Success(Left(SErrorDamlException(IE.FetchEmptyContractKeyMaintainers(T, _)))) =>
case Success(
Left(SErrorDamlException(IE.FetchEmptyContractKeyMaintainers(T, _, _)))
) =>
msgs shouldBe Seq("starts test", "maintainers")
}
}
@ -3163,7 +3174,9 @@ class EvaluationOrderTest(languageVersion: LanguageVersion)
Set(alice),
)
inside(res) {
case Success(Left(SErrorDamlException(IE.FetchEmptyContractKeyMaintainers(T, _)))) =>
case Success(
Left(SErrorDamlException(IE.FetchEmptyContractKeyMaintainers(T, _, _)))
) =>
msgs shouldBe Seq("starts test", "maintainers")
}
}

View File

@ -13,7 +13,13 @@ import com.daml.lf.speedy.SValue.SToken
import com.daml.lf.speedy.Speedy.{CachedKey, ContractInfo}
import com.daml.lf.testing.parser.ParserParameters
import com.daml.lf.testing.parser.Implicits.SyntaxHelper
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion, Versioned}
import com.daml.lf.transaction.{
GlobalKey,
GlobalKeyWithMaintainers,
TransactionVersion,
Util,
Versioned,
}
import com.daml.lf.value.Value
import com.daml.lf.value.Value.{ContractId, ContractInstance}
import org.scalatest.matchers.{MatchResult, Matcher}
@ -86,6 +92,7 @@ private[lf] class ExplicitDisclosureLib(
""",
evaluationOrder,
)
val useSharedKeys: Boolean = Util.sharedKey(defaultParserParameters.languageVersion)
val maintainerParty: IdString.Party = Ref.Party.assertFromString("maintainerParty")
val ledgerParty: IdString.Party = Ref.Party.assertFromString("ledgerParty")
val disclosureParty: IdString.Party = Ref.Party.assertFromString("disclosureParty")
@ -138,6 +145,7 @@ private[lf] class ExplicitDisclosureLib(
globalKeyWithMaintainers =
GlobalKeyWithMaintainers(buildContractKey(maintainer, label), Set(maintainer)),
key = buildContractSKey(maintainer),
shared = Util.sharedKey(TransactionVersion.maxVersion),
)
)
else
@ -189,6 +197,7 @@ private[lf] class ExplicitDisclosureLib(
GlobalKey.assertBuild(
houseTemplateType,
buildContractKeyValue(maintainer, label),
useSharedKeys,
)
def buildContractSKey(maintainer: Party, label: String = testKeyName): SValue =
@ -239,6 +248,7 @@ private[lf] class ExplicitDisclosureLib(
templateId: Ref.Identifier = houseTemplateId,
withKey: Boolean = true,
label: String = testKeyName,
sharedKey: Boolean = true,
): ContractInfo = {
val contract = SValue.SRecord(
templateId,
@ -253,8 +263,9 @@ private[lf] class ExplicitDisclosureLib(
Some(
CachedKey(
GlobalKeyWithMaintainers
.assertBuild(templateId, contract.toUnnormalizedValue, Set(maintainer)),
.assertBuild(templateId, contract.toUnnormalizedValue, Set(maintainer), sharedKey),
contract,
sharedKey,
)
)
else None

View File

@ -17,7 +17,7 @@ import com.daml.lf.speedy.SValue.{SValue => _, _}
import com.daml.lf.speedy.Speedy.{CachedKey, ContractInfo, Machine}
import com.daml.lf.testing.parser.Implicits.SyntaxHelper
import com.daml.lf.testing.parser.ParserParameters
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion}
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion, Util}
import com.daml.lf.value.Value
import com.daml.lf.value.Value.ValueArithmeticError
import org.scalatest.prop.TableDrivenPropertyChecks
@ -1813,11 +1813,21 @@ class SBuiltinTest(majorLanguageVersion: LanguageMajorVersion)
"when template key is defined" in {
val templateId = Ref.Identifier.assertFromString("-pkgId-:Mod:IouWithKey")
val sharedKey = Util.sharedKey(txVersion)
val (disclosedContract, Some((key, keyWithMaintainers))) =
buildDisclosedContract(contractId, alice, alice, templateId, withKey = true)
buildDisclosedContract(
contractId,
alice,
alice,
templateId,
withKey = true,
sharedKey = sharedKey,
)
val cachedKey = CachedKey(
GlobalKeyWithMaintainers.assertBuild(templateId, key.toUnnormalizedValue, Set(alice)),
GlobalKeyWithMaintainers
.assertBuild(templateId, key.toUnnormalizedValue, Set(alice), sharedKey),
key,
sharedKey,
)
val contractInfo = ContractInfo(
version = txVersion,
@ -2029,6 +2039,7 @@ final class SBuiltinTestHelpers(majorLanguageVersion: LanguageMajorVersion) {
maintainer: Party,
templateId: Ref.Identifier,
withKey: Boolean,
sharedKey: Boolean = true,
): (DisclosedContract, Option[(SValue, SValue)]) = {
val key = SValue.SRecord(
templateId,
@ -2053,7 +2064,12 @@ final class SBuiltinTestHelpers(majorLanguageVersion: LanguageMajorVersion) {
val globalKey =
if (withKey) {
Some(
GlobalKeyWithMaintainers.assertBuild(templateId, key.toUnnormalizedValue, Set(maintainer))
GlobalKeyWithMaintainers.assertBuild(
templateId,
key.toUnnormalizedValue,
Set(maintainer),
sharedKey,
)
)
} else {
None

View File

@ -77,6 +77,7 @@ object LanguageVersion {
val natTypeErasure = v1_dev
val packageUpgrades = v1_dev
val dynamicExercise = v1_dev
val sharedKeys = v1_dev
/** TYPE_REP_TYCON_NAME builtin */
val templateTypeRepToText = v1_dev

View File

@ -360,8 +360,19 @@ private[lf] class PackageInterface(val signatures: PartialFunction[PackageId, Pa
def lookupException(name: TypeConName): Either[LookupError, DefExceptionSignature] =
lookupException(name, Reference.Exception(name))
def lookupPackageLanguageVersion(pkgId: PackageId): Either[LookupError, LanguageVersion] =
lookupPackage(pkgId).map(_.languageVersion)
val packageLanguageVersion: PartialFunction[PackageId, LanguageVersion] =
signatures andThen (_.languageVersion)
def hasSharedKeys(packageId: PackageId): Boolean = {
// TODO https://github.com/digital-asset/daml/issues/17732
// Enable shared keys once there is LAPI support via
// packageLanguageVersion(packageId) >= LanguageVersion.Features.sharedKeys
false
}
}
object PackageInterface {

View File

@ -66,7 +66,7 @@ final class Adapter(
)
def adapt(gkey: GlobalKey): GlobalKey =
GlobalKey.assertBuild(adapt(gkey.templateId), adapt(gkey.key))
GlobalKey.assertBuild(adapt(gkey.templateId), adapt(gkey.key), GlobalKey.isShared(gkey))
private[this] def adapt(value: Value): Value =
value match {

View File

@ -45,9 +45,23 @@ trait TestNodeBuilder {
case CreateKey.NoKey =>
None
case CreateKey.SignatoryMaintainerKey(value) =>
Some(GlobalKeyWithMaintainers.assertBuild(templateId, value, signatories))
Some(
GlobalKeyWithMaintainers.assertBuild(
templateId,
value,
signatories,
Util.sharedKey(transactionVersion),
)
)
case CreateKey.KeyWithMaintainers(value, maintainers) =>
Some(GlobalKeyWithMaintainers.assertBuild(templateId, value, maintainers))
Some(
GlobalKeyWithMaintainers.assertBuild(
templateId,
value,
maintainers,
Util.sharedKey(transactionVersion),
)
)
}
val maintainers: Set[Party] = keyOpt.fold(Set.empty[Party])(_.maintainers)

View File

@ -121,19 +121,6 @@ object TransactionBuilder {
): TransactionVersion =
data.assertRight(assignVersion(v0, supportedVersions))
def asVersionedValue(
value: Value,
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.DevVersions,
): Either[String, TxValue] =
assignVersion(value, supportedVersions).map(Versioned(_, value))
@throws[IllegalArgumentException]
def assertAsVersionedValue(
value: Value,
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.DevVersions,
): TxValue =
data.assertRight(asVersionedValue(value, supportedVersions))
def asVersionedContract(
contract: ContractInstance,
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.DevVersions,

View File

@ -10,12 +10,13 @@ import com.daml.lf.data._
import com.daml.lf.transaction.{
GlobalKey,
GlobalKeyWithMaintainers,
Transaction,
Node,
NodeId,
Transaction,
TransactionVersion,
Versioned,
VersionedTransaction,
Util,
}
import com.daml.lf.transaction.test.TransactionBuilder
import com.daml.lf.value.Value._
@ -270,11 +271,14 @@ object ValueGenerators {
arg <- versionedValueGen
} yield arg.map(Value.ContractInstance(template, _))
def keyWithMaintainersGen(templateId: Ref.TypeConName): Gen[GlobalKeyWithMaintainers] = {
def keyWithMaintainersGen(
templateId: Ref.TypeConName,
version: TransactionVersion,
): Gen[GlobalKeyWithMaintainers] = {
for {
key <- valueGen()
maintainers <- genNonEmptyParties
gkey = GlobalKey.build(templateId, key).toOption
gkey = GlobalKey.build(templateId, key, Util.sharedKey(version)).toOption
if gkey.isDefined
} yield GlobalKeyWithMaintainers(gkey.get, maintainers)
}
@ -314,7 +318,7 @@ object ValueGenerators {
agreement <- Arbitrary.arbitrary[String]
signatories <- genNonEmptyParties
stakeholders <- genNonEmptyParties
key <- Gen.option(keyWithMaintainersGen(templateId))
key <- Gen.option(keyWithMaintainersGen(templateId, version))
} yield Node.Create(
coid = coid,
templateId = templateId,
@ -339,7 +343,7 @@ object ValueGenerators {
actingParties <- genNonEmptyParties
signatories <- genNonEmptyParties
stakeholders <- genNonEmptyParties
key <- Gen.option(keyWithMaintainersGen(templateId))
key <- Gen.option(keyWithMaintainersGen(templateId, version))
byKey <- Gen.oneOf(true, false)
} yield Node.Fetch(
coid = coid,
@ -392,7 +396,7 @@ object ValueGenerators {
.map(_.to(ImmArray))
exerciseResult <-
if (version < minExceptions) valueGen().map(Some(_)) else Gen.option(valueGen())
key <- Gen.option(keyWithMaintainersGen(templateId))
key <- Gen.option(keyWithMaintainersGen(templateId, version))
byKey <- Gen.oneOf(true, false)
} yield Node.Exercise(
targetCoid = targetCoid,
@ -418,7 +422,7 @@ object ValueGenerators {
version <- transactionVersionGen()
targetCoid <- coidGen
templateId <- idGen
key <- keyWithMaintainersGen(templateId)
key <- keyWithMaintainersGen(templateId, version)
result <- Gen.option(targetCoid)
} yield Node.LookupByKey(
templateId,

View File

@ -99,6 +99,7 @@ object Error {
final case class FetchEmptyContractKeyMaintainers(
templateId: TypeConName,
key: Value,
shared: Boolean,
) extends Error
/** We tried to fetch / exercise a contract of the wrong type --

View File

@ -295,39 +295,32 @@ object Hash {
def hashPrivateKey(s: String): Hash =
builder(Purpose.PrivateKey, noCid2String).add(s).build
@throws[HashingError]
def assertHashContractKey(
packageId: Option[Ref.PackageId],
qualifiedName: Ref.QualifiedName,
key: Value,
): Hash = {
val kb = builder(Purpose.ContractKey, noCid2String)
packageId.foreach(p => kb.add(p))
kb
.addQualifiedName(qualifiedName)
.addTypedValue(key)
.build
}
// This function assumes that key is well typed, i.e. :
// 1 - `templateId` is the identifier for a template with a key of type τ
// 2 - `key` is a value of type τ
@throws[HashingError]
def assertHashContractKey(templateId: Ref.Identifier, key: Value): Hash =
assertHashContractKey(Some(templateId.packageId), templateId.qualifiedName, key)
def hashContractKey(
packageId: Option[Ref.PackageId],
qualifiedName: Ref.QualifiedName,
key: Value,
): Either[HashingError, Hash] =
handleError(assertHashContractKey(packageId, qualifiedName, key))
def assertHashContractKey(templateId: Ref.Identifier, key: Value, shared: Boolean): Hash = {
val hashBuilder = builder(Purpose.ContractKey, noCid2String)
(if (shared) {
val sharedPackageIdLength = 0 // To ensure there cannot be a hash collision
hashBuilder.add(sharedPackageIdLength).addQualifiedName(templateId.qualifiedName)
} else {
hashBuilder.addIdentifier(templateId)
}).addTypedValue(key).build
}
def hashContractKey(
templateId: Ref.Identifier,
key: Value,
shared: Boolean,
): Either[HashingError, Hash] =
handleError(assertHashContractKey(templateId, key))
handleError(assertHashContractKey(templateId, key, shared))
// TODO https://github.com/digital-asset/daml/issues/17732
// For temporary backward compatibility, will be deprecated
def assertHashContractKey(templateId: Ref.Identifier, key: Value): Hash = {
assertHashContractKey(templateId, key, shared = false)
}
// This function assumes that `arg` is well typed, i.e. :
// 1 - `templateId` is the identifier for a template with a contract argument of type τ

View File

@ -9,8 +9,6 @@ import com.daml.lf.data.Ref
import com.daml.lf.data.Ref.TypeConName
import com.daml.lf.value.Value
import scala.language.implicitConversions
/** Useful in various circumstances -- basically this is what a ledger implementation must use as
* a key. The 'hash' is guaranteed to be stable over time.
*/
@ -27,81 +25,60 @@ final class GlobalKey private (
// Ready for refactoring where packageId becomes optional (#14486)
def packageId: Option[Ref.PackageId] = Some(templateId.packageId)
def qualifiedName: Ref.QualifiedName = templateId.qualifiedName
def shared: SharedGlobalKey =
SharedGlobalKey(Some(templateId.packageId), templateId.qualifiedName, key, hash)
override def hashCode(): Int = hash.hashCode()
override def toString: String = s"GlobalKey($templateId, $key)"
}
// TODO: https://github.com/digital-asset/daml/issues/17661 - the target state for GlobalKey
// once all call sites support SharedGlobalKey
final case class SharedGlobalKey private (
val packageId: Option[Ref.PackageId],
val qualifiedName: Ref.QualifiedName,
val key: Value,
val hash: crypto.Hash,
) extends data.NoCopy {
override def equals(obj: Any): Boolean = obj match {
case that: SharedGlobalKey => this.hash == that.hash
case _ => false
}
override def hashCode(): Int = hash.hashCode()
override def toString: String =
s"SharedGlobalKey($qualifiedName${packageId.fold("")(p => s"@$p")}, $key)"
def assertGlobalKey: GlobalKey =
GlobalKey.assertBuild(Ref.TypeConName(packageId.get, qualifiedName), key)
}
object SharedGlobalKey {
implicit def globalKeyToShared(gk: GlobalKey): SharedGlobalKey =
SharedGlobalKey(gk.packageId, gk.qualifiedName, gk.key, gk.hash)
def build(
packageId: Option[Ref.PackageId],
qualifiedName: Ref.QualifiedName,
key: Value,
): Either[crypto.Hash.HashingError, SharedGlobalKey] = {
crypto.Hash
.hashContractKey(packageId, qualifiedName, key)
.map(new SharedGlobalKey(packageId, qualifiedName, key, _))
}
// Like `build` but, in case of error, throws an exception instead of returning a message.
@throws[IllegalArgumentException]
def assertBuild(
packageId: Option[Ref.PackageId],
qualifiedName: Ref.QualifiedName,
key: Value,
): SharedGlobalKey =
data.assertRight(build(packageId, qualifiedName, key).left.map(_.msg))
private[lf] def unapply(
globalKey: SharedGlobalKey
): Some[(Option[Ref.PackageId], Ref.QualifiedName, Value)] =
Some((globalKey.packageId, globalKey.qualifiedName, globalKey.key))
}
object GlobalKey {
// Will fail if key contains contract ids
// TODO https://github.com/digital-asset/daml/issues/17732
// For temporary backward compatibility, will be deprecated
def build(templateId: Ref.TypeConName, key: Value): Either[crypto.Hash.HashingError, GlobalKey] =
crypto.Hash.hashContractKey(templateId, key).map(new GlobalKey(templateId, key, _))
build(templateId, key, shared = false)
// TODO https://github.com/digital-asset/daml/issues/17732
// For temporary backward compatibility, will be deprecated
def assertBuild(templateId: Ref.TypeConName, value: Value): GlobalKey =
assertBuild(templateId, value, shared = false)
def assertWithRenormalizedValue(key: GlobalKey, value: Value): GlobalKey = {
if (
key.key != value &&
Hash.assertHashContractKey(key.templateId, value, true) != key.hash &&
Hash.assertHashContractKey(key.templateId, value, false) != key.hash
) {
throw new IllegalArgumentException(
s"Hash must not change as a result of value renormalization key=$key, value=$value"
)
}
new GlobalKey(key.templateId, value, key.hash)
}
// Will fail if key contains contract ids
def build(
templateId: Ref.TypeConName,
key: Value,
shared: Boolean,
): Either[crypto.Hash.HashingError, GlobalKey] =
crypto.Hash
.hashContractKey(templateId, key, shared)
.map(new GlobalKey(templateId, key, _))
// Like `build` but, in case of error, throws an exception instead of returning a message.
@throws[IllegalArgumentException]
def assertBuild(templateId: Ref.TypeConName, key: Value): GlobalKey =
data.assertRight(build(templateId, key).left.map(_.msg))
def assertBuild(templateId: Ref.TypeConName, key: Value, shared: Boolean): GlobalKey =
data.assertRight(build(templateId, key, shared).left.map(_.msg))
private[lf] def unapply(globalKey: GlobalKey): Some[(TypeConName, Value)] =
Some((globalKey.templateId, globalKey.key))
def isShared(key: GlobalKey): Boolean =
Hash.hashContractKey(key.templateId, key.key, true) == Right(key.hash)
}
final case class GlobalKeyWithMaintainers(
@ -112,19 +89,31 @@ final case class GlobalKeyWithMaintainers(
}
object GlobalKeyWithMaintainers {
// TODO https://github.com/digital-asset/daml/issues/17732
// For temporary backward compatibility, will be deprecated
def assertBuild(
templateId: Ref.TypeConName,
value: Value,
maintainers: Set[Ref.Party],
): GlobalKeyWithMaintainers =
data.assertRight(build(templateId, value, maintainers).left.map(_.msg))
assertBuild(templateId, value, maintainers, shared = false)
def assertBuild(
templateId: Ref.TypeConName,
value: Value,
maintainers: Set[Ref.Party],
shared: Boolean,
): GlobalKeyWithMaintainers =
data.assertRight(build(templateId, value, maintainers, shared).left.map(_.msg))
def build(
templateId: Ref.TypeConName,
value: Value,
maintainers: Set[Ref.Party],
shared: Boolean,
): Either[Hash.HashingError, GlobalKeyWithMaintainers] =
GlobalKey.build(templateId, value).map(GlobalKeyWithMaintainers(_, maintainers))
GlobalKey.build(templateId, value, shared).map(GlobalKeyWithMaintainers(_, maintainers))
}
/** Controls whether the engine should error out when it encounters duplicate keys.

View File

@ -97,7 +97,7 @@ object Node {
override def byKey: Boolean = false
override private[lf] def updateVersion(version: TransactionVersion): Node.Create =
copy(version = version)
copy(version = version, keyOpt = keyOpt.map(rehash(version)))
override def mapCid(f: ContractId => ContractId): Node.Create =
copy(coid = f(coid), arg = arg.mapCid(f))
@ -133,7 +133,7 @@ object Node {
def key: Option[GlobalKeyWithMaintainers] = keyOpt
override private[lf] def updateVersion(version: TransactionVersion): Node.Fetch =
copy(version = version)
copy(version = version, keyOpt = keyOpt.map(rehash(version)))
override def mapCid(f: ContractId => ContractId): Node.Fetch =
copy(coid = f(coid))
@ -174,10 +174,8 @@ object Node {
@deprecated("use keyOpt", since = "2.6.0")
def key: Option[GlobalKeyWithMaintainers] = keyOpt
override private[lf] def updateVersion(
version: TransactionVersion
): Node.Exercise =
copy(version = version)
override private[lf] def updateVersion(version: TransactionVersion): Node.Exercise =
copy(version = version, keyOpt = keyOpt.map(rehash(version)))
override def mapCid(f: ContractId => ContractId): Node.Exercise = copy(
targetCoid = f(targetCoid),
@ -225,7 +223,7 @@ object Node {
override def byKey: Boolean = true
override private[lf] def updateVersion(version: TransactionVersion): Node.LookupByKey =
copy(version = version)
copy(version = version, key = rehash(version)(key))
override def packageIds: Iterable[PackageId] = Iterable(templateId.packageId)
@ -257,6 +255,16 @@ object Node {
override protected def self: Node = this
}
private def rehash(
version: TransactionVersion
)(gk: GlobalKeyWithMaintainers): GlobalKeyWithMaintainers =
GlobalKeyWithMaintainers.assertBuild(
gk.globalKey.templateId,
gk.value,
gk.maintainers,
Util.sharedKey(version),
)
}
final case class NodeId(index: Int)

View File

@ -95,7 +95,8 @@ class Normalization {
x match {
case GlobalKeyWithMaintainers(key, maintainers) =>
GlobalKeyWithMaintainers(
GlobalKey.assertBuild(key.templateId, normValue(version)(key.key)),
GlobalKey
.assertBuild(key.templateId, normValue(version)(key.key), Util.sharedKey(version)),
maintainers,
)
}

View File

@ -423,7 +423,10 @@ object TransactionCoder {
keyWithMaintainers.getKeyVersioned,
keyWithMaintainers.getKeyUnversioned,
)
gkey <- GlobalKey.build(templateId, value).left.map(hashErr => DecodeError(hashErr.msg))
gkey <- GlobalKey
.build(templateId, value, Util.sharedKey(version))
.left
.map(hashErr => DecodeError(hashErr.msg))
} yield GlobalKeyWithMaintainers(gkey, maintainers)
}
@ -441,7 +444,10 @@ object TransactionCoder {
keyWithMaintainers.getKeyVersioned,
keyWithMaintainers.getKeyUnversioned,
)
gkey <- GlobalKey.build(templateId, value).left.map(hashErr => DecodeError(hashErr.msg))
gkey <- GlobalKey
.build(templateId, value, Util.sharedKey(version))
.left
.map(hashErr => DecodeError(hashErr.msg))
} yield GlobalKeyWithMaintainers(gkey, maintainers)
private val RightNone = Right(None)
@ -885,7 +891,10 @@ object TransactionCoder {
for {
tmplId <- ValueCoder.decodeIdentifier(rawTmplId)
value <- ValueCoder.decodeValue(ValueCoder.NoCidDecoder, nodeVersion, rawKey)
key <- GlobalKey.build(tmplId, value).left.map(hashErr => DecodeError(hashErr.msg))
key <- GlobalKey
.build(tmplId, value, Util.sharedKey(nodeVersion))
.left
.map(hashErr => DecodeError(hashErr.msg))
} yield key
/*

View File

@ -59,6 +59,7 @@ object TransactionVersion {
private[lf] val minInterfaces = V15
private[lf] val minExplicitDisclosure = VDev
private[lf] val minChoiceAuthorizers = VDev
private[lf] val minSharedKeys = VDev
private[lf] val assignNodeVersion: LanguageVersion => TransactionVersion = {
import LanguageVersion._

View File

@ -4,6 +4,7 @@
package com.daml.lf
package transaction
import com.daml.lf.language.LanguageVersion
import com.daml.nameof.NameOf
object Util {
@ -92,7 +93,9 @@ object Util {
version: TransactionVersion,
): Either[String, GlobalKeyWithMaintainers] =
normalizeValue(key.globalKey.key, version).map(normalized =>
key.copy(globalKey = GlobalKey.assertBuild(key.globalKey.templateId, normalized))
key.copy(globalKey =
GlobalKey.assertBuild(key.globalKey.templateId, normalized, Util.sharedKey(version))
)
)
def normalizeOptKey(
@ -104,4 +107,18 @@ object Util {
case None => Right(None)
}
def sharedKey(version: TransactionVersion): Boolean = {
// TODO https://github.com/digital-asset/daml/issues/17732
// Enable shared keys once there is LAPI support via
// version >= TransactionVersion.minSharedKeys
false
}
def sharedKey(version: LanguageVersion): Boolean = {
// TODO https://github.com/digital-asset/daml/issues/17732
// Enable shared keys once there is LAPI support via
// version >= LanguageVersion.Features.sharedKeys
false
}
}

View File

@ -655,7 +655,45 @@ class HashSpec extends AnyWordSpec with Matchers {
}
}
private def defRef(module: String = "Module", name: String) =
"Hash.hashContractKey" should {
val templateId = defRef(name = "upgradable")
val nonSharedTrueHash =
Hash.assertFromString("efab35fcbc9e2336fcc63259ba65e6601903be0a373c0b0f4d761872ffb23ded")
"produce backwardly compatible non-shared contract keys" in {
Hash.assertHashContractKey(templateId, ValueTrue) shouldBe nonSharedTrueHash
}
"produce backwardly compatible keys when called with shared=false" in {
Hash.assertHashContractKey(templateId, ValueTrue, shared = false) shouldBe nonSharedTrueHash
}
"produce ignore the packageId when called with shared=true" in {
Hash.assertHashContractKey(
templateId,
ValueTrue,
shared = true,
) should not be nonSharedTrueHash
}
"produce an identical hash to the same template in a different package if shared=true" in {
val h1 = Hash.assertHashContractKey(
templateId.copy(packageId = Ref.PackageId.assertFromString("packageA")),
ValueTrue,
shared = true,
)
val h2 = Hash.assertHashContractKey(
templateId.copy(packageId = Ref.PackageId.assertFromString("packageB")),
ValueTrue,
shared = true,
)
h1 shouldBe h2
}
}
private def defRef(module: String = "Module", name: String): Ref.Identifier =
Ref.Identifier(
packageId0,
Ref.QualifiedName(

View File

@ -48,6 +48,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
val templateId: Ref.TypeConName = "Template:Id"
val choiceId: Ref.ChoiceName = "Choice"
val txVersion: TransactionVersion = TransactionVersion.maxVersion
val sharedKeys: Boolean = Util.sharedKey(txVersion)
val unit: Value = Value.ValueUnit
implicit def contractIdFromInt(coid: Int): ContractId = cid(coid)
@ -66,7 +67,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
templateId: Ref.TypeConName,
key: String,
): GlobalKeyWithMaintainers =
GlobalKeyWithMaintainers.assertBuild(templateId, Value.ValueText(key), aliceS)
GlobalKeyWithMaintainers.assertBuild(templateId, Value.ValueText(key), aliceS, sharedKeys)
private def toOptKeyWithMaintainers(
templateId: Ref.TypeConName,
@ -76,7 +77,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
else Some(toKeyWithMaintainers(templateId, key))
def gkey(key: String): GlobalKey =
GlobalKey.assertBuild(templateId, Value.ValueText(key))
GlobalKey.assertBuild(templateId, Value.ValueText(key), sharedKeys)
def mkCreate(
contractId: ContractId,

View File

@ -708,7 +708,7 @@ class TransactionCoderSpec
minSuccessful(2),
) { (create, time, salt) =>
forAll(
keyWithMaintainersGen(create.templateId),
keyWithMaintainersGen(create.templateId, create.version),
minSuccessful(2),
) { key =>
val normalizedCreate = adjustStakeholders(normalizeCreate(create))
@ -775,7 +775,7 @@ class TransactionCoderSpec
minSuccessful(2),
) { (party, create, time, salt) =>
forAll(
keyWithMaintainersGen(create.templateId),
keyWithMaintainersGen(create.templateId, create.version),
minSuccessful(2),
) { key =>
val normalizedCreate = adjustStakeholders(normalizeCreate(create))
@ -822,7 +822,7 @@ class TransactionCoderSpec
minSuccessful(2),
) { (party, create, time, salt) =>
forAll(
keyWithMaintainersGen(create.templateId),
keyWithMaintainersGen(create.templateId, create.version),
minSuccessful(2),
) { key =>
val normalizedCreate = adjustStakeholders(normalizeCreate(create))
@ -1299,7 +1299,11 @@ class TransactionCoderSpec
version: TransactionVersion,
) =
key.copy(globalKey =
GlobalKey.assertBuild(key.globalKey.templateId, normalize(key.value, version))
GlobalKey.assertBuild(
key.globalKey.templateId,
normalize(key.value, version),
GlobalKey.isShared(key.globalKey),
)
)
private[this] def normalizeContract(contract: Versioned[Value.ContractInstanceWithAgreement]) =

View File

@ -380,7 +380,11 @@ class TransactionSpec
"RolledBackFetchByKey",
"RolledBackSuccessfulLookup",
"RolledBackUnsuccessfulLookup",
).map(s => GlobalKey.assertBuild(create(cid(s)).templateId, V.ValueText(cid(s).coid))).toSet
).map(s => {
val node = create(cid(s))
GlobalKey
.assertBuild(node.templateId, V.ValueText(cid(s).coid), Util.sharedKey(node.version))
}).toSet
builder.build().contractKeys shouldBe expectedResults
}
@ -390,8 +394,9 @@ class TransactionSpec
import Transaction._
val dummyBuilder = new TxBuilder()
val parties = List("Alice")
val useSharedKeys = Util.sharedKey(TransactionVersion.StableVersions.max)
def keyValue(s: String) = V.ValueText(s)
def globalKey(k: String) = GlobalKey.assertBuild("Mod:T", keyValue(k))
def globalKey(k: String) = GlobalKey.assertBuild("Mod:T", keyValue(k), useSharedKeys)
def create(s: V.ContractId, k: String) = dummyBuilder
.create(
id = s,
@ -423,7 +428,9 @@ class TransactionSpec
val builder = new TxBuilder()
val createNode = create(cid("#0"), "k0")
builder.add(createNode)
builder.build().contractKeyInputs shouldBe Right(Map(globalKey("k0") -> KeyCreate))
builder.build().contractKeyInputs shouldBe Right(
Map(globalKey("k0") -> KeyCreate)
)
}
"return Some(_) for fetch and fetch-by-key" in {
val builder = new TxBuilder()
@ -705,6 +712,7 @@ class TransactionSpec
val (cid3, create3) = create(builder, parties, Some("key2"))
val (_, create4) = create(builder, parties, Some("key2"))
val (_, create5) = create(builder, parties, Some("key3"))
val sharedKeys = Util.sharedKey(create0.version)
builder.add(create0)
builder.add(exercise(builder, create0, parties, false))
builder.add(create1)
@ -717,7 +725,8 @@ class TransactionSpec
builder.add(create5, rollback)
builder.add(exercise(builder, create3, parties, true), rollback)
builder.add(create4, rollback)
def key(s: String) = GlobalKey.assertBuild("Mod:T", V.ValueText(s))
def key(s: String) = GlobalKey.assertBuild("Mod:T", V.ValueText(s), sharedKeys)
builder.build().updatedContractKeys shouldBe
Map(key("key0") -> Some(cid0), key("key1") -> None, key("key2") -> Some(cid3))
}

View File

@ -77,12 +77,27 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
private val samValue1: Val = V.ValueUnit
private val samValue2: Val = V.ValueText(samContractId1.coid)
private val samKWM1 =
GlobalKeyWithMaintainers.assertBuild(samTemplateId1, samValue1, samParties1)
private val samKWM2 =
GlobalKeyWithMaintainers.assertBuild(samTemplateId1, samValue1, samParties2)
private val samKWM3 =
GlobalKeyWithMaintainers.assertBuild(samTemplateId2, samValue2, samParties1)
private def samKWM1(version: TransactionVersion) =
GlobalKeyWithMaintainers.assertBuild(
samTemplateId1,
samValue1,
samParties1,
Util.sharedKey(version),
)
private def samKWM2(version: TransactionVersion) =
GlobalKeyWithMaintainers.assertBuild(
samTemplateId1,
samValue1,
samParties2,
Util.sharedKey(version),
)
private def samKWM3(version: TransactionVersion) =
GlobalKeyWithMaintainers.assertBuild(
samTemplateId2,
samValue2,
samParties1,
Util.sharedKey(version),
)
private val samVersion1: TransactionVersion = TransactionVersion.minVersion
private val samVersion2: TransactionVersion = TransactionVersion.maxVersion
@ -90,7 +105,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
private val someCreates: Seq[Node] =
for {
version <- Seq(samVersion1, samVersion2)
key <- Seq(None, Some(samKWM1))
key <- Seq(None, Some(samKWM1(version)))
} yield Node.Create(
coid = samContractId1,
templateId = samTemplateId1,
@ -105,7 +120,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
private val someFetches: Seq[Node] =
for {
version <- Seq(samVersion1, samVersion2)
key <- Seq(None, Some(samKWM2))
key <- Seq(None, Some(samKWM2(version)))
actingParties <- Seq(Set[Party](), Set(samParty1))
} yield Node.Fetch(
coid = samContractId1,
@ -125,14 +140,14 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
} yield Node.LookupByKey(
templateId = samTemplateId1,
result = result,
key = samKWM3,
key = samKWM3(version),
version = version,
)
private val someExercises: Seq[Exe] =
for {
version <- Seq(samVersion1, samVersion2)
key <- Seq(None, Some(samKWM1))
key <- Seq(None, Some(samKWM1(version)))
exerciseResult <- Seq(None, Some(samValue2))
} yield Node.Exercise(
targetCoid = samContractId2,
@ -236,13 +251,16 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
List(samParties1, samParties2, samParties3, samParties4).filter(set => set != xs)
}
private val tweakKeyMaintainers = Tweak[KWM] { case x =>
List(samKWM1, samKWM2, samKWM3).filter(y => x != y)
private def tweakKeyMaintainers(version: TransactionVersion) = Tweak[KWM] { case x =>
List(samKWM1(version), samKWM2(version), samKWM3(version)).filter(y => x != y)
}
private val tweakOptKeyMaintainers = Tweak[OKWM] {
case None => List(Some(samKWM1), Some(samKWM2), Some(samKWM3))
case Some(x) => None :: List(samKWM1, samKWM2, samKWM3).filter(y => x != y).map(Some(_))
private def tweakOptKeyMaintainers(version: TransactionVersion) = Tweak[OKWM] {
case None => List(Some(samKWM1(version)), Some(samKWM2(version)), Some(samKWM3(version)))
case Some(x) =>
None :: List(samKWM1(version), samKWM2(version), samKWM3(version))
.filter(y => x != y)
.map(Some(_))
}
private val tweakOptContractId = Tweak[Option[V.ContractId]] { case x =>
@ -269,10 +287,10 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
private val tweakCreateStakeholders = Tweak[Node] { case nc: Node.Create =>
tweakPartySet.run(nc.stakeholders).map { x => nc.copy(stakeholders = x) }
}
private def tweakCreateKey(tweakOptKeyMaintainers: Tweak[OKWM]) = Tweak[Node] {
case nc: Node.Create =>
tweakOptKeyMaintainers.run(nc.keyOpt).map { x => nc.copy(keyOpt = x) }
}
private def tweakCreateKey(tweakOptKeyMaintainers: TransactionVersion => Tweak[OKWM]) =
Tweak[Node] { case nc: Node.Create =>
tweakOptKeyMaintainers(nc.version).run(nc.keyOpt).map { x => nc.copy(keyOpt = x) }
}
private val tweakCreateVersion = Tweak.single[Node] { case nc: Node.Create =>
nc.copy(version = changeVersion(nc.version))
}
@ -306,10 +324,10 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
private val tweakFetchStakeholders = Tweak[Node] { case nf: Node.Fetch =>
tweakPartySet.run(nf.stakeholders).map { x => nf.copy(stakeholders = x) }
}
private def tweakFetchKey(tweakOptKeyMaintainers: Tweak[OKWM]) = Tweak[Node] {
case nf: Node.Fetch =>
tweakOptKeyMaintainers.run(nf.keyOpt).map { x => nf.copy(keyOpt = x) }
}
private def tweakFetchKey(tweakOptKeyMaintainers: TransactionVersion => Tweak[OKWM]) =
Tweak[Node] { case nf: Node.Fetch =>
tweakOptKeyMaintainers(nf.version).run(nf.keyOpt).map { x => nf.copy(keyOpt = x) }
}
private def tweakFetchByKey(whenVersion: TransactionVersion => Boolean) = Tweak.single[Node] {
case nf: Node.Fetch if whenVersion(nf.version) =>
nf.copy(byKey = changeBoolean(nf.byKey))
@ -336,7 +354,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
nl.copy(templateId = changeTemplateId(nl.templateId))
}
private val tweakLookupKey = Tweak[Node] { case nl: Node.LookupByKey =>
tweakKeyMaintainers.run(nl.key).map { x => nl.copy(key = x) }
tweakKeyMaintainers(nl.version).run(nl.key).map { x => nl.copy(key = x) }
}
private val tweakLookupResult = Tweak[Node] { case nl: Node.LookupByKey =>
tweakOptContractId.run(nl.result).map { x => nl.copy(result = x) }
@ -393,10 +411,10 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
}
}
private def tweakExerciseKey(tweakOptKeyMaintainers: Tweak[OKWM]) = Tweak[Node] {
case ne: Node.Exercise =>
tweakOptKeyMaintainers.run(ne.keyOpt).map { x => ne.copy(keyOpt = x) }
}
private def tweakExerciseKey(tweakOptKeyMaintainers: TransactionVersion => Tweak[OKWM]) =
Tweak[Node] { case ne: Node.Exercise =>
tweakOptKeyMaintainers(ne.version).run(ne.keyOpt).map { x => ne.copy(keyOpt = x) }
}
private def tweakExerciseByKey(whenVersion: TransactionVersion => Boolean) = Tweak.single[Node] {
case ne: Node.Exercise if whenVersion(ne.version) =>
ne.copy(byKey = changeBoolean(ne.byKey))

View File

@ -18,7 +18,7 @@ import com.daml.lf.language.Ast
import com.daml.lf.language.Ast.TTyCon
import com.daml.lf.scenario.{ScenarioLedger, ScenarioRunner}
import com.daml.lf.speedy.Speedy.Machine
import com.daml.lf.speedy.{SValue, TraceLog, WarningLog, SError}
import com.daml.lf.speedy.{SError, SValue, TraceLog, WarningLog}
import com.daml.lf.transaction.{
GlobalKey,
IncompleteTransaction,
@ -237,7 +237,11 @@ class IdeLedgerClient(
}
)
GlobalKey
.build(templateId, keyValue)
.build(
templateId,
keyValue,
compiledPackages.pkgInterface.hasSharedKeys(templateId.packageId),
)
.fold(keyBuilderError(_), Future.successful(_))
.flatMap { gkey =>
ledger.ledgerData.activeKeys.get(gkey) match {

View File

@ -271,6 +271,7 @@ class IdeLedgerClient(
mat: Materializer,
): Future[Option[ScriptLedgerClient.ActiveContract]] = {
val keyValue = key.toUnnormalizedValue
def keyBuilderError(err: crypto.Hash.HashingError): Future[GlobalKey] =
Future.failed(
err match {
@ -284,7 +285,11 @@ class IdeLedgerClient(
}
)
GlobalKey
.build(templateId, keyValue)
.build(
templateId,
keyValue,
compiledPackages.pkgInterface.hasSharedKeys(templateId.packageId),
)
.fold(keyBuilderError(_), Future.successful(_))
.flatMap { gkey =>
ledger.ledgerData.activeKeys.get(gkey) match {
@ -332,8 +337,10 @@ class IdeLedgerClient(
case _: TemplatePreconditionViolated => SubmitError.TemplatePreconditionViolated()
case CreateEmptyContractKeyMaintainers(tid, arg, _) =>
SubmitError.CreateEmptyContractKeyMaintainers(tid, arg)
case FetchEmptyContractKeyMaintainers(tid, keyValue) =>
SubmitError.FetchEmptyContractKeyMaintainers(GlobalKey.assertBuild(tid, keyValue))
case FetchEmptyContractKeyMaintainers(tid, keyValue, sharedKey) =>
SubmitError.FetchEmptyContractKeyMaintainers(
GlobalKey.assertBuild(tid, keyValue, sharedKey)
)
case WronglyTypedContract(cid, exp, act) => SubmitError.WronglyTypedContract(cid, exp, act)
case ContractDoesNotImplementInterface(iid, cid, tid) =>
SubmitError.ContractDoesNotImplementInterface(cid, tid, iid)

View File

@ -10,14 +10,13 @@ import com.daml.lf.data.Ref.{Identifier, Name}
import com.daml.lf.language.{Ast, StablePackagesV2}
import com.daml.lf.speedy.SValue
import com.daml.lf.speedy.SValue._
import com.daml.lf.transaction.{GlobalKey, SharedGlobalKey}
import com.daml.lf.transaction.GlobalKey
import com.daml.lf.value.Value
import com.daml.lf.value.Value.ContractId
import com.daml.nonempty.NonEmpty
import com.daml.platform.participant.util.LfEngineToApi.toApiIdentifier
import com.daml.lf.data.Ref._
import com.daml.lf.data.Time
import com.daml.lf.engine.preprocessing.LossyValueTranslator
import scala.util.control.NoStackTrace
@ -57,31 +56,10 @@ object SubmitError {
damlScriptVariant("SubmitError", name, rank, fields: _*)
}
private def globalKeyToAnyContractKey(env: Env, key: GlobalKey): SValue =
keyToAnyContractKey(env, key.templateId, key.key)
private def sharedKeyToAnyContractKey(env: Env, key: SharedGlobalKey): SValue = {
key.packageId match {
case Some(packageId) =>
keyToAnyContractKey(env, TypeConName(packageId, key.qualifiedName), key.key)
case None => sharedKeyToAnyContractKey(key.key, key.qualifiedName)
}
}
private val sharedKeyPackageId = PackageId.assertFromString("SharedKey")
/** TODO This is a workaround until the type can be established based on the qualified name alone,
* see issue #17646 for details of how this can be done.
*/
private def sharedKeyToAnyContractKey(value: Value, qualifiedName: QualifiedName): SValue = {
val (sValue, ty) = LossyValueTranslator.unsafeTranslate(value)
fromAnyContractKey(AnyContractKey(TypeConName(sharedKeyPackageId, qualifiedName), ty, sValue))
}
private def keyToAnyContractKey(env: Env, templateId: TypeConName, key: Value): SValue = {
val ty = env.lookupKeyTy(templateId).toOption.get
val sValue = env.translateValue(ty, key).toOption.get
fromAnyContractKey(AnyContractKey(templateId, ty, sValue))
def globalKeyToAnyContractKey(env: Env, key: GlobalKey): SValue = {
val ty = env.lookupKeyTy(key.templateId).toOption.get
val sValue = env.translateValue(ty, key.key).toOption.get
fromAnyContractKey(AnyContractKey(key.templateId, ty, sValue))
}
def fromNonEmptySet[A](set: NonEmpty[Seq[A]], conv: A => SValue): SValue = {
@ -198,15 +176,13 @@ object SubmitError {
}
}
final case class ContractKeyNotFound(key: SharedGlobalKey) extends SubmitError {
override def toDamlSubmitError(env: Env): SValue = {
val contractKey = sharedKeyToAnyContractKey(env, key)
final case class ContractKeyNotFound(key: GlobalKey) extends SubmitError {
override def toDamlSubmitError(env: Env): SValue =
SubmitErrorConverters(env).damlScriptError(
"ContractKeyNotFound",
1,
("contractKey", contractKey),
("contractKey", globalKeyToAnyContractKey(env, key)),
)
}
}
final case class AuthorizationError(message: String) extends SubmitError {

View File

@ -4,7 +4,7 @@
package com.daml.lf.engine.script.v2.ledgerinteraction
import com.daml.lf.data.Ref._
import com.daml.lf.transaction.{GlobalKey, SharedGlobalKey, TransactionVersion}
import com.daml.lf.transaction.{GlobalKey, TransactionVersion}
import com.daml.lf.value.Value.ContractId
import com.daml.lf.value.ValueCoder
import com.daml.lf.value.ValueCoder.CidDecoder
@ -86,38 +86,23 @@ object GrpcErrorParser {
}
case "CONTRACT_KEY_NOT_FOUND" =>
caseErr {
case Seq(
(ErrorResource.PackageId, pid),
(ErrorResource.QualifiedName, name),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
) =>
SubmitError.ContractKeyNotFound(
SharedGlobalKey.assertBuild(
Some(PackageId.assertFromString(pid)),
QualifiedName.assertFromString(name),
key,
)
)
case Seq(
(ErrorResource.QualifiedName, name),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
) =>
SubmitError.ContractKeyNotFound(
SharedGlobalKey.assertBuild(None, QualifiedName.assertFromString(name), key)
)
// TODO https://github.com/digital-asset/daml/issues/17661 - this match is only needed for
// temporary backward compatibility with Canton so can soon be removed
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
) =>
val ident = Identifier.assertFromString(tid)
SubmitError.ContractKeyNotFound(
SharedGlobalKey.assertBuild(
Some(ident.packageId),
ident.qualifiedName,
key,
)
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, false)
)
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
(ErrorResource.SharedKey, sharedKeyText),
) =>
SubmitError.ContractKeyNotFound(
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, sharedKeyText.toBoolean)
)
}
case "DAML_AUTHORIZATION_ERROR" => SubmitError.AuthorizationError(message)
@ -130,6 +115,8 @@ object GrpcErrorParser {
}
case "DISCLOSED_CONTRACT_KEY_HASHING_ERROR" =>
caseErr {
// TODO https://github.com/digital-asset/daml/issues/17661 - this match is only needed for
// temporary backward compatibility with Canton so can soon be removed
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractId, cid),
@ -138,18 +125,47 @@ object GrpcErrorParser {
) =>
SubmitError.DisclosedContractKeyHashingError(
ContractId.assertFromString(cid),
GlobalKey.assertBuild(Identifier.assertFromString(tid), key),
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, false),
keyHash,
)
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractId, cid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
(ErrorResource.SharedKey, sharedKeyText),
(ErrorResource.ContractKeyHash, keyHash),
) =>
SubmitError.DisclosedContractKeyHashingError(
ContractId.assertFromString(cid),
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, sharedKeyText.toBoolean),
keyHash,
)
}
case "DUPLICATE_CONTRACT_KEY" =>
caseErr {
// TODO https://github.com/digital-asset/daml/issues/17661 - this match is only needed for
// temporary backward compatibility with Canton so can soon be removed
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
) =>
SubmitError.DuplicateContractKey(
Some(GlobalKey.assertBuild(Identifier.assertFromString(tid), key))
Some(GlobalKey.assertBuild(Identifier.assertFromString(tid), key, false))
)
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
(ErrorResource.SharedKey, sharedKeyText),
) =>
SubmitError.DuplicateContractKey(
Some(
GlobalKey.assertBuild(
Identifier.assertFromString(tid),
key,
sharedKeyText.toBoolean,
)
)
)
// TODO[SW] Canton can omit the key, unsure why.
case Seq() => SubmitError.DuplicateContractKey(None)
@ -170,12 +186,24 @@ object GrpcErrorParser {
}
case "INCONSISTENT_CONTRACT_KEY" =>
caseErr {
// TODO https://github.com/digital-asset/daml/issues/17661 - this match is only needed for
// temporary backward compatibility with Canton so can soon be removed
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
) =>
SubmitError.InconsistentContractKey(
GlobalKey.assertBuild(Identifier.assertFromString(tid), key)
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, false)
)
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
(ErrorResource.SharedKey, sharedKeyText),
) =>
SubmitError.InconsistentContractKey(
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, sharedKeyText.toBoolean)
)
}
case "UNHANDLED_EXCEPTION" =>
@ -205,9 +233,10 @@ object GrpcErrorParser {
case Seq(
(ErrorResource.TemplateId, tid),
(ErrorResource.ContractKey, decodeValue.unlift(key)),
(ErrorResource.SharedKey, sharedKeyText),
) =>
SubmitError.FetchEmptyContractKeyMaintainers(
GlobalKey.assertBuild(Identifier.assertFromString(tid), key)
GlobalKey.assertBuild(Identifier.assertFromString(tid), key, sharedKeyText.toBoolean)
)
}
case "WRONGLY_TYPED_CONTRACT" =>

View File

@ -37,5 +37,6 @@ class Daml3ScriptTestRunnerDev extends DamlScriptTestRunner {
|Daml3ScriptTrySubmit:wronglyTypedContract SUCCESS
|""".stripMargin,
)
}
}

View File

@ -21,6 +21,7 @@ object ErrorResource {
ContractId,
ContractIds,
ContractKey,
SharedKey,
ContractKeyHash,
DalfPackage,
DevErrorType,
@ -33,8 +34,6 @@ object ErrorResource {
Parties,
Party,
TemplateId,
PackageId,
QualifiedName,
TransactionId,
User,
)
@ -50,6 +49,9 @@ object ErrorResource {
object ContractKey extends ErrorResource {
def asString: String = "CONTRACT_KEY"
}
object SharedKey extends ErrorResource {
def asString: String = "SHARED_KEY"
}
object ContractArg extends ErrorResource {
def asString: String = "CONTRACT_ARG"
}
@ -62,12 +64,6 @@ object ErrorResource {
object TemplateId extends ErrorResource {
def asString: String = "TEMPLATE_ID"
}
object PackageId extends ErrorResource {
def asString: String = "PACKAGE_ID"
}
object QualifiedName extends ErrorResource {
def asString: String = "QUALIFIED_NAME"
}
object InterfaceId extends ErrorResource {
def asString: String = "INTERFACE_ID"
}

View File

@ -3,7 +3,7 @@
package com.daml.error.definitions.groups
import com.daml.error.definitions.LedgerApiErrors
import com.daml.error.definitions.{LedgerApiErrors}
import com.daml.error.{
ContextualizedErrorLogger,
DamlErrorWithDefiniteAnswer,
@ -18,7 +18,7 @@ import com.daml.lf.data.Ref.Identifier
import com.daml.lf.engine.{Error => LfError}
import com.daml.lf.interpretation.{Error => LfInterpretationError}
import com.daml.lf.language.Ast
import com.daml.lf.transaction.{SharedGlobalKey, TransactionVersion}
import com.daml.lf.transaction.{GlobalKey, TransactionVersion}
import com.daml.lf.value.ValueCoder.CidEncoder
import com.daml.lf.value.{Value, ValueCoder}
@ -111,7 +111,7 @@ object CommandExecution extends ErrorGroup()(LedgerApiErrors.errorClass) {
final case class Reject(
override val cause: String,
key: SharedGlobalKey,
key: GlobalKey,
)(implicit
loggingContext: ContextualizedErrorLogger
) extends DamlErrorWithDefiniteAnswer(
@ -119,13 +119,11 @@ object CommandExecution extends ErrorGroup()(LedgerApiErrors.errorClass) {
) {
override def resources: Seq[(ErrorResource, String)] =
withEncodedValue(key.key) { encodedKey =>
key.packageId.fold[Seq[(ErrorResource, String)]](Seq.empty)(p =>
Seq((ErrorResource.PackageId, p))
) ++
Seq(
(ErrorResource.QualifiedName, key.qualifiedName.toString),
(ErrorResource.ContractKey, encodedKey),
)
Seq(
(ErrorResource.TemplateId, key.templateId.toString),
(ErrorResource.ContractKey, encodedKey),
(ErrorResource.SharedKey, GlobalKey.isShared(key).toString),
)
}
}
}
@ -175,6 +173,7 @@ object CommandExecution extends ErrorGroup()(LedgerApiErrors.errorClass) {
(ErrorResource.TemplateId, err.key.templateId.toString),
(ErrorResource.ContractId, err.coid.coid),
(ErrorResource.ContractKey, encodedKey),
(ErrorResource.SharedKey, GlobalKey.isShared(err.key).toString),
(ErrorResource.ContractKeyHash, err.declaredHash.toString),
)
}
@ -299,6 +298,7 @@ object CommandExecution extends ErrorGroup()(LedgerApiErrors.errorClass) {
Seq(
(ErrorResource.TemplateId, err.templateId.toString),
(ErrorResource.ContractKey, encodedKey),
(ErrorResource.SharedKey, err.shared.toString),
)
}
}

View File

@ -2,24 +2,24 @@
## Authorization:
- auth and auth-* should not be set together for the trigger service: [CliConfigTest.scala](triggers/service/src/test-suite/scala/com/daml/lf/engine/trigger/CliConfigTest.scala#L40)
- badly-authorized create is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L70)
- badly-authorized exercise is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L171)
- badly-authorized create is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L76)
- badly-authorized exercise is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L177)
- badly-authorized exercise/create (create is unauthorized) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L265)
- badly-authorized exercise/create (exercise is unauthorized) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L233)
- badly-authorized exercise/exercise (no implicit authority from outer exercise) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L324)
- badly-authorized fetch is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L105)
- badly-authorized lookup is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L128)
- create with no signatories is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L60)
- create with non-signatory maintainers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L82)
- badly-authorized fetch is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L111)
- badly-authorized lookup is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L134)
- create with no signatories is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L66)
- create with non-signatory maintainers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L88)
- error on specifying both authCommonUri and authInternalUri/authExternalUri for the trigger service: [AuthorizationConfigTest.scala](triggers/service/src/test-suite/scala/com/daml/lf/engine/trigger/AuthorizationConfigTest.scala#L24)
- error on specifying only authInternalUri and no authExternalUri for the trigger service: [AuthorizationConfigTest.scala](triggers/service/src/test-suite/scala/com/daml/lf/engine/trigger/AuthorizationConfigTest.scala#L52)
- exercise with no controllers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L161)
- well-authorized create is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L53)
- well-authorized exercise is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L154)
- exercise with no controllers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L167)
- well-authorized create is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L59)
- well-authorized exercise is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L160)
- well-authorized exercise/create is accepted: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L211)
- well-authorized exercise/exercise is accepted: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L367)
- well-authorized fetch is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L99)
- well-authorized lookup is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L121)
- well-authorized fetch is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L105)
- well-authorized lookup is accepted: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L127)
## Availability:
- Tail call optimization: Tail recursion does not blow the scala JVM stack.: [TailCallTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/TailCallTest.scala#L20)
@ -35,133 +35,133 @@
- ensure correct privacy for rollback subtree: [BlindingSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/BlindingSpec.scala#L224)
## Integrity:
- Evaluation order of create with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L580)
- Evaluation order of create with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L603)
- Evaluation order of create with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L656)
- Evaluation order of create with create argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L630)
- Evaluation order of create with duplicate contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L529)
- Evaluation order of create with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L554)
- Evaluation order of create with failed precondition: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L511)
- Evaluation order of create_interface with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L782)
- Evaluation order of create_interface with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L805)
- Evaluation order of create_interface with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L858)
- Evaluation order of create_interface with create argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L832)
- Evaluation order of create_interface with duplicate contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L731)
- 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#L756)
- Evaluation order of create_interface with failed precondition: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L711)
- 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#L1829)
- 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#L1811)
- 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#L1871)
- 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#L1177)
- 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#L932)
- Evaluation order of exercise of a non-cached global contract with inconsistent key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L958)
- 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#L1034)
- Evaluation order of exercise of a wrongly typed non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L917)
- Evaluation order of exercise of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1016)
- Evaluation order of exercise of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1118)
- Evaluation order of exercise of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1202)
- Evaluation order of exercise of an wrongly typed local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1138)
- 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#L1070)
- Evaluation order of exercise with argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1216)
- Evaluation order of exercise with output exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1244)
- Evaluation order of exercise-by-key of a cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1469)
- Evaluation order of exercise-by-key of a non-cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1349)
- 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#L1537)
- Evaluation order of exercise_by_key of a local contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1561)
- 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#L1322)
- 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#L1425)
- 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#L1406)
- 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#L1517)
- 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#L1596)
- 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#L1444)
- 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#L1611)
- 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#L1684)
- 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#L1640)
- 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#L1986)
- 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#L1755)
- 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#L1922)
- 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#L1941)
- 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#L1670)
- 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#L2274)
- 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#L2064)
- Evaluation order of fetch of a non-cached global contract with inconsistent key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2087)
- 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#L2152)
- Evaluation order of fetch of a wrongly typed disclosed contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2294)
- 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#L2049)
- Evaluation order of fetch of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2135)
- Evaluation order of fetch of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2221)
- Evaluation order of fetch of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2313)
- 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#L2239)
- 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#L2186)
- Evaluation order of fetch-by-key of a cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2484)
- Evaluation order of fetch-by-key of a non-cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2400)
- 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#L2467)
- 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#L2543)
- 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#L2377)
- 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#L2448)
- 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#L2525)
- 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#L2572)
- 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#L2602)
- 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#L2616)
- 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#L2588)
- 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#L2741)
- 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#L2869)
- 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#L2661)
- 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#L2680)
- 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#L2724)
- 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#L2814)
- 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#L2831)
- Evaluation order of fetch_interface of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2887)
- 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#L2779)
- Evaluation order of lookup of a cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L3037)
- Evaluation order of lookup of a non-cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2954)
- 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#L3020)
- 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#L3111)
- 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#L3095)
- 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#L2931)
- 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#L3002)
- 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#L3078)
- 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#L3141)
- 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#L3171)
- 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#L3185)
- 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#L3157)
- Evaluation order of successful create: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L487)
- Evaluation order of successful create_interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L686)
- 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#L1709)
- 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#L992)
- Evaluation order of successful exercise of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1095)
- 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#L890)
- 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#L1380)
- 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#L1493)
- 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#L1278)
- 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#L1786)
- 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#L1898)
- 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#L2118)
- Evaluation order of successful fetch of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2206)
- 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#L2026)
- 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#L2431)
- 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#L2509)
- 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#L2332)
- 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#L2707)
- 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#L2799)
- 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#L2637)
- 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#L2985)
- 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#L3062)
- 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#L2907)
- Evaluation order of create with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L587)
- Evaluation order of create with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L610)
- Evaluation order of create with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L663)
- Evaluation order of create with create argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L637)
- Evaluation order of create with duplicate contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L536)
- Evaluation order of create with empty contract key maintainers: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L561)
- Evaluation order of create with failed precondition: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L518)
- Evaluation order of create_interface with authorization failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L789)
- Evaluation order of create_interface with contract ID in contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L812)
- Evaluation order of create_interface with contract key exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L865)
- Evaluation order of create_interface with create argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L839)
- Evaluation order of create_interface with duplicate contract key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L738)
- 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#L763)
- Evaluation order of create_interface with failed precondition: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L718)
- 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#L1838)
- 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#L1820)
- 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#L1880)
- 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#L1184)
- 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#L939)
- Evaluation order of exercise of a non-cached global contract with inconsistent key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L965)
- 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#L1041)
- Evaluation order of exercise of a wrongly typed non-cached global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L924)
- Evaluation order of exercise of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1023)
- Evaluation order of exercise of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1125)
- Evaluation order of exercise of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1209)
- Evaluation order of exercise of an wrongly typed local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1145)
- 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#L1077)
- Evaluation order of exercise with argument exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1223)
- Evaluation order of exercise with output exceeding max nesting: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1251)
- Evaluation order of exercise-by-key of a cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1476)
- Evaluation order of exercise-by-key of a non-cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1356)
- 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#L1544)
- Evaluation order of exercise_by_key of a local contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1568)
- 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#L1329)
- 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#L1432)
- 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#L1413)
- 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#L1524)
- 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#L1603)
- 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#L1451)
- 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#L1618)
- 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#L1693)
- 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#L1647)
- 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#L1995)
- 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#L1764)
- 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#L1931)
- 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#L1950)
- 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#L1677)
- 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#L2283)
- 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#L2073)
- Evaluation order of fetch of a non-cached global contract with inconsistent key: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2096)
- 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#L2161)
- Evaluation order of fetch of a wrongly typed disclosed contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2303)
- 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#L2058)
- Evaluation order of fetch of an inactive global contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2144)
- Evaluation order of fetch of an inactive local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2230)
- Evaluation order of fetch of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2322)
- 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#L2248)
- 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#L2195)
- Evaluation order of fetch-by-key of a cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2493)
- Evaluation order of fetch-by-key of a non-cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2409)
- 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#L2476)
- 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#L2552)
- 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#L2386)
- 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#L2457)
- 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#L2534)
- 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#L2581)
- 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#L2613)
- 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#L2627)
- 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#L2597)
- 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#L2752)
- 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#L2880)
- 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#L2672)
- 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#L2691)
- 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#L2735)
- 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#L2825)
- 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#L2842)
- Evaluation order of fetch_interface of an unknown contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2898)
- 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#L2790)
- Evaluation order of lookup of a cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L3048)
- Evaluation order of lookup of a non-cached global contract with visibility failure: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2965)
- 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#L3031)
- 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#L3122)
- 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#L3106)
- 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#L2942)
- 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#L3013)
- 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#L3089)
- 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#L3152)
- 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#L3184)
- 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#L3198)
- 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#L3168)
- Evaluation order of successful create: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L494)
- Evaluation order of successful create_interface: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L693)
- 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#L1718)
- 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#L999)
- Evaluation order of successful exercise of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L1102)
- 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#L1387)
- 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#L1500)
- 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#L1285)
- 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#L1795)
- 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#L1907)
- 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#L2127)
- Evaluation order of successful fetch of a local contract: [EvaluationOrderTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/EvaluationOrderTest.scala#L2215)
- 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#L2035)
- 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#L2440)
- 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#L2518)
- 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#L2341)
- 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#L2718)
- 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#L2810)
- 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#L2648)
- 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#L2996)
- 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#L3073)
- 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#L2918)
- Exceptions, throw/catch.: [ExceptionTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/ExceptionTest.scala#L30)
- Rollback creates cannot be exercise: [EngineTest.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala#L2092)
- 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#L1966)
- 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#L1853)
- 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#L2851)
- contract key behaviour (non-unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L402)
- contract key behaviour (unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L412)
- 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#L218)
- contract keys should be evaluated after ensure clause: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L186)
- contract keys should be evaluated only when executing create: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L147)
- Rollback creates cannot be exercise: [EngineTest.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala#L2103)
- 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#L1975)
- 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#L1862)
- 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#L2862)
- contract key behaviour (non-unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L408)
- contract key behaviour (unique mode): [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L418)
- 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#L224)
- contract keys should be evaluated after ensure clause: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L192)
- contract keys should be evaluated only when executing create: [ContractKeySpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractKeySpec.scala#L153)
- ensure builtin operators have the correct type: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L66)
- ensure expression forms have the correct type: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L126)
- exercise-by-interface command is rejected for a: [ApiCommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ApiCommandPreprocessorSpec.scala#L186)
- 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#L1737)
- 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#L1746)
- ill-formed create API command is rejected: [ApiCommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ApiCommandPreprocessorSpec.scala#L174)
- ill-formed create replay command is rejected: [ReplayCommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ReplayCommandPreprocessorSpec.scala#L124)
- ill-formed create-and-exercise API command is rejected: [ApiCommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ApiCommandPreprocessorSpec.scala#L199)