From 688f1e1e0b4818c1f918199dfe11ab38de4a1f61 Mon Sep 17 00:00:00 2001 From: Moritz Kiefer Date: Thu, 20 Jan 2022 16:28:27 +0100 Subject: [PATCH] Drop v0 contract ids (#12464) * Drop v0 contract ids changelog_begin changelog_end * . changelog_begin changelog_end --- .../digitalasset/daml/lf/engine/Engine.scala | 1 - .../digitalasset/daml/lf/engine/Error.scala | 4 - .../preprocessing/CommandPreprocessor.scala | 3 - .../engine/preprocessing/Preprocessor.scala | 5 - .../preprocessing/ValueTranslator.scala | 9 - .../lf/engine/CommandPreprocessorSpec.scala | 30 +- .../daml/lf/engine/ValueEnricherSpec.scala | 9 +- .../daml/lf/engine/ValueTranslatorSpec.scala | 28 -- .../daml/lf/speedy/svalue/Ordering.scala | 10 - .../daml/lf/speedy/SBuiltinTest.scala | 13 +- .../daml/lf/speedy/svalue/OrderingSpec.scala | 5 +- .../TransactionConversionsSpec.scala | 36 ++- .../digitalasset/daml/lf/ScenarioRunner.scala | 1 - .../scala/lf/value/test/ValueGenerators.scala | 28 +- .../digitalasset/daml/lf/crypto/Hash.scala | 7 +- .../daml/lf/value/CidContainer.scala | 1 - .../digitalasset/daml/lf/value/Value.scala | 20 -- .../lf/transaction/TransactionCoderSpec.scala | 3 +- .../daml/lf/transaction/TransactionSpec.scala | 277 +++++++++--------- .../daml/lf/value/ValueSpec.scala | 5 +- .../daml/lf/engine/script/Converter.scala | 1 - .../daml/lf/engine/script/ScriptF.scala | 1 - .../ledgerinteraction/IdeLedgerClient.scala | 1 - .../http/query/ValuePredicateTest.scala | 4 +- .../util/ApiValueToLfValueConverterTest.scala | 4 - .../value/json/ApiCodecCompressedSpec.scala | 11 +- ledger/ledger-api-client/BUILD.bazel | 1 + .../ledger/client/CommandClientIT.scala | 15 +- .../api/ValueConversionRoundTripTest.scala | 4 +- .../SubmitRequestValidatorTest.scala | 6 +- .../BUILD.bazel | 1 + .../api/testtool/suites/ContractIdIT.scala | 71 ++--- .../indexer/ha/EndlessReadService.scala | 2 +- .../backend/StorageBackendTestValues.scala | 16 +- .../StorageBackendTestsContracts.scala | 29 +- .../backend/StorageBackendTestsEvents.scala | 66 ++++- ...orageBackendTestsInitializeIngestion.scala | 21 +- .../StorageBackendTestsIntegrity.scala | 18 +- .../StorageBackendTestsMigrationPruning.scala | 13 +- .../backend/StorageBackendTestsPruning.scala | 31 +- .../backend/StorageBackendTestsReset.scala | 6 +- .../StorageBackendTestsTimestamps.scala | 8 +- .../dao/JdbcLedgerDaoContractsSpec.scala | 7 +- ...dbcLedgerDaoPostCommitValidationSpec.scala | 5 +- .../store/dao/JdbcLedgerDaoSuite.scala | 3 +- .../services/ApiSubmissionServiceSpec.scala | 8 +- .../platform/index/BuffersUpdaterSpec.scala | 5 +- .../platform/index/EventFilterSpec.scala | 3 +- .../index/TransactionConversionSpec.scala | 22 +- .../platform/store/ConversionsSpec.scala | 14 +- .../events/PostCommitValidationSpec.scala | 3 +- .../MutableCacheBackedContractStoreSpec.scala | 3 +- .../kvutils/KeyValueCommittingSpec.scala | 4 +- ...mmitterModelConformanceValidatorSpec.scala | 16 +- .../TransactionConsistencyValidatorSpec.scala | 57 ++-- .../StateUpdateComparisonSpec.scala | 4 +- .../platform/sandbox/SandboxServer.scala | 2 +- .../ledger/sandbox/SandboxOnXRunner.scala | 2 +- .../ConflictCheckWithCommittedSpec.scala | 2 +- .../validate/PrepareSubmissionSpec.scala | 8 +- .../bridge/validate/SequenceSpec.scala | 8 +- .../bridge/validate/SequencerStateSpec.scala | 3 +- .../navigator/backend/DamlConstants.scala | 2 +- security-evidence.md | 28 +- .../daml/lf/engine/trigger/Converter.scala | 1 - 65 files changed, 514 insertions(+), 521 deletions(-) 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 c3d94ca7ae0..a18cb1de376 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 @@ -60,7 +60,6 @@ class Engine(val config: EngineConfig = Engine.StableConfig) { private[engine] val preprocessor = new preprocessing.Preprocessor( compiledPackages = compiledPackages, - forbidV0ContractId = config.forbidV0ContractId, requireV1ContractIdSuffix = config.requireSuffixedGlobalContractId, ) 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 9b2c6c9170f..2163215b36b 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 @@ -115,10 +115,6 @@ object Error { sealed abstract class Reason extends Serializable with Product { def details: String } - case object V0ContractId extends Reason { - def details = "V0 Contract IDs are forbidden" - def apply(cid: Value.ContractId.V0): IllegalContractId = IllegalContractId(cid, this) - } case object NonSuffixV1ContractId extends Reason { def details = "non-suffixed V1 Contract IDs are forbidden" def apply(cid: Value.ContractId.V1): IllegalContractId = IllegalContractId(cid, this) 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 0ddcbc80df6..e3987638008 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 @@ -14,15 +14,12 @@ import scala.annotation.tailrec private[lf] final class CommandPreprocessor( interface: language.PackageInterface, - // See Preprocessor scala doc for more details about the following flags. - forbidV0ContractId: Boolean, requireV1ContractIdSuffix: Boolean, ) { val valueTranslator = new ValueTranslator( interface = interface, - forbidV0ContractId = forbidV0ContractId, requireV1ContractIdSuffix = requireV1ContractIdSuffix, ) 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 831e939f1aa..c67a061f0ff 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 @@ -31,16 +31,12 @@ import scala.annotation.tailrec * Daml-LF package definitions against the command should * resolved/typechecked. It is updated dynamically each time the * [[ResultNeedPackage]] continuation is called. - * @param forbidV0ContractId when `true` the preprocessor will reject - * any value/command/transaction that contains V0 Contract IDs - * without suffixed. * @param requireV1ContractIdSuffix when `true` the preprocessor will reject * any value/command/transaction that contains V1 Contract IDs * without suffixed. */ private[engine] final class Preprocessor( compiledPackages: MutableCompiledPackages, - forbidV0ContractId: Boolean = true, requireV1ContractIdSuffix: Boolean = true, ) { @@ -51,7 +47,6 @@ private[engine] final class Preprocessor( val commandPreprocessor = new CommandPreprocessor( interface = interface, - forbidV0ContractId = forbidV0ContractId, requireV1ContractIdSuffix = requireV1ContractIdSuffix, ) val transactionPreprocessor = new TransactionPreprocessor(commandPreprocessor) 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 6496a7b3c8c..361cfb36fd2 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 @@ -16,8 +16,6 @@ import scala.annotation.tailrec private[lf] final class ValueTranslator( interface: language.PackageInterface, - // See Preprocessor scala doc for more details about the following flags. - forbidV0ContractId: Boolean, requireV1ContractIdSuffix: Boolean, ) { @@ -53,17 +51,10 @@ private[lf] final class ValueTranslator( else SValue.SContractId(_) - private[this] val unsafeTranslateV0Cid: ContractId.V0 => SValue.SContractId = - if (forbidV0ContractId) - cid => throw Error.Preprocessing.IllegalContractId.V0ContractId(cid) - else - SValue.SContractId(_) - @throws[Error.Preprocessing.Error] private[preprocessing] def unsafeTranslateCid(cid: ContractId): SValue.SContractId = cid match { case cid1: ContractId.V1 => unsafeTranslateV1Cid(cid1) - case cid0: ContractId.V0 => unsafeTranslateV0Cid(cid0) } // For efficient reason we do not produce here the monad Result[SValue] but rather throw diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala index 2e45dbf55a0..3cb7229e789 100644 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala +++ b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala @@ -72,7 +72,8 @@ class CommandPreprocessorSpec "preprocessCommand" should { - val defaultPreprocessor = new CommandPreprocessor(compiledPackage.interface, true, false) + val defaultPreprocessor = + new CommandPreprocessor(compiledPackage.interface, requireV1ContractIdSuffix = false) "reject improperly typed commands" in { @@ -233,7 +234,6 @@ class CommandPreprocessorSpec val cmdPreprocessor = new CommandPreprocessor( compiledPackage.interface, - forbidV0ContractId = false, requireV1ContractIdSuffix = false, ) @@ -245,7 +245,6 @@ class CommandPreprocessorSpec ), ContractId.V1 .assertBuild(crypto.Hash.hashPrivateKey("a non-suffixed V1 Contract ID"), Bytes.Empty), - ContractId.V0.assertFromString("#a V0 Contract ID"), ) cids.foreach(cid => @@ -256,35 +255,10 @@ class CommandPreprocessorSpec } - "reject V0 Contract IDs when requireV1ContractId flag is true" in { - - val cmdPreprocessor = new CommandPreprocessor( - compiledPackage.interface, - forbidV0ContractId = true, - requireV1ContractIdSuffix = false, - ) - - val List(aLegalCid, anotherLegalCid) = - List("a legal Contract ID", "another legal Contract ID").map(s => - ContractId.V1.assertBuild(crypto.Hash.hashPrivateKey(s), Bytes.assertFromString("00")) - ) - val illegalCid = ContractId.V0.assertFromString("#illegal Contract ID") - val failure = Failure(Error.Preprocessing.IllegalContractId.V0ContractId(illegalCid)) - - forEvery(contractIdTestCases(aLegalCid, anotherLegalCid))(cmd => - Try(cmdPreprocessor.unsafePreprocessCommand(cmd)) shouldBe a[Success[_]] - ) - - forEvery(contractIdTestCases(illegalCid, aLegalCid))(cmd => - Try(cmdPreprocessor.unsafePreprocessCommand(cmd)) shouldBe failure - ) - } - "reject non suffixed V1 Contract IDs when requireV1ContractIdSuffix is true" in { val cmdPreprocessor = new CommandPreprocessor( compiledPackage.interface, - forbidV0ContractId = true, requireV1ContractIdSuffix = true, ) val List(aLegalCid, anotherLegalCid) = diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueEnricherSpec.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueEnricherSpec.scala index 4994656741c..085ae9d501c 100644 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueEnricherSpec.scala +++ b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueEnricherSpec.scala @@ -4,6 +4,7 @@ package com.daml.lf package engine +import com.daml.lf.crypto.Hash import com.daml.lf.data._ import com.daml.lf.language.Ast.{TNat, TTyCon, Type} import com.daml.lf.language.Util._ @@ -23,6 +24,8 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper private[this] implicit val defaultPackageId: Ref.PackageId = defaultParserParameters.defaultPackageId + private def cid(key: String): ContractId = ContractId.V1(Hash.hashPrivateKey(key)) + val pkg = p""" module Mod { @@ -90,8 +93,8 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper (TParty, ValueParty("Alice"), ValueParty("Alice")), ( TContractId(TTyCon("Mod:Record")), - ValueContractId("#contractId"), - ValueContractId("#contractId"), + ValueContractId(cid("#contractId").coid), + ValueContractId(cid("#contractId").coid), ), ( TList(TText), @@ -138,7 +141,7 @@ class ValueEnricherSpec extends AnyWordSpec with Matchers with TableDrivenProper val builder = new TransactionBuilder(_ => TransactionVersion.minTypeErasure) val create = builder.create( - id = "#01", + id = cid("#01"), templateId = "Mod:Contract", argument = contract, signatories = Set("Alice"), diff --git a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueTranslatorSpec.scala b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueTranslatorSpec.scala index 6e06fc98278..0b6e49a360d 100644 --- a/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueTranslatorSpec.scala +++ b/daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/ValueTranslatorSpec.scala @@ -64,7 +64,6 @@ class ValueTranslatorSpec val valueTranslator = new ValueTranslator( compiledPackage.interface, - forbidV0ContractId = true, requireV1ContractIdSuffix = false, ) import valueTranslator.unsafeTranslateValue @@ -246,7 +245,6 @@ class ValueTranslatorSpec val valueTranslator = new ValueTranslator( compiledPackage.interface, - forbidV0ContractId = false, requireV1ContractIdSuffix = false, ) val cids = List( @@ -257,7 +255,6 @@ class ValueTranslatorSpec ), ContractId.V1 .assertBuild(crypto.Hash.hashPrivateKey("a non-suffixed V1 Contract ID"), Bytes.Empty), - ContractId.V0.assertFromString("#a V0 Contract ID"), ) cids.foreach(cid => @@ -267,35 +264,10 @@ class ValueTranslatorSpec ) } - "reject V0 Contract IDs when requireV1ContractId flag is true" in { - - val valueTranslator = new ValueTranslator( - compiledPackage.interface, - forbidV0ContractId = true, - requireV1ContractIdSuffix = false, - ) - val legalCid = - ContractId.V1.assertBuild( - crypto.Hash.hashPrivateKey("a legal Contract ID"), - Bytes.assertFromString("00"), - ) - val illegalCid = - ContractId.V0.assertFromString("#illegal Contract ID") - val failure = Failure(Error.Preprocessing.IllegalContractId.V0ContractId(illegalCid)) - - forEvery(testCasesForCid(legalCid))((typ, value) => - Try(valueTranslator.unsafeTranslateValue(typ, value)) shouldBe a[Success[_]] - ) - forEvery(testCasesForCid(illegalCid))((typ, value) => - Try(valueTranslator.unsafeTranslateValue(typ, value)) shouldBe failure - ) - } - "reject non suffixed V1 Contract IDs when requireV1ContractIdSuffix is true" in { val valueTranslator = new ValueTranslator( compiledPackage.interface, - forbidV0ContractId = true, requireV1ContractIdSuffix = true, ) val legalCid = diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/svalue/Ordering.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/svalue/Ordering.scala index 21f9df4ed51..0ca97f2c80e 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/svalue/Ordering.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/svalue/Ordering.scala @@ -107,17 +107,7 @@ object Ordering extends scala.math.Ordering[SValue] { } @inline private[this] def compareCid(cid1: ContractId, cid2: ContractId): Int = { - // Note that the engine never produce V0 contract IDs directly - // (V0 contract ID scheme can only be "emulated" at commit using - // `com.daml.lf.transaction.LegacyTransactionCommitter`). - // So we can assume here that all V0 Contract IDs are global. (cid1, cid2) match { - case (ContractId.V0(s1), ContractId.V0(s2)) => - s1 compareTo s2 - case (_: ContractId.V0, _: ContractId.V1) => - -1 - case (_: ContractId.V1, _: ContractId.V0) => - +1 case ( cid1 @ ContractId.V1(discriminator1, suffix1), cid2 @ ContractId.V1(discriminator2, suffix2), diff --git a/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/SBuiltinTest.scala b/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/SBuiltinTest.scala index 1e1c0b11ecc..655eb290cb9 100644 --- a/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/SBuiltinTest.scala +++ b/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/SBuiltinTest.scala @@ -5,6 +5,7 @@ package com.daml.lf package speedy import java.util +import com.daml.lf.crypto.Hash import com.daml.lf.data._ import com.daml.lf.interpretation.{Error => IE} import com.daml.lf.language.Ast._ @@ -730,8 +731,8 @@ class SBuiltinTest extends AnyFreeSpec with Matchers with TableDrivenPropertyChe "EQUAL @ContractId" - { "works as expected" in { - val cid1 = SContractId(Value.ContractId.assertFromString("#contract1")) - val cid2 = SContractId(Value.ContractId.assertFromString("#contract2")) + val cid1 = SContractId(Value.ContractId.V1(Hash.hashPrivateKey("#contract1"))) + val cid2 = SContractId(Value.ContractId.V1(Hash.hashPrivateKey("#contract2"))) evalApp(e"EQUAL @(ContractId Mod:T)", Array(cid1, cid1)) shouldBe Right(SBool(true)) evalApp(e"EQUAL @(ContractId Mod:T)", Array(cid1, cid2)) shouldBe Right(SBool(false)) } @@ -1298,19 +1299,21 @@ class SBuiltinTest extends AnyFreeSpec with Matchers with TableDrivenPropertyChe "CONTRACT_ID_TO_TEXT" - { "returns None on-ledger" in { val f = """(\(c:(ContractId Mod:T)) -> CONTRACT_ID_TO_TEXT @Mod:T c)""" + val cid = Value.ContractId.V1(Hash.hashPrivateKey("abc")) evalApp( e"$f", - Array(SContractId(Value.ContractId.assertFromString("#abc"))), + Array(SContractId(cid)), onLedger = true, ) shouldBe Right(SOptional(None)) } "returns Some(abc) off-ledger" in { val f = """(\(c:(ContractId Mod:T)) -> CONTRACT_ID_TO_TEXT @Mod:T c)""" + val cid = Value.ContractId.V1(Hash.hashPrivateKey("abc")) evalApp( e"$f", - Array(SContractId(Value.ContractId.assertFromString("#abc"))), + Array(SContractId(cid)), onLedger = false, - ) shouldBe Right(SOptional(Some(SText("#abc")))) + ) shouldBe Right(SOptional(Some(SText(cid.coid)))) } } diff --git a/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/svalue/OrderingSpec.scala b/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/svalue/OrderingSpec.scala index fd779fc9048..df009f53784 100644 --- a/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/svalue/OrderingSpec.scala +++ b/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/svalue/OrderingSpec.scala @@ -11,7 +11,7 @@ import com.daml.lf.speedy.SValue._ import com.daml.lf.speedy.SExpr.{SEApp, SEImportValue, SELocA, SEMakeClo} import com.daml.lf.value.Value import com.daml.lf.value.test.TypedValueGenerators.genAddend -import com.daml.lf.value.test.ValueGenerators.{cidV0Gen, comparableCoidsGen} +import com.daml.lf.value.test.ValueGenerators.{comparableCoidsGen, suffixedV1CidGen} import com.daml.lf.PureCompiledPackages import com.daml.lf.iface import com.daml.lf.interpretation.Error.ContractIdComparability @@ -111,8 +111,7 @@ class OrderingSpec // The tests are here as this is difficult to test outside daml-lf/interpreter. "txn Value Ordering" should { import Value.{ContractId => Cid} - // SContractId V1 ordering is nontotal so arbitrary generation of them is unsafe to use - implicit val cidArb: Arbitrary[Cid] = Arbitrary(cidV0Gen) + implicit val cidArb: Arbitrary[Cid] = Arbitrary(suffixedV1CidGen) implicit val svalueOrd: Order[SValue] = Order fromScalaOrdering Ordering implicit val cidOrd: Order[Cid] = svalueOrd contramap SContractId val EmptyScope: Value.LookupVariantEnum = _ => None diff --git a/daml-lf/kv-support/src/test/scala/com/daml/lf/kv/transactions/TransactionConversionsSpec.scala b/daml-lf/kv-support/src/test/scala/com/daml/lf/kv/transactions/TransactionConversionsSpec.scala index ab1d83536e1..76ca62b6e2e 100644 --- a/daml-lf/kv-support/src/test/scala/com/daml/lf/kv/transactions/TransactionConversionsSpec.scala +++ b/daml-lf/kv-support/src/test/scala/com/daml/lf/kv/transactions/TransactionConversionsSpec.scala @@ -31,7 +31,8 @@ import scala.jdk.CollectionConverters._ class TransactionConversionsSpec extends AnyWordSpec with Matchers { import TransactionConversionsSpec._ - import TransactionBuilder.Implicits._ + + private val cid = Value.ContractId.V1(crypto.Hash.hashPrivateKey("#id")) "TransactionUtilsSpec" should { "encodeTransaction" in { @@ -98,7 +99,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "extractTransactionOutputs" should { "return a single output for a create without a key" in { val builder = TransactionBuilder() - val createNode = create(builder, "#id") + val createNode = create(builder, cid) builder.add(createNode) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions @@ -110,7 +111,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return two outputs for a create with a key" in { val builder = TransactionBuilder() - val createNode = create(builder, "#id", hasKey = true) + val createNode = create(builder, cid, hasKey = true) builder.add(createNode) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions @@ -127,9 +128,9 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return a single output for a transient contract" in { val builder = TransactionBuilder() - val createNode = create(builder, "#id", hasKey = true) + val createNode = create(builder, cid, hasKey = true) builder.add(createNode) - builder.add(exercise(builder, "#id")) + builder.add(exercise(builder, cid)) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions .encodeTransaction(builder.build()) @@ -145,7 +146,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return a single output for an exercise without a key" in { val builder = TransactionBuilder() - val exerciseNode = exercise(builder, "#id") + val exerciseNode = exercise(builder, cid) builder.add(exerciseNode) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions @@ -157,7 +158,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return two outputs for a consuming exercise with a key" in { val builder = TransactionBuilder() - val exerciseNode = exercise(builder, "#id", hasKey = true) + val exerciseNode = exercise(builder, cid, hasKey = true) builder.add(exerciseNode) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions @@ -174,7 +175,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return two outputs for a non-consuming exercise with a key" in { val builder = TransactionBuilder() - val exerciseNode = exercise(builder, "#id", hasKey = true, consuming = false) + val exerciseNode = exercise(builder, cid, hasKey = true, consuming = false) builder.add(exerciseNode) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions @@ -191,8 +192,10 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return one output per fetch and fetch-by-key" in { val builder = TransactionBuilder() - val fetchNode1 = fetch(builder, "#id1", byKey = true) - val fetchNode2 = fetch(builder, "#id2", byKey = false) + val fetchNode1 = + fetch(builder, Value.ContractId.V1(crypto.Hash.hashPrivateKey("#id1")), byKey = true) + val fetchNode2 = + fetch(builder, Value.ContractId.V1(crypto.Hash.hashPrivateKey("#id2")), byKey = false) builder.add(fetchNode1) builder.add(fetchNode2) val result = TransactionConversions.extractTransactionOutputs( @@ -210,7 +213,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return no output for a failing lookup-by-key" in { val builder = TransactionBuilder() - builder.add(lookup(builder, "#id", found = false)) + builder.add(lookup(builder, cid, found = false)) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions .encodeTransaction(builder.build()) @@ -221,7 +224,7 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return no output for a successful lookup-by-key" in { val builder = TransactionBuilder() - builder.add(lookup(builder, "#id", found = true)) + builder.add(lookup(builder, cid, found = true)) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions .encodeTransaction(builder.build()) @@ -233,11 +236,14 @@ class TransactionConversionsSpec extends AnyWordSpec with Matchers { "return outputs for nodes under a rollback node" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - val createNode = create(builder, "#id1", hasKey = true) + val createNode = + create(builder, Value.ContractId.V1(crypto.Hash.hashPrivateKey("#id1")), hasKey = true) builder.add(createNode, rollback) - val exerciseNode = exercise(builder, "#id2", hasKey = true) + val exerciseNode = + exercise(builder, Value.ContractId.V1(crypto.Hash.hashPrivateKey("#id2")), hasKey = true) builder.add(exerciseNode, rollback) - val fetchNode = fetch(builder, "#id3", byKey = true) + val fetchNode = + fetch(builder, Value.ContractId.V1(crypto.Hash.hashPrivateKey("#id3")), byKey = true) builder.add(fetchNode, rollback) val result = TransactionConversions.extractTransactionOutputs( TransactionConversions 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 15d4ef10904..f46d9f79b13 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 @@ -390,7 +390,6 @@ object ScenarioRunner { val valueTranslator = new ValueTranslator( interface = compiledPackages.interface, - forbidV0ContractId = config.forbidV0ContractId, requireV1ContractIdSuffix = config.requireSuffixedGlobalContractId, ) def translateValue(typ: Ast.Type, value: Value): Result[SValue] = diff --git a/daml-lf/transaction-test-lib/src/main/scala/lf/value/test/ValueGenerators.scala b/daml-lf/transaction-test-lib/src/main/scala/lf/value/test/ValueGenerators.scala index ea66fde4833..fefec7dfbac 100644 --- a/daml-lf/transaction-test-lib/src/main/scala/lf/value/test/ValueGenerators.scala +++ b/daml-lf/transaction-test-lib/src/main/scala/lf/value/test/ValueGenerators.scala @@ -167,8 +167,6 @@ object ValueGenerators { ab <- Gen.containerOfN[Array, Byte](sz, arbitrary[Byte]) } yield Bytes fromByteArray ab - val cidV0Gen: Gen[ContractId.V0] = - Gen.alphaStr.map(t => Value.ContractId.V0.assertFromString('#' +: t.take(254))) private val cidV1Gen: Gen[ContractId.V1] = Gen.zip(genHash, genSuffixes) map { case (h, b) => ContractId.V1.assertBuild(h, b) @@ -176,21 +174,19 @@ object ValueGenerators { /** Universes of totally-ordered ContractIds. */ def comparableCoidsGen: Seq[Gen[ContractId]] = - Seq( - Gen.oneOf( - cidV0Gen, - Gen.zip(cidV1Gen, arbitrary[Byte]) map { case (b1, b) => - ContractId.V1 - .assertBuild( - b1.discriminator, - if (b1.suffix.nonEmpty) b1.suffix else Bytes fromByteArray Array(b), - ) - }, - ), - Gen.oneOf(cidV0Gen, cidV1Gen map (cid => ContractId.V1(cid.discriminator))), - ) + Seq(suffixedV1CidGen, nonSuffixedCidV1Gen) - def coidGen: Gen[ContractId] = Gen.oneOf(cidV0Gen, cidV1Gen) + def suffixedV1CidGen: Gen[ContractId] = Gen.zip(cidV1Gen, arbitrary[Byte]) map { case (b1, b) => + ContractId.V1 + .assertBuild( + b1.discriminator, + if (b1.suffix.nonEmpty) b1.suffix else Bytes fromByteArray Array(b), + ) + } + + def nonSuffixedCidV1Gen: Gen[ContractId] = cidV1Gen map (cid => ContractId.V1(cid.discriminator)) + + def coidGen: Gen[ContractId] = cidV1Gen def coidValueGen: Gen[ValueContractId] = coidGen.map(ValueContractId(_)) diff --git a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/crypto/Hash.scala b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/crypto/Hash.scala index 12d5b0c64fc..78ad634da32 100644 --- a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/crypto/Hash.scala +++ b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/crypto/Hash.scala @@ -77,11 +77,8 @@ object Hash { implicit val order: Order[Hash] = Order.fromScalaOrdering - private[lf] val aCid2Bytes: Value.ContractId => Bytes = { - case cid @ Value.ContractId.V1(_, _) => - cid.toBytes - case Value.ContractId.V0(s) => - Utf8.getBytes(s) + private[lf] val aCid2Bytes: Value.ContractId => Bytes = { case cid @ Value.ContractId.V1(_, _) => + cid.toBytes } private[lf] val noCid2String: Value.ContractId => Nothing = diff --git a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/CidContainer.scala b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/CidContainer.scala index 64dfed0bf8f..8845762332f 100644 --- a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/CidContainer.scala +++ b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/CidContainer.scala @@ -57,7 +57,6 @@ trait CidContainer[+A] { case Value.ContractId.V1(discriminator, Bytes.Empty) => Value.ContractId.V1.build(discriminator, f(discriminator)) case acoid @ Value.ContractId.V1(_, _) => Right(acoid) - case acoid @ Value.ContractId.V0(_) => Right(acoid) } } diff --git a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/Value.scala b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/Value.scala index de1ab0d4a42..fac09253c1d 100644 --- a/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/Value.scala +++ b/daml-lf/transaction/src/main/scala/com/digitalasset/daml/lf/value/Value.scala @@ -212,19 +212,6 @@ object Value { } object ContractId { - final case class V0(coid: Ref.ContractIdString) extends ContractId { - override def toString: String = s"ContractId($coid)" - } - - object V0 { - def fromString(s: String): Either[String, V0] = - Ref.ContractIdString.fromString(s).map(V0(_)) - - def assertFromString(s: String): V0 = assertRight(fromString(s)) - - implicit val `V0 Order`: Order[V0] = Order.fromScalaOrdering[String] contramap (_.coid) - } - final case class V1 private (discriminator: crypto.Hash, suffix: Bytes) extends ContractId with data.NoCopy { @@ -280,8 +267,6 @@ object Value { def fromString(s: String): Either[String, ContractId] = V1.fromString(s) - .left - .flatMap(_ => V0.fromString(s)) .left .map(_ => s"""cannot parse ContractId "$s"""") @@ -289,18 +274,13 @@ object Value { assertRight(fromString(s)) implicit val `Cid Order`: Order[ContractId] = new Order[ContractId] { - import scalaz.Ordering._ override def order(a: ContractId, b: ContractId) = (a, b) match { - case (a: V0, b: V0) => a ?|? b case (a: V1, b: V1) => a ?|? b - case (_: V0, _: V1) => LT - case (_: V1, _: V0) => GT } override def equal(a: ContractId, b: ContractId) = (a, b).match2 { - case a: V0 => { case b: V0 => a === b } case V1(discA, suffA) => { case V1(discB, suffB) => discA == discB && suffA.toByteString == suffB.toByteString } diff --git a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionCoderSpec.scala b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionCoderSpec.scala index 988be387716..6b995ea41b7 100644 --- a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionCoderSpec.scala +++ b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionCoderSpec.scala @@ -5,6 +5,7 @@ package com.daml package lf package transaction +import com.daml.lf.crypto.Hash import com.daml.lf.data.ImmArray import com.daml.lf.data.Ref.{Identifier, Party} import com.daml.lf.transaction.{TransactionOuterClass => proto} @@ -867,7 +868,7 @@ class TransactionCoderSpec } private def absCid(s: String): ContractId = - ContractId.assertFromString(s) + ContractId.V1(Hash.hashPrivateKey(s)) def versionNodes( version: TransactionVersion, diff --git a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala index cc6906c3c6d..4525cdfc497 100644 --- a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala +++ b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/transaction/TransactionSpec.scala @@ -4,6 +4,7 @@ package com.daml.lf package transaction +import com.daml.lf.crypto.Hash import com.daml.lf.data.{Bytes, ImmArray, Ref} import com.daml.lf.transaction.Transaction.{ AliasedNode, @@ -41,7 +42,7 @@ class TransactionSpec "detects dangling references in children" in { val tx = mkTransaction( - HashMap(NodeId(1) -> dummyExerciseNode("#cid1", ImmArray(NodeId(2)))), + HashMap(NodeId(1) -> dummyExerciseNode(cid("#cid1"), ImmArray(NodeId(2)))), ImmArray(NodeId(1)), ) tx.isWellFormed shouldBe Set(NotWellFormedError(NodeId(2), DanglingNodeId)) @@ -49,7 +50,7 @@ class TransactionSpec "detects cycles" in { val tx = mkTransaction( - HashMap(NodeId(1) -> dummyExerciseNode("#cid1", ImmArray(NodeId(1)))), + HashMap(NodeId(1) -> dummyExerciseNode(cid("#cid1"), ImmArray(NodeId(1)))), ImmArray(NodeId(1)), ) tx.isWellFormed shouldBe Set(NotWellFormedError(NodeId(1), AliasedNode)) @@ -58,9 +59,9 @@ class TransactionSpec "detects aliasing from roots and exercise" in { val tx = mkTransaction( HashMap( - NodeId(0) -> dummyExerciseNode("#cid0", ImmArray(NodeId(1))), - NodeId(1) -> dummyExerciseNode("#cid1", ImmArray(NodeId(2))), - NodeId(2) -> dummyCreateNode("#cid2"), + NodeId(0) -> dummyExerciseNode(cid("#cid0"), ImmArray(NodeId(1))), + NodeId(1) -> dummyExerciseNode(cid("#cid1"), ImmArray(NodeId(2))), + NodeId(2) -> dummyCreateNode(cid("#cid2")), ), ImmArray(NodeId(0), NodeId(2)), ) @@ -68,7 +69,7 @@ class TransactionSpec } "detects orphans" in { - val tx = mkTransaction(HashMap(NodeId(1) -> dummyCreateNode("#cid1")), ImmArray.Empty) + val tx = mkTransaction(HashMap(NodeId(1) -> dummyCreateNode(cid("#cid1"))), ImmArray.Empty) tx.isWellFormed shouldBe Set(NotWellFormedError(NodeId(1), OrphanedNode)) } } @@ -78,9 +79,9 @@ class TransactionSpec "collects contract IDs" in { val tx = mkTransaction( HashMap( - NodeId(0) -> dummyExerciseNode("#cid0", ImmArray(NodeId(1))), - NodeId(1) -> dummyExerciseNode("#cid1", ImmArray(NodeId(2))), - NodeId(2) -> dummyCreateNode("#cid2"), + NodeId(0) -> dummyExerciseNode(cid("#cid0"), ImmArray(NodeId(1))), + NodeId(1) -> dummyExerciseNode(cid("#cid1"), ImmArray(NodeId(2))), + NodeId(2) -> dummyCreateNode(cid("#cid2")), ), ImmArray(NodeId(0), NodeId(2)), ) @@ -91,7 +92,12 @@ class TransactionSpec cids.result() } - collectCids(tx) shouldBe Set[V.ContractId]("#cid0", "#cid1", "#cid2", "#dummyCid") + collectCids(tx) shouldBe Set[V.ContractId]( + cid("#cid0"), + cid("#cid1"), + cid("#cid2"), + cid("#dummyCid"), + ) } @@ -102,12 +108,12 @@ class TransactionSpec val tx = mkTransaction( HashMap( - NodeId(0) -> dummyCreateNode("#cid0"), - NodeId(1) -> dummyExerciseNode("#cid1", ImmArray(NodeId(2), NodeId(4))), - NodeId(2) -> dummyExerciseNode("#cid2", ImmArray.Empty), - NodeId(3) -> dummyCreateNode("#cid3"), + NodeId(0) -> dummyCreateNode(cid("#cid0")), + NodeId(1) -> dummyExerciseNode(cid("#cid1"), ImmArray(NodeId(2), NodeId(4))), + NodeId(2) -> dummyExerciseNode(cid("#cid2"), ImmArray.Empty), + NodeId(3) -> dummyCreateNode(cid("#cid3")), NodeId(4) -> dummyRollbackNode(ImmArray(NodeId(5))), - NodeId(5) -> dummyCreateNode("#cid5"), + NodeId(5) -> dummyCreateNode(cid("#cid5")), ), ImmArray(NodeId(0), NodeId(1), NodeId(3)), ) @@ -130,19 +136,19 @@ class TransactionSpec val tx = mkTransaction( HashMap( - NodeId(0) -> dummyCreateNode("#cid0"), - NodeId(1) -> dummyExerciseNode("#cid1", ImmArray(NodeId(2), NodeId(4))), - NodeId(2) -> dummyExerciseNode("#cid2", ImmArray.Empty), - NodeId(3) -> dummyCreateNode("#cid3"), + NodeId(0) -> dummyCreateNode(cid("#cid0")), + NodeId(1) -> dummyExerciseNode(cid("#cid1"), ImmArray(NodeId(2), NodeId(4))), + NodeId(2) -> dummyExerciseNode(cid("#cid2"), ImmArray.Empty), + NodeId(3) -> dummyCreateNode(cid("#cid3")), NodeId(4) -> dummyRollbackNode(ImmArray(NodeId(5))), - NodeId(5) -> dummyCreateNode("#cid5"), + NodeId(5) -> dummyCreateNode(cid("#cid5")), // these are not reachable - NodeId(10) -> dummyCreateNode("#cid10"), - NodeId(11) -> dummyExerciseNode("#cid11", ImmArray(NodeId(12), NodeId(14))), - NodeId(12) -> dummyExerciseNode("#cid12", ImmArray.Empty), - NodeId(13) -> dummyCreateNode("#cid13"), + NodeId(10) -> dummyCreateNode(cid("#cid10")), + NodeId(11) -> dummyExerciseNode(cid("#cid11"), ImmArray(NodeId(12), NodeId(14))), + NodeId(12) -> dummyExerciseNode(cid("#cid12"), ImmArray.Empty), + NodeId(13) -> dummyCreateNode(cid("#cid13")), NodeId(14) -> dummyRollbackNode(ImmArray(NodeId(15))), - NodeId(15) -> dummyCreateNode("#cid15"), + NodeId(15) -> dummyCreateNode(cid("#cid15")), ), ImmArray(NodeId(0), NodeId(1), NodeId(3)), ) @@ -248,8 +254,8 @@ class TransactionSpec val tx = mkTransaction( HashMap( NodeId(0) -> dummyCreateNode(cid1), - NodeId(0) -> dummyExerciseNode(cid1, ImmArray(NodeId(0))), - NodeId(1) -> dummyExerciseNode(cid2, ImmArray(NodeId(1))), + NodeId(0) -> dummyExerciseNode(cid1, ImmArray(NodeId(0)), true), + NodeId(1) -> dummyExerciseNode(cid2, ImmArray(NodeId(1)), true), ), ImmArray(NodeId(0), NodeId(1)), ) @@ -262,11 +268,6 @@ class TransactionSpec tx1 shouldBe Right(tx.mapCid(mapping2)) } - "suffixing v0 contract id should be a no op" in { - val v0Cid = V.ValueContractId(V.ContractId.V0.assertFromString("#deadbeef")) - val Right(v0CidSuffixed) = v0Cid.suffixCid(_ => Bytes.assertFromString("cafe")) - v0Cid shouldBe v0CidSuffixed - } } "contractKeys" - { @@ -275,36 +276,39 @@ class TransactionSpec val builder = TransactionBuilder() val parties = Set("Alice") - def create(s: String) = builder - .create( - id = s"#$s", - templateId = s"Mod:$s", - argument = V.ValueUnit, - signatories = parties, - observers = parties, - key = Some(V.ValueText(s)), - ) + def create(s: V.ContractId) = { + println(s) + builder + .create( + id = s, + templateId = s"Mod:t${s.coid}", + argument = V.ValueUnit, + signatories = parties, + observers = parties, + key = Some(V.ValueText(s.coid)), + ) + } - def exe(s: String, consuming: Boolean, byKey: Boolean) = + def exe(s: V.ContractId, consuming: Boolean, byKey: Boolean) = builder .exercise( contract = create(s), - choice = s"Choice$s", + choice = s"Choice${s.coid}", actingParties = parties.toSet, consuming = consuming, argument = V.ValueUnit, byKey = byKey, ) - def fetch(s: String, byKey: Boolean) = + def fetch(s: V.ContractId, byKey: Boolean) = builder.fetch(contract = create(s), byKey = byKey) - def lookup(s: String, found: Boolean) = + def lookup(s: V.ContractId, found: Boolean) = builder.lookupByKey(contract = create(s), found = found) val root1 = builder.create( - "#root", + cid("#root"), templateId = "Mod:Root", argument = V.ValueUnit, signatories = parties, @@ -322,25 +326,27 @@ class TransactionSpec builder.add(root1) val exeId = builder.add(root2) - builder.add(create("Create")) - builder.add(exe("NonConsumingExerciseById", false, false), exeId) - builder.add(exe("ConsumingExerciseById", true, false), exeId) - builder.add(exe("NonConsumingExerciseByKey", false, true), exeId) - builder.add(exe("NonConsumingExerciseByKey", true, true), exeId) - builder.add(fetch("FetchById", false), exeId) - builder.add(fetch("FetchByKey", true), exeId) - builder.add(lookup("SuccessfulLookup", true), exeId) - builder.add(lookup("UnsuccessfulLookup", true), exeId) + println(cid("Create")) + builder.add(create(cid("Create"): V.ContractId)) + println("created") + builder.add(exe(cid("NonConsumingExerciseById"), false, false), exeId) + builder.add(exe(cid("ConsumingExerciseById"), true, false), exeId) + builder.add(exe(cid("NonConsumingExerciseByKey"), false, true), exeId) + builder.add(exe(cid("NonConsumingExerciseByKey"), true, true), exeId) + builder.add(fetch(cid("FetchById"), false), exeId) + builder.add(fetch(cid("FetchByKey"), true), exeId) + builder.add(lookup(cid("SuccessfulLookup"), true), exeId) + builder.add(lookup(cid("UnsuccessfulLookup"), true), exeId) val rollbackId = builder.add(Node.Rollback(ImmArray.Empty)) - builder.add(create("RolledBackCreate")) - builder.add(exe("RolledBackNonConsumingExerciseById", false, false), rollbackId) - builder.add(exe("RolledBackConsumingExerciseById", true, false), rollbackId) - builder.add(exe("RolledBackNonConsumingExerciseByKey", false, true), rollbackId) - builder.add(exe("RolledBackNonConsumingExerciseByKey", true, true), rollbackId) - builder.add(fetch("RolledBackFetchById", false), rollbackId) - builder.add(fetch("RolledBackFetchByKey", true), rollbackId) - builder.add(lookup("RolledBackSuccessfulLookup", true), rollbackId) - builder.add(lookup("RolledBackUnsuccessfulLookup", true), rollbackId) + builder.add(create(cid("RolledBackCreate"))) + builder.add(exe(cid("RolledBackNonConsumingExerciseById"), false, false), rollbackId) + builder.add(exe(cid("RolledBackConsumingExerciseById"), true, false), rollbackId) + builder.add(exe(cid("RolledBackNonConsumingExerciseByKey"), false, true), rollbackId) + builder.add(exe(cid("RolledBackNonConsumingExerciseByKey"), true, true), rollbackId) + builder.add(fetch(cid("RolledBackFetchById"), false), rollbackId) + builder.add(fetch(cid("RolledBackFetchByKey"), true), rollbackId) + builder.add(lookup(cid("RolledBackSuccessfulLookup"), true), rollbackId) + builder.add(lookup(cid("RolledBackUnsuccessfulLookup"), true), rollbackId) val expectedResults = Iterator( @@ -362,7 +368,7 @@ class TransactionSpec "RolledBackFetchByKey", "RolledBackSuccessfulLookup", "RolledBackUnsuccessfulLookup", - ).map(s => GlobalKey.assertBuild("Mod:" + s, V.ValueText(s))).toSet + ).map(s => GlobalKey.assertBuild(create(cid(s)).templateId, V.ValueText(cid(s).coid))).toSet builder.build().contractKeys shouldBe expectedResults } @@ -373,18 +379,18 @@ class TransactionSpec val dummyBuilder = TransactionBuilder() val parties = List("Alice") def keyValue(s: String) = V.ValueText(s) - def globalKey(s: String) = GlobalKey("Mod:T", keyValue(s)) - def create(s: String) = dummyBuilder + def globalKey(s: V.ContractId) = GlobalKey("Mod:T", keyValue(s.coid)) + def create(s: V.ContractId) = dummyBuilder .create( id = s, templateId = "Mod:T", argument = V.ValueUnit, signatories = parties, observers = parties, - key = Some(keyValue(s)), + key = Some(keyValue(s.coid)), ) - def exe(s: String, consuming: Boolean, byKey: Boolean) = + def exe(s: V.ContractId, consuming: Boolean, byKey: Boolean) = dummyBuilder .exercise( contract = create(s), @@ -395,64 +401,69 @@ class TransactionSpec byKey = byKey, ) - def fetch(s: String, byKey: Boolean) = + def fetch(s: V.ContractId, byKey: Boolean) = dummyBuilder.fetch(contract = create(s), byKey = byKey) - def lookup(s: String, found: Boolean) = + def lookup(s: V.ContractId, found: Boolean) = dummyBuilder.lookupByKey(contract = create(s), found = found) "return None for create" in { val builder = TransactionBuilder() - val createNode = create("#0") + val createNode = create(cid("#0")) builder.add(createNode) - builder.build().contractKeyInputs shouldBe Right(Map(globalKey("#0") -> KeyCreate)) + builder.build().contractKeyInputs shouldBe Right(Map(globalKey(cid("#0")) -> KeyCreate)) } "return Some(_) for fetch and fetch-by-key" in { val builder = TransactionBuilder() - val fetchNode0 = fetch("#0", byKey = false) - val fetchNode1 = fetch("#1", byKey = true) + val fetchNode0 = fetch(cid("#0"), byKey = false) + val fetchNode1 = fetch(cid("#1"), byKey = true) builder.add(fetchNode0) builder.add(fetchNode1) builder.build().contractKeyInputs shouldBe Right( - Map(globalKey("#0") -> KeyActive("#0"), globalKey("#1") -> KeyActive("#1")) + Map( + globalKey(cid("#0")) -> KeyActive(cid("#0")), + globalKey(cid("#1")) -> KeyActive(cid("#1")), + ) ) } "return Some(_) for consuming/non-consuming exercise and exercise-by-key" in { val builder = TransactionBuilder() - val exe0 = exe("#0", consuming = false, byKey = false) - val exe1 = exe("#1", consuming = true, byKey = false) - val exe2 = exe("#2", consuming = false, byKey = true) - val exe3 = exe("#3", consuming = true, byKey = true) + val exe0 = exe(cid("#0"), consuming = false, byKey = false) + val exe1 = exe(cid("#1"), consuming = true, byKey = false) + val exe2 = exe(cid("#2"), consuming = false, byKey = true) + val exe3 = exe(cid("#3"), consuming = true, byKey = true) builder.add(exe0) builder.add(exe1) builder.add(exe2) builder.add(exe3) builder.build().contractKeyInputs shouldBe Right( - Seq("#0", "#1", "#2", "#3").map(s => globalKey(s) -> KeyActive(s)).toMap + Seq(cid("#0"), cid("#1"), cid("#2"), cid("#3")).map(s => globalKey(s) -> KeyActive(s)).toMap ) } "return None for negative lookup by key" in { val builder = TransactionBuilder() - val lookupNode = lookup("#0", found = false) + val lookupNode = lookup(cid("#0"), found = false) builder.add(lookupNode) - builder.build().contractKeyInputs shouldBe Right(Map(globalKey("#0") -> NegativeKeyLookup)) + builder.build().contractKeyInputs shouldBe Right( + Map(globalKey(cid("#0")) -> NegativeKeyLookup) + ) } "return Some(_) for negative lookup by key" in { val builder = TransactionBuilder() - val lookupNode = lookup("#0", found = true) + val lookupNode = lookup(cid("#0"), found = true) builder.add(lookupNode) inside(lookupNode.result) { case Some(cid) => - builder.build().contractKeyInputs shouldBe Right(Map(globalKey("#0") -> KeyActive(cid))) + builder.build().contractKeyInputs shouldBe Right(Map(globalKey(cid) -> KeyActive(cid))) } } "returns keys used under rollback nodes" in { val builder = TransactionBuilder() - val createNode = create("#0") - val exerciseNode = exe("#1", consuming = false, byKey = false) - val fetchNode = fetch("#2", byKey = false) - val lookupNode = lookup("#3", found = false) + val createNode = create(cid("#0")) + val exerciseNode = exe(cid("#1"), consuming = false, byKey = false) + val fetchNode = fetch(cid("#2"), byKey = false) + val lookupNode = lookup(cid("#3"), found = false) val rollback = builder.add(builder.rollback()) builder.add(createNode, rollback) builder.add(exerciseNode, rollback) @@ -460,101 +471,101 @@ class TransactionSpec builder.add(lookupNode, rollback) builder.build().contractKeyInputs shouldBe Right( Map( - globalKey("#0") -> KeyCreate, - globalKey("#1") -> KeyActive(exerciseNode.targetCoid), - globalKey("#2") -> KeyActive(fetchNode.coid), - globalKey("#3") -> NegativeKeyLookup, + globalKey(cid("#0")) -> KeyCreate, + globalKey(cid("#1")) -> KeyActive(exerciseNode.targetCoid), + globalKey(cid("#2")) -> KeyActive(fetchNode.coid), + globalKey(cid("#3")) -> NegativeKeyLookup, ) ) } "two creates conflict" in { val builder = TransactionBuilder() - builder.add(create("#0")) - builder.add(create("#0")) - builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey("#0"))) + builder.add(create(cid("#0"))) + builder.add(create(cid("#0"))) + builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey(cid("#0")))) } "two creates do not conflict if interleaved with archive" in { val builder = TransactionBuilder() - builder.add(create("#0")) - builder.add(exe("#0", consuming = true, byKey = false)) - builder.add(create("#0")) - builder.build().contractKeyInputs shouldBe Right(Map(globalKey("#0") -> KeyCreate)) + builder.add(create(cid("#0"))) + builder.add(exe(cid("#0"), consuming = true, byKey = false)) + builder.add(create(cid("#0"))) + builder.build().contractKeyInputs shouldBe Right(Map(globalKey(cid("#0")) -> KeyCreate)) } "two creates do not conflict if one is in rollback" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - builder.add(create("#0"), rollback) - builder.add(create("#0")) - builder.build().contractKeyInputs shouldBe Right(Map(globalKey("#0") -> KeyCreate)) + builder.add(create(cid("#0")), rollback) + builder.add(create(cid("#0"))) + builder.build().contractKeyInputs shouldBe Right(Map(globalKey(cid("#0")) -> KeyCreate)) } "negative lookup after create fails" in { val builder = TransactionBuilder() - builder.add(create("#0")) - builder.add(lookup("#0", found = false)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey("#0"))) + builder.add(create(cid("#0"))) + builder.add(lookup(cid("#0"), found = false)) + builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) } "inconsistent lookups conflict" in { val builder = TransactionBuilder() - builder.add(lookup("#0", found = true)) - builder.add(lookup("#0", found = false)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey("#0"))) + builder.add(lookup(cid("#0"), found = true)) + builder.add(lookup(cid("#0"), found = false)) + builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) } "inconsistent lookups conflict across rollback" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - builder.add(lookup("#0", found = true), rollback) - builder.add(lookup("#0", found = false)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey("#0"))) + builder.add(lookup(cid("#0"), found = true), rollback) + builder.add(lookup(cid("#0"), found = false)) + builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) } "positive lookup conflicts with create" in { val builder = TransactionBuilder() - builder.add(lookup("#0", found = true)) - builder.add(create("#0")) - builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey("#0"))) + builder.add(lookup(cid("#0"), found = true)) + builder.add(create(cid("#0"))) + builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey(cid("#0")))) } "positive lookup in rollback conflicts with create" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - builder.add(lookup("#0", found = true), rollback) - builder.add(create("#0")) - builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey("#0"))) + builder.add(lookup(cid("#0"), found = true), rollback) + builder.add(create(cid("#0"))) + builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey(cid("#0")))) } "rolled back archive does not prevent conflict" in { val builder = TransactionBuilder() - builder.add(create("#0")) + builder.add(create(cid("#0"))) val rollback = builder.add(builder.rollback()) - builder.add(exe("#0", consuming = true, byKey = true), rollback) - builder.add(create("#0")) - builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey("#0"))) + builder.add(exe(cid("#0"), consuming = true, byKey = true), rollback) + builder.add(create(cid("#0"))) + builder.build().contractKeyInputs shouldBe Left(DuplicateKeys(globalKey(cid("#0")))) } "successful, inconsistent lookups conflict" in { val builder = TransactionBuilder() - val create0 = create("#0") - val create1 = create("#1").copy( + val create0 = create(cid("#0")) + val create1 = create(cid("#1")).copy( key = Some( Node.KeyWithMaintainers( - key = keyValue("#0"), + key = keyValue(cid("#0").coid), maintainers = Set.empty, ) ) ) builder.add(builder.lookupByKey(create0, found = true)) builder.add(builder.lookupByKey(create1, found = true)) - builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey("#0"))) + builder.build().contractKeyInputs shouldBe Left(InconsistentKeys(globalKey(cid("#0")))) } "first negative input wins" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - val create0 = create("#0") + val create0 = create(cid("#0")) val lookup0 = builder.lookupByKey(create0, found = false) - val create1 = create("#1") + val create1 = create(cid("#1")) val lookup1 = builder.lookupByKey(create1, found = false) builder.add(create0, rollback) builder.add(lookup1, rollback) builder.add(lookup0) builder.add(create1) builder.build().contractKeyInputs shouldBe Right( - Map(globalKey("#0") -> KeyCreate, globalKey("#1") -> NegativeKeyLookup) + Map(globalKey(cid("#0")) -> KeyCreate, globalKey(cid("#1")) -> NegativeKeyLookup) ) } } @@ -648,6 +659,8 @@ object TransactionSpec { import TransactionBuilder.Implicits._ + def cid(s: String): V.ContractId = V.ContractId.V1(Hash.hashPrivateKey(s)) + def mkTransaction( nodes: HashMap[NodeId, Node], roots: ImmArray[NodeId], @@ -683,11 +696,11 @@ object TransactionSpec { version = TransactionVersion.minVersion, ) - def dummyCreateNode(cid: V.ContractId): Node.Create = + def dummyCreateNode(createCid: V.ContractId): Node.Create = Node.Create( - coid = cid, + coid = createCid, templateId = Ref.Identifier.assertFromString("-dummyPkg-:DummyModule:dummyName"), - arg = V.ValueContractId("#dummyCid"), + arg = V.ValueContractId(cid("#dummyCid")), agreementText = "dummyAgreement", signatories = Set.empty, stakeholders = Set.empty, diff --git a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/value/ValueSpec.scala b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/value/ValueSpec.scala index 0beed92917b..bb4ffacedb0 100644 --- a/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/value/ValueSpec.scala +++ b/daml-lf/transaction/src/test/scala/com/digitalasset/daml/lf/value/ValueSpec.scala @@ -8,7 +8,7 @@ import data.{Bytes, ImmArray, Ref} import Value._ import Ref.{Identifier, Name} -import test.ValueGenerators.{cidV0Gen, coidGen, idGen, nameGen} +import test.ValueGenerators.{suffixedV1CidGen, coidGen, idGen, nameGen} import test.TypedValueGenerators.{RNil, genAddend, ValueAddend => VA} import org.scalacheck.{Arbitrary, Gen} import org.scalatest.Inside @@ -85,8 +85,7 @@ class ValueSpec "Order" - { - // SContractId V1 ordering is nontotal so arbitrary generation of them is unsafe to use - implicit val cidArb: Arbitrary[Value.ContractId] = Arbitrary(cidV0Gen) + implicit val cidArb: Arbitrary[Value.ContractId] = Arbitrary(suffixedV1CidGen) val FooScope: Value.LookupVariantEnum = Map(fooVariantId -> ImmArray("quux", "baz"), fooEnumId -> ImmArray("quux", "baz")) diff --git a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/Converter.scala b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/Converter.scala index 0bac5f9ed05..d01bf59d300 100644 --- a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/Converter.scala +++ b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/Converter.scala @@ -758,7 +758,6 @@ object Converter { valueTranslator = new preprocessing.ValueTranslator( compiledPackages.interface, - forbidV0ContractId = false, requireV1ContractIdSuffix = false, ) sValue <- valueTranslator diff --git a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ScriptF.scala b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ScriptF.scala index 9e62e5b8b15..a010b1e2575 100644 --- a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ScriptF.scala +++ b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ScriptF.scala @@ -68,7 +68,6 @@ object ScriptF { def compiledPackages = machine.compiledPackages val valueTranslator = new ValueTranslator( interface = compiledPackages.interface, - forbidV0ContractId = false, requireV1ContractIdSuffix = false, ) val utcClock = Clock.systemUTC() diff --git a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/IdeLedgerClient.scala b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/IdeLedgerClient.scala index 3c24d44adde..d7a5f02cd31 100644 --- a/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/IdeLedgerClient.scala +++ b/daml-script/runner/src/main/scala/com/digitalasset/daml/lf/engine/script/ledgerinteraction/IdeLedgerClient.scala @@ -47,7 +47,6 @@ class IdeLedgerClient( private[this] val preprocessor = new preprocessing.CommandPreprocessor( compiledPackages.interface, - forbidV0ContractId = true, requireV1ContractIdSuffix = false, ) diff --git a/ledger-service/http-json/src/test/scala/com/digitalasset/http/query/ValuePredicateTest.scala b/ledger-service/http-json/src/test/scala/com/digitalasset/http/query/ValuePredicateTest.scala index 4d43e3a15f1..41912337c2f 100644 --- a/ledger-service/http-json/src/test/scala/com/digitalasset/http/query/ValuePredicateTest.scala +++ b/ledger-service/http-json/src/test/scala/com/digitalasset/http/query/ValuePredicateTest.scala @@ -12,7 +12,7 @@ import com.daml.http.dbbackend.SurrogateTemplateIdCache import com.daml.lf.iface import com.daml.lf.value.{Value => V} import com.daml.lf.value.test.TypedValueGenerators.{genAddendNoListMap, RNil, ValueAddend => VA} -import com.daml.lf.value.test.ValueGenerators.cidV0Gen +import com.daml.lf.value.test.ValueGenerators.coidGen import com.daml.metrics.Metrics import org.scalacheck.Arbitrary import org.scalactic.source @@ -33,7 +33,7 @@ class ValuePredicateTest with TableDrivenPropertyChecks { import ValuePredicateTest._ type Cid = V.ContractId - private[this] implicit val arbCid: Arbitrary[Cid] = Arbitrary(cidV0Gen) + private[this] implicit val arbCid: Arbitrary[Cid] = Arbitrary(coidGen) import Ref.QualifiedName.{assertFromString => qn} diff --git a/ledger-service/http-json/src/test/scala/com/digitalasset/http/util/ApiValueToLfValueConverterTest.scala b/ledger-service/http-json/src/test/scala/com/digitalasset/http/util/ApiValueToLfValueConverterTest.scala index 8d74655c886..afda5c06d39 100644 --- a/ledger-service/http-json/src/test/scala/com/digitalasset/http/util/ApiValueToLfValueConverterTest.scala +++ b/ledger-service/http-json/src/test/scala/com/digitalasset/http/util/ApiValueToLfValueConverterTest.scala @@ -43,10 +43,6 @@ class ApiValueToLfValueConverterTest } object ApiValueToLfValueConverterTest { - - type Cid = V.ContractId - type CidSrc = V.ContractId.V0 - // Numeric are normalized when converting from api to lf, // them we have to relax numeric equality private implicit def eqValue: Equal[V] = { (l, r) => diff --git a/ledger-service/lf-value-json/src/test/scala/com/digitalasset/daml/lf/value/json/ApiCodecCompressedSpec.scala b/ledger-service/lf-value-json/src/test/scala/com/digitalasset/daml/lf/value/json/ApiCodecCompressedSpec.scala index 6f14e08e0b1..198da775694 100644 --- a/ledger-service/lf-value-json/src/test/scala/com/digitalasset/daml/lf/value/json/ApiCodecCompressedSpec.scala +++ b/ledger-service/lf-value-json/src/test/scala/com/digitalasset/daml/lf/value/json/ApiCodecCompressedSpec.scala @@ -117,7 +117,7 @@ class ApiCodecCompressedSpec fUnit = (), fInt64 = 100L, fParty = Ref.Party assertFromString "BANK1", - fContractId = ContractId.assertFromString("#C0"), + fContractId = ContractId.assertFromString("00" + "00" * 32 + "c0"), fListOfText = Vector("foo", "bar"), fListOfUnit = Vector((), ()), fDate = Time.Date assertFromString "2019-01-28", @@ -260,7 +260,14 @@ class ApiCodecCompressedSpec val successes = Table( ("line#", "serialized", "serializedNumerically", "type", "parsed", "alternates"), - c("\"#123\"", VA.contractId)(ContractId.assertFromString("#123")), + c( + "\"0000000000000000000000000000000000000000000000000000000000000000000123\"", + VA.contractId, + )( + ContractId.assertFromString( + "0000000000000000000000000000000000000000000000000000000000000000000123" + ) + ), cn("\"42.0\"", "42.0", VA.numeric(Decimal.scale))( Decimal assertFromString "42", "\"42\"", diff --git a/ledger/ledger-api-client/BUILD.bazel b/ledger/ledger-api-client/BUILD.bazel index ee7e4d1a077..377af5b5c50 100644 --- a/ledger/ledger-api-client/BUILD.bazel +++ b/ledger/ledger-api-client/BUILD.bazel @@ -105,6 +105,7 @@ da_scala_test_suite( ], deps = [ ":ledger-api-client", + "//daml-lf/transaction", "//language-support/scala/bindings", "//ledger-api/rs-grpc-bridge", "//ledger-api/testing-utils", diff --git a/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala b/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala index ffd635c7aad..96890573f01 100644 --- a/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala +++ b/ledger/ledger-api-client/src/it/scala/com/digitalasset/ledger/client/CommandClientIT.scala @@ -38,6 +38,8 @@ import com.daml.ledger.client.services.commands.{ CompletionStreamElement, } import com.daml.ledger.client.services.testing.time.StaticTime +import com.daml.lf.crypto.Hash +import com.daml.lf.value.Value.ContractId import com.daml.platform.common.LedgerIdMode import com.daml.platform.participant.util.ValueConversions._ import com.daml.platform.sandbox.config.SandboxConfig @@ -483,12 +485,21 @@ final class CommandClientIT } "not accept exercises with bad contract IDs, return ABORTED" in { - val contractId = "#deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef-123" + val contractId = ContractId.V1( + Hash.hashPrivateKey( + "#deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef-123" + ) + ) val command = submitRequest( "Exercise_contract_not_found", List( - ExerciseCommand(Some(templateIds.dummy), contractId, "DummyChoice1", Some(unit)).wrap + ExerciseCommand( + Some(templateIds.dummy), + contractId.coid, + "DummyChoice1", + Some(unit), + ).wrap ), ) diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/ValueConversionRoundTripTest.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/ValueConversionRoundTripTest.scala index 37295a28dab..89dba21b2b8 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/ValueConversionRoundTripTest.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/ValueConversionRoundTripTest.scala @@ -7,7 +7,9 @@ import com.daml.error.{ErrorCodesVersionSwitcher, NoLogging} import com.daml.ledger.api.v1.value.Value.Sum import com.daml.ledger.api.v1.{value => api} import com.daml.ledger.api.validation.{ValidatorTestUtils, ValueValidator} +import com.daml.lf.crypto.Hash import com.daml.lf.data.Time +import com.daml.lf.value.Value.ContractId import com.daml.platform.participant.util.LfEngineToApi import com.daml.platform.server.api.validation.{ErrorFactories, FieldValidations} import com.google.protobuf.empty.Empty @@ -42,7 +44,7 @@ class ValueConversionRoundTripTest val testCases: TableFor1[Sum] = Table( "values", - Sum.ContractId("#coid"), + Sum.ContractId(ContractId.V1(Hash.hashPrivateKey("#coid")).coid), DomainMocks.values.validApiParty.sum, Sum.Int64(Long.MinValue), Sum.Int64(0), diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala index 64b4728ddb9..6327eca0333 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala @@ -445,10 +445,10 @@ class SubmitRequestValidatorTest "validating contractId values" should { "succeed" in { - val coid = Ref.ContractIdString.assertFromString("#coid") + val coid = Lf.ContractId.V1.assertFromString("00" + "00" * 32) - val input = Value(Sum.ContractId(coid)) - val expected = Lf.ValueContractId(Lf.ContractId.V0(coid)) + val input = Value(Sum.ContractId(coid.coid)) + val expected = Lf.ValueContractId(coid) testedValueValidator.validateValue(input) shouldEqual Right(expected) } diff --git a/ledger/ledger-api-test-tool-on-canton/BUILD.bazel b/ledger/ledger-api-test-tool-on-canton/BUILD.bazel index 42786d21728..630d7c8bedf 100644 --- a/ledger/ledger-api-test-tool-on-canton/BUILD.bazel +++ b/ledger/ledger-api-test-tool-on-canton/BUILD.bazel @@ -112,6 +112,7 @@ conformance_test( "TLSOnePointThreeIT", "TLSAtLeastOnePointTwoIT", "MonotonicRecordTimeIT", # KV-utils specific + "ContractIdIT", # temporarily disabled due to changed error codes ]), ], ) if not is_windows else None diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala index f0fcbcf766a..7cdf8002822 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala @@ -4,6 +4,7 @@ package com.daml.ledger.api.testtool.suites import com.daml.error.definitions.LedgerApiErrors +import com.daml.error.ErrorCode import com.daml.grpc.{GrpcException, GrpcStatus} import com.daml.ledger.api.refinements.ApiTypes.Party import com.daml.ledger.api.testtool.infrastructure.Allocation._ @@ -66,7 +67,10 @@ final class ContractIdIT extends LedgerTestSuite { case TestConfiguration(cidDescription, example, accepted, isSupported, disabledReason) => val result = if (accepted) "Accept" else "Reject" - def test(description: String)( + def test( + description: String, + errorCode: ErrorCode = LedgerApiErrors.RequestValidation.InvalidArgument, + )( update: ExecutionContext => ( ParticipantTestContext, Party, @@ -86,8 +90,8 @@ final class ContractIdIT extends LedgerTestSuite { alpha, err, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, - Some(s"""Illegal Contract ID "$example""""), + errorCode, + Some(s"""cannot parse ContractId "$example""""), checkDefiniteAnswerMetadata = true, ) () @@ -103,38 +107,39 @@ final class ContractIdIT extends LedgerTestSuite { .transformWith(Future.successful) } - test("exercise target") { implicit ec => (alpha, party) => - for { - contractCid <- alpha.create(party, Contract(party)) - result <- - alpha - .exercise( - party, - ContractId[ContractRef](example).exerciseChange(_, contractCid), - ) - .transformWith(Future.successful) - } yield result match { - // Assert V1 error code - case Failure(GrpcException(GrpcStatus(Status.Code.ABORTED, Some(msg)), _)) - if !alpha.features.selfServiceErrorCodes && msg.contains( - s"Contract could not be found with id $example" - ) => - Success(()) + test("exercise target", errorCode = LedgerApiErrors.RequestValidation.InvalidField) { + implicit ec => (alpha, party) => + for { + contractCid <- alpha.create(party, Contract(party)) + result <- + alpha + .exercise( + party, + ContractId[ContractRef](example).exerciseChange(_, contractCid), + ) + .transformWith(Future.successful) + } yield result match { + // Assert V1 error code + case Failure(GrpcException(GrpcStatus(Status.Code.ABORTED, Some(msg)), _)) + if !alpha.features.selfServiceErrorCodes && msg.contains( + s"Contract could not be found with id $example" + ) => + Success(()) - // Assert self-service error code - case Failure(exception: StatusRuntimeException) - if alpha.features.selfServiceErrorCodes && - Try( - assertSelfServiceErrorCode( - statusRuntimeException = exception, - expectedErrorCode = LedgerApiErrors.ConsistencyErrors.ContractNotFound, - ) - ).isSuccess => - Success(()) + // Assert self-service error code + case Failure(exception: StatusRuntimeException) + if alpha.features.selfServiceErrorCodes && + Try( + assertSelfServiceErrorCode( + statusRuntimeException = exception, + expectedErrorCode = LedgerApiErrors.ConsistencyErrors.ContractNotFound, + ) + ).isSuccess => + Success(()) - case Success(_) => Failure(new UnknownError("Unexpected Success")) - case otherwise => otherwise.map(_ => ()) - } + case Success(_) => Failure(new UnknownError("Unexpected Success")) + case otherwise => otherwise.map(_ => ()) + } } test("choice argument") { implicit ec => (alpha, party) => diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/indexer/ha/EndlessReadService.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/indexer/ha/EndlessReadService.scala index 72e6726ccb5..47bca0092cb 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/indexer/ha/EndlessReadService.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/indexer/ha/EndlessReadService.scala @@ -167,7 +167,7 @@ object EndlessReadService { def submissionId(i: Int): Ref.SubmissionId = Ref.SubmissionId.assertFromString(f"sub$i%08x") def transactionId(i: Int): Ref.TransactionId = Ref.TransactionId.assertFromString(f"tx$i%08x") def commandId(i: Int): Ref.CommandId = Ref.CommandId.assertFromString(f"cmd$i%08x") - def cid(i: Int): Value.ContractId = Value.ContractId.V0.assertFromString(s"#$i") + def cid(i: Int): Value.ContractId = Value.ContractId.V1(crypto.Hash.hashPrivateKey(i.toString)) def recordTime(i: Int): Timestamp = Timestamp.assertFromInstant(Instant.EPOCH.plusSeconds(i.toLong)) def completionInfo(i: Int): CompletionInfo = CompletionInfo( diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestValues.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestValues.scala index 6efa8cd36ef..7f041d7a6f8 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestValues.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestValues.scala @@ -10,10 +10,12 @@ import com.daml.daml_lf_dev.DamlLf import com.daml.ledger.api.domain.{LedgerId, ParticipantId} import com.daml.ledger.configuration.{Configuration, LedgerTimeModel} import com.daml.ledger.offset.Offset +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.data.Time.Timestamp import com.daml.lf.ledger.EventId import com.daml.lf.transaction.NodeId +import com.daml.lf.value.Value.ContractId import com.daml.platform.store.appendonlydao.JdbcLedgerDao import com.google.protobuf.ByteString @@ -21,6 +23,8 @@ import com.google.protobuf.ByteString */ private[backend] object StorageBackendTestValues { + def hashCid(key: String): ContractId = ContractId.V1(Hash.hashPrivateKey(key)) + /** Produces offsets that are ordered the same as the input value */ def offset(x: Long): Offset = Offset.fromHexString(Ref.HexString.assertFromString(f"$x%08d")) def ledgerEnd(o: Long, e: Long): ParameterStorageBackend.LedgerEnd = @@ -108,7 +112,7 @@ private[backend] object StorageBackendTestValues { def dtoCreate( offset: Offset, eventSequentialId: Long, - contractId: String, + contractId: ContractId, signatory: String = "signatory", observer: String = "observer", commandId: String = UUID.randomUUID().toString, @@ -125,7 +129,7 @@ private[backend] object StorageBackendTestValues { submitters = None, node_index = Some(0), event_id = Some(EventId(transactionId, NodeId(0)).toLedgerString), - contract_id = contractId, + contract_id = contractId.coid, template_id = Some(someTemplateId.toString), flat_event_witnesses = Set(signatory, observer), tree_event_witnesses = Set(signatory, observer), @@ -151,7 +155,7 @@ private[backend] object StorageBackendTestValues { offset: Offset, eventSequentialId: Long, consuming: Boolean, - contractId: String, + contractId: ContractId, signatory: String = "signatory", actor: String = "actor", commandId: String = UUID.randomUUID().toString, @@ -168,7 +172,7 @@ private[backend] object StorageBackendTestValues { submitters = Some(Set(actor)), node_index = Some(0), event_id = Some(EventId(transactionId, NodeId(0)).toLedgerString), - contract_id = contractId, + contract_id = contractId.coid, template_id = Some(someTemplateId.toString), flat_event_witnesses = if (consuming) Set(signatory) else Set.empty, tree_event_witnesses = Set(signatory, actor), @@ -190,7 +194,7 @@ private[backend] object StorageBackendTestValues { def dtoDivulgence( offset: Option[Offset], eventSequentialId: Long, - contractId: String, + contractId: ContractId, submitter: String = "signatory", divulgee: String = "divulgee", commandId: String = UUID.randomUUID().toString, @@ -201,7 +205,7 @@ private[backend] object StorageBackendTestValues { workflow_id = Some("workflow_id"), application_id = Some(someApplicationId), submitters = Some(Set(submitter)), - contract_id = contractId, + contract_id = contractId.coid, template_id = Some(someTemplateId.toString), tree_event_witnesses = Set(divulgee), create_argument = Some(someSerializedDamlLfValue), diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsContracts.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsContracts.scala index 66d9b92f044..d04caa021c4 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsContracts.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsContracts.scala @@ -4,7 +4,6 @@ package com.daml.platform.store.backend import com.daml.lf.data.Ref -import com.daml.lf.value.Value.ContractId import org.scalatest.Inside import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -20,12 +19,12 @@ private[backend] trait StorageBackendTestsContracts import StorageBackendTestValues._ it should "correctly find an active contract" in { - val contractId = ContractId.V0.assertFromString("#1") + val contractId = hashCid("#1") val signatory = Ref.Party.assertFromString("signatory") val dtos: Vector[DbDto] = Vector( // 1: transaction with create node - dtoCreate(offset(1), 1L, contractId = contractId.coid, signatory = signatory), + dtoCreate(offset(1), 1L, contractId = contractId, signatory = signatory), DbDto.CreateFilter(1L, someTemplateId.toString, signatory), dtoCompletion(offset(1)), ) @@ -50,16 +49,16 @@ private[backend] trait StorageBackendTestsContracts } it should "not find an archived contract" in { - val contractId = ContractId.V0.assertFromString("#1") + val contractId = hashCid("#1") val signatory = Ref.Party.assertFromString("signatory") val dtos: Vector[DbDto] = Vector( // 1: transaction with create node - dtoCreate(offset(1), 1L, contractId = contractId.coid, signatory = signatory), + dtoCreate(offset(1), 1L, contractId = contractId, signatory = signatory), DbDto.CreateFilter(1L, someTemplateId.toString, signatory), dtoCompletion(offset(1)), // 2: transaction that archives the contract - dtoExercise(offset(2), 2L, true, contractId.coid), + dtoExercise(offset(2), 2L, true, contractId), dtoCompletion(offset(2)), ) @@ -80,12 +79,12 @@ private[backend] trait StorageBackendTestsContracts } it should "correctly find a divulged contract" in { - val contractId = ContractId.V0.assertFromString("#1") + val contractId = hashCid("#1") val divulgee = Ref.Party.assertFromString("divulgee") val dtos: Vector[DbDto] = Vector( // 1: divulgence - dtoDivulgence(Some(offset(1)), 1L, contractId = contractId.coid, divulgee = divulgee), + dtoDivulgence(Some(offset(1)), 1L, contractId = contractId, divulgee = divulgee), DbDto.CreateFilter(1L, someTemplateId.toString, divulgee), dtoCompletion(offset(1)), ) @@ -110,17 +109,17 @@ private[backend] trait StorageBackendTestsContracts } it should "correctly find an active contract that is also divulged" in { - val contractId = ContractId.V0.assertFromString("#1") + val contractId = hashCid("#1") val signatory = Ref.Party.assertFromString("signatory") val divulgee = Ref.Party.assertFromString("divulgee") val dtos: Vector[DbDto] = Vector( // 1: transaction with create node - dtoCreate(offset(1), 1L, contractId = contractId.coid, signatory = signatory), + dtoCreate(offset(1), 1L, contractId = contractId, signatory = signatory), DbDto.CreateFilter(1L, someTemplateId.toString, signatory), dtoCompletion(offset(1)), // 2: divulgence without any optional information - dtoDivulgence(Some(offset(2)), 2L, contractId = contractId.coid, divulgee = divulgee) + dtoDivulgence(Some(offset(2)), 2L, contractId = contractId, divulgee = divulgee) .copy(template_id = None, create_argument = None, create_argument_compression = None), DbDto.CreateFilter(2L, someTemplateId.toString, divulgee), dtoCompletion(offset(2)), @@ -146,21 +145,21 @@ private[backend] trait StorageBackendTestsContracts } it should "not disclose to divulgees that a contract was archived" in { - val contractId = ContractId.V0.assertFromString("#1") + val contractId = hashCid("#1") val signatory = Ref.Party.assertFromString("signatory") val divulgee = Ref.Party.assertFromString("divulgee") val dtos: Vector[DbDto] = Vector( // 1: transaction with create node - dtoCreate(offset(1), 1L, contractId = contractId.coid, signatory = signatory), + dtoCreate(offset(1), 1L, contractId = contractId, signatory = signatory), DbDto.CreateFilter(1L, someTemplateId.toString, signatory), dtoCompletion(offset(1)), // 2: divulgence - dtoDivulgence(Some(offset(2)), 2L, contractId = contractId.coid, divulgee = divulgee), + dtoDivulgence(Some(offset(2)), 2L, contractId = contractId, divulgee = divulgee), DbDto.CreateFilter(2L, someTemplateId.toString, divulgee), dtoCompletion(offset(2)), // 3: transaction that archives the contract - dtoExercise(offset(3), 3L, true, contractId.coid, signatory = signatory), + dtoExercise(offset(3), 3L, true, contractId, signatory = signatory), dtoCompletion(offset(3)), ) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsEvents.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsEvents.scala index 8b3f2ad7b85..2589f079339 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsEvents.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsEvents.scala @@ -24,10 +24,22 @@ private[backend] trait StorageBackendTestsEvents val partyObserver2 = Ref.Party.assertFromString("observer2") val dtos = Vector( - dtoCreate(offset(1), 1L, "#1", signatory = partySignatory, observer = partyObserver1), + dtoCreate( + offset(1), + 1L, + hashCid("#1"), + signatory = partySignatory, + observer = partyObserver1, + ), dtoCreateFilter(1L, someTemplateId, partySignatory), dtoCreateFilter(1L, someTemplateId, partyObserver1), - dtoCreate(offset(2), 2L, "#2", signatory = partySignatory, observer = partyObserver2), + dtoCreate( + offset(2), + 2L, + hashCid("#2"), + signatory = partySignatory, + observer = partyObserver2, + ), dtoCreateFilter(2L, someTemplateId, partySignatory), dtoCreateFilter(2L, someTemplateId, partyObserver2), ) @@ -74,10 +86,22 @@ private[backend] trait StorageBackendTestsEvents val partyObserver2 = Ref.Party.assertFromString("observer2") val dtos = Vector( - dtoCreate(offset(1), 1L, "#1", signatory = partySignatory, observer = partyObserver1), + dtoCreate( + offset(1), + 1L, + hashCid("#1"), + signatory = partySignatory, + observer = partyObserver1, + ), dtoCreateFilter(1L, someTemplateId, partySignatory), dtoCreateFilter(1L, someTemplateId, partyObserver1), - dtoCreate(offset(2), 2L, "#2", signatory = partySignatory, observer = partyObserver2), + dtoCreate( + offset(2), + 2L, + hashCid("#2"), + signatory = partySignatory, + observer = partyObserver2, + ), dtoCreateFilter(2L, someTemplateId, partySignatory), dtoCreateFilter(2L, someTemplateId, partyObserver2), ) @@ -125,10 +149,22 @@ private[backend] trait StorageBackendTestsEvents val otherTemplate = Ref.Identifier.assertFromString("pkg:Mod:Template2") val dtos = Vector( - dtoCreate(offset(1), 1L, "#1", signatory = partySignatory, observer = partyObserver1), + dtoCreate( + offset(1), + 1L, + hashCid("#1"), + signatory = partySignatory, + observer = partyObserver1, + ), dtoCreateFilter(1L, someTemplateId, partySignatory), dtoCreateFilter(1L, someTemplateId, partyObserver1), - dtoCreate(offset(2), 2L, "#2", signatory = partySignatory, observer = partyObserver2), + dtoCreate( + offset(2), + 2L, + hashCid("#2"), + signatory = partySignatory, + observer = partyObserver2, + ), dtoCreateFilter(2L, someTemplateId, partySignatory), dtoCreateFilter(2L, someTemplateId, partyObserver2), ) @@ -176,7 +212,7 @@ private[backend] trait StorageBackendTestsEvents val unknownTemplate = Ref.Identifier.assertFromString("unknown:unknown:unknown") val dtos = Vector( - dtoCreate(offset(1), 1L, "#1", signatory = partySignatory, observer = partyObserver), + dtoCreate(offset(1), 1L, hashCid("#1"), signatory = partySignatory, observer = partyObserver), dtoCreateFilter(1L, someTemplateId, partySignatory), dtoCreateFilter(1L, someTemplateId, partyObserver), ) @@ -223,10 +259,22 @@ private[backend] trait StorageBackendTestsEvents val partyObserver2 = Ref.Party.assertFromString("observer2") val dtos = Vector( - dtoCreate(offset(1), 1L, "#1", signatory = partySignatory, observer = partyObserver1), + dtoCreate( + offset(1), + 1L, + hashCid("#1"), + signatory = partySignatory, + observer = partyObserver1, + ), dtoCreateFilter(1L, someTemplateId, partySignatory), dtoCreateFilter(1L, someTemplateId, partyObserver1), - dtoCreate(offset(2), 2L, "#2", signatory = partySignatory, observer = partyObserver2), + dtoCreate( + offset(2), + 2L, + hashCid("#2"), + signatory = partySignatory, + observer = partyObserver2, + ), dtoCreateFilter(2L, someTemplateId, partySignatory), dtoCreateFilter(2L, someTemplateId, partyObserver2), ) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsInitializeIngestion.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsInitializeIngestion.scala index b9344edafa1..4a37e3f4779 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsInitializeIngestion.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsInitializeIngestion.scala @@ -4,7 +4,6 @@ package com.daml.platform.store.backend import com.daml.lf.data.Ref -import com.daml.lf.value.Value.ContractId import org.scalatest.Inside import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -29,12 +28,12 @@ private[backend] trait StorageBackendTestsInitializeIngestion dtoPackage(offset(3)), dtoPackageEntry(offset(3)), // 4: transaction with create node - dtoCreate(offset(4), 1L, "#4"), + dtoCreate(offset(4), 1L, hashCid("#4")), DbDto.CreateFilter(1L, someTemplateId.toString, someParty.toString), dtoCompletion(offset(4)), // 5: transaction with exercise node and retroactive divulgence - dtoExercise(offset(5), 2L, false, "#4"), - dtoDivulgence(Some(offset(5)), 3L, "#4"), + dtoExercise(offset(5), 2L, false, hashCid("#4")), + dtoDivulgence(Some(offset(5)), 3L, hashCid("#4")), dtoCompletion(offset(5)), ) @@ -47,12 +46,12 @@ private[backend] trait StorageBackendTestsInitializeIngestion dtoPackage(offset(8)), dtoPackageEntry(offset(8)), // 9: transaction with create node - dtoCreate(offset(9), 4L, "#9"), + dtoCreate(offset(9), 4L, hashCid("#9")), DbDto.CreateFilter(4L, someTemplateId.toString, someParty.toString), dtoCompletion(offset(9)), // 10: transaction with exercise node and retroactive divulgence - dtoExercise(offset(10), 5L, false, "#9"), - dtoDivulgence(Some(offset(10)), 6L, "#9"), + dtoExercise(offset(10), 5L, false, hashCid("#9")), + dtoDivulgence(Some(offset(10)), 6L, hashCid("#9")), dtoCompletion(offset(10)), ) @@ -80,13 +79,13 @@ private[backend] trait StorageBackendTestsInitializeIngestion val contract41 = executeSql( backend.contract.activeContractWithoutArgument( readers, - ContractId.V0.assertFromString("#4"), + hashCid("#4"), ) ) val contract91 = executeSql( backend.contract.activeContractWithoutArgument( readers, - ContractId.V0.assertFromString("#9"), + hashCid("#9"), ) ) val filterIds1 = executeSql( @@ -113,13 +112,13 @@ private[backend] trait StorageBackendTestsInitializeIngestion val contract42 = executeSql( backend.contract.activeContractWithoutArgument( readers, - ContractId.V0.assertFromString("#4"), + hashCid("#4"), ) ) val contract92 = executeSql( backend.contract.activeContractWithoutArgument( readers, - ContractId.V0.assertFromString("#9"), + hashCid("#9"), ) ) val filterIds2 = executeSql( diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsIntegrity.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsIntegrity.scala index e91fbce8f78..c90053e3eec 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsIntegrity.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsIntegrity.scala @@ -15,8 +15,8 @@ private[backend] trait StorageBackendTestsIntegrity extends Matchers with Storag it should "find duplicate event ids" in { val updates = Vector( - dtoCreate(offset(7), 7L, "#7"), - dtoCreate(offset(7), 7L, "#7"), // duplicate id + dtoCreate(offset(7), 7L, hashCid("#7")), + dtoCreate(offset(7), 7L, hashCid("#7")), // duplicate id ) executeSql(backend.parameter.initializeParameters(someIdentityParams)) @@ -30,8 +30,8 @@ private[backend] trait StorageBackendTestsIntegrity extends Matchers with Storag it should "find non-consecutive event ids" in { val updates = Vector( - dtoCreate(offset(1), 1L, "#1"), - dtoCreate(offset(3), 3L, "#3"), // non-consecutive id + dtoCreate(offset(1), 1L, hashCid("#1")), + dtoCreate(offset(3), 3L, hashCid("#3")), // non-consecutive id ) executeSql(backend.parameter.initializeParameters(someIdentityParams)) @@ -45,11 +45,11 @@ private[backend] trait StorageBackendTestsIntegrity extends Matchers with Storag it should "not find errors beyond the ledger end" in { val updates = Vector( - dtoCreate(offset(1), 1L, "#1"), - dtoCreate(offset(2), 2L, "#2"), - dtoCreate(offset(7), 7L, "#7"), // beyond the ledger end - dtoCreate(offset(7), 7L, "#7"), // duplicate id (beyond ledger end) - dtoCreate(offset(9), 9L, "#9"), // non-consecutive id (beyond ledger end) + dtoCreate(offset(1), 1L, hashCid("#1")), + dtoCreate(offset(2), 2L, hashCid("#2")), + dtoCreate(offset(7), 7L, hashCid("#7")), // beyond the ledger end + dtoCreate(offset(7), 7L, hashCid("#7")), // duplicate id (beyond ledger end) + dtoCreate(offset(9), 9L, hashCid("#9")), // non-consecutive id (beyond ledger end) ) executeSql(backend.parameter.initializeParameters(someIdentityParams)) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsMigrationPruning.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsMigrationPruning.scala index b9bb246dc5d..8ab01424933 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsMigrationPruning.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsMigrationPruning.scala @@ -6,7 +6,6 @@ package com.daml.platform.store.backend import java.sql.Connection import com.daml.lf.data.Ref -import com.daml.platform.store.appendonlydao.events.ContractId import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -17,13 +16,15 @@ private[backend] trait StorageBackendTestsMigrationPruning import StorageBackendTestValues._ + private val cid = hashCid("#1") + it should "prune all divulgence events if pruning offset is after migration offset" in { val divulgee = Ref.Party.assertFromString("divulgee") val submitter = Ref.Party.assertFromString("submitter") - val create = dtoCreate(offset(1), 1L, "#1", submitter) - val divulgence = dtoDivulgence(None, 2L, "#1", submitter, divulgee) - val archive = dtoExercise(offset(2), 3L, consuming = true, "#1", submitter) + val create = dtoCreate(offset(1), 1L, cid, submitter) + val divulgence = dtoDivulgence(None, 2L, cid, submitter, divulgee) + val archive = dtoExercise(offset(2), 3L, consuming = true, cid, submitter) executeSql(backend.parameter.initializeParameters(someIdentityParams)) executeSql(ingest(Vector(create, divulgence, archive), _)) @@ -34,7 +35,7 @@ private[backend] trait StorageBackendTestsMigrationPruning val beforePruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString("#1"), + cid, ) ) @@ -70,7 +71,7 @@ private[backend] trait StorageBackendTestsMigrationPruning val afterPruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString("#1"), + cid, ) ) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsPruning.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsPruning.scala index 2b0dfa5fb99..dbff3edceac 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsPruning.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsPruning.scala @@ -4,7 +4,6 @@ package com.daml.platform.store.backend import com.daml.lf.data.Ref -import com.daml.platform.store.appendonlydao.events.ContractId import com.daml.platform.store.backend.EventStorageBackend.{FilterParams, RangeParams} import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers @@ -83,7 +82,7 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB val create = dtoCreate( offset = offset(1), eventSequentialId = 1L, - contractId = "#1", + contractId = hashCid("#1"), signatory = someParty, ) val createFilter1 = DbDto.CreateFilter(1L, someTemplateId.toString, "signatory") @@ -93,7 +92,7 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB offset = offset(2), eventSequentialId = 2L, consuming = true, - contractId = "#1", + contractId = hashCid("#1"), signatory = someParty, ) val range = RangeParams(0L, 2L, None, None) @@ -168,7 +167,7 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB val create = dtoCreate( offset = offset(2), eventSequentialId = 1L, - contractId = "#1", + contractId = hashCid("#1"), signatory = someParty, ) val createFilter1 = DbDto.CreateFilter(1L, someTemplateId.toString, "signatory") @@ -243,8 +242,8 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB it should "prune all retroactively and immediately divulged contracts (if pruneAllDivulgedContracts is set)" in { val partyName = "party" val divulgee = Ref.Party.assertFromString(partyName) - val contract1_id = "#1" - val contract2_id = "#2" + val contract1_id = hashCid("#1") + val contract2_id = hashCid("#2") val contract1_immediateDivulgence = dtoCreate( offset = offset(1), @@ -287,13 +286,13 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB val contract1_beforePruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract1_id), + contract1_id, ) ) val contract2_beforePruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract2_id), + contract2_id, ) ) executeSql( @@ -305,13 +304,13 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB val contract1_afterPruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract1_id), + contract1_id, ) ) val contract2_afterPruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract2_id), + contract2_id, ) ) @@ -327,8 +326,8 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB it should "only prune retroactively divulged contracts if there exists an associated consuming exercise (if pruneAllDivulgedContracts is not set)" in { val signatory = "signatory" val divulgee = Ref.Party.assertFromString("party") - val contract1_id = "#1" - val contract2_id = "#2" + val contract1_id = hashCid("#1") + val contract2_id = hashCid("#2") val contract1_create = dtoCreate( offset = offset(1), @@ -376,13 +375,13 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB val contract1_beforePruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract1_id), + contract1_id, ) ) val contract2_beforePruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract2_id), + contract2_id, ) ) executeSql( @@ -394,13 +393,13 @@ private[backend] trait StorageBackendTestsPruning extends Matchers with StorageB val contract1_afterPruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract1_id), + contract1_id, ) ) val contract2_afterPruning = executeSql( backend.contract.activeContractWithoutArgument( Set(divulgee), - ContractId.assertFromString(contract2_id), + contract2_id, ) ) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsReset.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsReset.scala index ac946a942d6..70062b947b9 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsReset.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsReset.scala @@ -54,12 +54,12 @@ private[backend] trait StorageBackendTestsReset extends Matchers with StorageBac dtoPackage(offset(3)), dtoPackageEntry(offset(3)), // 4: transaction with create node - dtoCreate(offset(4), 1L, "#4"), + dtoCreate(offset(4), 1L, hashCid("#4")), DbDto.CreateFilter(1L, someTemplateId.toString, someParty.toString), dtoCompletion(offset(4)), // 5: transaction with exercise node and retroactive divulgence - dtoExercise(offset(5), 2L, true, "#4"), - dtoDivulgence(Some(offset(5)), 3L, "#4"), + dtoExercise(offset(5), 2L, true, hashCid("#4")), + dtoDivulgence(Some(offset(5)), 3L, hashCid("#4")), dtoCompletion(offset(5)), ) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsTimestamps.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsTimestamps.scala index 77a3a2ba4a4..1c22f53a319 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsTimestamps.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/backend/StorageBackendTestsTimestamps.scala @@ -21,11 +21,11 @@ private[backend] trait StorageBackendTestsTimestamps extends Matchers with Stora it should "correctly read ledger effective time using maximumLedgerTime" in { val let = timestampFromInstant(Instant.now) - val cid = com.daml.lf.value.Value.ContractId.V0.assertFromString("#1") + val cid = hashCid("#1") val create = dtoCreate( offset = offset(1), eventSequentialId = 1L, - contractId = cid.coid, + contractId = cid, ledgerEffectiveTime = Some(let), ) @@ -49,11 +49,11 @@ private[backend] trait StorageBackendTestsTimestamps extends Matchers with Stora it should "correctly read ledger effective time using rawEvents" in { val let = timestampFromInstant(Instant.now) - val cid = com.daml.lf.value.Value.ContractId.V0.assertFromString("#1") + val cid = hashCid("#1") val create = dtoCreate( offset = offset(1), eventSequentialId = 1L, - contractId = cid.coid, + contractId = cid, ledgerEffectiveTime = Some(let), ) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoContractsSpec.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoContractsSpec.scala index f0980ac8d5b..5d6d18a658e 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoContractsSpec.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoContractsSpec.scala @@ -3,6 +3,7 @@ package com.daml.platform.store.dao +import com.daml.lf.crypto.Hash import com.daml.lf.data.Time.Timestamp import java.util.UUID @@ -164,7 +165,7 @@ private[dao] trait JdbcLedgerDaoContractsSpec extends LoneElement with Inside wi } it should "prevent retrieving the maximum ledger time if some contracts are not found" in { - val randomContractId = ContractId.assertFromString(s"#random-${UUID.randomUUID}") + val randomContractId = ContractId.V1(Hash.hashPrivateKey(UUID.randomUUID.toString)) for { failure <- contractsReader.lookupMaximumLedgerTime(Set(randomContractId)).failed } yield { @@ -184,7 +185,7 @@ private[dao] trait JdbcLedgerDaoContractsSpec extends LoneElement with Inside wi } it should "allow the retrieval of the maximum ledger time even when there are divulged contracts" in { - val divulgedContractId = ContractId.assertFromString(s"#divulged-${UUID.randomUUID}") + val divulgedContractId = ContractId.V1(Hash.hashPrivateKey(UUID.randomUUID.toString)) for { // Some contract divulged (its create node was not witnessed by any party on this participant) (_, _) <- storeCommitedContractDivulgence( @@ -221,7 +222,7 @@ private[dao] trait JdbcLedgerDaoContractsSpec extends LoneElement with Inside wi } it should "allow the retrieval of the maximum ledger time even when there are only divulged contracts" in { - val divulgedContractId = ContractId.assertFromString(s"#divulged-${UUID.randomUUID}") + val divulgedContractId = ContractId.V1(Hash.hashPrivateKey(UUID.randomUUID.toString)) for { // Some contract divulged (its create node was not witnessed by any party on this participant) (_, _) <- storeCommitedContractDivulgence( diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala index 0c2bd4302cb..c6df550d90c 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoPostCommitValidationSpec.scala @@ -7,6 +7,7 @@ import java.util.UUID import com.codahale.metrics.MetricRegistry import com.daml.ledger.resources.ResourceOwner +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.transaction.BlindingInfo import com.daml.lf.value.Value.ContractId @@ -191,8 +192,8 @@ private[dao] trait JdbcLedgerDaoPostCommitValidationSpec extends LoneElement { it should "be able to use divulged contract in later transaction" in { - val divulgedContractId = - ContractId.assertFromString(s"#${UUID.randomUUID}") + val divulgedContractId: ContractId = + ContractId.V1(Hash.hashPrivateKey(UUID.randomUUID.toString)) val divulgedContracts = Map((divulgedContractId, someVersionedContractInstance) -> Set(alice)) diff --git a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoSuite.scala b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoSuite.scala index 0cec6ffce70..42b19162942 100644 --- a/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoSuite.scala +++ b/ledger/participant-integration-api/src/test/lib/scala/platform/store/dao/JdbcLedgerDaoSuite.scala @@ -16,6 +16,7 @@ import com.daml.ledger.participant.state.index.v2 import com.daml.ledger.participant.state.{v2 => state} import com.daml.ledger.test.ModelTestDar import com.daml.lf.archive.DarParser +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref.{Identifier, Party} import com.daml.lf.data.Time.Timestamp import com.daml.lf.data.{FrontStack, ImmArray, Ref, Time} @@ -134,7 +135,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend { ), ) protected final val someChoiceResult = - LfValue.ValueContractId(ContractId.V0.assertFromString("#1")) + LfValue.ValueContractId(ContractId.V1(Hash.hashPrivateKey("#1"))) protected final def someContractKey(party: Party, value: String): LfValue.ValueRecord = LfValue.ValueRecord( diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala index 17e21b328ba..249c9268520 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/apiserver/services/ApiSubmissionServiceSpec.scala @@ -72,7 +72,7 @@ class ApiSubmissionServiceSpec val (signatories, observers) = informeesOfNode.splitAt(2) builder.add( builder.create( - s"#contractId$i", + Value.ContractId.V1(Hash.hashPrivateKey(i.toString)).coid, "test:test", Value.ValueNil, signatories.toSeq, @@ -199,7 +199,7 @@ class ApiSubmissionServiceSpec val builder = TransactionBuilder() builder.add( builder.create( - s"#contractId1", + "00" + "00" * 32 + "01", "test:test", Value.ValueNil, Seq(party), @@ -244,7 +244,9 @@ class ApiSubmissionServiceSpec val errorsToExpectedStatuses: Seq[(ErrorCause, Status)] = List( ErrorCause.DamlLf( LfError.Interpretation( - LfError.Interpretation.DamlException(LfInterpretationError.ContractNotFound("#cid")), + LfError.Interpretation.DamlException( + LfInterpretationError.ContractNotFound("00" + "00" * 32) + ), None, ) ) -> ((Status.ABORTED, Status.NOT_FOUND)), diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/index/BuffersUpdaterSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/index/BuffersUpdaterSpec.scala index f05be08f11a..673ab6dd0b3 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/index/BuffersUpdaterSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/index/BuffersUpdaterSpec.scala @@ -10,6 +10,7 @@ import akka.stream.scaladsl.Source import akka.stream.{Materializer, QueueOfferResult} import ch.qos.logback.classic.Level import com.daml.ledger.offset.Offset +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.data.Time.Timestamp import com.daml.lf.transaction.{TransactionVersion, Versioned} @@ -197,7 +198,7 @@ final class BuffersUpdaterSpec } "convert TransactionLogUpdate.Transaction to a series of ContractStateEvent (created/archived)" in { - val createdCid = ContractId.assertFromString("#createdCid") + val createdCid = ContractId.V1(Hash.hashPrivateKey("createdCid")) val createdOffset = Offset.fromByteArray(BigInt(1337L).toByteArray) val createdEventSeqId = 9876L val createdLedgerEffectiveTime = Timestamp.assertFromLong(987654321L) @@ -208,7 +209,7 @@ final class BuffersUpdaterSpec val createArgument = Versioned(TransactionVersion.VDev, ValueText("arg")) val createAgreement = "agreement" - val exercisedCid = ContractId.assertFromString("#exercisedCid") + val exercisedCid = ContractId.V1(Hash.hashPrivateKey("exercisedCid")) val exercisedKey = Versioned(TransactionVersion.VDev, ValueInt64(8974L)) val exercisedTemplateId = Ref.Identifier.assertFromString("exercised:template:id") val exercisedFlatEventWitnesses = Set("bob", "dan") diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/index/EventFilterSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/index/EventFilterSpec.scala index 65866da06aa..df9ee029484 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/index/EventFilterSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/index/EventFilterSpec.scala @@ -3,6 +3,7 @@ package com.daml.platform.index +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.value.Value import com.daml.ledger.api.domain.{Filters, InclusiveFilters, TransactionFilter} @@ -19,7 +20,7 @@ final class EventFilterSpec extends AnyWordSpec with Matchers with ScalaFutures private val otherPartyWhoSeesEvents = Ref.Party.assertFromString("otherParty") private val packageId = "myPackage" private val eventId = Ref.LedgerString.assertFromString("someEventId") - private val contractId = Value.ContractId.assertFromString("#someContractId") + private val contractId = Value.ContractId.V1(Hash.hashPrivateKey("someContractId")) private val party1 = Ref.Party.assertFromString("party1") private val party2 = Ref.Party.assertFromString("party2") private val module1 = "module1" diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/index/TransactionConversionSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/index/TransactionConversionSpec.scala index cfbb4b09196..08b21f47a81 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/index/TransactionConversionSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/index/TransactionConversionSpec.scala @@ -7,6 +7,7 @@ import com.daml.ledger.api.domain.LedgerOffset import com.daml.ledger.api.v1.event.{ArchivedEvent, CreatedEvent, Event, ExercisedEvent} import com.daml.ledger.api.v1.transaction.TreeEvent import com.daml.ledger.api.v1.{value => v} +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref.LedgerString import com.daml.lf.data.Time.Timestamp import com.daml.lf.data.{ImmArray, Ref} @@ -129,14 +130,15 @@ final class TransactionConversionSpec extends AnyWordSpec with Matchers { ) "remove rollback nodes" in { + def cid(s: String): String = Value.ContractId.V1(Hash.hashPrivateKey(s)).coid val builder = TransactionBuilder() - builder.add(create(builder, "#1")) - val rollbackParent = builder.add(exercise(builder, "#0")) + builder.add(create(builder, cid("#1"))) + val rollbackParent = builder.add(exercise(builder, cid("#0"))) val rollback = builder.add(builder.rollback(), rollbackParent) - builder.add(create(builder, "#2"), rollback) - builder.add(exercise(builder, "#1"), rollback) - val ex = builder.add(exercise(builder, "#1")) - builder.add(create(builder, "#3"), ex) + builder.add(create(builder, cid("#2")), rollback) + builder.add(exercise(builder, cid("#1")), rollback) + val ex = builder.add(exercise(builder, cid("#1"))) + builder.add(create(builder, cid("#3")), ex) val transactionEntry = toEntry(builder.buildCommitted()) TransactionConversion .ledgerEntryToTransactionTree( @@ -147,10 +149,10 @@ final class TransactionConversionSpec extends AnyWordSpec with Matchers { ) .get .eventsById shouldBe Map( - "#transactionId:0" -> createdEv("0", "#1"), - "#transactionId:1" -> exercisedEv("1", "#0", Seq.empty), - "#transactionId:5" -> exercisedEv("5", "#1", Seq("6")), - "#transactionId:6" -> createdEv("6", "#3"), + "#transactionId:0" -> createdEv("0", cid("#1")), + "#transactionId:1" -> exercisedEv("1", cid("#0"), Seq.empty), + "#transactionId:5" -> exercisedEv("5", cid("#1"), Seq("6")), + "#transactionId:6" -> createdEv("6", cid("#3")), ) } } diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala index 89cfd7f0bfa..9a002296eb2 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala @@ -10,10 +10,10 @@ import com.daml.error.{ } import com.daml.ledger.api.domain import com.daml.ledger.api.domain.RejectionReason +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.transaction.GlobalKey -import com.daml.lf.value.Value -import com.daml.lf.value.Value.ValueText +import com.daml.lf.value.Value.{ContractId, ValueText} import com.daml.logging.{ContextualizedLogger, LoggingContext} import com.daml.platform.server.api.validation.ErrorFactories import com.daml.platform.store.Conversions._ @@ -33,6 +33,8 @@ class ConversionsSpec extends AsyncWordSpec with Matchers { None, ) + private def cid(key: String): ContractId = ContractId.V1(Hash.hashPrivateKey(key)) + "converting rejection reasons" should { "convert an 'Inconsistent' rejection reason" in { assertConversion(domain.RejectionReason.Inconsistent("This was not very consistent."))( @@ -53,17 +55,17 @@ class ConversionsSpec extends AsyncWordSpec with Matchers { } "convert an 'InconsistentContractKeys' rejection reason" in { - val cId = "#cId1" + val cId = cid("#cId1") assertConversion( domain.RejectionReason - .InconsistentContractKeys(Some(Value.ContractId.assertFromString(cId)), None) + .InconsistentContractKeys(Some(cId), None) )( v1expectedCode = Status.Code.ABORTED.value(), v1expectedMessage = - s"Inconsistent: Contract key lookup with different results: expected [Some(ContractId($cId))], actual [$None]", + s"Inconsistent: Contract key lookup with different results: expected [Some($cId)], actual [$None]", v2expectedCode = Status.Code.FAILED_PRECONDITION.value(), v2expectedMessage = - s"INCONSISTENT_CONTRACT_KEY(9,0): Contract key lookup with different results: expected [Some(ContractId($cId))], actual [$None]", + s"INCONSISTENT_CONTRACT_KEY(9,0): Contract key lookup with different results: expected [Some($cId)], actual [$None]", ) } diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/store/appendonlydao/events/PostCommitValidationSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/store/appendonlydao/events/PostCommitValidationSpec.scala index 8c28200d6a4..42d3fac8166 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/store/appendonlydao/events/PostCommitValidationSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/store/appendonlydao/events/PostCommitValidationSpec.scala @@ -5,6 +5,7 @@ package com.daml.platform.store.appendonlydao.events import com.daml.ledger.api.domain.PartyDetails import com.daml.ledger.offset.Offset +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.data.Time.Timestamp import com.daml.lf.transaction.GlobalKey @@ -523,7 +524,7 @@ object PostCommitValidationSpec { private def genTestCreate(): Create = txBuilder.create( - id = s"#${UUID.randomUUID}", + id = ContractId.V1(Hash.hashPrivateKey(UUID.randomUUID.toString)), templateId = "bar:baz", argument = TxBuilder.record("field" -> "value"), signatories = Set("Alice"), diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/store/cache/MutableCacheBackedContractStoreSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/store/cache/MutableCacheBackedContractStoreSpec.scala index 59de97018a9..ab8f6bbdb39 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/store/cache/MutableCacheBackedContractStoreSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/store/cache/MutableCacheBackedContractStoreSpec.scala @@ -13,6 +13,7 @@ import akka.stream.{BoundedSourceQueue, Materializer} import com.codahale.metrics.MetricRegistry import com.daml.ledger.offset.Offset import com.daml.ledger.resources.ResourceContext +import com.daml.lf.crypto.Hash import com.daml.lf.data.ImmArray import com.daml.lf.data.Time.Timestamp import com.daml.lf.transaction.GlobalKey @@ -551,7 +552,7 @@ object MutableCacheBackedContractStoreSpec { } private def contractId(id: Int): ContractId = - ContractId.assertFromString(s"#contract-$id") + ContractId.V1(Hash.hashPrivateKey(id.toString)) private def globalKey(desc: String): Key = GlobalKey.assertBuild(Identifier.assertFromString(s"some:template:$desc"), ValueText(desc)) diff --git a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/KeyValueCommittingSpec.scala b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/KeyValueCommittingSpec.scala index 612b28cff2c..ff61815a92b 100644 --- a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/KeyValueCommittingSpec.scala +++ b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/KeyValueCommittingSpec.scala @@ -24,8 +24,6 @@ import org.scalatest.wordspec.AnyWordSpec class KeyValueCommittingSpec extends AnyWordSpec with Matchers { - import TransactionBuilder.Implicits._ - private val metrics: Metrics = new Metrics(new MetricRegistry) private val keyValueSubmission = new KeyValueSubmission(metrics) @@ -64,7 +62,7 @@ class KeyValueCommittingSpec extends AnyWordSpec with Matchers { private def toSubmission(builder: TransactionBuilder): DamlSubmission = this.toSubmission(builder.buildSubmitted()) - private val contractId = "#1" + private val contractId = Value.ContractId.V1(crypto.Hash.hashPrivateKey("#1")) private val dedupKey = DamlStateKey.newBuilder .setCommandDedup( diff --git a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/CommitterModelConformanceValidatorSpec.scala b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/CommitterModelConformanceValidatorSpec.scala index 0286d817369..ecabe5cf9ed 100644 --- a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/CommitterModelConformanceValidatorSpec.scala +++ b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/CommitterModelConformanceValidatorSpec.scala @@ -70,7 +70,7 @@ class CommitterModelConformanceValidatorSpec keyAndMaintainer = Some(inputContractKey -> inputContractKeyMaintainer), ) private val aCreate = create(aContractId) - private val anotherCreate = create("#anotherContractId") + private val anotherCreate = create(ContractId.V1(Hash.hashPrivateKey("#anotherContractId"))) private val exercise = txBuilder.exercise( contract = inputCreate, @@ -247,7 +247,7 @@ class CommitterModelConformanceValidatorSpec ) val contractInstance = defaultValidator.lookupContract(commitContext)( - Conversions.decodeContractId(inputContractId) + Conversions.decodeContractId(inputContractId.coid) ) contractInstance shouldBe Some(aContractInst) @@ -259,7 +259,7 @@ class CommitterModelConformanceValidatorSpec None, Map.empty, ) - )(Conversions.decodeContractId(inputContractId)) + )(Conversions.decodeContractId(inputContractId.coid)) } } @@ -272,7 +272,7 @@ class CommitterModelConformanceValidatorSpec "return Some when mapping exists" in { defaultValidator.lookupKey(contractKeyInputs)( aGlobalKeyWithMaintainers(inputContractKey, inputContractKeyMaintainer) - ) shouldBe Some(Conversions.decodeContractId(inputContractId)) + ) shouldBe Some(Conversions.decodeContractId(inputContractId.coid)) } "return None when mapping does not exist" in { @@ -400,10 +400,10 @@ class CommitterModelConformanceValidatorSpec object CommitterModelConformanceValidatorSpec { - private val inputContractId = "#inputContractId" - private val inputContractIdStateKey = makeContractIdStateKey(inputContractId) - private val aContractId = "#someContractId" - private val contractIdStateKey1 = makeContractIdStateKey(aContractId) + private val inputContractId = ContractId.V1(Hash.hashPrivateKey("#inputContractId")) + private val inputContractIdStateKey = makeContractIdStateKey(inputContractId.coid) + private val aContractId = ContractId.V1(Hash.hashPrivateKey("#someContractId")) + private val contractIdStateKey1 = makeContractIdStateKey(aContractId.coid) private val inputContractKey = "inputContractKey" private val inputContractKeyMaintainer = "inputContractKeyMaintainer" private val aKey = "key" diff --git a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/TransactionConsistencyValidatorSpec.scala b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/TransactionConsistencyValidatorSpec.scala index 6f43e35bdb4..e042d60b43f 100644 --- a/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/TransactionConsistencyValidatorSpec.scala +++ b/ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/validation/TransactionConsistencyValidatorSpec.scala @@ -32,6 +32,7 @@ import com.daml.ledger.participant.state.kvutils.store.{ DamlStateValue, } import com.daml.ledger.validator.TestHelper.{makeContractIdStateKey, makeContractIdStateValue} +import com.daml.lf.crypto.Hash import com.daml.lf.data.{ImmArray, Ref} import com.daml.lf.transaction.SubmittedTransaction import com.daml.lf.transaction.test.TransactionBuilder @@ -56,7 +57,7 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { private val txBuilder = TransactionBuilder() private val conflictingKey = { - val aCreateNode = newCreateNodeWithFixedKey("#dummy") + val aCreateNode = newCreateNodeWithFixedKey(Value.ContractId.V1(Hash.hashPrivateKey("#dummy"))) Conversions.encodeContractKey(aCreateNode.templateId, aCreateNode.key.get.key) } @@ -101,8 +102,8 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "return DuplicateKeys when two local contracts conflict" in { val builder = TransactionBuilder() - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() val context = commitContextWithContractStateKeys(conflictingKey -> None) @@ -116,9 +117,9 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "return DuplicateKeys when a local contract conflicts with a global contract" in { val builder = TransactionBuilder() - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() - val context = commitContextWithContractStateKeys(conflictingKey -> Some(s"#$freshContractId")) + val context = commitContextWithContractStateKeys(conflictingKey -> Some(freshContractId.coid)) val result = validate(context, transaction) result shouldBe a[StepStop] val rejectionReason = @@ -127,31 +128,31 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { } "succeeds when a global contract gets archived before a local contract gets created" in { - val globalCid = s"#$freshContractId" + val globalCid = freshContractId val globalCreate = newCreateNodeWithFixedKey(globalCid) val context = createCommitContext( recordTime = None, inputs = Map( - makeContractIdStateKey(globalCid) -> Some(makeContractIdStateValue()), - contractStateKey(conflictingKey) -> Some(contractKeyStateValue(globalCid)), + makeContractIdStateKey(globalCid.coid) -> Some(makeContractIdStateValue()), + contractStateKey(conflictingKey) -> Some(contractKeyStateValue(globalCid.coid)), ), ) val builder = TransactionBuilder() builder.add(archive(globalCreate, Set("Alice"))) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() val result = validate(context, transaction) result shouldBe a[StepContinue[_]] } "succeeds when a local contract gets archived before another local contract gets created" in { - val localCid = s"#$freshContractId" + val localCid = freshContractId val context = commitContextWithContractStateKeys(conflictingKey -> None) val builder = TransactionBuilder() val localCreate = newCreateNodeWithFixedKey(localCid) builder.add(localCreate) builder.add(archive(localCreate, Set("Alice"))) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() val result = validate(context, transaction) result shouldBe a[StepContinue[_]] @@ -160,9 +161,9 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "return DuplicateKeys when a create in a rollback conflicts with a global key" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId"), rollback) + builder.add(newCreateNodeWithFixedKey(freshContractId), rollback) val transaction = builder.buildSubmitted() - val context = commitContextWithContractStateKeys(conflictingKey -> Some(s"#$freshContractId")) + val context = commitContextWithContractStateKeys(conflictingKey -> Some(freshContractId.coid)) val result = validate(context, transaction) result shouldBe a[StepStop] @@ -175,8 +176,8 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "not return DuplicateKeys between local contracts if first create is rolled back" in { val builder = TransactionBuilder() val rollback = builder.add(builder.rollback()) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId"), rollback) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId), rollback) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() @@ -187,9 +188,9 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "return DuplicateKeys between local contracts even if second create is rolled back" in { val builder = TransactionBuilder() - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val rollback = builder.add(builder.rollback()) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId"), rollback) + builder.add(newCreateNodeWithFixedKey(freshContractId), rollback) val transaction = builder.buildSubmitted() val context = commitContextWithContractStateKeys(conflictingKey -> None) @@ -203,11 +204,11 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "return DuplicateKeys between local contracts even if the first one was archived in a rollback" in { val builder = TransactionBuilder() - val create = newCreateNodeWithFixedKey(s"#$freshContractId") + val create = newCreateNodeWithFixedKey(freshContractId) builder.add(create) val rollback = builder.add(builder.rollback()) builder.add(archive(create, Set("Alice")), rollback) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() val context = commitContextWithContractStateKeys(conflictingKey -> None) @@ -221,12 +222,12 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { "return InconsistentKeys on conflict local and global contracts even if global was archived in a rollback" in { val builder = TransactionBuilder() - val globalCid = s"#$freshContractId" + val globalCid = freshContractId val rollback = builder.add(builder.rollback()) builder.add(archive(globalCid, Set("Alice")), rollback) - builder.add(newCreateNodeWithFixedKey(s"#$freshContractId")) + builder.add(newCreateNodeWithFixedKey(freshContractId)) val transaction = builder.buildSubmitted() - val context = commitContextWithContractStateKeys(conflictingKey -> Some(globalCid)) + val context = commitContextWithContractStateKeys(conflictingKey -> Some(globalCid.coid)) val result = validate(context, transaction) result shouldBe a[StepStop] @@ -239,12 +240,12 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { } "fail if a contract is not active anymore" in { - val globalCid = s"#$freshContractId" + val globalCid = freshContractId val globalCreate = newCreateNodeWithFixedKey(globalCid) val context = createCommitContext( recordTime = None, inputs = Map( - makeContractIdStateKey(globalCid) -> Some( + makeContractIdStateKey(globalCid.coid) -> Some( makeContractIdStateValue().toBuilder .setContractState( DamlContractState.newBuilder().setArchivedAt(Timestamp.getDefaultInstance) @@ -268,7 +269,7 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { inRollback: Boolean, ): SubmittedTransaction = { val lookup = - txBuilder.lookupByKey(newCreateNodeWithFixedKey(contractId = s"#$freshContractId"), found) + txBuilder.lookupByKey(newCreateNodeWithFixedKey(contractId = freshContractId), found) val builder = TransactionBuilder() if (inRollback) { val rollback = builder.add(txBuilder.rollback()) @@ -279,7 +280,7 @@ class TransactionConsistencyValidatorSpec extends AnyWordSpec with Matchers { builder.buildSubmitted() } - private def newCreateNodeWithFixedKey(contractId: String): Node.Create = + private def newCreateNodeWithFixedKey(contractId: Value.ContractId): Node.Create = create(contractId, signatories = Set("Alice"), keyAndMaintainer = Some(aKey -> "Alice")) private def create( @@ -326,8 +327,8 @@ object TransactionConsistencyValidatorSpec { private val aKey = "key" private val aDummyValue = TransactionBuilder.record("field" -> "value") - private def freshContractId: String = - s"testContractId-${UUID.randomUUID().toString.take(10)}" + private def freshContractId: Value.ContractId = + Value.ContractId.V1(Hash.hashPrivateKey(UUID.randomUUID.toString)) private def commitContextWithContractStateKeys( contractKeyIdPairs: (DamlContractKey, Option[String])* diff --git a/ledger/participant-state/kvutils/tools/src/test/scala/ledger/participant/state/kvutils/tools/integritycheck/StateUpdateComparisonSpec.scala b/ledger/participant-state/kvutils/tools/src/test/scala/ledger/participant/state/kvutils/tools/integritycheck/StateUpdateComparisonSpec.scala index 137246f2d3d..1ce63885057 100644 --- a/ledger/participant-state/kvutils/tools/src/test/scala/ledger/participant/state/kvutils/tools/integritycheck/StateUpdateComparisonSpec.scala +++ b/ledger/participant-state/kvutils/tools/src/test/scala/ledger/participant/state/kvutils/tools/integritycheck/StateUpdateComparisonSpec.scala @@ -107,8 +107,8 @@ final class StateUpdateComparisonSpec private def buildATransaction(withFetchAndLookupByKeyNodes: Boolean): CommittedTransaction = { val builder = TransactionBuilder() - val create1 = create("#someContractId") - val create2 = create("#otherContractId") + val create1 = create(ContractId.V1(crypto.Hash.hashPrivateKey("#someContractId"))) + val create2 = create(ContractId.V1(crypto.Hash.hashPrivateKey("#otherContractId"))) val fetch1 = builder.fetch(create1) val lookup1 = builder.lookupByKey(create1, found = true) val fetch2 = builder.fetch(create2) diff --git a/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala b/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala index 5c8ae47c359..9a171d7a03d 100644 --- a/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala +++ b/ledger/sandbox-classic/src/main/scala/platform/sandbox/SandboxServer.scala @@ -384,7 +384,7 @@ final class SandboxServer( maxDeduplicationDurationEnforced = false, ), contractIdFeatures = ExperimentalContractIds.of( - v0 = ExperimentalContractIds.ContractIdV0Support.SUPPORTED, + v0 = ExperimentalContractIds.ContractIdV0Support.NOT_SUPPORTED, v1 = ExperimentalContractIds.ContractIdV1Support.NON_SUFFIXED, ), ), diff --git a/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/SandboxOnXRunner.scala b/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/SandboxOnXRunner.scala index 40c0ac8e32e..be0c9b9155b 100644 --- a/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/SandboxOnXRunner.scala +++ b/ledger/sandbox-on-x/src/main/scala/com/daml/ledger/sandbox/SandboxOnXRunner.scala @@ -260,7 +260,7 @@ object SandboxOnXRunner { maxDeduplicationDurationEnforced = false, ), contractIdFeatures = ExperimentalContractIds.of( - v0 = ExperimentalContractIds.ContractIdV0Support.SUPPORTED, + v0 = ExperimentalContractIds.ContractIdV0Support.NOT_SUPPORTED, v1 = ExperimentalContractIds.ContractIdV1Support.NON_SUFFIXED, ), ), diff --git a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/ConflictCheckWithCommittedSpec.scala b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/ConflictCheckWithCommittedSpec.scala index 8a5e31e51b3..f2840875cc9 100644 --- a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/ConflictCheckWithCommittedSpec.scala +++ b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/ConflictCheckWithCommittedSpec.scala @@ -227,7 +227,7 @@ object ConflictCheckWithCommittedSpec { private val offsetString = Ref.HexString.assertFromString("ab") private val offset = Offset.fromHexString(offsetString) - private def cid(i: Int): Value.ContractId = Value.ContractId.V0.assertFromString(s"#$i") + private def cid(i: Int): Value.ContractId = Value.ContractId.V1(Hash.hashPrivateKey(i.toString)) private def contractKey(idx: Long) = GlobalKey.assertBuild( templateId = templateId, key = Value.ValueInt64(idx), diff --git a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionSpec.scala b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionSpec.scala index c33f443ec0b..4477ac85b00 100644 --- a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionSpec.scala +++ b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/PrepareSubmissionSpec.scala @@ -39,6 +39,8 @@ class PrepareSubmissionSpec extends AsyncFlatSpec with Matchers { new BridgeMetrics(new Metrics(new MetricRegistry)) ) + private def cid(key: String): ContractId = ContractId.V1(Hash.hashPrivateKey(key)) + behavior of classOf[PrepareSubmissionImpl].getSimpleName it should "forward the correct failure on inconsistent keys" in { @@ -48,7 +50,7 @@ class PrepareSubmissionSpec extends AsyncFlatSpec with Matchers { val keyValue = Value.ValueText("key-1") val createNode = txBuilder.create( - id = ContractId.assertFromString("#1"), + id = cid("#1"), templateId = templateId, argument = Value.ValueInt64(1), signatories = Set.empty, @@ -60,7 +62,7 @@ class PrepareSubmissionSpec extends AsyncFlatSpec with Matchers { val contractKey = GlobalKey.assertBuild(templateId, keyValue) val otherCreateNode = txBuilder.create( - id = ContractId.assertFromString("#2"), + id = cid("#2"), templateId = templateId, argument = Value.ValueInt64(1), signatories = Set.empty, @@ -100,7 +102,7 @@ class PrepareSubmissionSpec extends AsyncFlatSpec with Matchers { val keyValue = Value.ValueText("key-1") val createNode = txBuilder.create( - id = ContractId.assertFromString("#1"), + id = cid("#1"), templateId = templateId, argument = Value.ValueInt64(1), signatories = Set.empty, diff --git a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequenceSpec.scala b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequenceSpec.scala index 019227d476e..02dccb25c15 100644 --- a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequenceSpec.scala +++ b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequenceSpec.scala @@ -155,7 +155,7 @@ class SequenceSpec extends AnyFlatSpec with MockitoSugar with Matchers with Argu // Reject when trying to archive a contract again val Seq((offset4, update4)) = sequence(consume(cId(3))) offset4 shouldBe toOffset(4L) - assertCommandRejected(update4, "Inconsistent: Could not lookup contracts: [#3]") + assertCommandRejected(update4, s"Inconsistent: Could not lookup contracts: [${cId(3).coid}]") // Archiving a contract with an assigned key for the first time succeeds val Seq((offset5, update5)) = sequence(consume(cId(4), Some(contractKey(2L)))) @@ -167,7 +167,7 @@ class SequenceSpec extends AnyFlatSpec with MockitoSugar with Matchers with Argu offset6 shouldBe toOffset(6L) assertCommandRejected( update6, - "Inconsistent: Contract key lookup with different results: expected [None], actual [Some(ContractId(#5))]", + s"Inconsistent: Contract key lookup with different results: expected [None], actual [Some(${cId(5)})]", ) // Reject on inconsistent key usage @@ -175,7 +175,7 @@ class SequenceSpec extends AnyFlatSpec with MockitoSugar with Matchers with Argu offset7 shouldBe toOffset(7L) assertCommandRejected( update7, - "Inconsistent: Contract key lookup with different results: expected [Some(ContractId(#1))], actual [Some(ContractId(#5))]", + s"Inconsistent: Contract key lookup with different results: expected [Some(${cId(1)})], actual [Some(${cId(5)})]", ) } @@ -426,5 +426,5 @@ class SequenceSpec extends AnyFlatSpec with MockitoSugar with Matchers with Argu GlobalKey(templateId, Value.ValueInt64(i)) } - private def cId(i: Int) = ContractId.assertFromString(s"#$i") + private def cId(i: Int) = ContractId.V1(Hash.hashPrivateKey(i.toString)) } diff --git a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequencerStateSpec.scala b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequencerStateSpec.scala index affa2945acd..07e8ba17091 100644 --- a/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequencerStateSpec.scala +++ b/ledger/sandbox-on-x/src/test/suite/scala/com/daml/ledger/sandbox/bridge/validate/SequencerStateSpec.scala @@ -7,6 +7,7 @@ import com.codahale.metrics.MetricRegistry import com.daml.ledger.sandbox.bridge.BridgeMetrics import com.daml.ledger.sandbox.bridge.LedgerBridge.toOffset import com.daml.ledger.sandbox.bridge.validate.SequencerState.SequencerQueue +import com.daml.lf.crypto.Hash import com.daml.lf.data.Ref import com.daml.lf.transaction.GlobalKey import com.daml.lf.value.Value @@ -117,5 +118,5 @@ class SequencerStateSpec extends AnyFlatSpec with Matchers { GlobalKey(templateId, Value.ValueInt64(i)) } - private def cid(i: Int) = ContractId.assertFromString(s"#$i") + private def cid(i: Int): ContractId = ContractId.V1(Hash.hashPrivateKey(i.toString)) } diff --git a/navigator/backend/src/test/scala/com/digitalasset/navigator/backend/DamlConstants.scala b/navigator/backend/src/test/scala/com/digitalasset/navigator/backend/DamlConstants.scala index 806658d862a..2942d8e0e7b 100644 --- a/navigator/backend/src/test/scala/com/digitalasset/navigator/backend/DamlConstants.scala +++ b/navigator/backend/src/test/scala/com/digitalasset/navigator/backend/DamlConstants.scala @@ -240,7 +240,7 @@ case object DamlConstants { ("fUnit", V.ValueUnit), ("fInt64", simpleInt64V), ("fParty", V.ValueParty(DamlLfRef.Party assertFromString "BANK1")), - ("fContractId", V.ValueContractId(V.ContractId.assertFromString("#C0"))), + ("fContractId", V.ValueContractId(V.ContractId.assertFromString("00" + "00" * 32 + "c0"))), ("fListOfText", V.ValueList(FrontStack(V.ValueText("foo"), V.ValueText("bar")))), ("fListOfUnit", V.ValueList(FrontStack(V.ValueUnit, V.ValueUnit))), ("fDate", simpleDateV), diff --git a/security-evidence.md b/security-evidence.md index 7c434086093..444dba5aceb 100644 --- a/security-evidence.md +++ b/security-evidence.md @@ -87,29 +87,29 @@ ## Input Validation: - ensure builtin operators have the correct type: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L47) - ensure expression forms have the correct type: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L107) -- ill-formed create command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L133) -- ill-formed create-and-exercise command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L154) +- ill-formed create command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L134) +- ill-formed create-and-exercise command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L155) - ill-formed exception definitions are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L1415) -- ill-formed exercise command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L138) -- ill-formed exercise-by-key command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L145) +- ill-formed exercise command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L139) +- ill-formed exercise-by-key command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L146) - ill-formed expressions are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L420) -- ill-formed fetch command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L167) -- ill-formed fetch-by-key command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L170) +- ill-formed fetch command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L168) +- ill-formed fetch-by-key command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L171) - ill-formed interfaces are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L1308) - ill-formed kinds are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L19) -- ill-formed lookup command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L175) +- ill-formed lookup command is rejected: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L176) - ill-formed records are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L1557) - ill-formed templates are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L936) - ill-formed type synonyms applications are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L1536) - ill-formed type synonyms definitions are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L1603) - ill-formed types are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L99) - ill-formed variants are rejected: [TypingSpec.scala](daml-lf/validation/src/test/scala/com/digitalasset/daml/lf/validation/TypingSpec.scala#L1580) -- well formed create command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L79) -- well formed create-and-exercise command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L98) -- well formed exercise command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L84) -- well formed exercise-by-key command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L91) -- well formed fetch command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L105) -- well formed fetch-by-key command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L110) -- well formed lookup command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L115) +- well formed create command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L80) +- well formed create-and-exercise command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L99) +- well formed exercise command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L85) +- well formed exercise-by-key command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L92) +- well formed fetch command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L106) +- well formed fetch-by-key command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L111) +- well formed lookup command is accepted: [CommandPreprocessorSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/CommandPreprocessorSpec.scala#L116) diff --git a/triggers/runner/src/main/scala/com/digitalasset/daml/lf/engine/trigger/Converter.scala b/triggers/runner/src/main/scala/com/digitalasset/daml/lf/engine/trigger/Converter.scala index 3750af2b280..074651f64bc 100644 --- a/triggers/runner/src/main/scala/com/digitalasset/daml/lf/engine/trigger/Converter.scala +++ b/triggers/runner/src/main/scala/com/digitalasset/daml/lf/engine/trigger/Converter.scala @@ -504,7 +504,6 @@ object Converter { def apply(compiledPackages: CompiledPackages, triggerIds: TriggerIds): Converter = { val valueTranslator = new preprocessing.ValueTranslator( compiledPackages.interface, - forbidV0ContractId = false, requireV1ContractIdSuffix = false, ) Converter(