mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
[LF] factorize GlobalKeyWithMaintainers and KeyWithMaintainers (#16251)
This commit is contained in:
parent
aa81f567db
commit
a75db47275
@ -8,7 +8,13 @@ import com.daml.lf.data.{ImmArray, Numeric, Ref}
|
||||
import com.daml.lf.ledger.EventId
|
||||
import com.daml.lf.scenario.api.{v1 => proto}
|
||||
import com.daml.lf.speedy.{SError, SValue, TraceLog, Warning, WarningLog}
|
||||
import com.daml.lf.transaction.{GlobalKey, IncompleteTransaction, Node, NodeId}
|
||||
import com.daml.lf.transaction.{
|
||||
GlobalKey,
|
||||
GlobalKeyWithMaintainers,
|
||||
IncompleteTransaction,
|
||||
Node,
|
||||
NodeId,
|
||||
}
|
||||
import com.daml.lf.ledger._
|
||||
import com.daml.lf.value.{Value => V}
|
||||
|
||||
@ -588,7 +594,7 @@ final class Conversions(
|
||||
.addAllSignatories(fetch.signatories.map(convertParty).asJava)
|
||||
.addAllStakeholders(fetch.stakeholders.map(convertParty).asJava)
|
||||
if (fetch.byKey) {
|
||||
fetch.versionedKey.foreach { key =>
|
||||
fetch.keyOpt.foreach { key =>
|
||||
fetchBuilder.setFetchByKey(convertKeyWithMaintainers(key))
|
||||
}
|
||||
}
|
||||
@ -615,7 +621,7 @@ final class Conversions(
|
||||
exerciseBuilder.setExerciseResult(convertValue(result))
|
||||
}
|
||||
if (ex.byKey) {
|
||||
ex.versionedKey.foreach { key =>
|
||||
ex.keyOpt.foreach { key =>
|
||||
exerciseBuilder.setExerciseByKey(convertKeyWithMaintainers(key))
|
||||
}
|
||||
}
|
||||
@ -625,7 +631,7 @@ final class Conversions(
|
||||
nodeInfo.optLocation.foreach(loc => builder.setLocation(convertLocation(loc)))
|
||||
val lbkBuilder = proto.Node.LookupByKey.newBuilder
|
||||
.setTemplateId(convertIdentifier(lbk.templateId))
|
||||
.setKeyWithMaintainers(convertKeyWithMaintainers(lbk.versionedKey))
|
||||
.setKeyWithMaintainers(convertKeyWithMaintainers(lbk.key))
|
||||
lbk.result.foreach(cid => lbkBuilder.setContractId(coidToEventId(cid).toLedgerString))
|
||||
builder.setLookupByKey(lbkBuilder)
|
||||
|
||||
@ -634,12 +640,12 @@ final class Conversions(
|
||||
}
|
||||
|
||||
def convertKeyWithMaintainers(
|
||||
key: Node.VersionedKeyWithMaintainers
|
||||
key: GlobalKeyWithMaintainers
|
||||
): proto.KeyWithMaintainers = {
|
||||
proto.KeyWithMaintainers
|
||||
.newBuilder()
|
||||
.setKey(convertVersionedValue(key.map(_.key)))
|
||||
.addAllMaintainers(key.unversioned.maintainers.map(convertParty).asJava)
|
||||
.setKey(convertValue(key.value))
|
||||
.addAllMaintainers(key.maintainers.map(convertParty).asJava)
|
||||
.build()
|
||||
}
|
||||
|
||||
@ -675,7 +681,7 @@ final class Conversions(
|
||||
)
|
||||
.addAllSignatories(create.signatories.map(convertParty).asJava)
|
||||
.addAllStakeholders(create.stakeholders.map(convertParty).asJava)
|
||||
create.versionedKey.foreach(key =>
|
||||
create.keyOpt.foreach(key =>
|
||||
createBuilder.setKeyWithMaintainers(convertKeyWithMaintainers(key))
|
||||
)
|
||||
optLocation.map(loc => builder.setLocation(convertLocation(loc)))
|
||||
@ -714,7 +720,7 @@ final class Conversions(
|
||||
optLocation.map(loc => builder.setLocation(convertLocation(loc)))
|
||||
builder.setLookupByKey({
|
||||
val builder = proto.Node.LookupByKey.newBuilder
|
||||
.setKeyWithMaintainers(convertKeyWithMaintainers(lookup.versionedKey))
|
||||
.setKeyWithMaintainers(convertKeyWithMaintainers(lookup.key))
|
||||
lookup.result.foreach(cid => builder.setContractId(coidToEventId(cid).toLedgerString))
|
||||
builder.build
|
||||
})
|
||||
@ -750,9 +756,6 @@ final class Conversions(
|
||||
|
||||
}
|
||||
|
||||
private def convertVersionedValue(value: V.VersionedValue): proto.Value =
|
||||
convertValue(value.unversioned)
|
||||
|
||||
def convertValue(value: V): proto.Value = {
|
||||
val builder = proto.Value.newBuilder
|
||||
value match {
|
||||
|
@ -5,9 +5,9 @@ package com.daml.lf
|
||||
package engine
|
||||
|
||||
import com.daml.lf.data.Ref.{ChoiceName, Identifier, Party}
|
||||
import com.daml.lf.transaction.Node._
|
||||
import com.daml.lf.transaction.NodeId
|
||||
import com.daml.lf.data.ImmArray
|
||||
import com.daml.lf.transaction.GlobalKeyWithMaintainers
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.lf.value.Value.ContractId
|
||||
import com.daml.scalautil.Statement.discard
|
||||
@ -33,7 +33,7 @@ sealed trait Event extends Product with Serializable {
|
||||
final case class CreateEvent(
|
||||
contractId: ContractId,
|
||||
templateId: Identifier,
|
||||
contractKey: Option[KeyWithMaintainers],
|
||||
contractKey: Option[GlobalKeyWithMaintainers],
|
||||
argument: Value,
|
||||
agreementText: String,
|
||||
signatories: Set[Party],
|
||||
|
@ -7,10 +7,13 @@ package engine
|
||||
import com.daml.lf.data.Ref.{Identifier, Name, PackageId}
|
||||
import com.daml.lf.language.{Ast, LookupError}
|
||||
import com.daml.lf.transaction.{
|
||||
GlobalKey,
|
||||
GlobalKeyWithMaintainers,
|
||||
IncompleteTransaction,
|
||||
Transaction,
|
||||
Node,
|
||||
NodeId,
|
||||
Versioned,
|
||||
VersionedTransaction,
|
||||
}
|
||||
import com.daml.lf.value.Value
|
||||
@ -120,35 +123,33 @@ final class ValueEnricher(
|
||||
private val ResultNone = ResultDone(None)
|
||||
|
||||
def enrichContractKey(
|
||||
tyCon: Identifier,
|
||||
key: Node.KeyWithMaintainers,
|
||||
): Result[Node.KeyWithMaintainers] =
|
||||
enrichContractKey(tyCon, key.key).map(normalizedKey => key.copy(key = normalizedKey))
|
||||
key: GlobalKeyWithMaintainers
|
||||
): Result[GlobalKeyWithMaintainers] =
|
||||
enrichContractKey(key.globalKey.templateId, key.globalKey.key).map(normalizedKey =>
|
||||
key.copy(globalKey = GlobalKey.assertBuild(key.globalKey.templateId, normalizedKey))
|
||||
)
|
||||
|
||||
def enrichContractKey(
|
||||
tyCon: Identifier,
|
||||
key: Option[Node.KeyWithMaintainers],
|
||||
): Result[Option[Node.KeyWithMaintainers]] =
|
||||
key: Option[GlobalKeyWithMaintainers]
|
||||
): Result[Option[GlobalKeyWithMaintainers]] =
|
||||
key match {
|
||||
case Some(k) =>
|
||||
enrichContractKey(tyCon, k).map(Some(_))
|
||||
enrichContractKey(k).map(Some(_))
|
||||
case None =>
|
||||
ResultNone
|
||||
}
|
||||
|
||||
def enrichVersionedContractKey(
|
||||
tyCon: Identifier,
|
||||
key: Node.VersionedKeyWithMaintainers,
|
||||
): Result[Node.VersionedKeyWithMaintainers] =
|
||||
enrichContractKey(tyCon, key.unversioned).map(normalizedValue => key.map(_ => normalizedValue))
|
||||
key: Versioned[GlobalKeyWithMaintainers]
|
||||
): Result[Versioned[GlobalKeyWithMaintainers]] =
|
||||
enrichContractKey(key.unversioned).map(normalizedValue => key.map(_ => normalizedValue))
|
||||
|
||||
def enrichVersionedContractKey(
|
||||
tyCon: Identifier,
|
||||
key: Option[Node.VersionedKeyWithMaintainers],
|
||||
): Result[Option[Node.VersionedKeyWithMaintainers]] =
|
||||
key: Option[Versioned[GlobalKeyWithMaintainers]]
|
||||
): Result[Option[Versioned[GlobalKeyWithMaintainers]]] =
|
||||
key match {
|
||||
case Some(k) =>
|
||||
enrichVersionedContractKey(tyCon, k).map(Some(_))
|
||||
enrichVersionedContractKey(k).map(Some(_))
|
||||
case None =>
|
||||
ResultNone
|
||||
}
|
||||
@ -162,15 +163,15 @@ final class ValueEnricher(
|
||||
case create: Node.Create =>
|
||||
for {
|
||||
arg <- enrichValue(Ast.TTyCon(create.templateId), create.arg)
|
||||
key <- enrichContractKey(create.templateId, create.key)
|
||||
} yield create.copy(arg = arg, key = key)
|
||||
key <- enrichContractKey(create.keyOpt)
|
||||
} yield create.copy(arg = arg, keyOpt = key)
|
||||
case fetch: Node.Fetch =>
|
||||
for {
|
||||
key <- enrichContractKey(fetch.templateId, fetch.key)
|
||||
} yield fetch.copy(key = key)
|
||||
key <- enrichContractKey(fetch.keyOpt)
|
||||
} yield fetch.copy(keyOpt = key)
|
||||
case lookup: Node.LookupByKey =>
|
||||
for {
|
||||
key <- enrichContractKey(lookup.templateId, lookup.key)
|
||||
key <- enrichContractKey(lookup.key)
|
||||
} yield lookup.copy(key = key)
|
||||
case exe: Node.Exercise =>
|
||||
for {
|
||||
@ -188,8 +189,8 @@ final class ValueEnricher(
|
||||
case None =>
|
||||
ResultNone
|
||||
}
|
||||
key <- enrichContractKey(exe.templateId, exe.key)
|
||||
} yield exe.copy(chosenValue = choiceArg, exerciseResult = result, key = key)
|
||||
key <- enrichContractKey(exe.keyOpt)
|
||||
} yield exe.copy(chosenValue = choiceArg, exerciseResult = result, keyOpt = key)
|
||||
}
|
||||
|
||||
def enrichTransaction(tx: Transaction): Result[Transaction] =
|
||||
|
@ -73,11 +73,11 @@ private[preprocessing] final class TransactionPreprocessor(
|
||||
case create: Node.Create =>
|
||||
acc :+ commandPreprocessor.unsafePreprocessCreate(create.templateId, create.arg)
|
||||
case exe: Node.Exercise =>
|
||||
val cmd = exe.key match {
|
||||
val cmd = exe.keyOpt match {
|
||||
case Some(key) if exe.byKey =>
|
||||
commandPreprocessor.unsafePreprocessExerciseByKey(
|
||||
exe.templateId,
|
||||
key.key,
|
||||
key.globalKey.key,
|
||||
exe.choiceId,
|
||||
exe.chosenValue,
|
||||
)
|
||||
|
@ -34,7 +34,7 @@ class AuthorizationSpec extends AnyFreeSpec with Matchers with Inside {
|
||||
argument = ValueRecord(None, ImmArray.Empty),
|
||||
signatories = signatories,
|
||||
observers = Seq("Carl"),
|
||||
key = Some(Value.ValueUnit),
|
||||
keyOpt = Some(Value.ValueUnit),
|
||||
maintainers = maintainers,
|
||||
)
|
||||
|
||||
|
@ -101,7 +101,7 @@ class BlindingSpec extends AnyFreeSpec with Matchers {
|
||||
argument = ValueRecord(None, ImmArray.empty),
|
||||
signatories = Seq("Alice", "Bob"),
|
||||
observers = Seq("Carl"),
|
||||
key = Some(ValueRecord(None, ImmArray.empty)),
|
||||
keyOpt = Some(ValueRecord(None, ImmArray.empty)),
|
||||
maintainers = Seq("Alice"),
|
||||
)
|
||||
val lookup = builder.lookupByKey(create, true)
|
||||
@ -122,7 +122,7 @@ class BlindingSpec extends AnyFreeSpec with Matchers {
|
||||
argument = ValueRecord(None, ImmArray.empty),
|
||||
signatories = Seq("Alice", "Bob"),
|
||||
observers = Seq("Carl"),
|
||||
key = Some(ValueRecord(None, ImmArray.empty)),
|
||||
keyOpt = Some(ValueRecord(None, ImmArray.empty)),
|
||||
maintainers = Seq("Alice"),
|
||||
)
|
||||
val lookup = builder.lookupByKey(create, false)
|
||||
|
@ -785,7 +785,7 @@ class EngineTest
|
||||
driverMetadata = usedDisclosedContract.metadata.driverMetadata,
|
||||
signatories = Set(alice),
|
||||
stakeholders = Set(alice),
|
||||
maybeKeyWithMaintainers = Some(
|
||||
keyOpt = Some(
|
||||
Versioned(
|
||||
transactionVersion,
|
||||
GlobalKeyWithMaintainers(
|
||||
@ -1533,7 +1533,7 @@ class EngineTest
|
||||
newEngine()
|
||||
.reinterpret(
|
||||
submitters,
|
||||
ReplayCommand.LookupByKey(lookupNode.templateId, lookupNode.key.key),
|
||||
ReplayCommand.LookupByKey(lookupNode.templateId, lookupNode.key.value),
|
||||
nodeSeedMap.get(nid),
|
||||
txMeta.submissionTime,
|
||||
now,
|
||||
@ -1577,7 +1577,7 @@ class EngineTest
|
||||
newEngine()
|
||||
.reinterpret(
|
||||
submitters,
|
||||
ReplayCommand.LookupByKey(lookupNode.templateId, lookupNode.key.key),
|
||||
ReplayCommand.LookupByKey(lookupNode.templateId, lookupNode.key.value),
|
||||
nodeSeedMap.get(nid),
|
||||
txMeta.submissionTime,
|
||||
now,
|
||||
@ -1680,7 +1680,7 @@ class EngineTest
|
||||
driverMetadata = usedDisclosedContract.metadata.driverMetadata,
|
||||
signatories = Set(alice),
|
||||
stakeholders = Set(alice),
|
||||
maybeKeyWithMaintainers = Some(
|
||||
keyOpt = Some(
|
||||
Versioned(
|
||||
transactionVersion,
|
||||
GlobalKeyWithMaintainers(
|
||||
@ -1742,7 +1742,7 @@ class EngineTest
|
||||
driverMetadata = usedDisclosedContract.metadata.driverMetadata,
|
||||
signatories = Set(alice),
|
||||
stakeholders = Set(alice),
|
||||
maybeKeyWithMaintainers = None,
|
||||
keyOpt = None,
|
||||
agreementText = s"'$alice'", // agreement show party
|
||||
),
|
||||
)
|
||||
@ -1824,7 +1824,7 @@ class EngineTest
|
||||
case Some(Node.Fetch(_, _, _, _, _, key, _, _)) =>
|
||||
key match {
|
||||
// just test that the maintainers match here, getting the key out is a bit hairier
|
||||
case Some(Node.KeyWithMaintainers(_, maintainers)) =>
|
||||
case Some(GlobalKeyWithMaintainers(_, maintainers)) =>
|
||||
assert(maintainers == Set(alice))
|
||||
case None => fail("the recomputed fetch didn't have a key")
|
||||
}
|
||||
@ -1894,9 +1894,9 @@ class EngineTest
|
||||
|
||||
tx.transaction.nodes
|
||||
.collectFirst { case (id, nf: Node.Fetch) =>
|
||||
nf.key match {
|
||||
nf.keyOpt match {
|
||||
// just test that the maintainers match here, getting the key out is a bit hairier
|
||||
case Some(Node.KeyWithMaintainers(_, maintainers)) =>
|
||||
case Some(GlobalKeyWithMaintainers(_, maintainers)) =>
|
||||
assert(maintainers == Set(alice))
|
||||
case None => fail("the recomputed fetch didn't have a key")
|
||||
}
|
||||
@ -2647,14 +2647,14 @@ object EngineTest {
|
||||
case create: Node.Create =>
|
||||
ReplayCommand.Create(create.templateId, create.arg)
|
||||
case fetch: Node.Fetch if fetch.byKey =>
|
||||
val key = fetch.key.getOrElse(sys.error("unexpected empty contract key")).key
|
||||
val key = fetch.keyOpt.getOrElse(sys.error("unexpected empty contract key")).value
|
||||
ReplayCommand.FetchByKey(fetch.templateId, key)
|
||||
case fetch: Node.Fetch =>
|
||||
ReplayCommand.Fetch(fetch.templateId, fetch.coid)
|
||||
case lookup: Node.LookupByKey =>
|
||||
ReplayCommand.LookupByKey(lookup.templateId, lookup.key.key)
|
||||
ReplayCommand.LookupByKey(lookup.templateId, lookup.key.value)
|
||||
case exe: Node.Exercise if exe.byKey =>
|
||||
val key = exe.key.getOrElse(sys.error("unexpected empty contract key")).key
|
||||
val key = exe.keyOpt.getOrElse(sys.error("unexpected empty contract key")).value
|
||||
ReplayCommand.ExerciseByKey(
|
||||
exe.templateId,
|
||||
key,
|
||||
@ -2805,8 +2805,8 @@ object EngineTest {
|
||||
create.coid,
|
||||
create.versionedCoinst,
|
||||
),
|
||||
create.key.fold(keys)(k =>
|
||||
keys.updated(GlobalKey.assertBuild(create.templateId, k.key), create.coid)
|
||||
create.keyOpt.fold(keys)(k =>
|
||||
keys.updated(GlobalKey.assertBuild(create.templateId, k.value), create.coid)
|
||||
),
|
||||
)
|
||||
case (acc, _) => acc
|
||||
|
@ -25,7 +25,7 @@ class MetaDataTest extends AnyWordSpec with Matchers with TableDrivenPropertyChe
|
||||
argument = ValueUnit,
|
||||
signatories = parties,
|
||||
observers = noOne,
|
||||
key = Some(ValueParty("alice")),
|
||||
keyOpt = Some(ValueParty("alice")),
|
||||
maintainers = parties,
|
||||
)
|
||||
val nodeWithoutInterface = Table[TransactionBuilder => Node](
|
||||
@ -56,7 +56,7 @@ class MetaDataTest extends AnyWordSpec with Matchers with TableDrivenPropertyChe
|
||||
argument = ValueUnit,
|
||||
signatories = parties,
|
||||
observers = noOne,
|
||||
key = Some(ValueParty("alice")),
|
||||
keyOpt = Some(ValueParty("alice")),
|
||||
maintainers = parties,
|
||||
)
|
||||
val nodeWithInterface = Table[TransactionBuilder => Node](
|
||||
|
@ -13,7 +13,12 @@ import com.daml.lf.ledger._
|
||||
import com.daml.lf.data.Ref._
|
||||
import com.daml.lf.scenario.ScenarioLedger.{TransactionId, Disclosure}
|
||||
import com.daml.lf.scenario._
|
||||
import com.daml.lf.transaction.{Node, NodeId, TransactionVersion => TxVersion}
|
||||
import com.daml.lf.transaction.{
|
||||
GlobalKeyWithMaintainers,
|
||||
Node,
|
||||
NodeId,
|
||||
TransactionVersion => TxVersion,
|
||||
}
|
||||
import com.daml.lf.speedy.SError._
|
||||
import com.daml.lf.speedy.SValue._
|
||||
import com.daml.lf.speedy.SBuiltin._
|
||||
@ -269,13 +274,9 @@ private[lf] object Pretty {
|
||||
prettyLoc(amf.optLocation)
|
||||
}
|
||||
|
||||
def prettyKeyWithMaintainers(key: Node.KeyWithMaintainers): Doc =
|
||||
def prettyKeyWithMaintainers(key: GlobalKeyWithMaintainers): Doc =
|
||||
// the maintainers are induced from the key -- so don't clutter
|
||||
prettyValue(false)(key.key)
|
||||
|
||||
def prettyVersionedKeyWithMaintainers(key: Node.VersionedKeyWithMaintainers): Doc =
|
||||
// the maintainers are induced from the key -- so don't clutter
|
||||
prettyKeyWithMaintainers(key.unversioned)
|
||||
prettyValue(false)(key.value)
|
||||
|
||||
def prettyEventInfo(l: ScenarioLedger, txId: TransactionId)(nodeId: NodeId): Doc = {
|
||||
def arrowRight(d: Doc) = text("└─>") & d
|
||||
@ -289,9 +290,9 @@ private[lf] object Pretty {
|
||||
text("rollback:") / stack(children.toList.map(prettyEventInfo(l, txId)))
|
||||
case create: Node.Create =>
|
||||
val d = "create" &: prettyContractInst(create.coinst)
|
||||
create.versionedKey match {
|
||||
create.keyOpt match {
|
||||
case None => d
|
||||
case Some(key) => d / text("key") & prettyVersionedKeyWithMaintainers(key)
|
||||
case Some(key) => d / text("key") & prettyKeyWithMaintainers(key)
|
||||
}
|
||||
case ea: Node.Fetch =>
|
||||
"ensure active" &: prettyContractId(ea.coid)
|
||||
@ -310,7 +311,7 @@ private[lf] object Pretty {
|
||||
.nested(4)
|
||||
case lbk: Node.LookupByKey =>
|
||||
text("lookup by key") & prettyIdentifier(lbk.templateId) /
|
||||
text("key") & prettyVersionedKeyWithMaintainers(lbk.versionedKey) /
|
||||
text("key") & prettyKeyWithMaintainers(lbk.key) /
|
||||
(lbk.result match {
|
||||
case None => text("not found")
|
||||
case Some(coid) => text("found") & prettyContractId(coid)
|
||||
|
@ -24,6 +24,7 @@ import com.daml.lf.transaction.{
|
||||
GlobalKey,
|
||||
GlobalKeyWithMaintainers,
|
||||
Transaction => Tx,
|
||||
TransactionVersion,
|
||||
}
|
||||
import com.daml.lf.value.{Value => V}
|
||||
import com.daml.lf.value.Value.ValueArithmeticError
|
||||
@ -982,15 +983,13 @@ private[lf] object SBuiltin {
|
||||
args: util.ArrayList[SValue],
|
||||
machine: UpdateMachine,
|
||||
): Control[Nothing] = {
|
||||
val cached = extractCachedContract(args.get(0))
|
||||
val version = machine.tmplId2TxVersion(cached.templateId)
|
||||
val createArgValue = cached.value.toNormalizedValue(version)
|
||||
val cached = extractCachedContract(machine.tmplId2TxVersion, args.get(0))
|
||||
cached.key match {
|
||||
case Some(cachedKey) if cachedKey.maintainers.isEmpty =>
|
||||
Control.Error(
|
||||
IE.CreateEmptyContractKeyMaintainers(
|
||||
cached.templateId,
|
||||
createArgValue,
|
||||
cached.arg,
|
||||
cachedKey.lfValue,
|
||||
)
|
||||
)
|
||||
@ -1000,7 +999,6 @@ private[lf] object SBuiltin {
|
||||
submissionTime = machine.submissionTime,
|
||||
contract = cached,
|
||||
optLocation = machine.getLastLocation,
|
||||
version = version,
|
||||
) match {
|
||||
case Right((coid, newPtx)) =>
|
||||
machine.updateCachedContracts(coid, cached)
|
||||
@ -1485,7 +1483,9 @@ private[lf] object SBuiltin {
|
||||
args: util.ArrayList[SValue],
|
||||
machine: UpdateMachine,
|
||||
): Control[Nothing] = {
|
||||
val cachedKey = extractKey(NameOf.qualifiedNameOfCurrentFunc, templateId, args.get(0))
|
||||
val keyVersion = machine.tmplId2TxVersion(templateId)
|
||||
val cachedKey =
|
||||
extractKey(NameOf.qualifiedNameOfCurrentFunc, keyVersion, templateId, args.get(0))
|
||||
val mbCoid = args.get(1) match {
|
||||
case SOptional(mb) =>
|
||||
mb.map {
|
||||
@ -1494,13 +1494,11 @@ private[lf] object SBuiltin {
|
||||
}
|
||||
case _ => crash(s"Non option value when inserting lookup node")
|
||||
}
|
||||
val version = machine.tmplId2TxVersion(templateId)
|
||||
machine.ptx.insertLookup(
|
||||
templateId = templateId,
|
||||
optLocation = machine.getLastLocation,
|
||||
key = cachedKey,
|
||||
result = mbCoid,
|
||||
version = version,
|
||||
keyVersion = keyVersion,
|
||||
) match {
|
||||
case Right(ptx) =>
|
||||
machine.ptx = ptx
|
||||
@ -1561,12 +1559,14 @@ private[lf] object SBuiltin {
|
||||
machine: UpdateMachine,
|
||||
): Control[Question.Update] = {
|
||||
val svalue = args.get(0)
|
||||
val cachedKey = extractKey(NameOf.qualifiedNameOfCurrentFunc, operation.templateId, svalue)
|
||||
val version = machine.tmplId2TxVersion(operation.templateId)
|
||||
val cachedKey =
|
||||
extractKey(NameOf.qualifiedNameOfCurrentFunc, version, operation.templateId, svalue)
|
||||
|
||||
if (cachedKey.maintainers.isEmpty) {
|
||||
Control.Error(
|
||||
IE.FetchEmptyContractKeyMaintainers(
|
||||
operation.templateId,
|
||||
cachedKey.templateId,
|
||||
cachedKey.lfValue,
|
||||
)
|
||||
)
|
||||
@ -2128,14 +2128,13 @@ private[lf] object SBuiltin {
|
||||
args: util.ArrayList[SValue],
|
||||
machine: UpdateMachine,
|
||||
): Control[Nothing] = {
|
||||
val cachedContract = extractCachedContract(args.get(0))
|
||||
val templateId = cachedContract.templateId
|
||||
val cachedContract = extractCachedContract(machine.tmplId2TxVersion, args.get(0))
|
||||
val optError: Option[Either[IE, Unit]] = for {
|
||||
cachedKey <- cachedContract.key
|
||||
} yield {
|
||||
for {
|
||||
result <- machine.disclosureKeyTable
|
||||
.addContractKey(templateId, cachedKey.globalKey.hash, contractId)
|
||||
.addContractKey(cachedContract.templateId, cachedKey.globalKey.hash, contractId)
|
||||
} yield result
|
||||
}
|
||||
|
||||
@ -2187,22 +2186,25 @@ private[lf] object SBuiltin {
|
||||
|
||||
private[this] def extractKey(
|
||||
location: String,
|
||||
version: TransactionVersion,
|
||||
templateId: Ref.TypeConName,
|
||||
v: SValue,
|
||||
): CachedKey =
|
||||
v match {
|
||||
case SStruct(_, vals) =>
|
||||
val keyValue = vals.get(keyIdx)
|
||||
val lfValue = keyValue.toUnnormalizedValue
|
||||
val lfValue = keyValue.toNormalizedValue(version)
|
||||
val gkey = GlobalKey
|
||||
.build(templateId, lfValue)
|
||||
.getOrElse(
|
||||
throw SErrorDamlException(IE.ContractIdInContractKey(keyValue.toUnnormalizedValue))
|
||||
)
|
||||
CachedKey(
|
||||
gkey,
|
||||
GlobalKeyWithMaintainers(
|
||||
gkey,
|
||||
extractParties(NameOf.qualifiedNameOfCurrentFunc, vals.get(maintainerIdx)),
|
||||
),
|
||||
keyValue,
|
||||
extractParties(NameOf.qualifiedNameOfCurrentFunc, vals.get(maintainerIdx)),
|
||||
)
|
||||
case _ => throw SErrorCrash(location, s"Invalid key with maintainers: $v")
|
||||
}
|
||||
@ -2229,7 +2231,10 @@ private[lf] object SBuiltin {
|
||||
private[speedy] val SBuildCachedContract =
|
||||
SBuiltin.SBStructCon(cachedContractStruct)
|
||||
|
||||
private[speedy] def extractCachedContract(v: SValue): CachedContract =
|
||||
private[speedy] def extractCachedContract(
|
||||
tmplId2TxVersion: TypeConName => TransactionVersion,
|
||||
v: SValue,
|
||||
): CachedContract =
|
||||
v match {
|
||||
case SStruct(_, vals) if vals.size == cachedContractStruct.size =>
|
||||
val templateId = vals.get(cachedContractTypeFieldIdx) match {
|
||||
@ -2237,9 +2242,10 @@ private[lf] object SBuiltin {
|
||||
case _ =>
|
||||
throw SErrorCrash(NameOf.qualifiedNameOfCurrentFunc, s"Invalid cached contract: $v")
|
||||
}
|
||||
val version = tmplId2TxVersion(templateId)
|
||||
val mbKey = vals.get(cachedContractKeyIdx) match {
|
||||
case SOptional(mbKey) =>
|
||||
mbKey.map(extractKey(NameOf.qualifiedNameOfCurrentFunc, templateId, _))
|
||||
mbKey.map(extractKey(NameOf.qualifiedNameOfCurrentFunc, version, templateId, _))
|
||||
case v =>
|
||||
throw SErrorCrash(
|
||||
NameOf.qualifiedNameOfCurrentFunc,
|
||||
@ -2247,6 +2253,7 @@ private[lf] object SBuiltin {
|
||||
)
|
||||
}
|
||||
CachedContract(
|
||||
version = version,
|
||||
templateId = templateId,
|
||||
value = vals.get(cachedContractArgIdx),
|
||||
agreementText =
|
||||
|
@ -111,16 +111,17 @@ private[lf] object Speedy {
|
||||
sealed abstract class LedgerMode extends Product with Serializable
|
||||
|
||||
final case class CachedKey(
|
||||
globalKey: GlobalKey,
|
||||
globalKeyWithMaintainers: GlobalKeyWithMaintainers,
|
||||
key: SValue,
|
||||
maintainers: Set[Party],
|
||||
) {
|
||||
def toNodeKey(version: TxVersion) =
|
||||
Node.KeyWithMaintainers(key.toNormalizedValue(version), maintainers)
|
||||
def globalKey: GlobalKey = globalKeyWithMaintainers.globalKey
|
||||
def templateId: TypeConName = globalKey.templateId
|
||||
def maintainers: Set[Party] = globalKeyWithMaintainers.maintainers
|
||||
val lfValue = globalKey.key
|
||||
}
|
||||
|
||||
final case class CachedContract(
|
||||
version: TxVersion,
|
||||
templateId: Ref.TypeConName,
|
||||
value: SValue,
|
||||
agreementText: String,
|
||||
@ -130,6 +131,18 @@ private[lf] object Speedy {
|
||||
) {
|
||||
val stakeholders: Set[Party] = signatories union observers
|
||||
private[speedy] val any = SValue.SAny(TTyCon(templateId), value)
|
||||
private[speedy] def arg = value.toNormalizedValue(version)
|
||||
private[speedy] def toCreateNode(coid: V.ContractId) =
|
||||
Node.Create(
|
||||
coid = coid,
|
||||
templateId = templateId,
|
||||
arg = arg,
|
||||
agreementText = agreementText,
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
keyOpt = key.map(_.globalKeyWithMaintainers),
|
||||
version = version,
|
||||
)
|
||||
}
|
||||
|
||||
private[this] def enforceLimit(actual: Int, limit: Int, error: Int => IError.Limit.Error): Unit =
|
||||
@ -331,23 +344,16 @@ private[lf] object Speedy {
|
||||
)
|
||||
)
|
||||
val transactionVersion = tmplId2TxVersion(cachedContract.templateId)
|
||||
val maybeKeyWithMaintainers =
|
||||
cachedContract.key
|
||||
.map(_.toNodeKey(transactionVersion))
|
||||
.map { case Node.KeyWithMaintainers(key, maintainers) =>
|
||||
GlobalKeyWithMaintainers(
|
||||
globalKey = GlobalKey.assertBuild(disclosedContract.templateId, key),
|
||||
maintainers = maintainers,
|
||||
)
|
||||
}
|
||||
.map(Versioned(transactionVersion, _))
|
||||
val keyOpt = cachedContract.key.map(k =>
|
||||
Versioned(cachedContract.version, k.globalKeyWithMaintainers)
|
||||
)
|
||||
|
||||
val engineEnrichedContractMetadata = EngineEnrichedContractMetadata(
|
||||
createdAt = disclosedContract.metadata.createdAt,
|
||||
driverMetadata = disclosedContract.metadata.driverMetadata,
|
||||
signatories = cachedContract.signatories,
|
||||
stakeholders = cachedContract.stakeholders,
|
||||
maybeKeyWithMaintainers = maybeKeyWithMaintainers,
|
||||
keyOpt = keyOpt,
|
||||
agreementText = cachedContract.agreementText,
|
||||
)
|
||||
val engineEnrichedDisclosedContract =
|
||||
@ -1704,7 +1710,7 @@ private[lf] object Speedy {
|
||||
private[speedy] final case class KCacheContract(cid: V.ContractId) extends Kont {
|
||||
override def execute[Q](machine: Machine[Q], sv: SValue): Control[Q] =
|
||||
machine.asUpdateMachine(productPrefix) { machine =>
|
||||
val cached = SBuiltin.extractCachedContract(sv)
|
||||
val cached = SBuiltin.extractCachedContract(machine.tmplId2TxVersion, sv)
|
||||
machine.checkContractVisibility(cid, cached)
|
||||
machine.addGlobalContract(cid, cached)
|
||||
Control.Value(cached.any)
|
||||
|
@ -73,7 +73,7 @@ private[lf] object DefaultAuthorizationChecker extends AuthorizationChecker {
|
||||
passIf = create.signatories.nonEmpty,
|
||||
failWith = FailedAuthorization.NoSignatories(create.templateId, optLocation),
|
||||
) ++
|
||||
(create.key match {
|
||||
(create.keyOpt match {
|
||||
case None => List()
|
||||
case Some(key) =>
|
||||
val maintainers = key.maintainers
|
||||
|
@ -11,6 +11,8 @@ import com.daml.lf.speedy.Speedy.{CachedContract, CachedKey}
|
||||
import com.daml.lf.transaction.ContractKeyUniquenessMode
|
||||
import com.daml.lf.transaction.{
|
||||
ContractStateMachine,
|
||||
GlobalKey,
|
||||
GlobalKeyWithMaintainers,
|
||||
Node,
|
||||
NodeId,
|
||||
SubmittedTransaction => SubmittedTx,
|
||||
@ -142,7 +144,7 @@ private[lf] object PartialTransaction {
|
||||
targetId: Value.ContractId,
|
||||
templateId: TypeConName,
|
||||
interfaceId: Option[TypeConName],
|
||||
contractKey: Option[Node.KeyWithMaintainers],
|
||||
contractKey: Option[GlobalKeyWithMaintainers],
|
||||
choiceId: ChoiceName,
|
||||
consuming: Boolean,
|
||||
actingParties: Set[Party],
|
||||
@ -347,28 +349,18 @@ private[speedy] case class PartialTransaction(
|
||||
submissionTime: Time.Timestamp,
|
||||
contract: CachedContract,
|
||||
optLocation: Option[Location],
|
||||
version: TxVersion,
|
||||
): Either[(PartialTransaction, Tx.TransactionError), (Value.ContractId, PartialTransaction)] = {
|
||||
val auth = Authorize(context.info.authorizers)
|
||||
val actionNodeSeed = context.nextActionChildSeed
|
||||
val discriminator =
|
||||
crypto.Hash.deriveContractDiscriminator(actionNodeSeed, submissionTime, contract.stakeholders)
|
||||
val cid = Value.ContractId.V1(discriminator)
|
||||
val createNode = Node.Create(
|
||||
cid,
|
||||
contract.templateId,
|
||||
contract.value.toNormalizedValue(version),
|
||||
contract.agreementText,
|
||||
contract.signatories,
|
||||
contract.stakeholders,
|
||||
contract.key.map(_.toNodeKey(version)),
|
||||
version,
|
||||
)
|
||||
val createNode = contract.toCreateNode(cid)
|
||||
val nid = NodeId(nextNodeIdx)
|
||||
val ptx = copy(
|
||||
actionNodeLocations = actionNodeLocations :+ optLocation,
|
||||
nextNodeIdx = nextNodeIdx + 1,
|
||||
context = context.addActionChild(nid, version),
|
||||
context = context.addActionChild(nid, createNode.version),
|
||||
nodes = nodes.updated(nid, createNode),
|
||||
actionNodeSeeds = actionNodeSeeds :+ actionNodeSeed,
|
||||
)
|
||||
@ -405,7 +397,7 @@ private[speedy] case class PartialTransaction(
|
||||
actingParties,
|
||||
contract.signatories,
|
||||
contract.stakeholders,
|
||||
contract.key.map(_.toNodeKey(version)),
|
||||
contract.key.map(_.globalKeyWithMaintainers),
|
||||
normByKey(version, byKey),
|
||||
version,
|
||||
)
|
||||
@ -427,15 +419,19 @@ private[speedy] case class PartialTransaction(
|
||||
}
|
||||
|
||||
def insertLookup(
|
||||
templateId: TypeConName,
|
||||
optLocation: Option[Location],
|
||||
key: CachedKey,
|
||||
result: Option[Value.ContractId],
|
||||
version: TxVersion,
|
||||
keyVersion: TxVersion,
|
||||
): Either[Tx.TransactionError, PartialTransaction] = {
|
||||
val auth = Authorize(context.info.authorizers)
|
||||
val nid = NodeId(nextNodeIdx)
|
||||
val node = Node.LookupByKey(templateId, key.toNodeKey(version), result, version)
|
||||
val node = Node.LookupByKey(
|
||||
key.templateId,
|
||||
key.globalKeyWithMaintainers,
|
||||
result,
|
||||
keyVersion,
|
||||
)
|
||||
// This method is only called after we have already resolved the key in com.daml.lf.speedy.SBuiltin.SBUKeyBuiltin.execute
|
||||
// so the current state's global key inputs must resolve the key.
|
||||
val keyInput = contractState.globalKeyInputs(key.globalKey)
|
||||
@ -444,7 +440,7 @@ private[speedy] case class PartialTransaction(
|
||||
authorizationChecker.authorizeLookupByKey(optLocation, node)(auth) match {
|
||||
case fa :: _ => Left(Tx.AuthFailureDuringExecution(nid, fa))
|
||||
case Nil =>
|
||||
Right(insertLeafNode(node, version, optLocation, newContractState))
|
||||
Right(insertLeafNode(node, keyVersion, optLocation, newContractState))
|
||||
}
|
||||
}
|
||||
|
||||
@ -471,7 +467,17 @@ private[speedy] case class PartialTransaction(
|
||||
targetId = targetId,
|
||||
templateId = contract.templateId,
|
||||
interfaceId = interfaceId,
|
||||
contractKey = contract.key.map(_.toNodeKey(version)),
|
||||
contractKey = contract.key.map {
|
||||
// We need to renormalize the key
|
||||
case CachedKey(GlobalKeyWithMaintainers(_, maintainers), key) =>
|
||||
GlobalKeyWithMaintainers(
|
||||
GlobalKey.assertBuild(
|
||||
contract.templateId,
|
||||
key.toNormalizedValue(version),
|
||||
),
|
||||
maintainers,
|
||||
)
|
||||
},
|
||||
choiceId = choiceId,
|
||||
consuming = consuming,
|
||||
actingParties = actingParties,
|
||||
@ -573,7 +579,7 @@ private[speedy] case class PartialTransaction(
|
||||
choiceObservers = ec.choiceObservers,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = None,
|
||||
key = ec.contractKey,
|
||||
keyOpt = ec.contractKey,
|
||||
byKey = normByKey(ec.version, ec.byKey),
|
||||
version = ec.version,
|
||||
)
|
||||
|
@ -14,7 +14,7 @@ import com.daml.lf.speedy.SError._
|
||||
import com.daml.lf.speedy.SExpr._
|
||||
import com.daml.lf.speedy.SValue._
|
||||
import com.daml.lf.testing.parser.Implicits.{defaultParserParameters => _, _}
|
||||
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion, Versioned}
|
||||
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, TransactionVersion, Versioned}
|
||||
import com.daml.lf.ledger.FailedAuthorization
|
||||
import com.daml.lf.ledger.FailedAuthorization.{
|
||||
ExerciseMissingAuthorization,
|
||||
@ -402,7 +402,7 @@ class EvaluationOrderTest extends AnyFreeSpec with Matchers with Inside {
|
||||
private[this] val getHelper = Map(helperCId -> helper)
|
||||
|
||||
private[this] val getKey = Map(
|
||||
GlobalKeyWithMaintainers(GlobalKey.assertBuild(T, keyValue), Set(alice)) -> cId
|
||||
GlobalKeyWithMaintainers.assertBuild(T, keyValue, Set(alice)) -> cId
|
||||
)
|
||||
|
||||
private[this] val dummyContract = Versioned(
|
||||
|
@ -222,14 +222,15 @@ object ExplicitDisclosureLib {
|
||||
if (withKey)
|
||||
Some(
|
||||
CachedKey(
|
||||
GlobalKey.assertBuild(templateId, contract.toUnnormalizedValue),
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(templateId, contract.toUnnormalizedValue, Set(maintainer)),
|
||||
contract,
|
||||
Set(maintainer),
|
||||
)
|
||||
)
|
||||
else None
|
||||
|
||||
CachedContract(
|
||||
TransactionVersion.minExplicitDisclosure,
|
||||
templateId,
|
||||
contract,
|
||||
agreementText = "",
|
||||
|
@ -306,7 +306,7 @@ object NormalizeRollbackSpec {
|
||||
agreementText = "dummyAgreement",
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
@ -338,7 +338,7 @@ object NormalizeRollbackSpec {
|
||||
choiceObservers = Set.empty,
|
||||
children = children,
|
||||
exerciseResult = None,
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
byKey = false,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
@ -42,6 +42,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
private[this] implicit class PartialTransactionExtra(val ptx: PartialTransaction) {
|
||||
|
||||
val contract = CachedContract(
|
||||
version = TransactionVersion.maxVersion,
|
||||
templateId = templateId,
|
||||
value = SValue.SUnit,
|
||||
agreementText = "agreement",
|
||||
@ -56,7 +57,6 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
submissionTime = data.Time.Timestamp.Epoch,
|
||||
contract = contract,
|
||||
optLocation = None,
|
||||
version = TransactionVersion.maxVersion,
|
||||
)
|
||||
.toOption
|
||||
.get
|
||||
|
@ -22,7 +22,7 @@ import com.daml.lf.speedy.SExpr._
|
||||
import com.daml.lf.speedy.SValue.{SValue => _, _}
|
||||
import com.daml.lf.speedy.Speedy.{CachedContract, Machine, CachedKey}
|
||||
import com.daml.lf.testing.parser.Implicits._
|
||||
import com.daml.lf.transaction.{GlobalKey, GlobalKeyWithMaintainers, TransactionVersion}
|
||||
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, TransactionVersion}
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.lf.value.Value.{ContractId, ValueArithmeticError, VersionedContractInstance}
|
||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||
@ -1651,6 +1651,7 @@ class SBuiltinTest extends AnyFreeSpec with Matchers with TableDrivenPropertyChe
|
||||
val (disclosedContract, None) =
|
||||
buildDisclosedContract(contractId, alice, alice, templateId, withKey = false)
|
||||
val cachedContract = CachedContract(
|
||||
version = txVersion,
|
||||
templateId,
|
||||
disclosedContract.argument,
|
||||
"",
|
||||
@ -1694,9 +1695,13 @@ class SBuiltinTest extends AnyFreeSpec with Matchers with TableDrivenPropertyChe
|
||||
val (disclosedContract, Some((key, keyWithMaintainers, keyHash))) =
|
||||
buildDisclosedContract(contractId, alice, alice, templateId, withKey = true)
|
||||
val optionalKey = Some(
|
||||
CachedKey(GlobalKey.assertBuild(templateId, key.toUnnormalizedValue), key, Set(alice))
|
||||
CachedKey(
|
||||
GlobalKeyWithMaintainers.assertBuild(templateId, key.toUnnormalizedValue, Set(alice)),
|
||||
key,
|
||||
)
|
||||
)
|
||||
val cachedContract = CachedContract(
|
||||
version = txVersion,
|
||||
templateId,
|
||||
disclosedContract.argument,
|
||||
"agreement",
|
||||
@ -1813,6 +1818,8 @@ object SBuiltinTest {
|
||||
|
||||
"""
|
||||
|
||||
private val txVersion = TransactionVersion.assignNodeVersion(pkg.languageVersion)
|
||||
|
||||
val compiledPackages: PureCompiledPackages =
|
||||
PureCompiledPackages.assertBuild(Map(defaultParserParameters.defaultPackageId -> pkg))
|
||||
|
||||
@ -1914,10 +1921,7 @@ object SBuiltinTest {
|
||||
val globalKey =
|
||||
if (withKey) {
|
||||
Some(
|
||||
GlobalKeyWithMaintainers(
|
||||
GlobalKey.assertBuild(templateId, key.toUnnormalizedValue),
|
||||
Set(maintainer),
|
||||
)
|
||||
GlobalKeyWithMaintainers.assertBuild(templateId, key.toUnnormalizedValue, Set(maintainer))
|
||||
)
|
||||
} else {
|
||||
None
|
||||
|
@ -537,7 +537,7 @@ object TransactionConversionsSpec {
|
||||
choiceObservers = choiceObservers,
|
||||
children = children,
|
||||
exerciseResult = None,
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
byKey = false,
|
||||
version = TransactionVersion.VDev,
|
||||
)
|
||||
|
@ -35,7 +35,7 @@ final class Adapter(
|
||||
create.copy(
|
||||
templateId = adapt(create.templateId),
|
||||
arg = adapt(create.arg),
|
||||
key = create.key.map(adapt),
|
||||
keyOpt = create.keyOpt.map(adapt),
|
||||
)
|
||||
case exe: Node.Exercise =>
|
||||
exe.copy(
|
||||
@ -43,12 +43,12 @@ final class Adapter(
|
||||
chosenValue = adapt(exe.chosenValue),
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = exe.exerciseResult.map(adapt),
|
||||
key = exe.key.map(adapt),
|
||||
keyOpt = exe.keyOpt.map(adapt),
|
||||
)
|
||||
case fetch: Node.Fetch =>
|
||||
fetch.copy(
|
||||
templateId = adapt(fetch.templateId),
|
||||
key = fetch.key.map(adapt),
|
||||
keyOpt = fetch.keyOpt.map(adapt),
|
||||
)
|
||||
case lookup: Node.LookupByKey =>
|
||||
lookup
|
||||
@ -58,20 +58,14 @@ final class Adapter(
|
||||
)
|
||||
}
|
||||
|
||||
// drop value version
|
||||
private[this] def adapt(
|
||||
k: Node.KeyWithMaintainers
|
||||
): Node.KeyWithMaintainers =
|
||||
k.copy(adapt(k.key))
|
||||
def adapt(k: GlobalKeyWithMaintainers): GlobalKeyWithMaintainers =
|
||||
k.copy(globalKey = adapt(k.globalKey))
|
||||
|
||||
def adapt(coinst: Value.VersionedContractInstance): Value.VersionedContractInstance =
|
||||
coinst.map(unversioned =>
|
||||
unversioned.copy(template = adapt(unversioned.template), arg = adapt(unversioned.arg))
|
||||
)
|
||||
|
||||
def adapt(gkey: GlobalKeyWithMaintainers): GlobalKeyWithMaintainers =
|
||||
GlobalKeyWithMaintainers(adapt(gkey.globalKey), gkey.maintainers)
|
||||
|
||||
def adapt(gkey: GlobalKey): GlobalKey =
|
||||
GlobalKey.assertBuild(adapt(gkey.templateId), adapt(gkey.key))
|
||||
|
||||
|
@ -11,7 +11,6 @@ import com.daml.lf.language.{Ast, LanguageVersion, Util => AstUtil}
|
||||
import com.daml.lf.testing.snapshot.Snapshot.SubmissionEntry.EntryCase
|
||||
import com.daml.lf.transaction.Transaction.ChildrenRecursion
|
||||
import com.daml.lf.transaction.{
|
||||
GlobalKey,
|
||||
GlobalKeyWithMaintainers,
|
||||
Node,
|
||||
SubmittedTransaction => SubmittedTx,
|
||||
@ -168,12 +167,7 @@ private[snapshot] object TransactionSnapshot {
|
||||
cid -> create.versionedCoinst
|
||||
}.toMap
|
||||
val contractKeys = relevantCreateNodes.view.flatMap { case (cid, create) =>
|
||||
create.key.map { case Node.KeyWithMaintainers(key, maintainers) =>
|
||||
GlobalKeyWithMaintainers(
|
||||
GlobalKey.assertBuild(create.templateId, key),
|
||||
maintainers,
|
||||
) -> cid
|
||||
}.toList
|
||||
create.keyOpt.map(_ -> cid).toList
|
||||
}.toMap
|
||||
new TransactionSnapshot(
|
||||
transaction = tx,
|
||||
|
@ -106,7 +106,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
||||
argument: Value,
|
||||
signatories: Set[Ref.Party],
|
||||
observers: Set[Ref.Party],
|
||||
key: Option[Value],
|
||||
keyOpt: Option[Value],
|
||||
maintainers: Set[Ref.Party],
|
||||
): Node.Create = {
|
||||
Node.Create(
|
||||
@ -116,7 +116,8 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
||||
agreementText = "",
|
||||
signatories = signatories,
|
||||
stakeholders = signatories | observers,
|
||||
key = key.map(Node.KeyWithMaintainers(_, maintainers)),
|
||||
keyOpt =
|
||||
keyOpt.map(key => GlobalKeyWithMaintainers.assertBuild(templateId, key, maintainers)),
|
||||
version = pkgTxVersion(templateId.packageId),
|
||||
)
|
||||
}
|
||||
@ -145,7 +146,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
||||
signatories = contract.signatories,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = result,
|
||||
key = contract.key,
|
||||
keyOpt = contract.keyOpt,
|
||||
byKey = byKey,
|
||||
version = pkgTxVersion(contract.templateId.packageId),
|
||||
)
|
||||
@ -169,7 +170,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
||||
actingParties = contract.signatories.map(Ref.Party.assertFromString),
|
||||
signatories = contract.signatories,
|
||||
stakeholders = contract.stakeholders,
|
||||
key = contract.key,
|
||||
keyOpt = contract.keyOpt,
|
||||
byKey = byKey,
|
||||
version = pkgTxVersion(contract.templateId.packageId),
|
||||
)
|
||||
@ -180,7 +181,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
||||
def lookupByKey(contract: Node.Create, found: Boolean = true): Node.LookupByKey =
|
||||
Node.LookupByKey(
|
||||
templateId = contract.templateId,
|
||||
key = contract.key.get,
|
||||
key = contract.keyOpt.get,
|
||||
result = if (found) Some(contract.coid) else None,
|
||||
version = pkgTxVersion(contract.templateId.packageId),
|
||||
)
|
||||
@ -195,8 +196,8 @@ object TransactionBuilder {
|
||||
|
||||
type TxValue = value.Value.VersionedValue
|
||||
|
||||
type KeyWithMaintainers = Node.KeyWithMaintainers
|
||||
type TxKeyWithMaintainers = Node.VersionedKeyWithMaintainers
|
||||
type KeyWithMaintainers = GlobalKeyWithMaintainers
|
||||
type TxKeyWithMaintainers = Versioned[GlobalKeyWithMaintainers]
|
||||
|
||||
def apply(
|
||||
pkgLangVersion: Ref.PackageId => LanguageVersion = _ => LanguageVersion.StableVersions.max
|
||||
|
@ -8,6 +8,8 @@ package test
|
||||
import com.daml.lf.data.Ref._
|
||||
import com.daml.lf.data._
|
||||
import com.daml.lf.transaction.{
|
||||
GlobalKey,
|
||||
GlobalKeyWithMaintainers,
|
||||
Transaction,
|
||||
Node,
|
||||
NodeId,
|
||||
@ -268,11 +270,13 @@ object ValueGenerators {
|
||||
arg <- versionedValueGen
|
||||
} yield arg.map(Value.ContractInstance(template, _))
|
||||
|
||||
val keyWithMaintainersGen: Gen[Node.KeyWithMaintainers] = {
|
||||
def keyWithMaintainersGen(templateId: Ref.TypeConName): Gen[GlobalKeyWithMaintainers] = {
|
||||
for {
|
||||
key <- valueGen()
|
||||
maintainers <- genNonEmptyParties
|
||||
} yield Node.KeyWithMaintainers(key, maintainers)
|
||||
gkey = GlobalKey.build(templateId, key).toOption
|
||||
if gkey.isDefined
|
||||
} yield GlobalKeyWithMaintainers(gkey.get, maintainers)
|
||||
}
|
||||
|
||||
val versionedContraactInstanceWithAgreement: Gen[Versioned[Value.ContractInstanceWithAgreement]] =
|
||||
@ -308,7 +312,7 @@ object ValueGenerators {
|
||||
agreement <- Arbitrary.arbitrary[String]
|
||||
signatories <- genNonEmptyParties
|
||||
stakeholders <- genNonEmptyParties
|
||||
key <- Gen.option(keyWithMaintainersGen)
|
||||
key <- Gen.option(keyWithMaintainersGen(templateId))
|
||||
} yield Node.Create(
|
||||
coid = coid,
|
||||
templateId = templateId,
|
||||
@ -316,7 +320,7 @@ object ValueGenerators {
|
||||
agreementText = agreement,
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
version = version,
|
||||
)
|
||||
|
||||
@ -333,7 +337,7 @@ object ValueGenerators {
|
||||
actingParties <- genNonEmptyParties
|
||||
signatories <- genNonEmptyParties
|
||||
stakeholders <- genNonEmptyParties
|
||||
key <- Gen.option(keyWithMaintainersGen)
|
||||
key <- Gen.option(keyWithMaintainersGen(templateId))
|
||||
byKey <- Gen.oneOf(true, false)
|
||||
} yield Node.Fetch(
|
||||
coid = coid,
|
||||
@ -341,7 +345,7 @@ object ValueGenerators {
|
||||
actingParties = actingParties,
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
byKey = byKey,
|
||||
version = version,
|
||||
)
|
||||
@ -384,7 +388,7 @@ object ValueGenerators {
|
||||
.map(_.to(ImmArray))
|
||||
exerciseResult <-
|
||||
if (version < minExceptions) valueGen().map(Some(_)) else Gen.option(valueGen())
|
||||
key <- Gen.option(keyWithMaintainersGen)
|
||||
key <- Gen.option(keyWithMaintainersGen(templateId))
|
||||
byKey <- Gen.oneOf(true, false)
|
||||
} yield Node.Exercise(
|
||||
targetCoid = targetCoid,
|
||||
@ -399,7 +403,7 @@ object ValueGenerators {
|
||||
choiceObservers = choiceObservers,
|
||||
children = children,
|
||||
exerciseResult = exerciseResult,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
byKey = byKey,
|
||||
version = version,
|
||||
)
|
||||
@ -409,7 +413,7 @@ object ValueGenerators {
|
||||
version <- transactionVersionGen()
|
||||
targetCoid <- coidGen
|
||||
templateId <- idGen
|
||||
key <- keyWithMaintainersGen
|
||||
key <- keyWithMaintainersGen(templateId)
|
||||
result <- Gen.option(targetCoid)
|
||||
} yield Node.LookupByKey(
|
||||
templateId,
|
||||
|
@ -144,6 +144,6 @@ final case class EngineEnrichedContractMetadata(
|
||||
driverMetadata: Bytes,
|
||||
signatories: Set[Party],
|
||||
stakeholders: Set[Party],
|
||||
maybeKeyWithMaintainers: Option[Versioned[GlobalKeyWithMaintainers]],
|
||||
keyOpt: Option[Versioned[GlobalKeyWithMaintainers]],
|
||||
agreementText: String,
|
||||
)
|
||||
|
@ -304,9 +304,6 @@ object Hash {
|
||||
.addTypedValue(key)
|
||||
.build
|
||||
|
||||
def safeHashContractKey(templateId: Ref.Identifier, key: Value): Hash =
|
||||
assertHashContractKey(templateId, key)
|
||||
|
||||
def hashContractKey(
|
||||
templateId: Ref.Identifier,
|
||||
key: Value,
|
||||
|
@ -125,7 +125,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
|
||||
|
||||
/** Visit a create node */
|
||||
def handleCreate(node: Node.Create): Either[KeyInputError, State] =
|
||||
visitCreate(node.coid, globalKeyOpt(node)).left.map(Right(_))
|
||||
visitCreate(node.coid, node.gkeyOpt).left.map(Right(_))
|
||||
|
||||
private[lf] def visitCreate(
|
||||
contractId: ContractId,
|
||||
@ -164,7 +164,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
|
||||
visitExercise(
|
||||
nid,
|
||||
exe.targetCoid,
|
||||
globalKeyOpt(exe),
|
||||
exe.gkeyOpt,
|
||||
exe.byKey,
|
||||
exe.consuming,
|
||||
).left
|
||||
@ -204,7 +204,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
|
||||
throw new UnsupportedOperationException(
|
||||
"handleLookup can only be used if all key nodes are considered"
|
||||
)
|
||||
visitLookup(globalKey(lookup), lookup.result, lookup.result).left.map(Left(_))
|
||||
visitLookup(lookup.gkey, lookup.result, lookup.result).left.map(Left(_))
|
||||
}
|
||||
|
||||
/** Must be used to handle lookups iff in [[com.daml.lf.transaction.ContractKeyUniquenessMode.Off]] mode
|
||||
@ -226,7 +226,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
|
||||
throw new UnsupportedOperationException(
|
||||
"handleLookupWith can only be used if only by-key nodes are considered"
|
||||
)
|
||||
visitLookup(globalKey(lookup), keyInput, lookup.result).left.map(Left(_))
|
||||
visitLookup(lookup.gkey, keyInput, lookup.result).left.map(Left(_))
|
||||
}
|
||||
|
||||
private[lf] def visitLookup(
|
||||
@ -274,7 +274,7 @@ class ContractStateMachine[Nid](mode: ContractKeyUniquenessMode) {
|
||||
}
|
||||
|
||||
def handleFetch(node: Node.Fetch): Either[KeyInputError, State] =
|
||||
visitFetch(node.coid, globalKeyOpt(node), node.byKey).left.map(Left(_))
|
||||
visitFetch(node.coid, node.gkeyOpt, node.byKey).left.map(Left(_))
|
||||
|
||||
private[lf] def visitFetch(
|
||||
contractId: ContractId,
|
||||
@ -532,10 +532,4 @@ object ContractStateMachine {
|
||||
def empty[Nid]: ActiveLedgerState[Nid] = EMPTY
|
||||
}
|
||||
|
||||
private def globalKeyOpt(node: Node.Action) =
|
||||
node.keyOpt.map(k => GlobalKey.assertBuild(node.templateId, k.key))
|
||||
|
||||
private def globalKey(node: Node.LookupByKey) =
|
||||
GlobalKey.assertBuild(node.templateId, node.key.key)
|
||||
|
||||
}
|
||||
|
@ -40,7 +40,18 @@ object GlobalKey {
|
||||
final case class GlobalKeyWithMaintainers(
|
||||
globalKey: GlobalKey,
|
||||
maintainers: Set[Ref.Party],
|
||||
)
|
||||
) {
|
||||
def value: Value = globalKey.key
|
||||
}
|
||||
|
||||
object GlobalKeyWithMaintainers {
|
||||
def assertBuild(
|
||||
templateId: Ref.TypeConName,
|
||||
value: Value,
|
||||
maintainers: Set[Ref.Party],
|
||||
): GlobalKeyWithMaintainers =
|
||||
GlobalKeyWithMaintainers(GlobalKey.assertBuild(templateId, value), maintainers)
|
||||
}
|
||||
|
||||
/** Controls whether the engine should error out when it encounters duplicate keys.
|
||||
* This is always turned on with the exception of Canton which allows turning this on or off
|
||||
|
@ -38,7 +38,12 @@ object Node {
|
||||
*/
|
||||
def packageIds: Iterable[PackageId]
|
||||
|
||||
def keyOpt: Option[KeyWithMaintainers]
|
||||
def keyOpt: Option[GlobalKeyWithMaintainers]
|
||||
|
||||
final def gkeyOpt: Option[GlobalKey] = keyOpt.map(_.globalKey)
|
||||
|
||||
def versionedKeyOpt: Option[Versioned[GlobalKeyWithMaintainers]] =
|
||||
keyOpt.map(Versioned(version, _))
|
||||
|
||||
final override protected def self: this.type = this
|
||||
|
||||
@ -71,21 +76,22 @@ object Node {
|
||||
agreementText: String,
|
||||
signatories: Set[Party],
|
||||
stakeholders: Set[Party],
|
||||
key: Option[KeyWithMaintainers],
|
||||
keyOpt: Option[GlobalKeyWithMaintainers],
|
||||
// For the sake of consistency between types with a version field, keep this field the last.
|
||||
override val version: TransactionVersion,
|
||||
) extends LeafOnlyAction
|
||||
with ActionNodeInfo.Create {
|
||||
|
||||
override def byKey: Boolean = false
|
||||
@deprecated("use keyOpt", since = "2.6.0")
|
||||
def key: Option[GlobalKeyWithMaintainers] = keyOpt
|
||||
|
||||
override def keyOpt: Option[KeyWithMaintainers] = key
|
||||
override def byKey: Boolean = false
|
||||
|
||||
override private[lf] def updateVersion(version: TransactionVersion): Node.Create =
|
||||
copy(version = version)
|
||||
|
||||
override def mapCid(f: ContractId => ContractId): Node.Create =
|
||||
copy(coid = f(coid), arg = arg.mapCid(f), key = key.map(_.mapCid(f)))
|
||||
copy(coid = f(coid), arg = arg.mapCid(f))
|
||||
|
||||
override def packageIds: Iterable[PackageId] = Iterable(templateId.packageId)
|
||||
|
||||
@ -96,9 +102,7 @@ object Node {
|
||||
|
||||
def versionedCoinst: Value.VersionedContractInstance = versioned(coinst)
|
||||
|
||||
def versionedKey: Option[VersionedKeyWithMaintainers] = key.map(versioned)
|
||||
|
||||
def keyValue: Option[Value] = key.map(_.key)
|
||||
def versionedKey: Option[Versioned[GlobalKeyWithMaintainers]] = keyOpt.map(versioned(_))
|
||||
}
|
||||
|
||||
/** Denotes that the contract identifier `coid` needs to be active for the transaction to be valid. */
|
||||
@ -108,26 +112,23 @@ object Node {
|
||||
actingParties: Set[Party],
|
||||
signatories: Set[Party],
|
||||
stakeholders: Set[Party],
|
||||
key: Option[KeyWithMaintainers],
|
||||
override val keyOpt: Option[GlobalKeyWithMaintainers],
|
||||
override val byKey: Boolean,
|
||||
// For the sake of consistency between types with a version field, keep this field the last.
|
||||
override val version: TransactionVersion,
|
||||
) extends LeafOnlyAction
|
||||
with ActionNodeInfo.Fetch {
|
||||
|
||||
override def keyOpt: Option[KeyWithMaintainers] = key
|
||||
@deprecated("use keyOpt", since = "2.6.0")
|
||||
def key: Option[GlobalKeyWithMaintainers] = keyOpt
|
||||
|
||||
override private[lf] def updateVersion(version: TransactionVersion): Node.Fetch =
|
||||
copy(version = version)
|
||||
|
||||
override def mapCid(f: ContractId => ContractId): Node.Fetch =
|
||||
copy(coid = f(coid), key = key.map(_.mapCid(f)))
|
||||
copy(coid = f(coid))
|
||||
|
||||
override def packageIds: Iterable[PackageId] = Iterable(templateId.packageId)
|
||||
|
||||
def versionedKey: Option[VersionedKeyWithMaintainers] = key.map(versioned)
|
||||
|
||||
def keyValue: Option[Value] = key.map(_.key)
|
||||
}
|
||||
|
||||
/** Denotes a transaction node for an exercise.
|
||||
@ -148,7 +149,7 @@ object Node {
|
||||
choiceObservers: Set[Party],
|
||||
children: ImmArray[NodeId],
|
||||
exerciseResult: Option[Value],
|
||||
key: Option[KeyWithMaintainers],
|
||||
keyOpt: Option[GlobalKeyWithMaintainers],
|
||||
override val byKey: Boolean,
|
||||
// For the sake of consistency between types with a version field, keep this field the last.
|
||||
override val version: TransactionVersion,
|
||||
@ -157,7 +158,8 @@ object Node {
|
||||
|
||||
def qualifiedChoiceName = QualifiedChoiceName(interfaceId, choiceId)
|
||||
|
||||
override def keyOpt: Option[KeyWithMaintainers] = key
|
||||
@deprecated("use keyOpt", since = "2.6.0")
|
||||
def key: Option[GlobalKeyWithMaintainers] = keyOpt
|
||||
|
||||
override private[lf] def updateVersion(
|
||||
version: TransactionVersion
|
||||
@ -168,7 +170,6 @@ object Node {
|
||||
targetCoid = f(targetCoid),
|
||||
chosenValue = chosenValue.mapCid(f),
|
||||
exerciseResult = exerciseResult.map(_.mapCid(f)),
|
||||
key = key.map(_.mapCid(f)),
|
||||
)
|
||||
|
||||
override def mapNodeId(f: NodeId => NodeId): Node.Exercise =
|
||||
@ -181,24 +182,25 @@ object Node {
|
||||
|
||||
def versionedExerciseResult: Option[Value.VersionedValue] = exerciseResult.map(versioned)
|
||||
|
||||
def versionedKey: Option[VersionedKeyWithMaintainers] = key.map(versioned)
|
||||
def versionedKey: Option[Versioned[GlobalKeyWithMaintainers]] = keyOpt.map(versioned)
|
||||
|
||||
def keyValue: Option[Value] = key.map(_.key)
|
||||
}
|
||||
|
||||
final case class LookupByKey(
|
||||
override val templateId: TypeConName,
|
||||
key: KeyWithMaintainers,
|
||||
key: GlobalKeyWithMaintainers,
|
||||
result: Option[ContractId],
|
||||
// For the sake of consistency between types with a version field, keep this field the last.
|
||||
override val version: TransactionVersion,
|
||||
) extends LeafOnlyAction
|
||||
with ActionNodeInfo.LookupByKey {
|
||||
|
||||
override def keyOpt: Some[KeyWithMaintainers] = Some(key)
|
||||
override def keyOpt: Some[GlobalKeyWithMaintainers] = Some(key)
|
||||
|
||||
def gkey: GlobalKey = key.globalKey
|
||||
|
||||
override def mapCid(f: ContractId => ContractId): Node.LookupByKey =
|
||||
copy(key = key.mapCid(f), result = result.map(f))
|
||||
copy(result = result.map(f))
|
||||
|
||||
override def keyMaintainers: Set[Party] = key.maintainers
|
||||
override def hasResult: Boolean = result.isDefined
|
||||
@ -208,25 +210,15 @@ object Node {
|
||||
copy(version = version)
|
||||
|
||||
override def packageIds: Iterable[PackageId] = Iterable(templateId.packageId)
|
||||
|
||||
def versionedKey: VersionedKeyWithMaintainers = versioned(key)
|
||||
|
||||
def keyValue: Value = key.key
|
||||
}
|
||||
|
||||
final case class KeyWithMaintainers(key: Value, maintainers: Set[Party])
|
||||
extends CidContainer[KeyWithMaintainers] {
|
||||
@deprecated("use GlobalKey", since = "2.6.0")
|
||||
type KeyWithMaintainers = GlobalKey
|
||||
@deprecated("use GlobalKey", since = "2.6.0")
|
||||
val KeyWithMaintainers = GlobalKey
|
||||
|
||||
def map(f: Value => Value): KeyWithMaintainers =
|
||||
copy(key = f(key))
|
||||
|
||||
override protected def self: this.type = this
|
||||
|
||||
override def mapCid(f: ContractId => ContractId): KeyWithMaintainers =
|
||||
copy(key = key.mapCid(f))
|
||||
}
|
||||
|
||||
type VersionedKeyWithMaintainers = Versioned[KeyWithMaintainers]
|
||||
@deprecated("use VersionedGlobalKey", since = "2.6.0")
|
||||
type VersionedKeyWithMaintainers = VersionedGlobalKey
|
||||
|
||||
final case class Rollback(
|
||||
children: ImmArray[NodeId]
|
||||
|
@ -28,7 +28,7 @@ class Normalization {
|
||||
* longer need this separate normalization pass.
|
||||
*/
|
||||
|
||||
private type KWM = Node.KeyWithMaintainers
|
||||
private type KWM = GlobalKeyWithMaintainers
|
||||
private type VTX = VersionedTransaction
|
||||
|
||||
def normalizeTx(vtx: VTX): VTX = {
|
||||
@ -55,7 +55,7 @@ class Normalization {
|
||||
case old: Node.Create =>
|
||||
old
|
||||
.copy(arg = normValue(old.version)(old.arg))
|
||||
.copy(key = old.key.map(normKWM(old.version)))
|
||||
.copy(keyOpt = old.keyOpt.map(normKWM(old.version)))
|
||||
|
||||
case old: Node.Fetch =>
|
||||
(if (old.version >= TransactionVersion.minByKey) {
|
||||
@ -64,7 +64,7 @@ class Normalization {
|
||||
old.copy(byKey = false)
|
||||
})
|
||||
.copy(
|
||||
key = old.key.map(normKWM(old.version))
|
||||
keyOpt = old.keyOpt.map(normKWM(old.version))
|
||||
)
|
||||
|
||||
case old: Node.Exercise =>
|
||||
@ -76,7 +76,7 @@ class Normalization {
|
||||
.copy(
|
||||
chosenValue = normValue(old.version)(old.chosenValue),
|
||||
exerciseResult = old.exerciseResult.map(normValue(old.version)),
|
||||
key = old.key.map(normKWM(old.version)),
|
||||
keyOpt = old.keyOpt.map(normKWM(old.version)),
|
||||
)
|
||||
|
||||
case old: Node.LookupByKey =>
|
||||
@ -95,8 +95,11 @@ class Normalization {
|
||||
|
||||
private def normKWM(version: TransactionVersion)(x: KWM): KWM = {
|
||||
x match {
|
||||
case Node.KeyWithMaintainers(key, maintainers) =>
|
||||
Node.KeyWithMaintainers(normValue(version)(key), maintainers)
|
||||
case GlobalKeyWithMaintainers(key, maintainers) =>
|
||||
GlobalKeyWithMaintainers(
|
||||
GlobalKey.assertBuild(key.templateId, normValue(version)(key.key)),
|
||||
maintainers,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,12 +237,12 @@ final case class Transaction(
|
||||
errs
|
||||
case _: Node.Fetch => errs
|
||||
case nc: Node.Create =>
|
||||
errs :++ f(nc.arg) :++ (nc.key match {
|
||||
errs :++ f(nc.arg) :++ (nc.keyOpt match {
|
||||
case None => ImmArray.Empty
|
||||
case Some(key) => f(key.key)
|
||||
case Some(key) => f(key.globalKey.key)
|
||||
})
|
||||
case ne: Node.Exercise => errs :++ f(ne.chosenValue)
|
||||
case nlbk: Node.LookupByKey => errs :++ f(nlbk.key.key)
|
||||
case nlbk: Node.LookupByKey => errs :++ f(nlbk.gkey.key)
|
||||
}
|
||||
}.toImmArray
|
||||
}
|
||||
@ -257,14 +257,14 @@ final case class Transaction(
|
||||
z
|
||||
case c: Node.Create =>
|
||||
val z1 = f(z, c.arg)
|
||||
val z2 = c.key match {
|
||||
val z2 = c.keyOpt match {
|
||||
case None => z1
|
||||
case Some(k) => f(z1, k.key)
|
||||
case Some(k) => f(z1, k.globalKey.key)
|
||||
}
|
||||
z2
|
||||
case nf: Node.Fetch => nf.key.fold(z)(k => f(z, k.key))
|
||||
case nf: Node.Fetch => nf.keyOpt.fold(z)(k => f(z, k.globalKey.key))
|
||||
case e: Node.Exercise => f(z, e.chosenValue)
|
||||
case lk: Node.LookupByKey => f(z, lk.key.key)
|
||||
case lk: Node.LookupByKey => f(z, lk.gkey.key)
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,17 +487,9 @@ sealed abstract class HasTxNodes {
|
||||
*/
|
||||
final def contractKeys: Set[GlobalKey] = {
|
||||
fold(Set.empty[GlobalKey]) {
|
||||
case (acc, (_, node: Node.Create)) =>
|
||||
node.key.fold(acc)(key => acc + GlobalKey.assertBuild(node.templateId, key.key))
|
||||
case (acc, (_, node: Node.Exercise)) =>
|
||||
node.key.fold(acc)(key => acc + GlobalKey.assertBuild(node.templateId, key.key))
|
||||
case (acc, (_, node: Node.Fetch)) =>
|
||||
node.key.fold(acc)(key => acc + GlobalKey.assertBuild(node.templateId, key.key))
|
||||
case (acc, (_, node: Node.LookupByKey)) =>
|
||||
acc + GlobalKey.assertBuild(node.templateId, node.key.key)
|
||||
case (acc, (_, _: Node.Authority)) =>
|
||||
acc
|
||||
case (acc, (_, _: Node.Rollback)) =>
|
||||
case (acc, (_, node: Node.Action)) =>
|
||||
node.gkeyOpt.fold(acc)(acc + _)
|
||||
case (acc, (_, (_: Node.Authority | _: Node.Rollback))) =>
|
||||
acc
|
||||
}
|
||||
}
|
||||
@ -570,9 +562,7 @@ sealed abstract class HasTxNodes {
|
||||
exerciseBegin = {
|
||||
case (acc, _, exec) if exec.consuming =>
|
||||
(
|
||||
exec.key.fold(acc)(key =>
|
||||
acc.updated(GlobalKey.assertBuild(exec.templateId, key.key), None)
|
||||
),
|
||||
exec.gkeyOpt.fold(acc)(acc.updated(_, None)),
|
||||
ChildrenRecursion.DoRecurse,
|
||||
)
|
||||
case (acc, _, _) => (acc, ChildrenRecursion.DoRecurse)
|
||||
@ -580,9 +570,7 @@ sealed abstract class HasTxNodes {
|
||||
rollbackBegin = (acc, _, _) => (acc, ChildrenRecursion.DoNotRecurse),
|
||||
leaf = {
|
||||
case (acc, _, create: Node.Create) =>
|
||||
create.key.fold(acc)(key =>
|
||||
acc.updated(GlobalKey.assertBuild(create.templateId, key.key), Some(create.coid))
|
||||
)
|
||||
create.gkeyOpt.fold(acc)(acc.updated(_, Some(create.coid)))
|
||||
case (acc, _, _: Node.Fetch | _: Node.LookupByKey) => acc
|
||||
},
|
||||
exerciseEnd = (acc, _, _) => acc,
|
||||
|
@ -181,9 +181,8 @@ object TransactionCoder {
|
||||
)
|
||||
|
||||
private[this] def encodeKeyWithMaintainers(
|
||||
encodeCid: ValueCoder.EncodeCid,
|
||||
version: TransactionVersion,
|
||||
key: Node.KeyWithMaintainers,
|
||||
key: GlobalKeyWithMaintainers,
|
||||
): Either[EncodeError, TransactionOuterClass.KeyWithMaintainers] = {
|
||||
val builder =
|
||||
TransactionOuterClass.KeyWithMaintainers
|
||||
@ -191,24 +190,23 @@ object TransactionCoder {
|
||||
.addAllMaintainers(key.maintainers.toSet[String].asJava)
|
||||
if (version < TransactionVersion.minNoVersionValue) {
|
||||
ValueCoder
|
||||
.encodeVersionedValue(encodeCid, version, key.key)
|
||||
.encodeVersionedValue(ValueCoder.UnsafeNoCidEncoder, version, key.value)
|
||||
.map(builder.setKeyVersioned(_).build())
|
||||
} else {
|
||||
ValueCoder
|
||||
.encodeValue(encodeCid, version, key.key)
|
||||
.encodeValue(ValueCoder.UnsafeNoCidEncoder, version, key.value)
|
||||
.map(builder.setKeyUnversioned(_).build())
|
||||
}
|
||||
}
|
||||
|
||||
private[this] def encodeAndSetContractKey(
|
||||
encodeCid: ValueCoder.EncodeCid,
|
||||
version: TransactionVersion,
|
||||
key: Option[Node.KeyWithMaintainers],
|
||||
key: Option[GlobalKeyWithMaintainers],
|
||||
setKey: TransactionOuterClass.KeyWithMaintainers => GeneratedMessageV3.Builder[_],
|
||||
) = {
|
||||
key match {
|
||||
case Some(key) =>
|
||||
encodeKeyWithMaintainers(encodeCid, version, key).map(k => discard(setKey(k)))
|
||||
encodeKeyWithMaintainers(version, key).map(k => discard(setKey(k)))
|
||||
case None =>
|
||||
Right(())
|
||||
}
|
||||
@ -303,9 +301,8 @@ object TransactionCoder {
|
||||
)
|
||||
}
|
||||
_ <- encodeAndSetContractKey(
|
||||
encodeCid,
|
||||
nodeVersion,
|
||||
nc.key,
|
||||
nc.keyOpt,
|
||||
builder.setKeyWithMaintainers,
|
||||
)
|
||||
} yield nodeBuilder.setCreate(builder).build()
|
||||
@ -322,9 +319,8 @@ object TransactionCoder {
|
||||
nf.actingParties.foreach(builder.addActors)
|
||||
for {
|
||||
_ <- encodeAndSetContractKey(
|
||||
encodeCid,
|
||||
nodeVersion,
|
||||
nf.key,
|
||||
nf.keyOpt,
|
||||
builder.setKeyWithMaintainers,
|
||||
)
|
||||
} yield nodeBuilder.setFetch(builder).build()
|
||||
@ -382,9 +378,8 @@ object TransactionCoder {
|
||||
)
|
||||
}
|
||||
_ <- encodeAndSetContractKey(
|
||||
encodeCid,
|
||||
nodeVersion,
|
||||
ne.key,
|
||||
ne.keyOpt,
|
||||
builder.setKeyWithMaintainers,
|
||||
)
|
||||
} yield nodeBuilder.setExercise(builder).build()
|
||||
@ -396,7 +391,7 @@ object TransactionCoder {
|
||||
discard(builder.setContractIdStruct(encodeCid.encode(cid)))
|
||||
)
|
||||
for {
|
||||
encodedKey <- encodeKeyWithMaintainers(encodeCid, nlbk.version, nlbk.key)
|
||||
encodedKey <- encodeKeyWithMaintainers(nlbk.version, nlbk.key)
|
||||
} yield {
|
||||
discard(builder.setKeyWithMaintainers(encodedKey))
|
||||
nodeBuilder.setLookupByKey(builder).build()
|
||||
@ -407,42 +402,33 @@ object TransactionCoder {
|
||||
}
|
||||
|
||||
private[this] def decodeKeyWithMaintainers(
|
||||
decodeCid: ValueCoder.DecodeCid,
|
||||
version: TransactionVersion,
|
||||
templateId: Ref.TypeConName,
|
||||
keyWithMaintainers: TransactionOuterClass.KeyWithMaintainers,
|
||||
): Either[DecodeError, Node.KeyWithMaintainers] = {
|
||||
): Either[DecodeError, GlobalKeyWithMaintainers] = {
|
||||
for {
|
||||
maintainers <- toPartySet(keyWithMaintainers.getMaintainersList)
|
||||
key <- decodeValue(
|
||||
decodeCid,
|
||||
value <- decodeValue(
|
||||
ValueCoder.NoCidDecoder,
|
||||
version,
|
||||
keyWithMaintainers.getKeyVersioned,
|
||||
keyWithMaintainers.getKeyUnversioned,
|
||||
)
|
||||
} yield Node.KeyWithMaintainers(key, maintainers)
|
||||
gkey <- GlobalKey.build(templateId, value).left.map(DecodeError)
|
||||
} yield GlobalKeyWithMaintainers(gkey, maintainers)
|
||||
}
|
||||
|
||||
private val RightNone = Right(None)
|
||||
|
||||
private[this] def decodeOptionalKeyWithMaintainers(
|
||||
decodeCid: ValueCoder.DecodeCid,
|
||||
version: TransactionVersion,
|
||||
templateId: Ref.TypeConName,
|
||||
keyWithMaintainers: TransactionOuterClass.KeyWithMaintainers,
|
||||
): Either[DecodeError, Option[Node.KeyWithMaintainers]] = {
|
||||
if (keyWithMaintainers == TransactionOuterClass.KeyWithMaintainers.getDefaultInstance) {
|
||||
): Either[DecodeError, Option[GlobalKeyWithMaintainers]] =
|
||||
if (keyWithMaintainers == TransactionOuterClass.KeyWithMaintainers.getDefaultInstance)
|
||||
RightNone
|
||||
} else {
|
||||
for {
|
||||
maintainers <- toPartySet(keyWithMaintainers.getMaintainersList)
|
||||
key <- decodeValue(
|
||||
decodeCid,
|
||||
version,
|
||||
keyWithMaintainers.getKeyVersioned,
|
||||
keyWithMaintainers.getKeyUnversioned,
|
||||
)
|
||||
} yield Some(Node.KeyWithMaintainers(key, maintainers))
|
||||
}
|
||||
}
|
||||
else
|
||||
decodeKeyWithMaintainers(version, templateId, keyWithMaintainers).map(Some(_))
|
||||
|
||||
// package private for test, do not use outside TransactionCoder
|
||||
private[lf] def decodeValue(
|
||||
@ -520,9 +506,9 @@ object TransactionCoder {
|
||||
Value.ContractInstanceWithAgreement(ci, agreementText) = entry
|
||||
stakeholders <- toPartySet(protoCreate.getStakeholdersList)
|
||||
signatories <- toPartySet(protoCreate.getSignatoriesList)
|
||||
key <- decodeOptionalKeyWithMaintainers(
|
||||
decodeCid,
|
||||
keyOpt <- decodeOptionalKeyWithMaintainers(
|
||||
nodeVersion,
|
||||
ci.template,
|
||||
protoCreate.getKeyWithMaintainers,
|
||||
)
|
||||
} yield ni -> Node.Create(
|
||||
@ -532,7 +518,7 @@ object TransactionCoder {
|
||||
agreementText = agreementText,
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
keyOpt = keyOpt,
|
||||
version = nodeVersion,
|
||||
)
|
||||
case NodeTypeCase.FETCH =>
|
||||
@ -544,9 +530,9 @@ object TransactionCoder {
|
||||
actingParties <- toPartySet(protoFetch.getActorsList)
|
||||
stakeholders <- toPartySet(protoFetch.getStakeholdersList)
|
||||
signatories <- toPartySet(protoFetch.getSignatoriesList)
|
||||
key <- decodeOptionalKeyWithMaintainers(
|
||||
decodeCid,
|
||||
keyOpt <- decodeOptionalKeyWithMaintainers(
|
||||
nodeVersion,
|
||||
templateId,
|
||||
protoFetch.getKeyWithMaintainers,
|
||||
)
|
||||
byKey =
|
||||
@ -559,7 +545,7 @@ object TransactionCoder {
|
||||
actingParties = actingParties,
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
keyOpt = keyOpt,
|
||||
byKey = byKey,
|
||||
version = nodeVersion,
|
||||
)
|
||||
@ -567,6 +553,7 @@ object TransactionCoder {
|
||||
case NodeTypeCase.EXERCISE =>
|
||||
val protoExe = protoNode.getExercise
|
||||
for {
|
||||
templateId <- ValueCoder.decodeIdentifier(protoExe.getTemplateId)
|
||||
rvOpt <-
|
||||
if (!protoExe.hasResultVersioned && protoExe.getResultUnversioned.isEmpty) {
|
||||
Either.cond(
|
||||
@ -585,7 +572,11 @@ object TransactionCoder {
|
||||
).map(v => Some(v))
|
||||
}
|
||||
keyWithMaintainers <-
|
||||
decodeOptionalKeyWithMaintainers(decodeCid, nodeVersion, protoExe.getKeyWithMaintainers)
|
||||
decodeOptionalKeyWithMaintainers(
|
||||
nodeVersion,
|
||||
templateId,
|
||||
protoExe.getKeyWithMaintainers,
|
||||
)
|
||||
ni <- nodeId
|
||||
targetCoid <- decodeCid.decode(protoExe.getContractIdStruct)
|
||||
children <- decodeChildren(decodeNid, protoExe.getChildrenList)
|
||||
@ -595,7 +586,6 @@ object TransactionCoder {
|
||||
protoExe.getArgVersioned,
|
||||
protoExe.getArgUnversioned,
|
||||
)
|
||||
templateId <- ValueCoder.decodeIdentifier(protoExe.getTemplateId)
|
||||
actingParties <- toPartySet(protoExe.getActorsList)
|
||||
signatories <- toPartySet(protoExe.getSignatoriesList)
|
||||
stakeholders <- toPartySet(protoExe.getStakeholdersList)
|
||||
@ -629,7 +619,7 @@ object TransactionCoder {
|
||||
choiceObservers = choiceObservers,
|
||||
children = children,
|
||||
exerciseResult = rvOpt,
|
||||
key = keyWithMaintainers,
|
||||
keyOpt = keyWithMaintainers,
|
||||
byKey = byKey,
|
||||
version = nodeVersion,
|
||||
)
|
||||
@ -639,7 +629,11 @@ object TransactionCoder {
|
||||
ni <- nodeId
|
||||
templateId <- ValueCoder.decodeIdentifier(protoLookupByKey.getTemplateId)
|
||||
key <-
|
||||
decodeKeyWithMaintainers(decodeCid, nodeVersion, protoLookupByKey.getKeyWithMaintainers)
|
||||
decodeKeyWithMaintainers(
|
||||
nodeVersion,
|
||||
templateId,
|
||||
protoLookupByKey.getKeyWithMaintainers,
|
||||
)
|
||||
cid <- decodeCid.decodeOptional(protoLookupByKey.getContractIdStruct)
|
||||
} yield ni -> Node.LookupByKey(templateId, key, cid, nodeVersion)
|
||||
case NodeTypeCase.NODETYPE_NOT_SET => Left(DecodeError("Unset Node type"))
|
||||
|
@ -88,15 +88,17 @@ object Util {
|
||||
.map(normalized => contract.map(_.copy(arg = normalized)))
|
||||
|
||||
def normalizeKey(
|
||||
key: Node.KeyWithMaintainers,
|
||||
key: GlobalKeyWithMaintainers,
|
||||
version: TransactionVersion,
|
||||
): Either[String, Node.KeyWithMaintainers] =
|
||||
normalizeValue(key.key, version).map(normalized => key.copy(key = normalized))
|
||||
): Either[String, GlobalKeyWithMaintainers] =
|
||||
normalizeValue(key.globalKey.key, version).map(normalized =>
|
||||
key.copy(globalKey = GlobalKey.assertBuild(key.globalKey.templateId, normalized))
|
||||
)
|
||||
|
||||
def normalizeOptKey(
|
||||
key: Option[Node.KeyWithMaintainers],
|
||||
key: Option[GlobalKeyWithMaintainers],
|
||||
version: TransactionVersion,
|
||||
): Either[String, Option[Node.KeyWithMaintainers]] =
|
||||
): Either[String, Option[GlobalKeyWithMaintainers]] =
|
||||
key match {
|
||||
case Some(value) => normalizeKey(value, version).map(Some(_))
|
||||
case None => Right(None)
|
||||
|
@ -30,4 +30,6 @@ package object transaction {
|
||||
val CommittedTransaction = DiscriminatedSubtype[VersionedTransaction]
|
||||
type CommittedTransaction = CommittedTransaction.T
|
||||
|
||||
type VersionedGlobalKey = Versioned[GlobalKey]
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import com.daml.lf.data._
|
||||
import com.daml.lf.transaction.{TransactionVersion, Versioned}
|
||||
import com.daml.lf.value.Value._
|
||||
import com.daml.lf.value.{ValueOuterClass => proto}
|
||||
import com.daml.nameof.NameOf
|
||||
import com.daml.scalautil.Statement.discard
|
||||
import com.google.protobuf
|
||||
import com.google.protobuf.{ByteString, CodedInputStream}
|
||||
@ -90,6 +91,12 @@ object ValueCoder {
|
||||
override def decodeOptional(structForm: ValueOuterClass.ContractId) = Right(None)
|
||||
}
|
||||
|
||||
// To be use only when certain the value does not contain Contract Ids
|
||||
val UnsafeNoCidEncoder: EncodeCid = new EncodeCid {
|
||||
override private[lf] def encode(contractId: ContractId) =
|
||||
InternalError.runtimeException(NameOf.qualifiedNameOfCurrentFunc, "unexpected contract ID")
|
||||
}
|
||||
|
||||
/** Simple encoding to wire of identifiers
|
||||
* @param id identifier value
|
||||
* @return wire format identifier
|
||||
|
@ -14,7 +14,6 @@ import com.daml.lf.transaction.ContractStateMachine.{
|
||||
KeyResolver,
|
||||
}
|
||||
import com.daml.lf.transaction.ContractStateMachineSpec._
|
||||
import com.daml.lf.transaction.Node.KeyWithMaintainers
|
||||
import com.daml.lf.transaction.Transaction.{
|
||||
ChildrenRecursion,
|
||||
DuplicateContractKey,
|
||||
@ -60,8 +59,18 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
|
||||
ContractId.V1(hash)
|
||||
}
|
||||
|
||||
private def toKeyWithMaintainers(key: String): Option[KeyWithMaintainers] =
|
||||
if (key.isEmpty) None else Some(Node.KeyWithMaintainers(Value.ValueText(key), aliceS))
|
||||
private def toKeyWithMaintainers(
|
||||
templateId: Ref.TypeConName,
|
||||
key: String,
|
||||
): GlobalKeyWithMaintainers =
|
||||
GlobalKeyWithMaintainers.assertBuild(templateId, Value.ValueText(key), aliceS)
|
||||
|
||||
private def toOptKeyWithMaintainers(
|
||||
templateId: Ref.TypeConName,
|
||||
key: String,
|
||||
): Option[GlobalKeyWithMaintainers] =
|
||||
if (key.isEmpty) None
|
||||
else Some(toKeyWithMaintainers(templateId, key))
|
||||
|
||||
def gkey(key: String): GlobalKey =
|
||||
GlobalKey.assertBuild(templateId, Value.ValueText(key))
|
||||
@ -77,7 +86,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
|
||||
agreementText = "",
|
||||
signatories = aliceS,
|
||||
stakeholders = aliceS,
|
||||
key = toKeyWithMaintainers(key),
|
||||
keyOpt = toOptKeyWithMaintainers(templateId, key),
|
||||
version = txVersion,
|
||||
)
|
||||
|
||||
@ -100,7 +109,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
|
||||
choiceObservers = Set.empty,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = None,
|
||||
key = toKeyWithMaintainers(key),
|
||||
keyOpt = toOptKeyWithMaintainers(templateId, key),
|
||||
byKey = byKey,
|
||||
version = txVersion,
|
||||
)
|
||||
@ -117,7 +126,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
|
||||
actingParties = aliceS,
|
||||
signatories = aliceS,
|
||||
stakeholders = aliceS,
|
||||
key = toKeyWithMaintainers(key),
|
||||
keyOpt = toOptKeyWithMaintainers(templateId, key),
|
||||
byKey = byKey,
|
||||
version = txVersion,
|
||||
)
|
||||
@ -129,7 +138,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
|
||||
): Node.LookupByKey =
|
||||
Node.LookupByKey(
|
||||
templateId = templateId,
|
||||
key = Node.KeyWithMaintainers(Value.ValueText(key), aliceS),
|
||||
key = toKeyWithMaintainers(templateId, key),
|
||||
result = contractId,
|
||||
version = txVersion,
|
||||
)
|
||||
@ -655,9 +664,7 @@ class ContractStateMachineSpec extends AnyWordSpec with Matchers with TableDrive
|
||||
case _: Node.Authority =>
|
||||
??? // TODO #15882 -- treat like exercise with no keys. recurse directly on children
|
||||
case actionNode: Node.Action =>
|
||||
lazy val gkeyO =
|
||||
actionNode.keyOpt.map(key => GlobalKey.assertBuild(actionNode.templateId, key.key))
|
||||
state.handleNode((), actionNode, gkeyO.flatMap(resolver))
|
||||
state.handleNode((), actionNode, actionNode.gkeyOpt.flatMap(resolver))
|
||||
case _: Node.Rollback =>
|
||||
Right(state.beginRollback())
|
||||
}
|
||||
@ -736,25 +743,24 @@ object ContractStateMachineSpec {
|
||||
def resolverFromTx(tx: HasTxNodes): KeyResolver = {
|
||||
def updateKey(
|
||||
resolver: KeyResolver,
|
||||
templateId: Ref.TypeConName,
|
||||
mbKey: Option[KeyWithMaintainers],
|
||||
mbKey: Option[GlobalKey],
|
||||
mapping: KeyMapping,
|
||||
): KeyResolver = mbKey.fold(resolver) { key =>
|
||||
val gkey = GlobalKey.assertBuild(templateId, key.key)
|
||||
): KeyResolver = mbKey.fold(resolver) { gkey =>
|
||||
if (resolver.contains(gkey)) resolver else resolver.updated(gkey, mapping)
|
||||
}
|
||||
|
||||
tx.foldInExecutionOrder(Map.empty: KeyResolver)(
|
||||
exerciseBegin = (s, _, ex) =>
|
||||
updateKey(s, ex.templateId, ex.key, KeyActive(ex.targetCoid)) ->
|
||||
updateKey(s, ex.gkeyOpt, KeyActive(ex.targetCoid)) ->
|
||||
ChildrenRecursion.DoRecurse,
|
||||
exerciseEnd = (s, _, _) => s,
|
||||
leaf = (s, _, leaf) =>
|
||||
leaf match {
|
||||
case create: Node.Create => updateKey(s, create.templateId, create.key, KeyInactive)
|
||||
case fetch: Node.Fetch => updateKey(s, fetch.templateId, fetch.key, KeyActive(fetch.coid))
|
||||
case create: Node.Create => updateKey(s, create.gkeyOpt, KeyInactive)
|
||||
case fetch: Node.Fetch =>
|
||||
updateKey(s, fetch.gkeyOpt, KeyActive(fetch.coid))
|
||||
case lookup: Node.LookupByKey =>
|
||||
updateKey(s, lookup.templateId, Some(lookup.key), lookup.result)
|
||||
updateKey(s, Some(lookup.gkey), lookup.result)
|
||||
},
|
||||
rollbackBegin = (s, _, _) => s -> ChildrenRecursion.DoRecurse,
|
||||
rollbackEnd = (s, _, _) => s,
|
||||
|
@ -232,7 +232,7 @@ class TransactionCoderSpec
|
||||
agreementText = "agreement",
|
||||
signatories = Set(Party.assertFromString("alice")),
|
||||
stakeholders = Set(Party.assertFromString("alice"), Party.assertFromString("bob")),
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
@ -410,7 +410,7 @@ class TransactionCoderSpec
|
||||
|
||||
"fail if try to encode a fetch node containing value with version different from node" in {
|
||||
forAll(fetchNodeGen, transactionVersionGen(), minSuccessful(5)) { (node, version) =>
|
||||
whenever(node.version != version && node.key.isDefined) {
|
||||
whenever(node.version != version && node.keyOpt.isDefined) {
|
||||
val nodeVersion = node.version
|
||||
val encodeVersion = ValueCoder.encodeValueVersion(version)
|
||||
val Right(encodedNode) = TransactionCoder.encodeNode(
|
||||
@ -845,13 +845,13 @@ class TransactionCoderSpec
|
||||
}
|
||||
def withoutContractKeyInExercise(gn: Node): Node =
|
||||
gn match {
|
||||
case ne: Node.Exercise => ne copy (key = None)
|
||||
case ne: Node.Exercise => ne copy (keyOpt = None)
|
||||
case _ => gn
|
||||
}
|
||||
def withoutMaintainersInExercise(gn: Node): Node =
|
||||
gn match {
|
||||
case ne: Node.Exercise =>
|
||||
ne copy (key = ne.key.map(_.copy(maintainers = Set.empty)))
|
||||
ne copy (keyOpt = ne.keyOpt.map(_.copy(maintainers = Set.empty)))
|
||||
case _ => gn
|
||||
}
|
||||
|
||||
@ -908,13 +908,13 @@ class TransactionCoderSpec
|
||||
): Node.Create = {
|
||||
create.copy(
|
||||
arg = normalize(create.arg, create.version),
|
||||
key = create.key.map(normalizeKey(_, create.version)),
|
||||
keyOpt = create.keyOpt.map(normalizeKey(_, create.version)),
|
||||
)
|
||||
}
|
||||
|
||||
private[this] def normalizeFetch(fetch: Node.Fetch) =
|
||||
fetch.copy(
|
||||
key = fetch.key.map(normalizeKey(_, fetch.version)),
|
||||
keyOpt = fetch.keyOpt.map(normalizeKey(_, fetch.version)),
|
||||
byKey =
|
||||
if (fetch.version >= TransactionVersion.minByKey)
|
||||
fetch.byKey
|
||||
@ -940,7 +940,7 @@ class TransactionCoderSpec
|
||||
},
|
||||
choiceObservers =
|
||||
exe.choiceObservers.filter(_ => exe.version >= TransactionVersion.minChoiceObservers),
|
||||
key = exe.key.map(normalizeKey(_, exe.version)),
|
||||
keyOpt = exe.keyOpt.map(normalizeKey(_, exe.version)),
|
||||
byKey =
|
||||
if (exe.version >= TransactionVersion.minByKey)
|
||||
exe.byKey
|
||||
@ -948,11 +948,12 @@ class TransactionCoderSpec
|
||||
)
|
||||
|
||||
private[this] def normalizeKey(
|
||||
key: Node.KeyWithMaintainers,
|
||||
key: GlobalKeyWithMaintainers,
|
||||
version: TransactionVersion,
|
||||
) = {
|
||||
key.copy(key = normalize(key.key, version))
|
||||
}
|
||||
) =
|
||||
key.copy(globalKey =
|
||||
GlobalKey.assertBuild(key.globalKey.templateId, normalize(key.value, version))
|
||||
)
|
||||
|
||||
private[this] def normalizeContract(contract: Versioned[Value.ContractInstanceWithAgreement]) =
|
||||
contract.map(
|
||||
|
@ -59,7 +59,7 @@ class TransactionNodeStatisticsSpec
|
||||
argument = Value.ValueUnit,
|
||||
signatories = parties,
|
||||
observers = Set.empty,
|
||||
key = if (withKey) Some(Value.ValueUnit) else None,
|
||||
keyOpt = if (withKey) Some(Value.ValueUnit) else None,
|
||||
maintainers = if (withKey) parties else Set.empty,
|
||||
)
|
||||
}
|
||||
|
@ -559,9 +559,10 @@ class TransactionSpec
|
||||
val builder = TransactionBuilder()
|
||||
val create0 = create(cid("#0"))
|
||||
val create1 = create(cid("#1")).copy(
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(
|
||||
key = keyValue(cid("#0").coid),
|
||||
keyOpt = Some(
|
||||
GlobalKeyWithMaintainers.assertBuild(
|
||||
templateId = "Mod:T",
|
||||
value = keyValue(cid("#0").coid),
|
||||
maintainers = Set.empty,
|
||||
)
|
||||
)
|
||||
@ -1043,7 +1044,7 @@ object TransactionSpec {
|
||||
choiceObservers = Set.empty,
|
||||
children = children,
|
||||
exerciseResult = if (hasExerciseResult) Some(V.ValueUnit) else None,
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
byKey = false,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
@ -1056,7 +1057,7 @@ object TransactionSpec {
|
||||
agreementText = "dummyAgreement",
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
|
@ -44,7 +44,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
// --[types]--
|
||||
|
||||
private type Val = V
|
||||
private type KWM = Node.KeyWithMaintainers
|
||||
private type KWM = GlobalKeyWithMaintainers
|
||||
private type OKWM = Option[KWM]
|
||||
private type Exe = Node.Exercise
|
||||
private type VTX = VersionedTransaction
|
||||
@ -75,11 +75,14 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
private val samParties4: Set[Party] = Set(samParty1, samParty2)
|
||||
|
||||
private val samValue1: Val = V.ValueUnit
|
||||
private val samValue2: Val = V.ValueContractId(samContractId1)
|
||||
private val samValue2: Val = V.ValueText(samContractId1.coid)
|
||||
|
||||
private val samKWM1 = Node.KeyWithMaintainers(samValue1, samParties1)
|
||||
private val samKWM2 = Node.KeyWithMaintainers(samValue1, samParties2)
|
||||
private val samKWM3 = Node.KeyWithMaintainers(samValue2, samParties1)
|
||||
private val samKWM1 =
|
||||
GlobalKeyWithMaintainers.assertBuild(samTemplateId1, samValue1, samParties1)
|
||||
private val samKWM2 =
|
||||
GlobalKeyWithMaintainers.assertBuild(samTemplateId1, samValue1, samParties2)
|
||||
private val samKWM3 =
|
||||
GlobalKeyWithMaintainers.assertBuild(samTemplateId2, samValue2, samParties1)
|
||||
|
||||
private val samVersion1: TransactionVersion = TransactionVersion.minVersion
|
||||
private val samVersion2: TransactionVersion = TransactionVersion.maxVersion
|
||||
@ -95,7 +98,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
agreementText = samText1,
|
||||
signatories = samParties1,
|
||||
stakeholders = samParties2,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
version = version,
|
||||
)
|
||||
|
||||
@ -110,7 +113,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
actingParties = actingParties,
|
||||
signatories = samParties2,
|
||||
stakeholders = samParties3,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
byKey = samBool1,
|
||||
version = version,
|
||||
)
|
||||
@ -146,7 +149,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
choiceObservers = samParties4,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = exerciseResult,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
byKey = samBool2,
|
||||
version = version,
|
||||
)
|
||||
@ -267,7 +270,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
}
|
||||
private def tweakCreateKey(tweakOptKeyMaintainers: Tweak[OKWM]) = Tweak[Node] {
|
||||
case nc: Node.Create =>
|
||||
tweakOptKeyMaintainers.run(nc.key).map { x => nc.copy(key = x) }
|
||||
tweakOptKeyMaintainers.run(nc.keyOpt).map { x => nc.copy(keyOpt = x) }
|
||||
}
|
||||
private val tweakCreateVersion = Tweak.single[Node] { case nc: Node.Create =>
|
||||
nc.copy(version = changeVersion(nc.version))
|
||||
@ -304,7 +307,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
}
|
||||
private def tweakFetchKey(tweakOptKeyMaintainers: Tweak[OKWM]) = Tweak[Node] {
|
||||
case nf: Node.Fetch =>
|
||||
tweakOptKeyMaintainers.run(nf.key).map { x => nf.copy(key = x) }
|
||||
tweakOptKeyMaintainers.run(nf.keyOpt).map { x => nf.copy(keyOpt = x) }
|
||||
}
|
||||
private def tweakFetchByKey(whenVersion: TransactionVersion => Boolean) = Tweak.single[Node] {
|
||||
case nf: Node.Fetch if whenVersion(nf.version) =>
|
||||
@ -391,7 +394,7 @@ class ValidationSpec extends AnyFreeSpec with Matchers with TableDrivenPropertyC
|
||||
|
||||
private def tweakExerciseKey(tweakOptKeyMaintainers: Tweak[OKWM]) = Tweak[Node] {
|
||||
case ne: Node.Exercise =>
|
||||
tweakOptKeyMaintainers.run(ne.key).map { x => ne.copy(key = x) }
|
||||
tweakOptKeyMaintainers.run(ne.keyOpt).map { x => ne.copy(keyOpt = x) }
|
||||
}
|
||||
private def tweakExerciseByKey(whenVersion: TransactionVersion => Boolean) = Tweak.single[Node] {
|
||||
case ne: Node.Exercise if whenVersion(ne.version) =>
|
||||
|
@ -12,7 +12,7 @@ import com.daml.lf.data.LawlessTraversals._
|
||||
import com.daml.lf.data.Ref.Identifier
|
||||
import com.daml.lf.data.{Numeric, Ref}
|
||||
import com.daml.lf.ledger.EventId
|
||||
import com.daml.lf.transaction.{Node, NodeId}
|
||||
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Node, NodeId}
|
||||
import com.daml.lf.value.{Value => Lf}
|
||||
import com.google.protobuf.empty.Empty
|
||||
import com.google.protobuf.timestamp.Timestamp
|
||||
@ -173,13 +173,13 @@ object LfEngineToApi {
|
||||
|
||||
def lfContractKeyToApiValue(
|
||||
verbose: Boolean,
|
||||
lf: Node.KeyWithMaintainers,
|
||||
lf: GlobalKeyWithMaintainers,
|
||||
): Either[String, api.Value] =
|
||||
lfValueToApiValue(verbose, lf.key)
|
||||
lfValueToApiValue(verbose, lf.value)
|
||||
|
||||
def lfContractKeyToApiValue(
|
||||
verbose: Boolean,
|
||||
lf: Option[Node.KeyWithMaintainers],
|
||||
lf: Option[GlobalKeyWithMaintainers],
|
||||
): Either[String, Option[api.Value]] =
|
||||
lf.fold[Either[String, Option[api.Value]]](Right(None))(
|
||||
lfContractKeyToApiValue(verbose, _).map(Some(_))
|
||||
@ -193,7 +193,7 @@ object LfEngineToApi {
|
||||
): Either[String, Event] =
|
||||
for {
|
||||
arg <- lfValueToApiRecord(verbose, node.arg)
|
||||
key <- lfContractKeyToApiValue(verbose, node.key)
|
||||
key <- lfContractKeyToApiValue(verbose, node.keyOpt)
|
||||
} yield Event(
|
||||
Event.Event.Created(
|
||||
CreatedEvent(
|
||||
@ -238,7 +238,7 @@ object LfEngineToApi {
|
||||
): Either[String, TreeEvent] =
|
||||
for {
|
||||
arg <- lfValueToApiRecord(verbose, node.arg)
|
||||
key <- lfContractKeyToApiValue(verbose, node.key)
|
||||
key <- lfContractKeyToApiValue(verbose, node.keyOpt)
|
||||
} yield TreeEvent(
|
||||
TreeEvent.Kind.Created(
|
||||
CreatedEvent(
|
||||
|
@ -11,7 +11,6 @@ import com.daml.ledger.api.DeduplicationPeriod.{DeduplicationDuration, Deduplica
|
||||
import com.daml.ledger.offset.Offset
|
||||
import com.daml.ledger.participant.state.v2.{CompletionInfo, Update}
|
||||
import com.daml.ledger.resources.ResourceOwner
|
||||
import com.daml.lf.crypto.Hash
|
||||
import com.daml.lf.data.Ref.HexString
|
||||
import com.daml.lf.engine.Blinding
|
||||
import com.daml.lf.ledger.EventId
|
||||
@ -250,7 +249,7 @@ private[platform] object InMemoryStateUpdater {
|
||||
commandId = txAccepted.optCompletionInfo.map(_.commandId).getOrElse(""),
|
||||
workflowId = txAccepted.transactionMeta.workflowId.getOrElse(""),
|
||||
contractKey =
|
||||
create.key.map(k => com.daml.lf.transaction.Versioned(create.version, k.key)),
|
||||
create.keyOpt.map(k => com.daml.lf.transaction.Versioned(create.version, k.value)),
|
||||
treeEventWitnesses = blinding.disclosure.getOrElse(nodeId, Set.empty),
|
||||
flatEventWitnesses = create.stakeholders,
|
||||
submitters = txAccepted.optCompletionInfo
|
||||
@ -260,7 +259,7 @@ private[platform] object InMemoryStateUpdater {
|
||||
createSignatories = create.signatories,
|
||||
createObservers = create.stakeholders.diff(create.signatories),
|
||||
createAgreementText = Some(create.agreementText).filter(_.nonEmpty),
|
||||
createKeyHash = create.key.map(_.key).map(Hash.safeHashContractKey(create.templateId, _)),
|
||||
createKeyHash = create.keyOpt.map(_.globalKey.hash),
|
||||
driverMetadata = txAccepted.contractMetadata.get(create.coid),
|
||||
)
|
||||
case (nodeId, exercise: Exercise) =>
|
||||
@ -276,7 +275,7 @@ private[platform] object InMemoryStateUpdater {
|
||||
commandId = txAccepted.optCompletionInfo.map(_.commandId).getOrElse(""),
|
||||
workflowId = txAccepted.transactionMeta.workflowId.getOrElse(""),
|
||||
contractKey =
|
||||
exercise.key.map(k => com.daml.lf.transaction.Versioned(exercise.version, k.key)),
|
||||
exercise.keyOpt.map(k => com.daml.lf.transaction.Versioned(exercise.version, k.value)),
|
||||
treeEventWitnesses = blinding.disclosure.getOrElse(nodeId, Set.empty),
|
||||
flatEventWitnesses = if (exercise.consuming) exercise.stakeholders else Set.empty,
|
||||
submitters = txAccepted.optCompletionInfo
|
||||
|
@ -234,8 +234,7 @@ object UpdateToDbDto {
|
||||
create_agreement_text = Some(create.agreementText).filter(_.nonEmpty),
|
||||
create_key_value = createKeyValue
|
||||
.map(compressionStrategy.createKeyValueCompression.compress),
|
||||
create_key_hash = create.key
|
||||
.map(key => Key.assertBuild(create.templateId, key.key).hash.bytes.toHexString),
|
||||
create_key_hash = create.keyOpt.map(_.globalKey.hash.bytes.toHexString),
|
||||
create_argument_compression = compressionStrategy.createArgumentCompression.id,
|
||||
create_key_value_compression =
|
||||
compressionStrategy.createKeyValueCompression.id.filter(_ =>
|
||||
|
@ -123,7 +123,7 @@ final class LfValueTranslation(
|
||||
private def serializeNullableKeyOrThrow(c: Create): Option[Array[Byte]] =
|
||||
c.versionedKey.map(k =>
|
||||
ValueSerializer.serializeValue(
|
||||
value = k.map(_.key),
|
||||
value = k.map(_.value),
|
||||
errorContext = cantSerialize(attribute = "key", forContract = c.coid),
|
||||
)
|
||||
)
|
||||
@ -131,7 +131,7 @@ final class LfValueTranslation(
|
||||
private def serializeNullableKeyOrThrow(e: Exercise): Option[Array[Byte]] = {
|
||||
e.versionedKey.map(k =>
|
||||
ValueSerializer.serializeValue(
|
||||
value = k.map(_.key),
|
||||
value = k.map(_.value),
|
||||
errorContext = cantSerialize(attribute = "key", forContract = e.targetCoid),
|
||||
)
|
||||
)
|
||||
|
@ -3,8 +3,7 @@
|
||||
|
||||
package com.daml.platform.store.dao
|
||||
|
||||
import com.daml.lf.transaction.GlobalKey
|
||||
import com.daml.lf.transaction.Node.KeyWithMaintainers
|
||||
import com.daml.lf.transaction.GlobalKeyWithMaintainers
|
||||
import com.daml.lf.value.Value.{ValueText, VersionedContractInstance}
|
||||
import com.daml.platform.store.interfaces.LedgerDaoContractsReader
|
||||
import org.scalatest.flatspec.AsyncFlatSpec
|
||||
@ -146,21 +145,28 @@ private[dao] trait JdbcLedgerDaoContractsSpec extends LoneElement with Inside wi
|
||||
it should "present the contract key state at a specific event sequential id" in {
|
||||
val aTextValue = ValueText(scala.util.Random.nextString(10))
|
||||
|
||||
val key = GlobalKeyWithMaintainers.assertBuild(someTemplateId, aTextValue, Set(alice, bob))
|
||||
|
||||
for {
|
||||
(_, tx) <- createAndStoreContract(
|
||||
submittingParties = Set(alice),
|
||||
signatories = Set(alice, bob),
|
||||
stakeholders = Set(alice, bob),
|
||||
key = Some(KeyWithMaintainers(aTextValue, Set(alice, bob))),
|
||||
key = Some(key),
|
||||
)
|
||||
key = GlobalKey.assertBuild(someTemplateId, aTextValue)
|
||||
contractId = nonTransient(tx).loneElement
|
||||
_ <- store(singleNonConsumingExercise(contractId))
|
||||
ledgerEndAtCreate <- ledgerDao.lookupLedgerEnd()
|
||||
_ <- store(txArchiveContract(alice, (contractId, None)))
|
||||
ledgerEndAfterArchive <- ledgerDao.lookupLedgerEnd()
|
||||
queryAfterCreate <- contractsReader.lookupKeyState(key, ledgerEndAtCreate.lastOffset)
|
||||
queryAfterArchive <- contractsReader.lookupKeyState(key, ledgerEndAfterArchive.lastOffset)
|
||||
queryAfterCreate <- contractsReader.lookupKeyState(
|
||||
key.globalKey,
|
||||
ledgerEndAtCreate.lastOffset,
|
||||
)
|
||||
queryAfterArchive <- contractsReader.lookupKeyState(
|
||||
key.globalKey,
|
||||
ledgerEndAfterArchive.lastOffset,
|
||||
)
|
||||
} yield {
|
||||
queryAfterCreate match {
|
||||
case LedgerDaoContractsReader.KeyAssigned(fetchedContractId, stakeholders) =>
|
||||
|
@ -7,8 +7,7 @@ import java.util.UUID
|
||||
|
||||
import com.daml.lf.data.{ImmArray, Ref}
|
||||
import com.daml.lf.data.Time.Timestamp
|
||||
import com.daml.lf.transaction.Node
|
||||
import com.daml.lf.transaction.TransactionVersion
|
||||
import com.daml.lf.transaction.{GlobalKeyWithMaintainers, Node, TransactionVersion}
|
||||
import com.daml.lf.transaction.test.TransactionBuilder
|
||||
import com.daml.lf.value.Value.{ValueParty, VersionedContractInstance}
|
||||
import com.daml.platform.store.entries.LedgerEntry
|
||||
@ -33,7 +32,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
agreementText = someAgreement,
|
||||
signatories = Set(alice),
|
||||
stakeholders = Set(alice),
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
)
|
||||
@ -50,8 +49,9 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
someAgreement,
|
||||
signatories = Set(bob),
|
||||
stakeholders = Set(bob),
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(someContractKey(bob, "some key"), Set(bob))
|
||||
keyOpt = Some(
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob))
|
||||
),
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
@ -74,7 +74,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
choiceObservers = Set.empty,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
byKey = false,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
@ -86,8 +86,8 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
actingParties = Set(bob),
|
||||
signatories = Set(bob),
|
||||
stakeholders = Set(bob),
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(ValueParty(bob), Set(bob))
|
||||
keyOpt = Some(
|
||||
GlobalKeyWithMaintainers.assertBuild(someTemplateId, ValueParty(bob), Set(bob))
|
||||
),
|
||||
byKey = false,
|
||||
version = TransactionVersion.minVersion,
|
||||
@ -108,8 +108,9 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
choiceObservers = Set.empty,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(someContractKey(bob, "some key"), Set(bob))
|
||||
keyOpt = Some(
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob))
|
||||
),
|
||||
byKey = false,
|
||||
version = TransactionVersion.minVersion,
|
||||
@ -124,8 +125,9 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
||||
someAgreement,
|
||||
signatories = Set(bob),
|
||||
stakeholders = Set(alice, bob),
|
||||
key = Some(
|
||||
Node.KeyWithMaintainers(someContractKey(bob, "some key"), Set(bob))
|
||||
keyOpt = Some(
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(someTemplateId, someContractKey(bob, "some key"), Set(bob))
|
||||
),
|
||||
version = TransactionVersion.minVersion,
|
||||
),
|
||||
|
@ -208,7 +208,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
absCid: ContractId,
|
||||
signatories: Set[Party],
|
||||
stakeholders: Set[Party],
|
||||
key: Option[Node.KeyWithMaintainers] = None,
|
||||
key: Option[GlobalKeyWithMaintainers] = None,
|
||||
templateId: Identifier = someTemplateId,
|
||||
contractArgument: LfValue = someContractArgument,
|
||||
): Node.Create =
|
||||
@ -219,13 +219,13 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
agreementText = someAgreement,
|
||||
signatories = signatories,
|
||||
stakeholders = stakeholders,
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
version = txVersion,
|
||||
)
|
||||
|
||||
protected final def exerciseNode(
|
||||
targetCid: ContractId,
|
||||
key: Option[Node.KeyWithMaintainers] = None,
|
||||
key: Option[GlobalKeyWithMaintainers] = None,
|
||||
): Node.Exercise =
|
||||
Node.Exercise(
|
||||
targetCoid = targetCid,
|
||||
@ -240,7 +240,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
choiceObservers = Set.empty,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = key,
|
||||
keyOpt = key,
|
||||
byKey = false,
|
||||
version = txVersion,
|
||||
)
|
||||
@ -339,18 +339,16 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
|
||||
protected final def createTestKey(
|
||||
maintainers: Set[Party]
|
||||
): (Node.KeyWithMaintainers, GlobalKey) = {
|
||||
): GlobalKeyWithMaintainers = {
|
||||
val aTextValue = ValueText(scala.util.Random.nextString(10))
|
||||
val keyWithMaintainers = Node.KeyWithMaintainers(aTextValue, maintainers)
|
||||
val globalKey = GlobalKey.assertBuild(someTemplateId, aTextValue)
|
||||
(keyWithMaintainers, globalKey)
|
||||
GlobalKeyWithMaintainers.assertBuild(someTemplateId, aTextValue, maintainers)
|
||||
}
|
||||
|
||||
protected final def createAndStoreContract(
|
||||
submittingParties: Set[Party],
|
||||
signatories: Set[Party],
|
||||
stakeholders: Set[Party],
|
||||
key: Option[Node.KeyWithMaintainers],
|
||||
key: Option[GlobalKeyWithMaintainers],
|
||||
contractArgument: LfValue = someContractArgument,
|
||||
): Future[(Offset, LedgerEntry.Transaction)] =
|
||||
store(
|
||||
@ -397,7 +395,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
choiceObservers = Set.empty,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = Some(someChoiceResult),
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
byKey = false,
|
||||
version = txVersion,
|
||||
)
|
||||
@ -432,7 +430,7 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
|
||||
protected def singleExercise(
|
||||
targetCid: ContractId,
|
||||
key: Option[Node.KeyWithMaintainers] = None,
|
||||
key: Option[GlobalKeyWithMaintainers] = None,
|
||||
): (Offset, LedgerEntry.Transaction) = {
|
||||
val txBuilder = newBuilder()
|
||||
val nid = txBuilder.add(exerciseNode(targetCid, key))
|
||||
@ -731,7 +729,10 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
agreementText = someAgreement,
|
||||
signatories = Set(party),
|
||||
stakeholders = Set(party),
|
||||
key = Some(Node.KeyWithMaintainers(someContractKey(party, key), Set(party))),
|
||||
keyOpt = Some(
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(someTemplateId, someContractKey(party, key), Set(party))
|
||||
),
|
||||
version = txVersion,
|
||||
)
|
||||
)
|
||||
@ -771,7 +772,10 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
choiceObservers = Set.empty,
|
||||
children = ImmArray.Empty,
|
||||
exerciseResult = Some(LfValue.ValueUnit),
|
||||
key = maybeKey.map(k => Node.KeyWithMaintainers(someContractKey(party, k), Set(party))),
|
||||
keyOpt = maybeKey.map(k =>
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(someTemplateId, someContractKey(party, k), Set(party))
|
||||
),
|
||||
byKey = false,
|
||||
version = txVersion,
|
||||
)
|
||||
@ -800,7 +804,8 @@ private[dao] trait JdbcLedgerDaoSuite extends JdbcLedgerDaoBackend {
|
||||
val lookupByKeyNodeId = txBuilder.add(
|
||||
Node.LookupByKey(
|
||||
someTemplateId,
|
||||
Node.KeyWithMaintainers(someContractKey(party, key), Set(party)),
|
||||
GlobalKeyWithMaintainers
|
||||
.assertBuild(someTemplateId, someContractKey(party, key), Set(party)),
|
||||
result,
|
||||
version = txVersion,
|
||||
)
|
||||
|
@ -80,7 +80,7 @@ class LedgerTimeAwareCommandExecutorSpec
|
||||
driverMetadata = Bytes.Empty,
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
maybeKeyWithMaintainers = None,
|
||||
keyOpt = None,
|
||||
agreementText = "",
|
||||
),
|
||||
),
|
||||
|
@ -80,7 +80,7 @@ class ResolveMaximumLedgerTimeSpec
|
||||
driverMetadata = Bytes.Empty,
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
maybeKeyWithMaintainers = None,
|
||||
keyOpt = None,
|
||||
agreementText = "",
|
||||
),
|
||||
)
|
||||
|
@ -45,7 +45,7 @@ class StoreBackedCommandExecutorSpec
|
||||
driverMetadata = Bytes.Empty,
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
maybeKeyWithMaintainers = None,
|
||||
keyOpt = None,
|
||||
agreementText = "some agreement text",
|
||||
),
|
||||
),
|
||||
|
@ -218,7 +218,7 @@ class ApiSubmissionServiceSpec
|
||||
driverMetadata = Bytes.Empty,
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
maybeKeyWithMaintainers = None,
|
||||
keyOpt = None,
|
||||
agreementText = "",
|
||||
),
|
||||
)
|
||||
|
@ -1573,14 +1573,18 @@ object UpdateToDbDtoSpec {
|
||||
|
||||
/** Returns (contract argument, contract key) */
|
||||
override def serialize(eventId: EventId, create: Create): (Array[Byte], Option[Array[Byte]]) =
|
||||
(emptyArray, create.key.map(_ => emptyArray))
|
||||
(emptyArray, create.keyOpt.map(_ => emptyArray))
|
||||
|
||||
/** Returns (choice argument, exercise result, contract key) */
|
||||
override def serialize(
|
||||
eventId: EventId,
|
||||
exercise: Exercise,
|
||||
): (Array[Byte], Option[Array[Byte]], Option[Array[Byte]]) =
|
||||
(emptyArray, exercise.exerciseResult.map(_ => emptyArray), exercise.key.map(_ => emptyArray))
|
||||
(
|
||||
emptyArray,
|
||||
exercise.exerciseResult.map(_ => emptyArray),
|
||||
exercise.keyOpt.map(_ => emptyArray),
|
||||
)
|
||||
override def deserialize[E](
|
||||
raw: Raw.Created[E],
|
||||
eventProjectionProperties: EventProjectionProperties,
|
||||
|
@ -30,7 +30,7 @@ class BridgeWriteServiceTest extends AnyFlatSpec with MockitoSugar with Matchers
|
||||
agreementText = "dummyAgreement",
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
key = None,
|
||||
keyOpt = None,
|
||||
version = TransactionVersion.minVersion,
|
||||
)
|
||||
|
||||
|
@ -306,7 +306,7 @@ class ConflictCheckWithCommittedSpec
|
||||
driverMetadata = contractId.toBytes,
|
||||
signatories = Set.empty,
|
||||
stakeholders = Set.empty,
|
||||
maybeKeyWithMaintainers = None,
|
||||
keyOpt = None,
|
||||
agreementText = "",
|
||||
),
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user