From 9f23bf39a811ab3fd7e2286673e4e8c32fcf9cdb Mon Sep 17 00:00:00 2001 From: Remy Haemmerle Date: Thu, 19 Aug 2021 12:35:52 +0200 Subject: [PATCH] LF: Drop contract ID Freshness check As stated in #10504 the contract ID freshness check cannot be implemented correctly in general. This PR drops the support for this (buggy) check. This corresponds to the fist task of #10504. CHANGELOG_BEGIN CHANGELOG_END --- .../digitalasset/daml/lf/engine/Engine.scala | 15 +- .../digitalasset/daml/lf/engine/Error.scala | 8 - .../preprocessing/CommandPreprocessor.scala | 77 ++-- .../engine/preprocessing/Preprocessor.scala | 8 +- .../TransactionPreprocessor.scala | 43 +- .../preprocessing/ValueTranslator.scala | 9 +- ...tractDiscriminatorFreshnessCheckSpec.scala | 373 ------------------ .../daml/lf/engine/EngineTest.scala | 45 +-- .../daml/lf/speedy/SBuiltin.scala | 31 +- .../digitalasset/daml/lf/speedy/Speedy.scala | 35 +- .../digitalasset/daml/lf/ScenarioRunner.scala | 1 - .../speedy/MachineImportValueBenchmark.scala | 1 - 12 files changed, 70 insertions(+), 576 deletions(-) delete mode 100644 daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractDiscriminatorFreshnessCheckSpec.scala diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Engine.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Engine.scala index d97dd8084183..ae37e4046987 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Engine.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Engine.scala @@ -96,7 +96,7 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV val submissionTime = cmds.ledgerEffectiveTime preprocessor .preprocessCommands(cmds.commands) - .flatMap { case (processedCmds, globalCids) => + .flatMap { processedCmds => interpretCommands( validating = false, submitters = submitters, @@ -105,7 +105,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerTime = cmds.ledgerEffectiveTime, submissionTime = submissionTime, seeding = Engine.initialSeeding(submissionSeed, participantId, submissionTime), - globalCids, ) map { case (tx, meta) => // Annotate the transaction with the package dependencies. Since // all commands are actions on a contract template, with a fully typed @@ -146,8 +145,7 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerEffectiveTime: Time.Timestamp, ): Result[(SubmittedTransaction, Tx.Metadata)] = for { - commandWithCids <- preprocessor.preprocessCommand(command) - (speedyCommand, globalCids) = commandWithCids + speedyCommand <- preprocessor.preprocessCommand(command) sexpr = compiledPackages.compiler.unsafeCompileForReinterpretation(speedyCommand) // reinterpret is never used for submission, only for validation. result <- interpretExpression( @@ -158,7 +156,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerTime = ledgerEffectiveTime, submissionTime = submissionTime, seeding = InitialSeeding.RootNodeSeeds(ImmArray(nodeSeed)), - globalCids = globalCids, ) (tx, meta) = result } yield (tx, meta) @@ -172,8 +169,7 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV submissionSeed: crypto.Hash, ): Result[(SubmittedTransaction, Tx.Metadata)] = for { - commandsWithCids <- preprocessor.translateTransactionRoots(tx.transaction) - (commands, globalCids) = commandsWithCids + commands <- preprocessor.translateTransactionRoots(tx.transaction) result <- interpretCommands( validating = true, submitters = submitters, @@ -182,7 +178,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerTime = ledgerEffectiveTime, submissionTime = submissionTime, seeding = Engine.initialSeeding(submissionSeed, participantId, submissionTime), - globalCids, ) } yield result @@ -273,7 +268,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerTime: Time.Timestamp, submissionTime: Time.Timestamp, seeding: speedy.InitialSeeding, - globalCids: Set[Value.ContractId], ): Result[(SubmittedTransaction, Tx.Metadata)] = { val sexpr = compiledPackages.compiler.unsafeCompile(commands) interpretExpression( @@ -284,7 +278,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerTime, submissionTime, seeding, - globalCids, ) } @@ -304,7 +297,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV ledgerTime: Time.Timestamp, submissionTime: Time.Timestamp, seeding: speedy.InitialSeeding, - globalCids: Set[Value.ContractId], ): Result[(SubmittedTransaction, Tx.Metadata)] = runSafely(NameOf.qualifiedNameOfCurrentFunc) { val machine = Machine( @@ -312,7 +304,6 @@ class Engine(val config: EngineConfig = new EngineConfig(LanguageVersion.StableV submissionTime = submissionTime, initialSeeding = seeding, expr = SExpr.SEApp(sexpr, Array(SExpr.SEValue.Token)), - globalCids = globalCids, committers = submitters, readAs = readAs, validating = validating, diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Error.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Error.scala index 38a1409e9466..f8a3166eddc5 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Error.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/Error.scala @@ -107,14 +107,6 @@ object Error { final case class RootNode(nodeId: NodeId, override val message: String) extends Error - final case class ContractIdFreshness( - localContractIds: Set[Value.ContractId], - globalContractIds: Set[Value.ContractId], - ) extends Error { - assert(localContractIds exists globalContractIds) - def message: String = "Conflicting discriminators between a global and local contract ID." - } - } // Error happening during interpretation diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/CommandPreprocessor.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/CommandPreprocessor.scala index aa5fdde46576..8060fd0ae8e4 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/CommandPreprocessor.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/CommandPreprocessor.scala @@ -9,7 +9,6 @@ import com.daml.lf.data._ import com.daml.lf.language.Ast import com.daml.lf.speedy.SValue import com.daml.lf.value.Value -import com.daml.nameof.NameOf import scala.annotation.tailrec @@ -24,9 +23,9 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) def unsafePreprocessCreate( templateId: Ref.Identifier, argument: Value[Value.ContractId], - ): (speedy.Command.Create, Set[Value.ContractId]) = { - val (arg, argCids) = valueTranslator.unsafeTranslateValue(Ast.TTyCon(templateId), argument) - speedy.Command.Create(templateId, arg) -> argCids + ): speedy.Command.Create = { + val arg = valueTranslator.unsafeTranslateValue(Ast.TTyCon(templateId), argument) + speedy.Command.Create(templateId, arg) } @throws[Error.Preprocessing.Error] @@ -35,11 +34,10 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) contractId: Value.ContractId, choiceId: Ref.ChoiceName, argument: Value[Value.ContractId], - ): (speedy.Command.Exercise, Set[Value.ContractId]) = { + ): speedy.Command.Exercise = { val choice = handleLookup(interface.lookupChoice(templateId, choiceId)).argBinder._2 - val (arg, argCids) = valueTranslator.unsafeTranslateValue(choice, argument) - val cids = argCids + contractId - speedy.Command.Exercise(templateId, SValue.SContractId(contractId), choiceId, arg) -> cids + val arg = valueTranslator.unsafeTranslateValue(choice, argument) + speedy.Command.Exercise(templateId, SValue.SContractId(contractId), choiceId, arg) } @throws[Error.Preprocessing.Error] @@ -48,20 +46,12 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) contractKey: Value[Value.ContractId], choiceId: Ref.ChoiceName, argument: Value[Value.ContractId], - ): (speedy.Command.ExerciseByKey, Set[Value.ContractId]) = { + ): speedy.Command.ExerciseByKey = { val choiceArgType = handleLookup(interface.lookupChoice(templateId, choiceId)).argBinder._2 val ckTtype = handleLookup(interface.lookupTemplateKey(templateId)).typ - val (arg, argCids) = valueTranslator.unsafeTranslateValue(choiceArgType, argument) - val (key, keyCids) = valueTranslator.unsafeTranslateValue(ckTtype, contractKey) - keyCids.foreach { coid => - // The type checking of contractKey done by unsafeTranslateValue should ensure - // keyCids is empty - throw Error.Preprocessing.Internal( - NameOf.qualifiedNameOfCurrentFunc, - s"Unexpected contract IDs in contract key of $templateId: $coid", - ) - } - speedy.Command.ExerciseByKey(templateId, key, choiceId, arg) -> argCids + val arg = valueTranslator.unsafeTranslateValue(choiceArgType, argument) + val key = valueTranslator.unsafeTranslateValue(ckTtype, contractKey) + speedy.Command.ExerciseByKey(templateId, key, choiceId, arg) } @throws[Error.Preprocessing.Error] @@ -70,11 +60,11 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) createArgument: Value[Value.ContractId], choiceId: Ref.ChoiceName, choiceArgument: Value[Value.ContractId], - ): (speedy.Command.CreateAndExercise, Set[Value.ContractId]) = { - val (createArg, createArgCids) = + ): speedy.Command.CreateAndExercise = { + val createArg = valueTranslator.unsafeTranslateValue(Ast.TTyCon(templateId), createArgument) val choiceArgType = handleLookup(interface.lookupChoice(templateId, choiceId)).argBinder._2 - val (choiceArg, choiceArgCids) = + val choiceArg = valueTranslator.unsafeTranslateValue(choiceArgType, choiceArgument) speedy.Command .CreateAndExercise( @@ -82,7 +72,7 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) createArg, choiceId, choiceArg, - ) -> (createArgCids | choiceArgCids) + ) } @throws[Error.Preprocessing.Error] @@ -91,22 +81,14 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) contractKey: Value[Nothing], ): speedy.Command.LookupByKey = { val ckTtype = handleLookup(interface.lookupTemplateKey(templateId)).typ - val (key, keyCids) = valueTranslator.unsafeTranslateValue(ckTtype, contractKey) - keyCids.foreach { coid => - // The type checking of contractKey done by unsafeTranslateValue should ensure - // keyCids is empty - throw Error.Preprocessing.Internal( - NameOf.qualifiedNameOfCurrentFunc, - s"Unexpected contract IDs in contract key of $templateId: $coid", - ) - } + val key = valueTranslator.unsafeTranslateValue(ckTtype, contractKey) speedy.Command.LookupByKey(templateId, key) } // returns the speedy translation of an LF command together with all the contract IDs contains inside. private[preprocessing] def unsafePreprocessCommand( cmd: command.Command - ): (speedy.Command, Set[Value.ContractId]) = { + ): speedy.Command = { cmd match { case command.CreateCommand(templateId, argument) => unsafePreprocessCreate(templateId, argument) @@ -127,41 +109,36 @@ private[lf] final class CommandPreprocessor(compiledPackages: CompiledPackages) choiceArgument, ) case command.FetchCommand(templateId, coid) => - (speedy.Command.Fetch(templateId, SValue.SContractId(coid)), Set(coid)) + speedy.Command.Fetch(templateId, SValue.SContractId(coid)) case command.FetchByKeyCommand(templateId, key) => val ckTtype = handleLookup(interface.lookupTemplateKey(templateId)).typ - val (sKey, cids) = valueTranslator.unsafeTranslateValue(ckTtype, key) - assert(cids.isEmpty) - (speedy.Command.FetchByKey(templateId, sKey), Set.empty) + val sKey = valueTranslator.unsafeTranslateValue(ckTtype, key) + speedy.Command.FetchByKey(templateId, sKey) case command.LookupByKeyCommand(templateId, key) => val ckTtype = handleLookup(interface.lookupTemplateKey(templateId)).typ - val (sKey, cids) = valueTranslator.unsafeTranslateValue(ckTtype, key) - assert(cids.isEmpty) - (speedy.Command.LookupByKey(templateId, sKey), Set.empty) + val sKey = valueTranslator.unsafeTranslateValue(ckTtype, key) + speedy.Command.LookupByKey(templateId, sKey) } } @throws[Error.Preprocessing.Error] - def unsafePreprocessCommands( - cmds: ImmArray[command.ApiCommand] - ): (ImmArray[speedy.Command], Set[Value.ContractId]) = { + def unsafePreprocessCommands(cmds: ImmArray[command.ApiCommand]): ImmArray[speedy.Command] = { @tailrec def go( toProcess: FrontStack[command.ApiCommand], processed: BackStack[speedy.Command], - acc: Set[Value.ContractId], - ): (ImmArray[speedy.Command], Set[Value.ContractId]) = { + ): ImmArray[speedy.Command] = { toProcess match { case FrontStackCons(cmd, rest) => - val (speedyCmd, newCids) = unsafePreprocessCommand(cmd) - go(rest, processed :+ speedyCmd, acc | newCids) + val speedyCmd = unsafePreprocessCommand(cmd) + go(rest, processed :+ speedyCmd) case FrontStack() => - (processed.toImmArray, acc) + processed.toImmArray } } - go(FrontStack(cmds), BackStack.empty, Set.empty) + go(FrontStack(cmds), BackStack.empty) } } diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/Preprocessor.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/Preprocessor.scala index 87afe5bd70a2..5051d7bdfb2c 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/Preprocessor.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/Preprocessor.scala @@ -128,11 +128,11 @@ private[engine] final class Preprocessor(compiledPackages: MutableCompiledPackag def translateValue(ty0: Ast.Type, v0: Value[Value.ContractId]): Result[SValue] = safelyRun(getDependencies(List(ty0), List.empty)) { unsafeTranslateValue(ty0, v0) - }.map(_._1) + } private[engine] def preprocessCommand( cmd: command.Command - ): Result[(speedy.Command, Set[Value.ContractId])] = + ): Result[speedy.Command] = safelyRun(getDependencies(List.empty, List(cmd.templateId))) { unsafePreprocessCommand(cmd) } @@ -141,14 +141,14 @@ private[engine] final class Preprocessor(compiledPackages: MutableCompiledPackag */ def preprocessCommands( cmds: data.ImmArray[command.ApiCommand] - ): Result[(ImmArray[speedy.Command], Set[Value.ContractId])] = + ): Result[ImmArray[speedy.Command]] = safelyRun(getDependencies(List.empty, cmds.map(_.templateId).toList)) { unsafePreprocessCommands(cmds) } def translateTransactionRoots[Cid <: Value.ContractId]( tx: GenTransaction[NodeId, Cid] - ): Result[(ImmArray[speedy.Command], Set[Value.ContractId])] = + ): Result[ImmArray[speedy.Command]] = safelyRun( getDependencies(List.empty, tx.rootNodes.toList.map(_.templateId)) ) { diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/TransactionPreprocessor.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/TransactionPreprocessor.scala index 1c518f74b311..ddd82a6a9a41 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/TransactionPreprocessor.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/TransactionPreprocessor.scala @@ -8,7 +8,6 @@ package preprocessing import com.daml.lf.data.{BackStack, ImmArray} import com.daml.lf.transaction.{GenTransaction, Node, NodeId} import com.daml.lf.value.Value -import com.daml.lf.value.Value.ContractId private[preprocessing] final class TransactionPreprocessor( compiledPackages: MutableCompiledPackages @@ -16,23 +15,6 @@ private[preprocessing] final class TransactionPreprocessor( val commandPreprocessor = new CommandPreprocessor(compiledPackages) - // Accumulator used by unsafeTranslateTransactionRoots method. - private[this] case class Acc( - globalCids: Set[ContractId], - localCids: Set[ContractId], - commands: BackStack[speedy.Command], - ) { - def update( - newInputCids: Iterable[ContractId], - newLocalCids: Iterable[ContractId], - cmd: speedy.Command, - ) = Acc( - globalCids ++ newInputCids.filterNot(localCids), - localCids ++ newLocalCids, - commands :+ cmd, - ) - } - private[this] def invalidRootNode(nodeId: NodeId, message: String) = throw Error.Preprocessing.RootNode(nodeId, message) @@ -85,18 +67,17 @@ private[preprocessing] final class TransactionPreprocessor( @throws[Error.Preprocessing.Error] def unsafeTranslateTransactionRoots[Cid <: Value.ContractId]( tx: GenTransaction[NodeId, Cid] - ): (ImmArray[speedy.Command], Set[ContractId]) = { + ): ImmArray[speedy.Command] = { - val result = tx.roots.foldLeft(Acc(Set.empty, Set.empty, BackStack.empty)) { (acc, id) => + val result = tx.roots.foldLeft(BackStack.empty[speedy.Command]) { (acc, id) => tx.nodes.get(id) match { case Some(node: Node.GenActionNode[_, Cid]) => node match { case create: Node.NodeCreate[Cid] => - val (cmd, newCids) = - commandPreprocessor.unsafePreprocessCreate(create.templateId, create.arg) - acc.update(newCids, List(create.coid), cmd) + val cmd = commandPreprocessor.unsafePreprocessCreate(create.templateId, create.arg) + acc :+ cmd case exe: Node.NodeExercises[_, Cid] => - val (cmd, newCids) = exe.key match { + val cmd = exe.key match { case Some(key) if exe.byKey => commandPreprocessor.unsafePreprocessExerciseByKey( exe.templateId, @@ -112,8 +93,7 @@ private[preprocessing] final class TransactionPreprocessor( exe.chosenValue, ) } - val newLocalCids = GenTransaction(tx.nodes, ImmArray(id)).localContracts.keys - acc.update(newCids, newLocalCids, cmd) + acc :+ cmd case _: Node.NodeFetch[_] => invalidRootNode(id, s"Transaction contains a fetch root node $id") case _: Node.NodeLookupByKey[_] => @@ -126,16 +106,7 @@ private[preprocessing] final class TransactionPreprocessor( } } - // The following check ensures that `localCids ∩ globalCids = ∅`. - // It is probably not 100% necessary, as the reinterpretation should catch the cases where it is not true. - // We still prefer to perform the check here as: - // - it is cheap, - // - it catches obviously buggy transaction, - // - it is easier to reason about "soundness" of preprocessing under the disjointness assumption. - if (result.localCids exists result.globalCids) - throw Error.Preprocessing.ContractIdFreshness(result.localCids, result.globalCids) - - result.commands.toImmArray -> result.globalCids + result.toImmArray } } diff --git a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/ValueTranslator.scala b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/ValueTranslator.scala index d592d9252f3c..1742745fb7a2 100644 --- a/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/ValueTranslator.scala +++ b/daml-lf/engine/src/main/scala/com/digitalasset/daml/lf/engine/preprocessing/ValueTranslator.scala @@ -44,9 +44,7 @@ private[engine] final class ValueTranslator(interface: language.Interface) { private[preprocessing] def unsafeTranslateValue( ty: Type, value: Value[ContractId], - ): (SValue, Set[Value.ContractId]) = { - - val cids = Set.newBuilder[Value.ContractId] + ): SValue = { def go(ty0: Type, value0: Value[ContractId], nesting: Int = 0): SValue = if (nesting > Value.MAXIMUM_NESTING) { @@ -91,7 +89,6 @@ private[engine] final class ValueTranslator(interface: language.Interface) { typeError() } case (BTContractId, ValueContractId(c)) => - cids += c SValue.SContractId(c) case (BTOptional, ValueOptional(mbValue)) => mbValue match { @@ -224,7 +221,7 @@ private[engine] final class ValueTranslator(interface: language.Interface) { } } - go(ty, value) -> cids.result() + go(ty, value) } // This does not try to pull missing packages, return an error instead. @@ -232,6 +229,6 @@ private[engine] final class ValueTranslator(interface: language.Interface) { ty: Type, value: Value[ContractId], ): Either[Error.Preprocessing.Error, SValue] = - safelyRun(unsafeTranslateValue(ty, value)._1) + safelyRun(unsafeTranslateValue(ty, value)) } diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractDiscriminatorFreshnessCheckSpec.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractDiscriminatorFreshnessCheckSpec.scala deleted file mode 100644 index 632ae717959a..000000000000 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ContractDiscriminatorFreshnessCheckSpec.scala +++ /dev/null @@ -1,373 +0,0 @@ -// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.daml.lf -package engine - -import com.daml.lf.data._ -import com.daml.lf.testing.parser.Implicits._ -import com.daml.lf.transaction.{GenTransaction, GlobalKey, Node, NodeId} -import com.daml.lf.transaction.test.TransactionBuilder -import com.daml.lf.value.Value -import com.daml.lf.value.Value.ContractId -import org.scalatest.Inside.inside -import org.scalatest.prop.TableDrivenPropertyChecks -import org.scalatest.matchers.should.Matchers -import org.scalatest.wordspec.AnyWordSpec - -import scala.language.implicitConversions - -class ContractDiscriminatorFreshnessCheckSpec - extends AnyWordSpec - with Matchers - with TableDrivenPropertyChecks { - - private val pkg = p""" - module Mod { - record @serializable Key = { - party: Party, - idx: Int64 - }; - - record @serializable Contract = { - key: Mod:Key, - cids: List (ContractId Mod:Contract) - }; - - val @noPartyLiterals keyParties: (Mod:Key -> List Party) = - \(key: Mod:Key) -> - Cons @Party [Mod:Key {party} key] (Nil @Party); - - val @noPartyLiterals contractParties : (Mod:Contract -> List Party) = - \(contract: Mod:Contract) -> - Mod:keyParties (Mod:Contract {key} contract); - - template (this : Contract) = { - precondition True, - signatories Mod:contractParties this, - observers Mod:contractParties this, - agreement "Agreement", - choices { - choice @nonConsuming Noop (self) (u: Unit) : Unit, - controllers - Mod:contractParties this - to - upure @Unit (), - choice @nonConsuming Identity (self) (cid: ContractId Mod:Contract) : ContractId Mod:Contract, - controllers - Mod:contractParties this - to - upure @(ContractId Mod:Contract) cid, - choice @nonConsuming LookupByKey (self) (key: Mod:Key) : Option (ContractId Mod:Contract), - controllers - Mod:contractParties this - to - lookup_by_key @Mod:Contract key, - choice @nonConsuming Create (self) (contract: Mod:Contract): (ContractId Mod:Contract), - controllers - Mod:contractParties this - to - create @Mod:Contract contract - }, - key @Mod:Key (Mod:Contract {key} this) Mod:keyParties - }; - } - """ - private val pkgId = defaultParserParameters.defaultPackageId - private val pkgs = Map(pkgId -> pkg).lift - - private val keyId = Ref.Identifier(pkgId, Ref.QualifiedName.assertFromString("Mod:Key")) - private val tmplId = Ref.Identifier(pkgId, Ref.QualifiedName.assertFromString("Mod:Contract")) - - private def contractId(discriminator: crypto.Hash, suffix: Bytes): Value.ContractId = - Value.ContractId.V1.assertBuild(discriminator, suffix) - - private def keyRecord(party: Ref.Party, idx: Int) = - Value.ValueRecord( - Some(keyId), - ImmArray( - Some[Ref.Name]("party") -> Value.ValueParty(party), - Some[Ref.Name]("idx") -> Value.ValueInt64(idx.toLong), - ), - ) - - private def contractRecord(party: Ref.Party, idx: Int, cids: List[ContractId]) = - Value.ValueRecord( - Some(tmplId), - ImmArray( - Some[Ref.Name]("key") -> keyRecord(party, idx), - Some[Ref.Name]("cids") -> Value.ValueList(FrontStack(cids.map(Value.ValueContractId(_)))), - ), - ) - - private val hash1 = crypto.Hash.hashPrivateKey("hash1") - private val hash2 = crypto.Hash.hashPrivateKey("hash2") - private val suffix1 = Utf8.getBytes("suffix") - private val suffix2 = Utf8.getBytes("extension") - private val suffix3 = Utf8.getBytes("final-addition") - - private def contractInstance(party: Ref.Party, idx: Int, cids: List[ContractId]) = - Value.ContractInst( - tmplId, - TransactionBuilder.assertAsVersionedValue(contractRecord(party, idx, cids)), - "Agreement", - ) - - private def globalKey(party: Ref.Party, idx: Int) = - GlobalKey(tmplId, keyRecord(party, idx)) - - private val alice = Ref.Party.assertFromString("Alice") - private val participant = Ref.ParticipantId.assertFromString("participant") - - private val submissionSeed = crypto.Hash.hashPrivateKey(getClass.getName) - private val let = Time.Timestamp.MinValue - private val transactionSeed = crypto.Hash.deriveTransactionSeed( - submissionSeed, - participant, - let, - ) - - private def submit( - cmds: ImmArray[command.ApiCommand], - pcs: Value.ContractId => Option[Value.ContractInst[Value.VersionedValue[ContractId]]], - keys: GlobalKey => Option[ContractId], - ) = - engine - .submit( - submitters = Set(alice), - readAs = Set.empty, - cmds = command.Commands( - commands = cmds, - ledgerEffectiveTime = let, - commandsReference = "test", - ), - participantId = participant, - submissionSeed = submissionSeed, - ) - .consume( - pcs, - pkgs, - keyWithMaintainers => keys(keyWithMaintainers.globalKey), - ) - - val engine = Engine.DevEngine() - - "conflict freshness check" should { - - "fails when a global contract conflicts with a local contract previously created" ignore { - - val conflictingCid = { - val createNodeSeed = crypto.Hash.deriveNodeSeed(transactionSeed, 0) - val conflictingDiscriminator = - crypto.Hash.deriveContractDiscriminator(createNodeSeed, let, Set(alice)) - contractId(conflictingDiscriminator, suffix3) - } - - val exercisedCid1 = contractId(hash1, suffix1) - val exercisedCid2 = contractId(hash2, suffix2) - val contractsData = - List( - (exercisedCid1, 1, List.empty), - (exercisedCid2, 2, List(conflictingCid)), - (conflictingCid, 3, List.empty), - ) - val contractLookup = - contractsData - .map { case (cid, idx, cids) => - cid -> contractInstance(alice, idx, cids) - } - .toMap - .lift - val keyLookup = contractsData - .map { case (cid, idx, _) => - globalKey(alice, idx) -> cid - } - .toMap - .lift - - def run(cmd: command.ApiCommand) = - submit( - ImmArray( - command.CreateCommand(tmplId, contractRecord(alice, 0, List.empty)), - cmd, - ), - pcs = contractLookup, - keys = keyLookup, - ) - - val negativeTestCases = Table( - "successful commands", - command.ExerciseCommand(tmplId, exercisedCid1, "Noop", Value.ValueUnit), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 1), "Noop", Value.ValueUnit), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, -1)), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, 1)), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, 2)), - ) - - val positiveTestCases = Table( - "failing commands", - command.ExerciseCommand(tmplId, conflictingCid, "Noop", Value.ValueUnit), - command.ExerciseCommand(tmplId, exercisedCid2, "Noop", Value.ValueUnit), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 2), "Noop", Value.ValueUnit), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 3), "Noop", Value.ValueUnit), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, 3)), - ) - - forAll(negativeTestCases) { cmd => - run(cmd) shouldBe a[Right[_, _]] - } - - forAll(positiveTestCases) { cmd => - val r = run(cmd) - r shouldBe a[Left[_, _]] - r.left.exists(_.message.contains("Conflicting discriminators")) shouldBe true - } - - } - - "fails when a local conflicts with a global contract previously fetched" in { - - val conflictingCid = { - val createNodeSeed = crypto.Hash.deriveNodeSeed(transactionSeed, 1) - val conflictingDiscriminator = - crypto.Hash.deriveContractDiscriminator(createNodeSeed, let, Set(alice)) - contractId(conflictingDiscriminator, suffix3) - } - - val exercisedCid1 = contractId(hash1, suffix1) - val exercisedCid2 = contractId(hash2, suffix2) - val contractsData = - List( - (exercisedCid1, 1, List.empty), - (exercisedCid2, 2, List(conflictingCid)), - (conflictingCid, 3, List.empty), - ) - val contractLookup = - contractsData - .map { case (cid, idx, cids) => - cid -> contractInstance(alice, idx, cids) - } - .toMap - .lift - val keyLookup = contractsData - .map { case (cid, idx, _) => - globalKey(alice, idx) -> cid - } - .toMap - .lift - - def run(cmd: command.ApiCommand) = - submit( - ImmArray( - cmd, - command.CreateCommand(tmplId, contractRecord(alice, 0, List.empty)), - ), - pcs = contractLookup, - keys = keyLookup, - ) - - val negativeTestCases = Table( - "successful commands", - command.ExerciseCommand(tmplId, exercisedCid1, "Noop", Value.ValueUnit), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 1), "Noop", Value.ValueUnit), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, -1)), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, 1)), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, 2)), - ) - - val positiveTestCases = Table( - "failing commands", - command.ExerciseCommand(tmplId, conflictingCid, "Noop", Value.ValueUnit), - command.ExerciseCommand(tmplId, exercisedCid2, "Noop", Value.ValueUnit), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 2), "Noop", Value.ValueUnit), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 3), "Noop", Value.ValueUnit), - command.ExerciseCommand(tmplId, exercisedCid1, "LookupByKey", keyRecord(alice, 3)), - ) - - forAll(negativeTestCases) { cmd => - Right(cmd) shouldBe a[Right[_, _]] - } - - forAll(positiveTestCases) { cmd => - val r = run(cmd) - r shouldBe a[Left[_, _]] - r.left.exists(_.message.contains("Conflicting discriminators")) shouldBe true - } - - } - - "fail when preprocessing a transaction when a cid appear before before being created" in { - - val cid0: ContractId = ContractId.V1(crypto.Hash.hashPrivateKey("test"), Bytes.Empty) - - val Right((tx, _)) = submit( - ImmArray( - command.CreateAndExerciseCommand( - tmplId, - contractRecord(alice, 1, List.empty), - "Identity", - Value.ValueContractId(cid0), - ), - command.CreateCommand(tmplId, contractRecord(alice, 2, List.empty)), - ), - pcs = (cid => if (cid == cid0) Some(contractInstance(alice, 0, List.empty)) else None), - keys = _ => None, - ) - - val lastCreatedCid = tx.fold(cid0) { - case (_, (_, create: Node.NodeCreate[ContractId])) => create.coid - case (acc, _) => acc - } - - assert(lastCreatedCid != cid0) - - val newNodes = tx.fold(tx.nodes) { - case (nodes, (nid, exe: Node.NodeExercises[NodeId, ContractId])) - if exe.choiceId == "Identity" => - nodes.updated(nid, exe.copy(chosenValue = Value.ValueContractId(lastCreatedCid))) - case (acc, _) => acc - } - - val result = - new preprocessing.Preprocessor(ConcurrentCompiledPackages(speedy.Compiler.Config.Dev)) - .translateTransactionRoots(GenTransaction(newNodes, tx.roots)) - .consume(_ => None, pkgs, _ => None) - - inside(result) { case Left(Error.Preprocessing(err)) => - err shouldBe a[Error.Preprocessing.ContractIdFreshness] - } - - } - - "does not fail when replaying an exercise by key of a non-root local Contract" in { - // regression test for https://discuss.daml.com/t/ledger-api-error-message-conflicting-discriminators-between-a-global-and-local-contract-id/2416/3 - val Right((tx, txMeta)) = submit( - ImmArray( - command.CreateAndExerciseCommand( - tmplId, - contractRecord(alice, 0, List.empty), - "Create", - contractRecord(alice, 1, List.empty), - ), - command.ExerciseByKeyCommand(tmplId, keyRecord(alice, 1), "Noop", Value.ValueUnit), - ), - pcs = _ => None, - keys = _ => None, - ) - engine - .replay( - submitters = Set(alice), - tx, - ledgerEffectiveTime = txMeta.submissionTime, - participantId = participant, - submissionTime = txMeta.submissionTime, - submissionSeed = txMeta.submissionSeed.get, - ) - .consume(_ => None, pkgs, _ => None) shouldBe a[Right[_, _]] - } - - } - - private implicit def toName(s: String): Ref.Name = Ref.Name.assertFromString(s) - -} diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala index 1104775e2c2e..87fed7cade3d 100644 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala +++ b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/EngineTest.scala @@ -684,7 +684,7 @@ class EngineTest res shouldBe a[Right[_, _]] val interpretResult = res - .flatMap { case (cmds, globalCids) => + .flatMap { cmds => engine .interpretCommands( validating = false, @@ -694,7 +694,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume( lookupContract, @@ -821,7 +820,7 @@ class EngineTest res shouldBe a[Right[_, _]] val result = res - .flatMap { case (cmds, globalCids) => + .flatMap { cmds => engine .interpretCommands( validating = false, @@ -831,7 +830,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume( lookupContract, @@ -935,7 +933,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(seed), - globalCids = Set.empty, ) .consume(_ => None, lookupPackage, lookupKey) @@ -974,7 +971,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(seed), - globalCids = Set.empty, ) .consume(_ => None, lookupPackage, lookupKey) @@ -1010,7 +1006,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(seed), - globalCids = Set.empty, ) .consume(_ => None, lookupPackage, lookupKey) @@ -1057,7 +1052,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(seed), - globalCids = Set.empty, ) .consume(_ => None, lookupPackage, lookupKey) @@ -1103,7 +1097,7 @@ class EngineTest res shouldBe a[Right[_, _]] val interpretResult = res - .flatMap { case (cmds, globalCids) => + .flatMap { cmds => engine .interpretCommands( validating = false, @@ -1113,7 +1107,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = globalCids, ) .consume( lookupContract, @@ -1384,7 +1377,7 @@ class EngineTest val txSeed = crypto.Hash.deriveTransactionSeed(submissionSeed, participant, submissionTime) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(command)) .consume(lookupContract, lookupPackage, lookupKey) val Right((rtx, _)) = engine @@ -1396,7 +1389,6 @@ class EngineTest ledgerTime = let, submissionTime = submissionTime, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = globalCids, ) .consume(lookupContract, lookupPackage, lookupKey) @@ -1552,7 +1544,7 @@ class EngineTest .consume(lookupContract, lookupPackage, lookupKey) res - .flatMap { case (cmds, globalCids) => + .flatMap { cmds => engine .interpretCommands( validating = false, @@ -1562,7 +1554,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume( lookupContract, @@ -1840,7 +1831,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(seed), - globalCids = Set.empty, ) .consume(_ => None, lookupPackage, lookupKey) @@ -1907,7 +1897,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = Set(fetchedCid), ) .consume( lookupContractMap.get, @@ -1955,7 +1944,7 @@ class EngineTest val submitters = Set(alice) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands( ImmArray( ExerciseCommand( @@ -1981,7 +1970,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = globalCids, ) .consume( lookupContractMap.get, @@ -2173,7 +2161,7 @@ class EngineTest val submitters = Set(alice) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands( ImmArray( CreateAndExerciseCommand(templateId, createArg, "DontExecuteCreate", exerciseArg) @@ -2190,7 +2178,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = globalCids, ) .consume(_ => None, lookupPackage, lookupKey) result shouldBe a[Right[_, _]] @@ -2207,7 +2194,7 @@ class EngineTest val submitters = Set(alice) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(CreateCommand(templateId, createArg))) .consume(_ => None, lookupPackage, lookupKey) @@ -2220,7 +2207,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = globalCids, ) .consume(_ => None, lookupPackage, lookupKey) result shouldBe a[Left[_, _]] @@ -2240,7 +2226,7 @@ class EngineTest val submitters = Set(alice) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(CreateCommand(templateId, createArg))) .consume(_ => None, lookupPackage, lookupKey) val result = engine @@ -2252,7 +2238,6 @@ class EngineTest ledgerTime = now, submissionTime = now, seeding = InitialSeeding.TransactionSeed(txSeed), - globalCids = globalCids, ) .consume(_ => None, lookupPackage, lookupKey) @@ -2314,7 +2299,7 @@ class EngineTest choice, argument, ) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(cmd)) .consume(lookupContract, lookupPackage, lookupKey) engine @@ -2326,7 +2311,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume(lookupContract, lookupPackage, lookupKey) } @@ -2436,7 +2420,7 @@ class EngineTest } def run(cmd: ApiCommand) = { val submitters = Set(party) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(cmd)) .consume( lookupContract, @@ -2452,7 +2436,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume( lookupContract, @@ -2547,7 +2530,7 @@ class EngineTest } def run(cmd: ApiCommand) = { val submitters = Set(party) - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(cmd)) .consume( lookupContract, @@ -2563,7 +2546,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume( lookupContract, @@ -2630,7 +2612,7 @@ class EngineTest keyLookups += 1 lookupKey(key) } - val Right((cmds, globalCids)) = preprocessor + val Right(cmds) = preprocessor .preprocessCommands(ImmArray(cmd)) .consume( lookupContract, @@ -2646,7 +2628,6 @@ class EngineTest ledgerTime = let, submissionTime = let, seeding = seeding, - globalCids = globalCids, ) .consume( lookupContract, diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala index 3f2a14d53f5f..a26ebb272a9b 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala @@ -11,7 +11,7 @@ import com.daml.lf.data.Ref._ import com.daml.lf.data._ import com.daml.lf.data.Numeric.Scale import com.daml.lf.interpretation.{Error => IE} -import com.daml.lf.language.{Ast, Util => AstUtil} +import com.daml.lf.language.Ast import com.daml.lf.speedy.SError._ import com.daml.lf.speedy.SExpr._ import com.daml.lf.speedy.Speedy._ @@ -1145,19 +1145,11 @@ private[lf] object SBuiltin { private[this] abstract class KeyOperation { val templateId: TypeConName - private[this] val typ = AstUtil.TContractId(Ast.TTyCon(templateId)) - final protected def importCid(cid: V.ContractId): SEImportValue = - // We have to check that the discriminator of cid does not conflict with a local ones - // however we cannot raise an exception in case of failure here. - // We delegate to CtrlImportValue the task to check cid. - SEImportValue(typ, V.ValueContractId(cid)) // Callback from the engine returned NotFound - def handleInputKeyFound(machine: Machine, cid: V.ContractId): Unit + def handleKeyFound(machine: Machine, cid: V.ContractId): Unit // We already saw this key, but it was undefined or was archived def handleKeyNotFound(machine: Machine, gkey: GlobalKey): Boolean - // We already saw this key and it is still active - def handleActiveKey(machine: Machine, cid: V.ContractId): Unit final def handleKnownInputKey( machine: Machine, @@ -1165,33 +1157,28 @@ private[lf] object SBuiltin { keyMapping: PartialTransaction.KeyMapping, ): Unit = keyMapping match { - case PartialTransaction.KeyActive(cid) => handleActiveKey(machine, cid) + case PartialTransaction.KeyActive(cid) => handleKeyFound(machine, cid) case PartialTransaction.KeyInactive => discard(handleKeyNotFound(machine, gkey)) } } private[this] object KeyOperation { final class Fetch(override val templateId: TypeConName) extends KeyOperation { - override def handleInputKeyFound(machine: Machine, cid: V.ContractId): Unit = - machine.ctrl = importCid(cid) + override def handleKeyFound(machine: Machine, cid: V.ContractId): Unit = + machine.returnValue = SContractId(cid) override def handleKeyNotFound(machine: Machine, gkey: GlobalKey): Boolean = { machine.ctrl = SEDamlException(IE.ContractKeyNotFound(gkey)) false } - - override def handleActiveKey(machine: Machine, cid: V.ContractId): Unit = - machine.returnValue = SContractId(cid) } final class Lookup(override val templateId: TypeConName) extends KeyOperation { - override def handleInputKeyFound(machine: Machine, cid: V.ContractId): Unit = - machine.ctrl = SBSome(importCid(cid)) + override def handleKeyFound(machine: Machine, cid: V.ContractId): Unit = + machine.returnValue = SOptional(Some(SContractId(cid))) override def handleKeyNotFound(machine: Machine, key: GlobalKey): Boolean = { machine.returnValue = SValue.SValue.None true } - override def handleActiveKey(machine: Machine, cid: V.ContractId): Unit = - machine.returnValue = SOptional(Some(SContractId(cid))) } } @@ -1233,7 +1220,7 @@ private[lf] object SBuiltin { val stakeholders = cachedContract.signatories union cachedContract.observers onLedger.visibleToStakeholders(stakeholders) match { case SVisibleToStakeholders.Visible => - operation.handleActiveKey(machine, coid) + operation.handleKeyFound(machine, coid) case SVisibleToStakeholders.NotVisible(actAs, readAs) => machine.ctrl = SEDamlException( IE.LocalContractKeyNotVisible(coid, gkey, actAs, readAs, stakeholders) @@ -1261,7 +1248,7 @@ private[lf] object SBuiltin { onLedger.ptx = onLedger.ptx.copy( keys = onLedger.ptx.keys.updated(gkey, KeyActive(cid)) ) - operation.handleInputKeyFound(machine, cid) + operation.handleKeyFound(machine, cid) true case _ => onLedger.ptx = onLedger.ptx.copy( diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala index 08126a524a3c..2e9df66854d5 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala @@ -122,7 +122,6 @@ private[lf] object Speedy { /* Flag to trace usage of get_time builtins */ var dependsOnTime: Boolean, // global contract discriminators, that are discriminators from contract created in previous transactions - var globalDiscriminators: Set[crypto.Hash], var cachedContracts: Map[V.ContractId, CachedContract], ) extends LedgerMode { private[lf] val visibleToStakeholders: Set[Party] => SVisibleToStakeholders = @@ -358,30 +357,10 @@ private[lf] object Speedy { key: Option[Node.KeyWithMaintainers[V[Nothing]]], ) = withOnLedger("addLocalContract") { onLedger => - coid match { - case V.ContractId.V1(discriminator, _) - if onLedger.globalDiscriminators.contains(discriminator) => - throw SErrorDamlException( - interpretation.Error.ContractIdFreshness(discriminator) - ) - case _ => - onLedger.cachedContracts = onLedger.cachedContracts.updated( - coid, - CachedContract(templateId, arg, signatories, observers, key), - ) - } - } - - def addGlobalCid(cid: V.ContractId) = - withOnLedger("addGlobalCid") { onLedger => - cid match { - case V.ContractId.V1(discriminator, _) => - if (onLedger.ptx.localContracts.contains(V.ContractId.V1(discriminator))) - throw SErrorDamlException(interpretation.Error.ContractIdFreshness(discriminator)) - else - onLedger.globalDiscriminators = onLedger.globalDiscriminators + discriminator - case _ => - } + onLedger.cachedContracts = onLedger.cachedContracts.updated( + coid, + CachedContract(templateId, arg, signatories, observers, key), + ) } /** Reuse an existing speedy machine to evaluate a new expression. @@ -672,7 +651,6 @@ private[lf] object Speedy { case elemType :: Nil => value match { case V.ValueContractId(cid) => - addGlobalCid(cid) SValue.SContractId(cid) case V.ValueNumeric(d) => SValue.SNumeric(d) @@ -778,7 +756,6 @@ private[lf] object Speedy { submissionTime: Time.Timestamp, initialSeeding: InitialSeeding, expr: SExpr, - globalCids: Set[V.ContractId], committers: Set[Party], readAs: Set[Party], validating: Boolean = false, @@ -808,9 +785,6 @@ private[lf] object Speedy { readAs = readAs, commitLocation = commitLocation, dependsOnTime = false, - globalDiscriminators = globalCids.collect { case V.ContractId.V1(discriminator, _) => - discriminator - }, cachedContracts = Map.empty, contractKeyUniqueness = contractKeyUniqueness, ), @@ -850,7 +824,6 @@ private[lf] object Speedy { submissionTime = Time.Timestamp.MinValue, initialSeeding = InitialSeeding.TransactionSeed(transactionSeed), expr = SEApp(updateSE, Array(SEValue.Token)), - globalCids = Set.empty, committers = Set(committer), readAs = Set.empty, ) diff --git a/daml-lf/scenario-interpreter/src/main/scala/com/digitalasset/daml/lf/ScenarioRunner.scala b/daml-lf/scenario-interpreter/src/main/scala/com/digitalasset/daml/lf/ScenarioRunner.scala index 12f05d06a3f7..d13f7d5464ca 100644 --- a/daml-lf/scenario-interpreter/src/main/scala/com/digitalasset/daml/lf/ScenarioRunner.scala +++ b/daml-lf/scenario-interpreter/src/main/scala/com/digitalasset/daml/lf/ScenarioRunner.scala @@ -399,7 +399,6 @@ object ScenarioRunner { submissionTime = Time.Timestamp.MinValue, initialSeeding = InitialSeeding.TransactionSeed(seed), expr = SExpr.SEApp(commands, Array(SExpr.SEValue(SValue.SToken))), - globalCids = Set.empty, committers = committers, readAs = readAs, traceLog = traceLog, diff --git a/ledger/participant-state/kvutils/tools/codec-benchmark/src/benchmark/scala/com/daml/lf/speedy/MachineImportValueBenchmark.scala b/ledger/participant-state/kvutils/tools/codec-benchmark/src/benchmark/scala/com/daml/lf/speedy/MachineImportValueBenchmark.scala index 7e7535a5d4b4..58bbf4729a60 100644 --- a/ledger/participant-state/kvutils/tools/codec-benchmark/src/benchmark/scala/com/daml/lf/speedy/MachineImportValueBenchmark.scala +++ b/ledger/participant-state/kvutils/tools/codec-benchmark/src/benchmark/scala/com/daml/lf/speedy/MachineImportValueBenchmark.scala @@ -24,7 +24,6 @@ class MachineImportValueBenchmark extends BenchmarkWithLedgerExport { submissionTime = Time.Timestamp.MinValue, initialSeeding = InitialSeeding.NoSeed, expr = null, - globalCids = Set.empty, committers = Set.empty, readAs = Set.empty, )