diff --git a/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala b/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala index 24a3edaa1c3a..76be32d09efb 100644 --- a/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala +++ b/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala @@ -43,7 +43,7 @@ private[lf] object Pretty { char('\'') + text(p) + char('\'') def prettyParties(p: Set[Party]): Doc = - char('{') & intercalate(char(','), p.map(prettyParty)) & char('{') + char('{') & intercalate(char(','), p.map(prettyParty)) & char('}') def prettyDamlException(error: interpretation.Error): Doc = { import interpretation.Error._ diff --git a/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala b/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala index f971d2b40b6e..f768f3569a57 100644 --- a/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala +++ b/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SBuiltin.scala @@ -1197,7 +1197,7 @@ private[lf] object SBuiltin { coid: V.ContractId, ifaceId: TypeConName, )(k: SAny => Control[Question.Update]): Control[Question.Update] = { - fetchAny(machine, None, coid) { (_, srcContract) => + fetchAny(machine, None, coid) { (_, srcContract, _) => val (tplId, arg) = getSAnyContract(ArrayList.single(srcContract), 0) ensureTemplateImplementsInterface(machine, ifaceId, coid, tplId) { viewInterface(machine, ifaceId, tplId, arg) { srcView => @@ -1218,12 +1218,12 @@ private[lf] object SBuiltin { coid: V.ContractId, interfaceId: TypeConName, )(k: SAny => Control[Question.Update]): Control[Question.Update] = - fetchAny(machine, None, coid) { (maybePkgName, srcContract) => + fetchAny(machine, None, coid) { (maybePkgName, srcContractAny, srcContract) => maybePkgName match { case None => crash(s"unexpected contract instance without packageName") case Some(pkgName) => - val (srcTplId, srcArg) = getSAnyContract(ArrayList.single(srcContract), 0) + val (srcTplId, srcArg) = getSAnyContract(ArrayList.single(srcContractAny), 0) ensureTemplateImplementsInterface(machine, interfaceId, coid, srcTplId) { viewInterface(machine, interfaceId, srcTplId, srcArg) { srcView => resolvePackageName(machine, pkgName) { pkgId => @@ -1251,7 +1251,7 @@ private[lf] object SBuiltin { if (dstTplId == srcTplId) k(SAny(Ast.TTyCon(dstTplId), dstArg)) else { - validateContractInfo(machine, coid, dstTplId, contract) { () => + checkContractUpgradable(coid, srcContract, contract) { () => executeExpression(machine, SEPreventCatch(dstView)) { dstViewValue => if (srcViewValue != dstViewValue) { @@ -1306,7 +1306,7 @@ private[lf] object SBuiltin { machine: UpdateMachine, ): Control[Question.Update] = { val coid = getSContractId(args, 0) - fetchAny(machine, optTargetTemplateId, coid) { (_, sv) => + fetchAny(machine, optTargetTemplateId, coid) { (_, sv, _) => Control.Value(sv) } } @@ -2369,7 +2369,7 @@ private[lf] object SBuiltin { optTargetTemplateId: Option[TypeConName], coid: V.ContractId, )(f: SValue => Control[Question.Update]): Control[Question.Update] = { - fetchAny(machine, optTargetTemplateId, coid) { (_, fetched) => + fetchAny(machine, optTargetTemplateId, coid) { (_, fetched, _) => // The SBCastAnyContract check can never fail when the upgrading feature flag is enabled. // This is because the contract got up/down-graded when imported by importValue. @@ -2386,16 +2386,62 @@ private[lf] object SBuiltin { } } + /** Checks that the metadata of [original] and [recomputed] are the same, fails with a [Control.Error] if not. */ + private def checkContractUpgradable( + coid: V.ContractId, + original: ContractInfo, + recomputed: ContractInfo, + )( + k: () => Control[Question.Update] + ): Control[Question.Update] = { + + def check[T](getter: ContractInfo => T, desc: String): Option[String] = + Option.when(getter(recomputed) != getter(original))( + s"$desc mismatch: $original vs $recomputed" + ) + + List( + check(_.signatories, "signatories"), + // This definition of observers allows observers to lose parties that are signatories + check(c => c.nonSignatoryStakeholders, "non signatory stakeholders"), + check(_.keyOpt.map(_.maintainers), "key maintainers"), + check(_.keyOpt.map(_.globalKey.key), "key value"), + ).flatten match { + case Nil => k() + case errors => + Control.Error( + IE.Upgrade( + // TODO(https://github.com/digital-asset/daml/issues/20305): also include the original metadata + IE.Upgrade.ValidationFailed( + coid = coid, + srcTemplateId = original.templateId, + dstTemplateId = recomputed.templateId, + signatories = recomputed.signatories, + observers = recomputed.observers, + keyOpt = recomputed.keyOpt.map(_.globalKeyWithMaintainers), + msg = errors.mkString("['", "', '", "']"), + ) + ) + ) + } + } + // This is the core function which fetches a contract given its coid. // Regardless of it being a local, disclosed or global contract private def fetchAny( machine: UpdateMachine, optTargetTemplateId: Option[TypeConName], coid: V.ContractId, - )(f: (Option[Ref.PackageName], SValue) => Control[Question.Update]): Control[Question.Update] = { + )( + f: (Option[Ref.PackageName], SValue, ContractInfo) => Control[Question.Update] + ): Control[Question.Update] = { - def importContract(coinst: V.ContractInstance) = { - val V.ContractInstance(_, srcTmplId, coinstArg) = coinst + def importContract( + srcContract: ContractInfo + ) = { + val srcTmplId = srcContract.templateId + val coinst = + V.ContractInstance(srcContract.packageName, srcContract.templateId, srcContract.arg) val (upgradingIsEnabled, dstTmplId) = optTargetTemplateId match { case Some(tycon) if coinst.upgradable => (true, tycon) @@ -2411,19 +2457,19 @@ private[lf] object SBuiltin { dstTmplId.packageId, language.Reference.Template(dstTmplId), ) { () => - importValue(machine, dstTmplId, coinstArg) { templateArg => + importValue(machine, dstTmplId, srcContract.arg) { templateArg => getContractInfo( machine, coid, dstTmplId, templateArg, allowCatchingContractInfoErrors = false, - ) { contract => - ensureContractActive(machine, coid, contract.templateId) { + ) { dstContract => + ensureContractActive(machine, coid, dstContract.templateId) { - machine.checkContractVisibility(coid, contract) + machine.checkContractVisibility(coid, dstContract) machine.enforceLimitAddInputContract() - machine.enforceLimitSignatoriesAndObservers(coid, contract) + machine.enforceLimitSignatoriesAndObservers(coid, dstContract) // In Validation mode, we always call validateContractInfo // In Submission mode, we only call validateContractInfo when src != dest @@ -2435,12 +2481,11 @@ private[lf] object SBuiltin { upgradingIsEnabled && (srcTmplId.packageId != dstTmplId.packageId) } if (needValidationCall) { - - validateContractInfo(machine, coid, srcTmplId, contract) { () => - f(contract.packageName, contract.any) + checkContractUpgradable(coid, srcContract, dstContract) { () => + f(dstContract.packageName, dstContract.any, dstContract) } } else { - f(contract.packageName, contract.any) + f(dstContract.packageName, dstContract.any, dstContract) } } } @@ -2461,58 +2506,32 @@ private[lf] object SBuiltin { if (optTargetTemplateId.forall(_ == templateId)) { // If the local contract has the same package ID as the target template ID, then we don't need to // import its value and validate its contract info again. - f(contract.packageName, SValue.SAnyContract(templateId, templateArg)) + f(contract.packageName, SValue.SAnyContract(templateId, templateArg), contract) } else { - importContract(V.ContractInstance(contract.packageName, templateId, contract.arg)) + importContract(contract) } } } case None => - machine.lookupGlobalContract(coid)(importContract) + machine.lookupGlobalContract(coid)(coinst => + machine.ensurePackageIsLoaded( + coinst.template.packageId, + language.Reference.Template(coinst.template), + ) { () => + importValue(machine, coinst.template, coinst.arg) { templateArg => + getContractInfo( + machine, + coid, + coinst.template, + templateArg, + allowCatchingContractInfoErrors = false, + )(importContract) + } + } + ) } } - private def validateContractInfo( - machine: UpdateMachine, - coid: V.ContractId, - srcTemplateId: Ref.Identifier, - contract: ContractInfo, - )( - continue: () => Control[Question.Update] - ): Control[Question.Update] = { - - val keyOpt: Option[GlobalKeyWithMaintainers] = contract.keyOpt match { - case None => None - case Some(cachedKey) => - Some(cachedKey.globalKeyWithMaintainers) - } - machine.needUpgradeVerification( - location = NameOf.qualifiedNameOfCurrentFunc, - coid = coid, - signatories = contract.signatories, - observers = contract.observers, - keyOpt = keyOpt, - continue = { - case None => - continue() - case Some(msg) => - Control.Error( - IE.Upgrade( - IE.Upgrade.ValidationFailed( - coid = coid, - srcTemplateId = srcTemplateId, - dstTemplateId = contract.templateId, - signatories = contract.signatories, - observers = contract.observers, - keyOpt = keyOpt, - msg = msg, - ) - ) - ) - }, - ) - } - private def importValue[Q](machine: Machine[Q], templateId: TypeConName, coinstArg: V)( f: SValue => Control[Q] ): Control[Q] = { diff --git a/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala b/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala index 142639b6afbf..d3093d98e455 100644 --- a/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala +++ b/sdk/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Speedy.scala @@ -146,6 +146,7 @@ private[lf] object Speedy { keyOpt: Option[CachedKey], ) { val stakeholders: Set[Party] = signatories union observers + lazy val nonSignatoryStakeholders: Set[Party] = stakeholders -- signatories private[speedy] val any = SValue.SAnyContract(templateId, value) private[speedy] def arg = value.toNormalizedValue(version) diff --git a/sdk/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/UpgradeTest.scala b/sdk/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/UpgradeTest.scala index 646bcb5c193c..56846e8c4ac9 100644 --- a/sdk/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/UpgradeTest.scala +++ b/sdk/daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/UpgradeTest.scala @@ -165,6 +165,9 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) val do_fetch: ContractId M:T -> Update M:T = \(cId: ContractId M:T) -> fetch_template @M:T cId; + + val do_exercise: ContractId M:T -> Update Unit = + \(cId: ContractId M:T) -> exercise @M:T NoOp cId (); } """ } @@ -193,6 +196,8 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) \(cId: ContractId M:T) -> fetch_template @M:T cId; + val do_exercise: ContractId M:T -> Update Unit = + \(cId: ContractId M:T) -> exercise @M:T NoOp cId (); } """ } @@ -315,7 +320,11 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) } // The given contractSValue is wrapped as a disclosedContract - def goDisclosed(e: Expr, contractSValue: SValue): Either[SError, Success] = { + def goDisclosed( + e: Expr, + templateId: Ref.TypeConName, + contractSValue: SValue, + ): Either[SError, Success] = { val se: SExpr = pkgs.compiler.unsafeCompile(e) val args = Array[SValue](SContractId(theCid)) @@ -330,7 +339,7 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) Speedy.ContractInfo( version = V17, packageName = pkgName, - templateId = i"'-unknown-':M:T", + templateId = templateId, value = contractSValue, agreementText = "meh", signatories = Set.empty, @@ -425,43 +434,6 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) v shouldBe v_missingField } } - - "missing non-optional field -- should be rejected" in { - // should be caught by package upgradability check - val v_missingField = makeRecord(ValueParty(alice)) - - inside( - go(e"'-pkg1-':M:do_fetch", ContractInstance(pkgName, i"'-unknow-':M:T", v_missingField)) - ) { case Left(SError.SErrorCrash(_, reason)) => - reason should include( - "Unexpected non-optional extra template field type encountered during upgrading" - ) - } - } - - "mismatching qualified name -- should be rejected" in { - val v = - makeRecord( - ValueParty(alice), - ValueParty(bob), - ValueInt64(100), - ValueOptional(None), - ) - - val expectedTyCon = i"'-pkg3-':M:T" - val negativeTestCase = i"'-pkg2-':M:T" - val positiveTestCases = Table("tyCon", i"'-pkg2-':M1:T", i"'-pkg2-':M2:T") - go(e"'-pkg3-':M:do_fetch", ContractInstance(pkgName, negativeTestCase, v)) shouldBe a[ - Right[_, _] - ] - - forEvery(positiveTestCases) { tyCon => - inside(go(e"'-pkg3-':M:do_fetch", ContractInstance(pkgName, tyCon, v))) { - case Left(SError.SErrorDamlException(e)) => - e shouldBe IE.WronglyTypedContract(theCid, expectedTyCon, tyCon) - } - } - } } "downgrade attempted" - { @@ -475,28 +447,6 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) } } - "extra field (text) - something is very wrong" in { - // should be caught by package upgradability check - - val v1_extraText = - makeRecord( - ValueParty(alice), - ValueParty(bob), - ValueInt64(100), - ValueText("extra"), - ) - - val res = - go(e"'-pkg1-':M:do_fetch", ContractInstance(pkgName, i"'-unknown-':M:T", v1_extraText)) - - inside(res) { case Left(SError.SErrorCrash(_, reason)) => - reason should include( - "Unexpected non-optional extra contract field encountered during downgrading" - ) - } - - } - "extra field (Some) - cannot be dropped" in { val v1_extraSome = @@ -525,7 +475,7 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) ) val res = - go(e"'-pkg2-':M:do_fetch", ContractInstance(pkgName, i"'-unknow-':M:T", v1_extraNone)) + go(e"'-pkg1-':M:do_fetch", ContractInstance(pkgName, i"'-pkg3-':M:T", v1_extraNone)) inside(res) { case Right((_, v, _)) => v shouldBe v1_base @@ -560,10 +510,8 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) in upure @(ContractId '-pkg1-':M:T) cid """ ) - inside(res) { case Right((_, ValueContractId(cid), verificationRequests)) => - verificationRequests shouldBe List( - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v1_key)) - ) + inside(res) { case Right((_, v, List())) => + v shouldBe a[ValueContractId] } } @@ -576,11 +524,8 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) in upure @(ContractId '-pkg1-':M:T) cid """ ) - inside(res) { case Right((_, ValueContractId(cid), verificationRequests)) => - verificationRequests shouldBe List( - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v2_key)), - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v2_key)), - ) + inside(res) { case Right((_, v, List())) => + v shouldBe a[ValueContractId] } } @@ -592,10 +537,8 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) in upure @(ContractId '-pkg1-':M:T) cid """ ) - inside(res) { case Right((_, ValueContractId(cid), verificationRequests)) => - verificationRequests shouldBe List( - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v1_key)) - ) + inside(res) { case Right((_, v, List())) => + v shouldBe a[ValueContractId] } } @@ -608,16 +551,12 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) in upure @(ContractId '-pkg1-':M:T) cid """ ) - inside(res) { case Right((_, ValueContractId(cid), verificationRequests)) => - verificationRequests shouldBe List( - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v2_key)), - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v2_key)), - ) + inside(res) { case Right((_, v, List())) => + v shouldBe a[ValueContractId] } } - // TODO(https://github.com/digital-asset/daml/issues/20099): re-enable this test once fixed - "be able to exercise by interface locally created contract using different versions" ignore { + "be able to exercise by interface locally created contract using different versions" in { val res = go( e"""let alice : Party = '-pkg1-':M:mkParty "alice" in ubind @@ -630,10 +569,8 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) """, packageResolution = Map(Ref.PackageName.assertFromString("-upgrade-test-") -> pkgId2), ) - inside(res) { case Right((_, ValueContractId(cid), verificationRequests)) => - verificationRequests shouldBe List( - UpgradeVerificationRequest(cid, Set(alice), Set(bob), Some(v1_key)) - ) + inside(res) { case Right((_, v, List())) => + v shouldBe a[ValueContractId] } } @@ -643,79 +580,13 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) e"""\(cid: ContractId '-pkg1-':M:T) -> ubind x1: Unit <- '-pkg2-':M:do_fetch cid; - x2: Unit <- '-pkg4-':M:do_fetch cid + x2: Unit <- '-pkg3-':M:do_fetch cid in upure @Unit () """, ContractInstance(pkgName, i"'-pkg1-':M:T", v1_base), ) - inside(res) { case Right((_, _, verificationRequests)) => - val v4_key = GlobalKeyWithMaintainers.assertBuild( - i"'-pkg1-':M:T", - ValueParty(bob), - Set(bob), - crypto.Hash.KeyPackageName.assertBuild(pkgName, V17), - ) - verificationRequests shouldBe List( - UpgradeVerificationRequest(theCid, Set(alice), Set(bob), Some(v1_key)), - UpgradeVerificationRequest(theCid, Set(bob), Set(alice), Some(v4_key)), - ) - } - } - } - - "Correct calls to ResultNeedUpgradeVerification" in { - - implicit val pkgId: Ref.PackageId = Ref.PackageId.assertFromString("-no-pkg-") - - val v_alice_none = - makeRecord( - ValueParty(alice), - ValueParty(bob), - ValueInt64(100), - ValueOptional(None), - ) - - val v_alice_no_none = - makeRecord( - ValueParty(alice), - ValueParty(bob), - ValueInt64(100), - ) - - val v_alice_some = - makeRecord( - ValueParty(alice), - ValueParty(bob), - ValueInt64(100), - ValueOptional(Some(ValueParty(bob))), - ) - - inside( - go( - e"'-pkg3-':M:do_fetch", - ContractInstance(pkgName, i"'-misspelled-pkg3-':M:T", v_alice_none), - ) - ) { case Right((_, v, List(uv))) => - v shouldBe v_alice_no_none - uv.coid shouldBe theCid - uv.signatories.toList shouldBe List(alice) - uv.observers.toList shouldBe List(bob) - uv.keyOpt shouldBe Some(v1_key) - } - - inside( - go( - e"'-pkg3-':M:do_fetch", - ContractInstance(pkgName, i"'-misspelled-pkg3-':M:T", v_alice_some), - ) - ) { case Right((_, v, List(uv))) => - v shouldBe v_alice_some - uv.coid shouldBe theCid - uv.signatories.toList shouldBe List(alice, bob) - uv.observers.toList shouldBe List(bob) - uv.keyOpt shouldBe Some(v1_key) + res shouldBe a[Right[_, _]] } - } "Disclosed contracts" - { @@ -740,8 +611,9 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) SValue.SRecord(i"'-pkg1-':M:T", fields, values) } - inside(goDisclosed(e"'-pkg1-':M:do_fetch", sv1_base)) { case Right((_, v, _)) => - v shouldBe v1_base + inside(goDisclosed(e"'-pkg1-':M:do_fetch", i"'-pkg1-':M:T", sv1_base)) { + case Right((_, v, _)) => + v shouldBe v1_base } } @@ -764,8 +636,9 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) SValue.SRecord(i"'-unknown-':M:T", fields, values) } - inside(goDisclosed(e"'-pkg1-':M:do_fetch", sv1_base)) { case Right((_, v, _)) => - v shouldBe v1_base + inside(goDisclosed(e"'-pkg1-':M:do_fetch", i"'-pkg1-':M:T", sv1_base)) { + case Right((_, v, _)) => + v shouldBe v1_base } } } @@ -781,7 +654,7 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) ValueOptional(None), ) - val se: SExpr = pkgs.compiler.unsafeCompile(e"'-pkg4-':M:do_exercise") + val se: SExpr = pkgs.compiler.unsafeCompile(e"'-pkg3-':M:do_exercise") val args: Array[SValue] = Array(SContractId(theCid)) val sexprToEval: SExpr = SEApp(se, args) @@ -794,13 +667,13 @@ class UpgradeTest(majorLanguageVersion: LanguageMajorVersion) SpeedyTestLib.buildTransactionCollectRequests( machine, getContract = - Map(theCid -> Versioned(V17, ContractInstance(pkgName, i"'-pkg3-':M:T", v_alice_none))), + Map(theCid -> Versioned(V17, ContractInstance(pkgName, i"'-pkg2-':M:T", v_alice_none))), ) inside(res.map(_._1.nodes.values.toList)) { case Right(List(exe: Node.Exercise)) => exe.packageName shouldBe Some("-upgrade-test-") - exe.creationPackageId shouldBe Some("-pkg3-") - exe.templateId.packageId shouldBe "-pkg4-" + exe.creationPackageId shouldBe Some("-pkg2-") + exe.templateId.packageId shouldBe "-pkg3-" } } } diff --git a/sdk/daml-script/test/daml/upgrades/MetadataChanged.daml b/sdk/daml-script/test/daml/upgrades/MetadataChanged.daml new file mode 100644 index 000000000000..e5df29f554e4 --- /dev/null +++ b/sdk/daml-script/test/daml/upgrades/MetadataChanged.daml @@ -0,0 +1,1036 @@ +-- Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +-- SPDX-License-Identifier: Apache-2.0 + +module MetadataChanged (main) where + +import DA.Text (isInfixOf) + +import UpgradeTestLib + +import qualified V1.MetadataChangedMod as V1 +import qualified V2.MetadataChangedMod as V2 +import qualified ClientMod as Client +import V1.Common +import DA.Exception + +main : TestTree +main = tests + [ subtree "local" + [ subtree "exercise" + [ subtree "signatories" + [ ("changed", exerciseSignatoriesChangedLocal) + , ("unchanged", exerciseSignatoriesUnchangedLocal) + ] + , subtree "observers" + [ ("changed", exerciseObserversChangedLocal) + , ("unchanged", exerciseObserversUnchangedLocal) + ] + , subtree "key" + [ ("changed", exerciseKeyChangedLocal) + , ("unchanged", exerciseKeyUnchangedLocal) + ] + , subtree "maintainer" + [ ("changed", exerciseMaintainerChangedLocal) + , ("unchanged", exerciseMaintainerUnchangedLocal) + ] + ] + , subtree "exercise by interface" + [ subtree "signatories" + [ ("changed", exerciseByInterfaceSignatoriesChangedLocal) + , ("unchanged", exerciseByInterfaceSignatoriesUnchangedLocal) + ] + , subtree "observers" + [ ("changed", exerciseByInterfaceObserversChangedLocal) + , ("unchanged", exerciseByInterfaceObserversUnchangedLocal) + ] + , subtree "key" + [ ("changed", exerciseByInterfaceKeyChangedLocal) + , ("unchanged", exerciseByInterfaceKeyUnchangedLocal) + ] + , subtree "maintainer" + [ ("changed", exerciseByInterfaceMaintainerChangedLocal) + , ("unchanged", exerciseByInterfaceMaintainerUnchangedLocal) + ] + ] + , subtree "exercise by key" + [ subtree "signatories" + [ ("changed", exerciseByKeySignatoriesChangedLocal) + , ("unchanged", exerciseByKeySignatoriesUnchangedLocal) + ] + , subtree "observers" + [ ("changed", exerciseByKeyObserversChangedLocal) + , ("unchanged", exerciseByKeyObserversUnchangedLocal) + ] + , subtree "key" + [ ("changed", exerciseByKeyKeyChangedLocal) + , ("unchanged", exerciseByKeyKeyUnchangedLocal) + ] + , subtree "maintainer" + [ ("changed", exerciseByKeyMaintainerChangedLocal) + , ("unchanged", exerciseByKeyMaintainerUnchangedLocal) + ] + ] + ] + , subtree "global" + [ subtree "exercise" + [ subtree "signatories" + [ ("changed", exerciseSignatoriesChangedGlobal) + , ("unchanged", exerciseSignatoriesUnchangedGlobal) + ] + , subtree "observers" + [ ("changed", exerciseObserversChangedGlobal) + , ("unchanged", exerciseObserversUnchangedGlobal) + ] + , subtree "key" + [ ("changed", exerciseKeyChangedGlobal) + , ("unchanged", exerciseKeyUnchangedGlobal) + ] + , subtree "maintainer" + [ ("changed", exerciseMaintainerChangedGlobal) + , ("unchanged", exerciseMaintainerUnchangedGlobal) + ] + ] + , subtree "exercise by interface" + [ subtree "signatories" + [ ("changed", exerciseByInterfaceSignatoriesChangedGlobal) + , ("unchanged", exerciseByInterfaceSignatoriesUnchangedGlobal) + ] + , subtree "observers" + [ ("changed", exerciseByInterfaceObserversChangedGlobal) + , ("unchanged", exerciseByInterfaceObserversUnchangedGlobal) + ] + , subtree "key" + [ ("changed", exerciseByInterfaceKeyChangedGlobal) + , ("unchanged", exerciseByInterfaceKeyUnchangedGlobal) + ] + , subtree "maintainer" + [ ("changed", exerciseByInterfaceMaintainerChangedGlobal) + , ("unchanged", exerciseByInterfaceMaintainerUnchangedGlobal) + ] + ] + , subtree "exercise by key" + [ subtree "signatories" + [ ("changed", exerciseByKeySignatoriesChangedGlobal) + , ("unchanged", exerciseByKeySignatoriesUnchangedGlobal) + ] + , subtree "observers" + [ ("changed", exerciseByKeyObserversChangedGlobal) + , ("unchanged", exerciseByKeyObserversUnchangedGlobal) + ] + , subtree "key" + [ ("changed", exerciseByKeyKeyChangedGlobal) + , ("unchanged", exerciseByKeyKeyUnchangedGlobal) + ] + , subtree "maintainer" + [ ("changed", exerciseByKeyMaintainerChangedGlobal) + , ("unchanged", exerciseByKeyMaintainerUnchangedGlobal) + ] + ] + ] + ] + +{- PACKAGE +name: metadata-changed-common +versions: 1 +-} + +{- MODULE +package: metadata-changed-common +contents: | + module Common where + + data IV = IV with + ctl : Party + + interface I where + viewtype IV + + getVersion : Text + nonconsuming choice DynamicCall: Text + controller (view this).ctl + do + pure $ getVersion this + + data MyKey = MyKey with + p1 : Party + p2 : Party + n : Int + deriving (Eq, Show) +-} + +{- PACKAGE +name: metadata-changed +versions: 2 +depends: metadata-changed-common-1.0.0 +-} + +{- MODULE +package: metadata-changed +contents: | + module MetadataChangedMod where + + import V1.Common + + template ChangedSignatories + with + party1 : Party + party2 : Party + where + signatory party1 -- @V 1 + signatory party2 -- @V 2 + key (MyKey party1 party2 0) : MyKey + maintainer key.p1 + + nonconsuming choice ChangedSignatoriesCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for ChangedSignatories where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template UnchangedSignatories + with + party1 : Party + party2 : Party + where + signatory party1 -- @V 1 + signatory [] <> [party1] -- @V 2 + key (MyKey party1 party2 0) : MyKey + maintainer key.p1 + + nonconsuming choice UnchangedSignatoriesCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for UnchangedSignatories where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template ChangedObservers + with + party1 : Party + party2 : Party + where + signatory party1 + observer party1 -- @V 1 + observer party2 -- @V 2 + key (MyKey party1 party2 0) : MyKey + maintainer key.p1 + + nonconsuming choice ChangedObserversCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for ChangedObservers where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template UnchangedObservers + with + party1 : Party + party2 : Party + where + signatory party1 + observer party1 -- @V 1 + observer [] <> [party1] -- @V 2 + key (MyKey party1 party2 0) : MyKey + maintainer key.p1 + + nonconsuming choice UnchangedObserversCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for UnchangedObservers where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template ChangedKey + with + party1 : Party + party2 : Party + where + signatory party1 + observer party1 + key (MyKey party1 party2 0) : MyKey -- @V 1 + key (MyKey party1 party2 1) : MyKey -- @V 2 + maintainer key.p1 + + nonconsuming choice ChangedKeyCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for ChangedKey where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template UnchangedKey + with + party1 : Party + party2 : Party + where + signatory party1 + observer party1 + key (MyKey party1 party2 0) : MyKey -- @V 1 + key (MyKey party1 party2 (0+0)) : MyKey -- @V 2 + maintainer key.p1 + + nonconsuming choice UnchangedKeyCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for UnchangedKey where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template ChangedMaintainer + with + party1 : Party + party2 : Party + where + signatory party1 + observer party1 + key (MyKey party1 party2 0) : MyKey + maintainer key.p1 -- @V 1 + maintainer key.p2 -- @V 2 + + nonconsuming choice ChangedMaintainerCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for ChangedMaintainer where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 + + template UnchangedMaintainer + with + party1 : Party + party2 : Party + where + signatory party1 + observer party1 + key (MyKey party1 party2 0) : MyKey + maintainer key.p1 -- @V 1 + maintainer [] <> [key.p1] -- @V 2 + + nonconsuming choice UnchangedMaintainerCall : Text + controller party1 + do pure "V1" -- @V 1 + do pure "V2" -- @V 2 + + interface instance I for UnchangedMaintainer where + view = IV party1 + getVersion = "V1" -- @V 1 + getVersion = "V2" -- @V 2 +-} + +{- PACKAGE +name: metadata-changed-client +versions: 1 +depends: | + metadata-changed-1.0.0 + metadata-changed-2.0.0 + metadata-changed-common-1.0.0 +-} + +{- MODULE +package: metadata-changed-client +contents: | + module ClientMod where + + import DA.Exception + import qualified V1.MetadataChangedMod as V1 + import qualified V2.MetadataChangedMod as V2 + import V1.Common + + template Client + with + party : Party + where + signatory party + + -- CHANGED SIGNATORIES + + nonconsuming choice ExerciseSignatoriesChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedSignatories p1 p2) + exercise @V2.ChangedSignatories (coerceContractId cid) V2.ChangedSignatoriesCall + pure () + + nonconsuming choice ExerciseByInterfaceSignatoriesChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedSignatories p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeySignatoriesChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedSignatories p1 p2) + exerciseByKey @V2.ChangedSignatories (MyKey p1 p2 0) V2.ChangedSignatoriesCall + pure () + + -- UNCHANGED SIGNATORIES + + nonconsuming choice ExerciseSignatoriesUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedSignatories p1 p2) + exercise @V2.UnchangedSignatories (coerceContractId cid) V2.UnchangedSignatoriesCall + pure () + + nonconsuming choice ExerciseByInterfaceSignatoriesUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedSignatories p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeySignatoriesUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedSignatories p1 p2) + exerciseByKey @V2.UnchangedSignatories (MyKey p1 p2 0) V2.UnchangedSignatoriesCall + pure () + + -- CHANGED OBSERVERS + + nonconsuming choice ExerciseObserversChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedObservers p1 p2) + exercise @V2.ChangedObservers (coerceContractId cid) V2.ChangedObserversCall + pure () + + nonconsuming choice ExerciseByInterfaceObserversChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedObservers p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeyObserversChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedObservers p1 p2) + exerciseByKey @V2.ChangedObservers (MyKey p1 p2 0) V2.ChangedObserversCall + pure () + + -- UNCHANGED OBSERVERS + + nonconsuming choice ExerciseObserversUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedObservers p1 p2) + exercise @V2.UnchangedObservers (coerceContractId cid) V2.UnchangedObserversCall + pure () + + nonconsuming choice ExerciseByInterfaceObserversUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedObservers p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeyObserversUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedObservers p1 p2) + exerciseByKey @V2.UnchangedObservers (MyKey p1 p2 0) V2.UnchangedObserversCall + pure () + + -- CHANGED KEY + + nonconsuming choice ExerciseKeyChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedKey p1 p2) + exercise @V2.ChangedKey (coerceContractId cid) V2.ChangedKeyCall + pure () + + nonconsuming choice ExerciseByInterfaceKeyChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedKey p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeyKeyChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedKey p1 p2) + exerciseByKey @V2.ChangedKey (MyKey p1 p2 0) V2.ChangedKeyCall + pure () + + -- UNCHANGED KEY + + nonconsuming choice ExerciseKeyUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedKey p1 p2) + exercise @V2.UnchangedKey (coerceContractId cid) V2.UnchangedKeyCall + pure () + + nonconsuming choice ExerciseByInterfaceKeyUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedKey p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeyKeyUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedKey p1 p2) + exerciseByKey @V2.UnchangedKey (MyKey p1 p2 0) V2.UnchangedKeyCall + pure () + + -- CHANGED MAINTAINER + + nonconsuming choice ExerciseMaintainerChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedMaintainer p1 p2) + exercise @V2.ChangedMaintainer (coerceContractId cid) V2.ChangedMaintainerCall + pure () + + nonconsuming choice ExerciseByInterfaceMaintainerChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedMaintainer p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeyMaintainerChanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.ChangedMaintainer p1 p2) + exerciseByKey @V2.ChangedMaintainer (MyKey p1 p2 0) V2.ChangedMaintainerCall + pure () + + -- UNCHANGED MAINTAINER + + nonconsuming choice ExerciseMaintainerUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedMaintainer p1 p2) + exercise @V2.UnchangedMaintainer (coerceContractId cid) V2.UnchangedMaintainerCall + pure () + + nonconsuming choice ExerciseByInterfaceMaintainerUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedMaintainer p1 p2) + exercise @I (toInterfaceContractId cid) DynamicCall + pure () + + nonconsuming choice ExerciseByKeyMaintainerUnchanged : () + with + p1 : Party + p2 : Party + controller [p1, p2] + do + cid <- create (V1.UnchangedMaintainer p1 p2) + exerciseByKey @V2.UnchangedMaintainer (MyKey p1 p2 0) V2.UnchangedMaintainerCall + pure () +-} + +{- CHANGED SIGNATORIES -} + +exerciseSignatoriesChangedLocal : Test +exerciseSignatoriesChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseSignatoriesChanged a b)) + +exerciseByInterfaceSignatoriesChangedLocal : Test +exerciseByInterfaceSignatoriesChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceSignatoriesChanged a b)) + +exerciseByKeySignatoriesChangedLocal : Test +exerciseByKeySignatoriesChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeySignatoriesChanged a b)) + +exerciseSignatoriesChangedGlobal : Test +exerciseSignatoriesChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedSignatories a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.ChangedSignatories (coerceContractId cid) V2.ChangedSignatoriesCall) + +exerciseByInterfaceSignatoriesChangedGlobal : Test +exerciseByInterfaceSignatoriesChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedSignatories a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeySignatoriesChangedGlobal : Test +exerciseByKeySignatoriesChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedSignatories a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.ChangedSignatories (MyKey a b 0) V2.ChangedSignatoriesCall) + +{- UNCHANGED SIGNATORIES -} + +exerciseSignatoriesUnchangedLocal : Test +exerciseSignatoriesUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseSignatoriesUnchanged a b)) + +exerciseByInterfaceSignatoriesUnchangedLocal : Test +exerciseByInterfaceSignatoriesUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceSignatoriesUnchanged a b)) + +exerciseByKeySignatoriesUnchangedLocal : Test +exerciseByKeySignatoriesUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeySignatoriesUnchanged a b)) + +exerciseSignatoriesUnchangedGlobal : Test +exerciseSignatoriesUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedSignatories a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.UnchangedSignatories (coerceContractId cid) V2.UnchangedSignatoriesCall) + +exerciseByInterfaceSignatoriesUnchangedGlobal : Test +exerciseByInterfaceSignatoriesUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedSignatories a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeySignatoriesUnchangedGlobal : Test +exerciseByKeySignatoriesUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedSignatories a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.UnchangedSignatories (MyKey a b 0) V2.UnchangedSignatoriesCall) + +{- CHANGED OBSERVERS -} + +exerciseObserversChangedLocal : Test +exerciseObserversChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseObserversChanged a b)) + +exerciseByInterfaceObserversChangedLocal : Test +exerciseByInterfaceObserversChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceObserversChanged a b)) + +exerciseByKeyObserversChangedLocal : Test +exerciseByKeyObserversChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeyObserversChanged a b)) + +exerciseObserversChangedGlobal : Test +exerciseObserversChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedObservers a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.ChangedObservers (coerceContractId cid) V2.ChangedObserversCall) + +exerciseByInterfaceObserversChangedGlobal : Test +exerciseByInterfaceObserversChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedObservers a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeyObserversChangedGlobal : Test +exerciseByKeyObserversChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedObservers a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.ChangedObservers (MyKey a b 0) V2.ChangedObserversCall) + +{- UNCHANGED OBSERVERS -} + +exerciseObserversUnchangedLocal : Test +exerciseObserversUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseObserversUnchanged a b)) + +exerciseByInterfaceObserversUnchangedLocal : Test +exerciseByInterfaceObserversUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceObserversUnchanged a b)) + +exerciseByKeyObserversUnchangedLocal : Test +exerciseByKeyObserversUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeyObserversUnchanged a b)) + +exerciseObserversUnchangedGlobal : Test +exerciseObserversUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedObservers a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.UnchangedObservers (coerceContractId cid) V2.UnchangedObserversCall) + +exerciseByInterfaceObserversUnchangedGlobal : Test +exerciseByInterfaceObserversUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedObservers a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeyObserversUnchangedGlobal : Test +exerciseByKeyObserversUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedObservers a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.UnchangedObservers (MyKey a b 0) V2.UnchangedObserversCall) + +{- CHANGED KEY -} + +exerciseKeyChangedLocal : Test +exerciseKeyChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseKeyChanged a b)) + +exerciseByInterfaceKeyChangedLocal : Test +exerciseByInterfaceKeyChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceKeyChanged a b)) + +exerciseByKeyKeyChangedLocal : Test +exerciseByKeyKeyChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeyKeyChanged a b)) + +exerciseKeyChangedGlobal : Test +exerciseKeyChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedKey a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.ChangedKey (coerceContractId cid) V2.ChangedKeyCall) + +exerciseByInterfaceKeyChangedGlobal : Test +exerciseByInterfaceKeyChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedKey a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeyKeyChangedGlobal : Test +exerciseByKeyKeyChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedKey a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.ChangedKey (MyKey a b 0) V2.ChangedKeyCall) + +{- UNCHANGED KEY -} + +exerciseKeyUnchangedLocal : Test +exerciseKeyUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseKeyUnchanged a b)) + +exerciseByInterfaceKeyUnchangedLocal : Test +exerciseByInterfaceKeyUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceKeyUnchanged a b)) + +exerciseByKeyKeyUnchangedLocal : Test +exerciseByKeyKeyUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeyKeyUnchanged a b)) + +exerciseKeyUnchangedGlobal : Test +exerciseKeyUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedKey a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.UnchangedKey (coerceContractId cid) V2.UnchangedKeyCall) + +exerciseByInterfaceKeyUnchangedGlobal : Test +exerciseByInterfaceKeyUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedKey a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeyKeyUnchangedGlobal : Test +exerciseByKeyKeyUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedKey a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.UnchangedKey (MyKey a b 0) V2.UnchangedKeyCall) + +{- CHANGED MAINTAINER -} + +exerciseMaintainerChangedLocal : Test +exerciseMaintainerChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseMaintainerChanged a b)) + +exerciseByInterfaceMaintainerChangedLocal : Test +exerciseByInterfaceMaintainerChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceMaintainerChanged a b)) + +exerciseByKeyMaintainerChangedLocal : Test +exerciseByKeyMaintainerChangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeyMaintainerChanged a b)) + +exerciseMaintainerChangedGlobal : Test +exerciseMaintainerChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedMaintainer a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.ChangedMaintainer (coerceContractId cid) V2.ChangedMaintainerCall) + +exerciseByInterfaceMaintainerChangedGlobal : Test +exerciseByInterfaceMaintainerChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedMaintainer a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeyMaintainerChangedGlobal : Test +exerciseByKeyMaintainerChangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.ChangedMaintainer a b) + expectMetadataChangedError =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.ChangedMaintainer (MyKey a b 0) V2.ChangedMaintainerCall) + +{- UNCHANGED MAINTAINER -} + +exerciseMaintainerUnchangedLocal : Test +exerciseMaintainerUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseMaintainerUnchanged a b)) + +exerciseByInterfaceMaintainerUnchangedLocal : Test +exerciseByInterfaceMaintainerUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByInterfaceMaintainerUnchanged a b)) + +exerciseByKeyMaintainerUnchangedLocal : Test +exerciseByKeyMaintainerUnchangedLocal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (Client.Client a) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseCmd cid (Client.ExerciseByKeyMaintainerUnchanged a b)) + +exerciseMaintainerUnchangedGlobal : Test +exerciseMaintainerUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedMaintainer a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @V2.UnchangedMaintainer (coerceContractId cid) V2.UnchangedMaintainerCall) + +exerciseByInterfaceMaintainerUnchangedGlobal : Test +exerciseByInterfaceMaintainerUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedMaintainer a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseExactCmd @I (toInterfaceContractId cid) DynamicCall) + +exerciseByKeyMaintainerUnchangedGlobal : Test +exerciseByKeyMaintainerUnchangedGlobal = test $ do + a <- allocateParty "alice" + b <- allocateParty "bob" + cid <- a `submit` createExactCmd (V1.UnchangedMaintainer a b) + expectSuccess =<< + trySubmitMulti [a,b] [] (exerciseByKeyExactCmd @V2.UnchangedMaintainer (MyKey a b 0) V2.UnchangedMaintainerCall) + +------------------------------------------------------------------------------------------------------------------------ + +expectSuccess : Either SubmitError a -> Script () +expectSuccess r = case r of + Right _ -> pure () + Left e -> assertFail $ "Expected success but got " <> show e + +expectMetadataChangedError : Either SubmitError a -> Script () +expectMetadataChangedError r = case r of + Right _ -> assertFail "Expected failure but got success" + Left (UpgradeError msg) + | "Verify that neither the signatories, nor the observers, nor the contract key, nor the key's maintainers have changed" `isInfixOf` msg + -> pure () + Left e -> assertFail $ "Expected Upgrade error but got " <> show e