diff --git a/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala b/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala index 53cd8b41aa7d..9e3975ed54b1 100644 --- a/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala +++ b/compiler/scenario-service/server/src/main/scala/com/digitalasset/daml/lf/scenario/Conversions.scala @@ -29,10 +29,10 @@ final class Conversions( private val ptxCoidToNodeId = machine.ptx.nodes .collect { case (nodeId, node: N.NodeCreate[V.ContractId, _]) => - node.coid -> ledger.ptxNodeId(nodeId) + node.coid -> ledger.ptxEventId(nodeId) } - private val coidToNodeId = ledger.ledgerData.coidToNodeId ++ ptxCoidToNodeId + private val coidToEventId = ledger.ledgerData.coidToNodeId ++ ptxCoidToNodeId private val nodes = ledger.ledgerData.nodeInfos.map(Function.tupled(convertNode)) @@ -307,7 +307,7 @@ final class Conversions( def mkContractRef(coid: V.ContractId, templateId: Ref.Identifier): ContractRef = ContractRef.newBuilder .setRelative(false) - .setContractId(coidToNodeId(coid)) + .setContractId(coidToEventId(coid).toLedgerString) .setTemplateId(convertIdentifier(templateId)) .build @@ -352,7 +352,7 @@ final class Conversions( rtx: Ledger.RichTransaction, ): Transaction = { val convertedGlobalImplicitDisclosure = rtx.globalImplicitDisclosure.map { - case (coid, parties) => coidToNodeId(coid) -> parties + case (coid, parties) => coidToEventId(coid) -> parties } Transaction.newBuilder .setCommitter(convertParty(rtx.committer)) @@ -392,13 +392,13 @@ final class Conversions( builder.build } - def convertNodeId(nodeId: Ledger.ScenarioNodeId): NodeId = - NodeId.newBuilder.setId(nodeId).build + def convertNodeId(nodeId: Ledger.EventId): NodeId = + NodeId.newBuilder.setId(nodeId.toLedgerString).build def convertTxNodeId(nodeId: Tx.NodeId): NodeId = NodeId.newBuilder.setId(nodeId.index.toString).build - def convertNode(nodeId: Ledger.ScenarioNodeId, nodeInfo: Ledger.LedgerNodeInfo): Node = { + def convertNode(nodeId: Ledger.EventId, nodeInfo: Ledger.LedgerNodeInfo): Node = { val builder = Node.newBuilder builder .setNodeId(convertNodeId(nodeId)) @@ -435,14 +435,14 @@ final class Conversions( case fetch: N.NodeFetch.WithTxValue[V.ContractId] => builder.setFetch( Node.Fetch.newBuilder - .setContractId(coidToNodeId(fetch.coid)) + .setContractId(coidToEventId(fetch.coid).toLedgerString) .setTemplateId(convertIdentifier(fetch.templateId)) .addAllSignatories(fetch.signatories.map(convertParty).asJava) .addAllStakeholders(fetch.stakeholders.map(convertParty).asJava) .build, ) case ex: N.NodeExercises[ - Ledger.ScenarioNodeId, + Ledger.EventId, V.ContractId, Tx.Value[ V.ContractId, @@ -450,7 +450,7 @@ final class Conversions( ex.optLocation.map(loc => builder.setLocation(convertLocation(loc))) builder.setExercise( Node.Exercise.newBuilder - .setTargetContractId(coidToNodeId(ex.targetCoid)) + .setTargetContractId(coidToEventId(ex.targetCoid).toLedgerString) .setTemplateId(convertIdentifier(ex.templateId)) .setChoiceId(ex.choiceId) .setConsuming(ex.consuming) @@ -460,7 +460,7 @@ final class Conversions( .addAllStakeholders(ex.stakeholders.map(convertParty).asJava) .addAllChildren( ex.children - .map(nid => NodeId.newBuilder.setId(nid).build) + .map(nid => NodeId.newBuilder.setId(nid.toLedgerString).build) .toSeq .asJava, ) @@ -472,7 +472,7 @@ final class Conversions( val lbkBuilder = Node.LookupByKey.newBuilder .setTemplateId(convertIdentifier(lbk.templateId)) .setKeyWithMaintainers(convertKeyWithMaintainers(convertVersionedValue, lbk.key)) - lbk.result.foreach(cid => lbkBuilder.setContractId(coidToNodeId(cid))) + lbk.result.foreach(cid => lbkBuilder.setContractId(coidToEventId(cid).toLedgerString)) builder.setLookupByKey(lbkBuilder) } @@ -518,7 +518,7 @@ final class Conversions( case fetch: N.NodeFetch[V.ContractId, Val] => builder.setFetch( Node.Fetch.newBuilder - .setContractId(coidToNodeId(fetch.coid)) + .setContractId(coidToEventId(fetch.coid).toLedgerString) .setTemplateId(convertIdentifier(fetch.templateId)) .addAllSignatories(fetch.signatories.map(convertParty).asJava) .addAllStakeholders(fetch.stakeholders.map(convertParty).asJava) @@ -528,7 +528,7 @@ final class Conversions( ex.optLocation.map(loc => builder.setLocation(convertLocation(loc))) builder.setExercise( Node.Exercise.newBuilder - .setTargetContractId(coidToNodeId(ex.targetCoid)) + .setTargetContractId(coidToEventId(ex.targetCoid).toLedgerString) .setTemplateId(convertIdentifier(ex.templateId)) .setChoiceId(ex.choiceId) .setConsuming(ex.consuming) @@ -550,7 +550,7 @@ final class Conversions( builder.setLookupByKey({ val builder = Node.LookupByKey.newBuilder .setKeyWithMaintainers(convertKeyWithMaintainers(convertValue, lookup.key)) - lookup.result.foreach(cid => builder.setContractId(coidToNodeId(cid))) + lookup.result.foreach(cid => builder.setContractId(coidToEventId(cid).toLedgerString)) builder.build }) } @@ -635,7 +635,7 @@ final class Conversions( tycon.foreach(x => eBuilder.setEnumId(convertIdentifier(x))) builder.setEnum(eBuilder.build) case V.ValueContractId(coid) => - builder.setContractId(coidToNodeId(coid)) + builder.setContractId(coidToEventId(coid).toLedgerString) case V.ValueList(values) => builder.setList( v1.List.newBuilder diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala index bc7f00f7ad32..b60381cb0998 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/Pretty.scala @@ -248,16 +248,16 @@ object Pretty { text("mustFailAt") & prettyParty(amf.actor) & prettyLoc(amf.optLocation) } + def prettyKeyWithMaintainers(key: KeyWithMaintainers[Value[ContractId]]): Doc = + // the maintainers are induced from the key -- so don't clutter + prettyValue(false)(key.key) + def prettyVersionedKeyWithMaintainers( key: KeyWithMaintainers[Transaction.Value[ContractId]]): Doc = // the maintainers are induced from the key -- so don't clutter prettyVersionedValue(false)(key.key) - def prettyKeyWithMaintainers(key: KeyWithMaintainers[Value[ContractId]]): Doc = - // the maintainers are induced from the key -- so don't clutter - prettyValue(false)(key.key) - - def prettyNodeInfo(l: L.Ledger)(nodeId: L.ScenarioNodeId): Doc = { + def prettyNodeInfo(l: L.Ledger)(nodeId: L.EventId): Doc = { def arrowRight(d: Doc) = text("└─>") & d def meta(d: Doc) = text("│ ") & d @@ -272,11 +272,10 @@ object Pretty { case ea: NodeFetch[ContractId, Transaction.Value[ContractId]] => "ensure active" &: prettyContractId(ea.coid) case ex: NodeExercises[ - L.ScenarioNodeId, + L.EventId, ContractId, - Transaction.Value[ - ContractId - ]] => + Transaction.Value[ContractId] + ] => val children = if (ex.children.nonEmpty) text("children:") / stack(ex.children.toList.map(prettyNodeInfo(l))) @@ -334,8 +333,8 @@ object Pretty { ) } - def prettyLedgerNodeId(n: L.ScenarioNodeId): Doc = - text(n) + def prettyLedgerNodeId(n: L.EventId): Doc = + text(n.toLedgerString) def prettyContractInst(coinst: ContractInst[Value[ContractId]]): Doc = (prettyIdentifier(coinst.template) / text("with:") & diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SError.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SError.scala index 604003b5d10d..88de59717a1f 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SError.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/speedy/SError.scala @@ -76,7 +76,7 @@ object SError { final case class ScenarioErrorContractNotActive( coid: ContractId, templateId: Identifier, - consumedBy: Ledger.ScenarioNodeId, + consumedBy: Ledger.EventId, ) extends SErrorScenario /** We tried to fetch / exercise a contract of the wrong type -- diff --git a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/types/Ledger.scala b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/types/Ledger.scala index f5eeb8502e40..4ac2c538ef26 100644 --- a/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/types/Ledger.scala +++ b/daml-lf/interpreter/src/main/scala/com/digitalasset/daml/lf/types/Ledger.scala @@ -4,10 +4,10 @@ package com.daml.lf package types -import com.daml.lf.data.Ref +import com.daml.lf.data.Ref._ import com.daml.lf.data.{ImmArray, Time} import com.daml.lf.transaction.Node._ -import com.daml.lf.transaction.Transaction +import com.daml.lf.transaction.{Transaction => Tx} import com.daml.lf.value.Value import Value._ import com.daml.lf.data.Relation.Relation @@ -16,31 +16,47 @@ import scala.annotation.tailrec import scala.collection.generic.CanBuildFrom import scala.collection.breakOut import scala.collection.immutable +import scala.util.Try /** An in-memory representation of a ledger for scenarios */ object Ledger { - import Ref.{ContractIdString => _, _} + // transactionId should be small so the concatenation in toLedgerString do not exceed 255 chars + case class EventId( + transactionId: LedgerString, + nodeId: Tx.NodeId + ) { + lazy val toLedgerString: LedgerString = { + val builder = StringBuilder.newBuilder + builder += '#' + builder ++= transactionId + builder += ':' + builder ++= nodeId.index.toString + LedgerString.assertFromString(builder.result()) + } + } - type ScenarioNodeId = LedgerString + object EventId { + def fromString(s: String): Either[String, EventId] = { + def err = Left(s"""cannot parse eventId $s""") + s.split(":") match { + case Array(transactionId, index) => + transactionId.splitAt(1) match { + case ("#", transIdString) => + for { + ix <- Try(index.toInt).fold(_ => err, Right(_)) + transId <- LedgerString.fromString(transIdString) + } yield EventId(transId, Tx.NodeId(ix)) + case _ => err + } + case _ => err + } + } - private object ScenarioNodeId { - def apply(commitPrefix: LedgerString, txnid: Transaction.NodeId): ScenarioNodeId = - txNodeIdToScenarioNodeId(commitPrefix, txnid.index) + def assertFromString(s: String): EventId = + data.assertRight(fromString(s)) } - /** This is the function that we use to turn relative contract ids (which are made of - * transaction node ids) in the still - * to be committed transaction into contract ids in the ledger. - */ - // The prefix should be smaller than 244 chars. - @inline - private def txNodeIdToScenarioNodeId( - commitPrefix: LedgerString, - txnidx: Int, - ): ScenarioNodeId = - LedgerString.assertConcat(commitPrefix, LedgerString.fromInt(txnidx)) - @inline def assertNoContractId(key: Value[Value.ContractId]): Value[Nothing] = key.ensureNoCid.fold( @@ -48,16 +64,11 @@ object Ledger { identity, ) - private val `:` = LedgerString.assertFromString(":") - private val `#` = LedgerString.assertFromString("#") - case class ScenarioTransactionId(index: Int) extends Ordered[ScenarioTransactionId] { def next: ScenarioTransactionId = ScenarioTransactionId(index + 1) // The resulting LedgerString is at most 11 chars long val id: LedgerString = LedgerString.fromLong(index.toLong) override def compare(that: ScenarioTransactionId): Int = index compare that.index - // The resulting LedgerString is at most 13 chars long - def makeCommitPrefix: LedgerString = LedgerString.assertConcat(`#`, id, `:`) } /** Errors */ @@ -76,7 +87,7 @@ object Ledger { * transaction node * in the node identifier, where here the identifier * is global. */ - type Node = GenNode.WithTxValue[ScenarioNodeId, ContractId] + type Node = GenNode.WithTxValue[EventId, ContractId] /** A transaction as it is committed to the ledger. * @@ -103,10 +114,10 @@ object Ledger { final case class RichTransaction( committer: Party, effectiveAt: Time.Timestamp, - roots: ImmArray[ScenarioNodeId], - nodes: immutable.HashMap[ScenarioNodeId, Node], - explicitDisclosure: Relation[ScenarioNodeId, Party], - localImplicitDisclosure: Relation[ScenarioNodeId, Party], + roots: ImmArray[EventId], + nodes: immutable.HashMap[EventId, Node], + explicitDisclosure: Relation[EventId, Party], + localImplicitDisclosure: Relation[EventId, Party], globalImplicitDisclosure: Relation[ContractId, Party], failedAuthorizations: FailedAuthorizations, ) { @@ -115,14 +126,14 @@ object Ledger { final case class EnrichedTransaction( // The transaction root nodes. - roots: ImmArray[Transaction.NodeId], + roots: ImmArray[Tx.NodeId], // All nodes of this transaction. - nodes: immutable.HashMap[Transaction.NodeId, Transaction.Node], + nodes: immutable.HashMap[Tx.NodeId, Tx.Node], // A relation between a node id and the parties to which this node gets explicitly disclosed. - explicitDisclosure: Relation[Transaction.NodeId, Party], + explicitDisclosure: Relation[Tx.NodeId, Party], // A relation between a node id and the parties to which this node get implictly disclosed // (aka divulgence) - localImplicitDisclosure: Relation[Transaction.NodeId, Party], + localImplicitDisclosure: Relation[Tx.NodeId, Party], // A relation between contract id and the parties to which the contract id gets // explicitly disclosed. globalImplicitDisclosure: Relation[ContractId, Party], @@ -131,7 +142,7 @@ object Ledger { ) /** - * Translate an EnrichedTransaction to a RichTransaction. EnrichedTransaction's contain relative + * Translate an EnrichedTransaction to a RichTransaction. EnrichedTransaction's contain local * node id's and contain additional information in the most detailed form suitable for different * consumers. The RichTransaction is the transaction that we serialize in the sandbox to compare * different ledgers. All relative and absolute node id's are translated to absolute node id's of @@ -146,19 +157,19 @@ object Ledger { RichTransaction( committer = committer, effectiveAt = effectiveAt, - roots = enrichedTx.roots.map(ScenarioNodeId(commitPrefix, _)), + roots = enrichedTx.roots.map(EventId(commitPrefix, _)), nodes = enrichedTx.nodes.map { case (nodeId, node) => - ScenarioNodeId(commitPrefix, nodeId) -> node - .mapNodeId(ScenarioNodeId(commitPrefix, _)) + EventId(commitPrefix, nodeId) -> node + .mapNodeId(EventId(commitPrefix, _)) }(breakOut), explicitDisclosure = enrichedTx.explicitDisclosure.map { case (nodeId, ps) => - (ScenarioNodeId(commitPrefix, nodeId), ps) + (EventId(commitPrefix, nodeId), ps) }, localImplicitDisclosure = enrichedTx.localImplicitDisclosure.map { case (nodeId, ps) => - (ScenarioNodeId(commitPrefix, nodeId), ps) + (EventId(commitPrefix, nodeId), ps) }, globalImplicitDisclosure = enrichedTx.globalImplicitDisclosure, failedAuthorizations = enrichedTx.failedAuthorizations, @@ -216,9 +227,9 @@ object Ledger { transaction: ScenarioTransactionId, effectiveAt: Time.Timestamp, observingSince: Map[Party, ScenarioTransactionId], - referencedBy: Set[ScenarioNodeId], - consumedBy: Option[ScenarioNodeId], - parent: Option[ScenarioNodeId], + referencedBy: Set[EventId], + consumedBy: Option[EventId], + parent: Option[EventId], ) { /** 'True' if the given 'View' contains the given 'Node'. */ @@ -233,7 +244,7 @@ object Ledger { } } - type LedgerNodeInfos = Map[ScenarioNodeId, LedgerNodeInfo] + type LedgerNodeInfos = Map[EventId, LedgerNodeInfo] /* * Result from lookupGlobalContract. We provide detailed information why a lookup @@ -243,7 +254,7 @@ object Ledger { final case class LookupOk( coid: ContractId, - coinst: ContractInst[Transaction.Value[ContractId]], + coinst: ContractInst[Tx.Value[ContractId]], stakeholders: Set[Party], ) extends LookupResult final case class LookupContractNotFound(coid: ContractId) extends LookupResult @@ -256,7 +267,7 @@ object Ledger { final case class LookupContractNotActive( coid: ContractId, templateId: Identifier, - consumedBy: ScenarioNodeId, + consumedBy: EventId, ) extends LookupResult final case class LookupContractNotVisible( coid: ContractId, @@ -349,9 +360,9 @@ object Ledger { } // Given a ledger and the node index of a node in a partial transaction - // turn it into a node it that can be used in scenario error messages. - def ptxNodeId(nodeIdx: NodeId): ScenarioNodeId = - ScenarioNodeId(scenarioStepId.makeCommitPrefix, nodeIdx) + // turn it into a event id that can be used in scenario error messages. + def ptxEventId(nodeIdx: NodeId): EventId = + EventId(scenarioStepId.id, nodeIdx) } sealed trait CommitError @@ -372,16 +383,15 @@ object Ledger { committer: Party, effectiveAt: Time.Timestamp, optLocation: Option[Location], - tr: Transaction.Transaction, + tr: Tx.Transaction, l: Ledger, ): Either[CommitError, CommitResult] = { - val i = l.scenarioStepId - // commitPrefix is small enough (< 20 chars), so we do no exceed the 255 - // chars limit when concatenate in txNodeIdToScenarioNodeId method. - val commitPrefix = i.makeCommitPrefix + // transactionId is small enough (< 20 chars), so we do no exceed the 255 + // chars limit when concatenate in EventId#toLedgerString method. + val transactionId = l.scenarioStepId.id val richTr = enrichedTransactionToRichTransaction( - commitPrefix, + transactionId, committer, effectiveAt, enrichTransaction(Authorize(Set(committer)), tr), @@ -389,17 +399,20 @@ object Ledger { if (richTr.failedAuthorizations.nonEmpty) Left(CommitError.FailedAuthorizations(richTr.failedAuthorizations)) else { - processTransaction(i, richTr, l.ledgerData) match { + processTransaction(l.scenarioStepId, richTr, l.ledgerData) match { case Left(err) => Left(CommitError.UniqueKeyViolation(err)) case Right(updatedCache) => Right( CommitResult( l.copy( - scenarioSteps = l.scenarioSteps + (i.index -> Commit(i, richTr, optLocation)), + scenarioSteps = l.scenarioSteps + (l.scenarioStepId.index -> Commit( + l.scenarioStepId, + richTr, + optLocation)), scenarioStepId = l.scenarioStepId.next, ledgerData = updatedCache, ), - i, + l.scenarioStepId, richTr, ), ) @@ -438,7 +451,7 @@ object Ledger { sealed trait FailedAuthorization - type FailedAuthorizations = Map[Transaction.NodeId, FailedAuthorization] + type FailedAuthorizations = Map[Tx.NodeId, FailedAuthorization] final case class FACreateMissingAuthorization( templateId: Identifier, @@ -496,16 +509,16 @@ object Ledger { /** State to use during enriching a transaction with disclosure information. */ final case class EnrichState( - nodes: Map[ScenarioNodeId, Node], - disclosures: Relation[Transaction.NodeId, Party], - localDivulgences: Relation[Transaction.NodeId, Party], + nodes: Map[EventId, Node], + disclosures: Relation[Tx.NodeId, Party], + localDivulgences: Relation[Tx.NodeId, Party], globalDivulgences: Relation[ContractId, Party], - failedAuthorizations: Map[Transaction.NodeId, FailedAuthorization], + failedAuthorizations: Map[Tx.NodeId, FailedAuthorization], ) { def discloseNode( parentWitnesses: Set[Party], - nid: Transaction.NodeId, - node: Transaction.Node, + nid: Tx.NodeId, + node: Tx.Node, ): (Set[Party], EnrichState) = { val witnesses = parentWitnesses union node.informeesOfNode witnesses -> @@ -528,7 +541,7 @@ object Ledger { } def authorize( - nodeId: Transaction.NodeId, + nodeId: Tx.NodeId, passIf: Boolean, failWith: FailedAuthorization, ): EnrichState = @@ -540,7 +553,7 @@ object Ledger { copy(failedAuthorizations = failedAuthorizations + (nodeId -> failWith)) def authorizeCreate( - nodeId: Transaction.NodeId, + nodeId: Tx.NodeId, create: NodeCreate.WithTxValue[ContractId], signatories: Set[Party], authorization: Authorization, @@ -581,8 +594,8 @@ object Ledger { }) def authorizeExercise( - nodeId: Transaction.NodeId, - ex: NodeExercises.WithTxValue[Transaction.NodeId, ContractId], + nodeId: Tx.NodeId, + ex: NodeExercises.WithTxValue[Tx.NodeId, ContractId], actingParties: Set[Party], authorization: Authorization, controllersDifferFromActors: Boolean, @@ -624,7 +637,7 @@ object Ledger { } def authorizeFetch( - nodeId: Transaction.NodeId, + nodeId: Tx.NodeId, fetch: NodeFetch.WithTxValue[ContractId], stakeholders: Set[Party], authorization: Authorization, @@ -714,7 +727,7 @@ object Ledger { that `authorizers ∩ stakeholders ≠ ∅`. */ def authorizeLookupByKey( - nodeId: Transaction.NodeId, + nodeId: Tx.NodeId, lbk: NodeLookupByKey.WithTxValue[ContractId], authorization: Authorization, ): EnrichState = { @@ -768,7 +781,7 @@ object Ledger { */ def enrichTransaction( authorization: Authorization, - tr: Transaction.Transaction, + tr: Tx.Transaction, ): EnrichedTransaction = { // Before we traversed through an exercise node the exercise witnesses @@ -783,7 +796,7 @@ object Ledger { state: EnrichState, parentExerciseWitnesses: Set[Party], authorization: Authorization, - nodeId: Transaction.NodeId, + nodeId: Tx.NodeId, ): EnrichState = { val node = tr.nodes @@ -824,7 +837,7 @@ object Ledger { authorization = authorization, ) - case ex: NodeExercises.WithTxValue[Transaction.NodeId, ContractId] => + case ex: NodeExercises.WithTxValue[Tx.NodeId, ContractId] => // ------------------------------------------------------------------ // witnesses: // | consuming -> stakeholders(targetId) union witnesses of parent exercise node @@ -953,7 +966,7 @@ object Ledger { activeContracts: Set[ContractId], nodeInfos: LedgerNodeInfos, activeKeys: Map[GlobalKey, ContractId], - coidToNodeId: Map[ContractId, ScenarioNodeId], + coidToNodeId: Map[ContractId, EventId], ) { def nodeInfoByCoid(coid: ContractId): LedgerNodeInfo = nodeInfos(coidToNodeId(coid)) @@ -963,7 +976,7 @@ object Ledger { coidToNodeId.get(coid).map(updateLedgerNodeInfo(_)(f)).getOrElse(this) def updateLedgerNodeInfo( - nodeId: ScenarioNodeId, + nodeId: EventId, )(f: (LedgerNodeInfo) => LedgerNodeInfo): LedgerData = copy( nodeInfos = nodeInfos @@ -978,7 +991,7 @@ object Ledger { def markAsInactive(coid: ContractId): LedgerData = copy(activeContracts = activeContracts - coid) - def createdIn(coid: ContractId, nodeId: ScenarioNodeId): LedgerData = + def createdIn(coid: ContractId, nodeId: EventId): LedgerData = copy(coidToNodeId = coidToNodeId + (coid -> nodeId)) def addKey(key: GlobalKey, acoid: ContractId): LedgerData = @@ -996,7 +1009,7 @@ object Ledger { richTr: RichTransaction, ledgerData: LedgerData, ): Either[UniqueKeyViolation, LedgerData] = { - type ExerciseNodeProcessing = (Option[ScenarioNodeId], List[ScenarioNodeId]) + type ExerciseNodeProcessing = (Option[EventId], List[EventId]) @tailrec def processNodes( @@ -1055,7 +1068,7 @@ object Ledger { processNodes(Right(newCacheP), idsToProcess) - case ex: NodeExercises.WithTxValue[ScenarioNodeId, ContractId] => + case ex: NodeExercises.WithTxValue[EventId, ContractId] => val newCache0 = newCache.updateLedgerNodeInfo(ex.targetCoid)( info => @@ -1069,11 +1082,7 @@ object Ledger { val nc = newCache0_1 .nodeInfoByCoid(ex.targetCoid) .node - .asInstanceOf[NodeCreate[ - ContractId, - Transaction.Value[ - ContractId - ]]] + .asInstanceOf[NodeCreate[ContractId, Tx.Value[ContractId]]] nc.key match { case None => newCache0_1 case Some(keyWithMaintainers) => diff --git a/ledger/sandbox/BUILD.bazel b/ledger/sandbox/BUILD.bazel index fe92b44d31a8..051f7dc5ce33 100644 --- a/ledger/sandbox/BUILD.bazel +++ b/ledger/sandbox/BUILD.bazel @@ -225,6 +225,7 @@ da_scala_library( "//daml-lf/archive:daml_lf_archive_reader", "//daml-lf/archive:daml_lf_dev_archive_java_proto", "//daml-lf/data", + "//daml-lf/interpreter", "//daml-lf/transaction", "//language-support/scala/bindings", "//ledger-api/rs-grpc-bridge", diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/apiserver/services/transaction/ApiTransactionService.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/apiserver/services/transaction/ApiTransactionService.scala index d7faae451089..63a64c869c5d 100644 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/apiserver/services/transaction/ApiTransactionService.scala +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/apiserver/services/transaction/ApiTransactionService.scala @@ -23,8 +23,7 @@ import com.daml.ledger.api.validation.PartyNameChecker import com.daml.logging.LoggingContext.withEnrichedLoggingContext import com.daml.logging.{ContextualizedLogger, LoggingContext} import com.daml.platform.apiserver.services.logging -import com.daml.platform.events.EventIdFormatter -import com.daml.platform.events.EventIdFormatter.TransactionIdWithIndex +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.server.api.services.domain.TransactionService import com.daml.platform.server.api.services.grpc.GrpcTransactionService import com.daml.platform.server.api.validation.ErrorFactories @@ -103,8 +102,8 @@ final class ApiTransactionService private ( logging.parties(request.requestingParties), ) { implicit logCtx => logger.debug(s"Received $request") - EventIdFormatter - .split(request.eventId.unwrap) + TransactionIdWithIndex + .fromString(request.eventId.unwrap) .map { case TransactionIdWithIndex(transactionId, _) => lookUpTreeByTransactionId(TransactionId(transactionId), request.requestingParties) @@ -134,15 +133,17 @@ final class ApiTransactionService private ( logging.eventId(request.eventId), logging.parties(request.requestingParties), ) { implicit logCtx => - EventIdFormatter - .split(request.eventId.unwrap) + TransactionIdWithIndex + .fromString(request.eventId.unwrap) .fold( - Future.failed[GetFlatTransactionResponse](Status.NOT_FOUND - .withDescription(s"invalid eventId: ${request.eventId}") - .asRuntimeException())) { - case TransactionIdWithIndex(transactionId, _) => - lookUpFlatByTransactionId(TransactionId(transactionId), request.requestingParties) - } + err => + Future.failed[GetFlatTransactionResponse]( + Status.NOT_FOUND.withDescription(s"invalid eventId: $err").asRuntimeException()), + eventId => + lookUpFlatByTransactionId( + TransactionId(eventId.transactionId), + request.requestingParties) + ) .andThen(logger.logErrorsOnCall[GetFlatTransactionResponse]) } diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/events/EventIdFormatter.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/events/EventIdFormatter.scala deleted file mode 100644 index 5c8749cd9356..000000000000 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/events/EventIdFormatter.scala +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.daml.platform.events - -import com.daml.lf.data.Ref.LedgerString -import com.daml.lf.transaction.Transaction -import com.daml.lf.types.Ledger -import com.daml.ledger.EventId - -import scala.util.{Failure, Success, Try} - -object EventIdFormatter { - private val `#` = LedgerString.assertFromString("#") - private val `:` = LedgerString.assertFromString(":") - - case class TransactionIdWithIndex(transactionId: LedgerString, nodeId: Transaction.NodeId) - - // this method defines the EventId format used by the sandbox - def fromTransactionId(transactionId: LedgerString, nid: Transaction.NodeId): EventId = - fromTransactionId(transactionId, LedgerString.fromInt(nid.index)) - - /** When loading a scenario we get already absolute nids from the ledger -- still prefix them with the transaction - * id, just to be safe. - * `TransactionId`` and `nid`` should be sufficiently small for the concatenation to be smaller than 255 bytes. - */ - def fromTransactionId( - transactionId: LedgerString, - nid: Ledger.ScenarioNodeId, - ): LedgerString = - LedgerString.assertConcat(`#`, transactionId, `:`, nid) - - def split(eventId: String): Option[TransactionIdWithIndex] = - eventId.split(":") match { - case Array(transactionId, index) => - transactionId.splitAt(1) match { - case ("#", transIdString) => - (for { - ix <- Try(index.toInt) - transId <- LedgerString - .fromString(transIdString) - .fold(err => Failure(new IllegalArgumentException(err)), Success(_)) - _ <- Try(transId) - } yield TransactionIdWithIndex(transId, Transaction.NodeId(ix))).toOption - case _ => None - } - case _ => None - } -} diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/events/package.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/events/package.scala new file mode 100644 index 000000000000..29332e968d9e --- /dev/null +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/events/package.scala @@ -0,0 +1,13 @@ +// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.daml.platform + +import com.daml.lf.types.Ledger + +package object events { + + type TransactionIdWithIndex = Ledger.EventId + val TransactionIdWithIndex: Ledger.EventId.type = Ledger.EventId + +} diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/index/TransactionConversion.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/index/TransactionConversion.scala index d1c3aeed2687..ef91a283b62a 100644 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/index/TransactionConversion.scala +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/index/TransactionConversion.scala @@ -10,6 +10,7 @@ import com.daml.lf.engine.Blinding import com.daml.lf.transaction.GenTransaction import com.daml.lf.transaction.Node.{GenNode, NodeCreate, NodeExercises} import com.daml.lf.value.{Value => Lf} +import com.daml.lf.types.Ledger import com.daml.ledger.{CommandId, EventId, TransactionId} import com.daml.ledger.api.domain import com.daml.ledger.api.v1.event.Event @@ -20,7 +21,6 @@ import com.daml.ledger.api.v1.transaction.{ } import com.daml.platform.api.v1.event.EventOps.EventOps import com.daml.platform.api.v1.event.EventOps.TreeEventOps -import com.daml.platform.events.EventIdFormatter.{fromTransactionId, split} import com.daml.platform.participant.util.LfEngineToApi.{ assertOrRuntimeEx, lfNodeCreateToEvent, @@ -109,13 +109,13 @@ object TransactionConversion { ): Option[Relation[EventId, Ref.Party]] = Some( Blinding - .blind(transaction.mapNodeId(split(_).get.nodeId)) + .blind(transaction.mapNodeId(Ledger.EventId.assertFromString(_).nodeId)) .disclosure .flatMap { case (nodeId, disclosure) => List(disclosure.intersect(parties)).collect { case disclosure if disclosure.nonEmpty => - fromTransactionId(transactionId, nodeId) -> disclosure + Ledger.EventId(transactionId, nodeId).toLedgerString -> disclosure } } ).filter(_.nonEmpty) diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/Ledger.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/Ledger.scala index e3fb491583a7..bcb5027473c3 100644 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/Ledger.scala +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/Ledger.scala @@ -15,7 +15,7 @@ import com.daml.lf.value.Value import com.daml.lf.value.Value.ContractId import com.daml.daml_lf_dev.DamlLf.Archive import com.daml.ledger.EventId -import com.daml.platform.events.EventIdFormatter +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.ReadOnlyLedger import scala.concurrent.Future @@ -80,11 +80,11 @@ object Ledger { // convert LF NodeId to Index EventId val disclosureForIndex: Map[EventId, Set[Party]] = blindingInfo.disclosure.map { case (nodeId, parties) => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> parties + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> parties } val transactionForIndex: TransactionForIndex = - committedTransaction.mapNodeId(EventIdFormatter.fromTransactionId(transactionId, _)) + committedTransaction.mapNodeId(TransactionIdWithIndex(transactionId, _).toLedgerString) (transactionForIndex, disclosureForIndex, blindingInfo.globalDivulgence) } diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/ScenarioLoader.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/ScenarioLoader.scala index 5f0b9a97b6da..ad13b81913ba 100644 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/ScenarioLoader.scala +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/sandbox/stores/ledger/ScenarioLoader.scala @@ -6,7 +6,8 @@ package com.daml.platform.sandbox.stores.ledger import java.time.Instant import com.daml.lf.{CompiledPackages, crypto} -import com.daml.lf.data._ +import com.daml.lf.data.{Relation => _, _} +import com.daml.lf.data.Relation.Relation import com.daml.lf.language.Ast.{DDataType, DTypeSyn, DValue, Definition} import com.daml.lf.language.Ast import com.daml.lf.speedy.{ScenarioRunner, Speedy} @@ -204,7 +205,6 @@ object ScenarioLoader { } } - private val transactionIdPrefix = Ref.LedgerString.assertFromString(s"scenario-transaction-") private val workflowIdPrefix = Ref.LedgerString.assertFromString(s"scenario-workflow-") private val scenarioLoader = Ref.LedgerString.assertFromString("scenario-loader") @@ -231,9 +231,10 @@ object ScenarioLoader { val transactionId = txId.id val workflowId = Some(Ref.LedgerString.assertConcat(workflowIdPrefix, Ref.LedgerString.fromInt(stepId))) - val tx = GenTransaction(richTransaction.nodes, richTransaction.roots) - val mappedExplicitDisclosure = richTransaction.explicitDisclosure - val mappedLocalImplicitDisclosure = richTransaction.localImplicitDisclosure + val tx = + GenTransaction(richTransaction.nodes, richTransaction.roots).mapNodeId(_.toLedgerString) + val mappedExplicitDisclosure = + Relation.mapKeys(richTransaction.explicitDisclosure)(_.toLedgerString) val mappedGlobalImplicitDisclosure = richTransaction.globalImplicitDisclosure // copies non-absolute-able node IDs, but IDs that don't match // get intersected away later diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/JdbcLedgerDao.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/JdbcLedgerDao.scala index 1f15265d33f6..fb627eeb1fd8 100644 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/JdbcLedgerDao.scala +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/JdbcLedgerDao.scala @@ -23,17 +23,17 @@ import com.daml.ledger.participant.state.index.v2.{ PackageDetails } import com.daml.ledger.participant.state.v1._ -import com.daml.ledger.{EventId, WorkflowId} +import com.daml.ledger.WorkflowId import com.daml.lf.archive.Decode import com.daml.lf.data.Ref import com.daml.lf.data.Ref.{PackageId, Party} import com.daml.lf.transaction.Node -import com.daml.lf.value.Value.{ContractId, NodeId} +import com.daml.lf.value.Value.ContractId import com.daml.logging.{ContextualizedLogger, LoggingContext} import com.daml.metrics.{Metrics, Timed} import com.daml.platform.ApiOffset.ApiOffsetConverter import com.daml.platform.configuration.ServerRole -import com.daml.platform.events.EventIdFormatter.split +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.Conversions._ import com.daml.platform.store.SimpleSqlAsVectorOf.SimpleSqlAsVectorOf import com.daml.platform.store._ @@ -462,9 +462,6 @@ private class JdbcLedgerDao( override def lookupKey(key: Node.GlobalKey, forParty: Party): Future[Option[ContractId]] = contractsReader.lookupContractKey(forParty, key) - private def splitOrThrow(id: EventId): NodeId = - split(id).fold(sys.error(s"Illegal format for event identifier $id"))(_.nodeId) - override def storeTransaction( submitterInfo: Option[SubmitterInfo], workflowId: Option[WorkflowId], @@ -559,7 +556,8 @@ private class JdbcLedgerDao( transactionId = tx.transactionId, ledgerEffectiveTime = tx.ledgerEffectiveTime, offset = offset, - transaction = tx.transaction.mapNodeId(splitOrThrow), + transaction = + tx.transaction.mapNodeId(TransactionIdWithIndex.assertFromString(_).nodeId), divulgedContracts = Nil, ) .write(metrics) diff --git a/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/events/RawBatch.scala b/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/events/RawBatch.scala index de9658e40808..faf60c668e79 100644 --- a/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/events/RawBatch.scala +++ b/ledger/sandbox/src/main/scala/com/digitalasset/platform/store/dao/events/RawBatch.scala @@ -9,7 +9,7 @@ import anorm.NamedParameter import com.daml.ledger.EventId import com.daml.ledger.participant.state.v1.Offset import com.daml.ledger.{ApplicationId, CommandId, TransactionId, WorkflowId} -import com.daml.platform.events.EventIdFormatter.fromTransactionId +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.Conversions._ import com.daml.platform.store.dao.events.RawBatch.PartialParameters @@ -68,7 +68,7 @@ private[events] object RawBatch { treeWitnesses: Set[Party], specific: Specific, ) extends PartialParameters { - private[this] val eventId = fromTransactionId(transactionId, nodeId) + private[this] val eventId = TransactionIdWithIndex(transactionId, nodeId).toLedgerString private[this] val base: Vector[NamedParameter] = Vector[NamedParameter]( "event_id" -> eventId, @@ -135,7 +135,7 @@ private[events] object RawBatch { lfValueTranslation: LfValueTranslation, ): Vector[NamedParameter] = (partial :+ ("exercise_child_event_ids" -> exercise.children - .map(fromTransactionId(transactionId, _)) + .map(TransactionIdWithIndex(transactionId, _).toLedgerString) .toArray[String]: NamedParameter)) ++ lfValueTranslation.serialize(eventId, exercise) } diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/V25__Backfill_Participant_Events.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/V25__Backfill_Participant_Events.scala index 8367db7374e3..c3ae44c20987 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/V25__Backfill_Participant_Events.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/V25__Backfill_Participant_Events.scala @@ -5,7 +5,7 @@ package db.migration.postgres import com.daml.ledger.participant.state.v1.Offset import com.daml.lf.data.Ref -import com.daml.platform.events.EventIdFormatter +import com.daml.platform.events.TransactionIdWithIndex import db.migration.postgres.v25_backfill_participant_events.V25TransactionsWriter import db.migration.translation.TransactionSerializer import org.flywaydb.core.api.migration.{BaseJavaMigration, Context} @@ -35,7 +35,7 @@ class V25__Backfill_Participant_Events extends BaseJavaMigration { val transaction = TransactionSerializer .deserializeTransaction(rows.getBinaryStream("transaction")) .getOrElse(sys.error(s"failed to deserialize transaction $transactionId")) - .mapNodeId(evId => EventIdFormatter.split(evId).map(_.nodeId).get) + .mapNodeId(TransactionIdWithIndex.assertFromString(_).nodeId) V25TransactionsWriter.apply( applicationId, diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/V29__Fix_participant_events.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/V29__Fix_participant_events.scala index 9a9cbe3efe56..8a191782c685 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/V29__Fix_participant_events.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/V29__Fix_participant_events.scala @@ -5,7 +5,7 @@ package db.migration.postgres import com.daml.ledger.participant.state.v1.Offset import com.daml.lf.data.Ref -import com.daml.platform.events.EventIdFormatter +import com.daml.platform.events.TransactionIdWithIndex import db.migration.postgres.v29_fix_participant_events.V29TransactionsWriter import db.migration.translation.TransactionSerializer import org.flywaydb.core.api.migration.{BaseJavaMigration, Context} @@ -44,7 +44,7 @@ class V29__Fix_participant_events extends BaseJavaMigration { val transaction = TransactionSerializer .deserializeTransaction(rows.getBinaryStream("transaction")) .getOrElse(sys.error(s"failed to deserialize transaction $transactionId")) - .mapNodeId(evId => EventIdFormatter.split(evId).map(_.nodeId).get) + .mapNodeId(TransactionIdWithIndex.assertFromString(_).nodeId) V29TransactionsWriter.apply( applicationId, diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/V2_1__Rebuild_Acs.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/V2_1__Rebuild_Acs.scala index b5ae4727b308..c218c7ba2d80 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/V2_1__Rebuild_Acs.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/V2_1__Rebuild_Acs.scala @@ -24,7 +24,7 @@ import com.daml.lf.value.Value.ContractId import com.daml.ledger.api.domain.RejectionReason import com.daml.ledger.api.domain.RejectionReason._ import com.daml.ledger.{ApplicationId, CommandId, WorkflowId} -import com.daml.platform.events.EventIdFormatter +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.Contract.ActiveContract import com.daml.platform.store.Conversions._ import com.daml.platform.store.entries.LedgerEntry @@ -667,7 +667,7 @@ class V2_1__Rebuild_Acs extends BaseJavaMigration { .collect { case tx: LedgerEntry.Transaction => tx } .foreach(tx => { val unmappedTx: Transaction.Transaction = tx.transaction - .mapNodeId(EventIdFormatter.split(_).get.nodeId) + .mapNodeId(TransactionIdWithIndex.assertFromString(_).nodeId) val blindingInfo = Blinding.blind(unmappedTx) diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25EventsTableInsert.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25EventsTableInsert.scala index 62ba71317ff3..9d113e87d84b 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25EventsTableInsert.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25EventsTableInsert.scala @@ -8,7 +8,7 @@ import java.time.Instant import anorm.{BatchSql, NamedParameter} import com.daml.ledger.participant.state.v1.Offset import com.daml.ledger._ -import com.daml.platform.events.EventIdFormatter.fromTransactionId +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.Conversions._ import com.daml.platform.store.serialization.ValueSerializer.{serializeValue => serialize} @@ -87,7 +87,7 @@ private[v25_backfill_participant_events] object V25EventsTableInsert { create: Create, ): Vector[NamedParameter] = Vector[NamedParameter]( - "event_id" -> fromTransactionId(transactionId, nodeId), + "event_id" -> TransactionIdWithIndex(transactionId, nodeId).toLedgerString, "event_offset" -> offset, "contract_id" -> create.coid.coid, "transaction_id" -> transactionId, @@ -143,7 +143,7 @@ private[v25_backfill_participant_events] object V25EventsTableInsert { exercise: Exercise, ): Vector[NamedParameter] = Vector[NamedParameter]( - "event_id" -> fromTransactionId(transactionId, nodeId), + "event_id" -> TransactionIdWithIndex(transactionId, nodeId).toLedgerString, "event_offset" -> offset, "contract_id" -> exercise.targetCoid.coid, "transaction_id" -> transactionId, @@ -162,7 +162,7 @@ private[v25_backfill_participant_events] object V25EventsTableInsert { "exercise_result" -> serializeNullableExerciseResultOrThrow(exercise), "exercise_actors" -> exercise.actingParties.toArray[String], "exercise_child_event_ids" -> exercise.children - .map(fromTransactionId(transactionId, _)) + .map(TransactionIdWithIndex(transactionId, _).toLedgerString) .toArray[String], ) diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25TransactionsWriter.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25TransactionsWriter.scala index 25fc243efb5c..7eab0b5a747a 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25TransactionsWriter.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/v25_backfill_participant_events/V25TransactionsWriter.scala @@ -10,7 +10,7 @@ import com.daml.ledger.participant.state.v1.Offset import com.daml.ledger.{ApplicationId, CommandId, EventId, TransactionId, WorkflowId} import com.daml.lf.engine.Blinding import com.daml.lf.transaction.BlindingInfo -import com.daml.platform.events.EventIdFormatter +import com.daml.platform.events.TransactionIdWithIndex object V25TransactionsWriter extends V25TransactionsWriter { @@ -20,9 +20,9 @@ object V25TransactionsWriter extends V25TransactionsWriter { ): WitnessRelation[EventId] = transaction.nodes.collect { case (nodeId, c: Create) => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> c.stakeholders + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> c.stakeholders case (nodeId, e: Exercise) if e.consuming => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> e.stakeholders + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> e.stakeholders } private def computeDisclosureForTransactionTree( @@ -37,7 +37,7 @@ object V25TransactionsWriter extends V25TransactionsWriter { }.keySet blinding.disclosure.collect { case (nodeId, party) if disclosed(nodeId) => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> party + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> party } } diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29EventsTableInsert.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29EventsTableInsert.scala index b41e538897be..a7ec57be2655 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29EventsTableInsert.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29EventsTableInsert.scala @@ -8,7 +8,7 @@ import java.time.Instant import anorm.{BatchSql, NamedParameter} import com.daml.ledger.participant.state.v1.Offset import com.daml.ledger._ -import com.daml.platform.events.EventIdFormatter.fromTransactionId +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.Conversions._ import com.daml.platform.store.serialization.ValueSerializer.{serializeValue => serialize} @@ -85,7 +85,7 @@ private[v29_fix_participant_events] object V29EventsTableInsert { create: Create, ): Vector[NamedParameter] = Vector[NamedParameter]( - "event_id" -> fromTransactionId(transactionId, nodeId), + "event_id" -> TransactionIdWithIndex(transactionId, nodeId).toLedgerString, "event_offset" -> offset, "contract_id" -> create.coid.coid, "transaction_id" -> transactionId, @@ -137,7 +137,7 @@ private[v29_fix_participant_events] object V29EventsTableInsert { exercise: Exercise, ): Vector[NamedParameter] = Vector[NamedParameter]( - "event_id" -> fromTransactionId(transactionId, nodeId), + "event_id" -> TransactionIdWithIndex(transactionId, nodeId).toLedgerString, "event_offset" -> offset, "contract_id" -> exercise.targetCoid.coid, "transaction_id" -> transactionId, @@ -154,7 +154,7 @@ private[v29_fix_participant_events] object V29EventsTableInsert { "exercise_result" -> serializeNullableExerciseResultOrThrow(exercise), "exercise_actors" -> exercise.actingParties.toArray[String], "exercise_child_event_ids" -> exercise.children - .map(fromTransactionId(transactionId, _)) + .map(TransactionIdWithIndex(transactionId, _).toLedgerString) .toArray[String], ) diff --git a/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29TransactionsWriter.scala b/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29TransactionsWriter.scala index dba7a54c0f69..97e80ad448fa 100644 --- a/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29TransactionsWriter.scala +++ b/ledger/sandbox/src/main/scala/db/migration/postgres/v29_fix_participant_events/V29TransactionsWriter.scala @@ -10,7 +10,7 @@ import com.daml.ledger.participant.state.v1.Offset import com.daml.ledger.{ApplicationId, CommandId, EventId, TransactionId, WorkflowId} import com.daml.lf.engine.Blinding import com.daml.lf.transaction.BlindingInfo -import com.daml.platform.events.EventIdFormatter +import com.daml.platform.events.TransactionIdWithIndex object V29TransactionsWriter extends V29TransactionsWriter { @@ -20,9 +20,9 @@ object V29TransactionsWriter extends V29TransactionsWriter { ): WitnessRelation[EventId] = transaction.nodes.collect { case (nodeId, c: Create) => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> c.stakeholders + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> c.stakeholders case (nodeId, e: Exercise) if e.consuming => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> e.stakeholders + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> e.stakeholders } private def computeDisclosureForTransactionTree( @@ -37,7 +37,7 @@ object V29TransactionsWriter extends V29TransactionsWriter { }.keySet blinding.disclosure.collect { case (nodeId, party) if disclosed(nodeId) => - EventIdFormatter.fromTransactionId(transactionId, nodeId) -> party + TransactionIdWithIndex(transactionId, nodeId).toLedgerString -> party } } diff --git a/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoSuite.scala b/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoSuite.scala index d6b880186d1e..275d1d8162d1 100644 --- a/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoSuite.scala +++ b/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoSuite.scala @@ -31,8 +31,7 @@ import com.daml.lf.value.ValueVersions import com.daml.daml_lf_dev.DamlLf import com.daml.ledger.api.testing.utils.AkkaBeforeAndAfterAll import com.daml.ledger.{EventId, TransactionId} -import com.daml.platform.events.EventIdFormatter -import com.daml.platform.events.EventIdFormatter.split +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.entries.LedgerEntry import org.scalatest.Suite @@ -108,7 +107,7 @@ private[dao] trait JdbcLedgerDaoSuite extends AkkaBeforeAndAfterAll with JdbcLed Ref.LedgerString.assertFromString(s) protected final def event(txid: TransactionId, idx: Long): EventId = - EventIdFormatter.fromTransactionId(txid, NodeId(idx.toInt)) + TransactionIdWithIndex(txid, NodeId(idx.toInt)).toLedgerString private def create( absCid: ContractId, @@ -429,9 +428,6 @@ private[dao] trait JdbcLedgerDaoSuite extends AkkaBeforeAndAfterAll with JdbcLed ) } - private def splitOrThrow(id: EventId): NodeId = - split(id).fold(sys.error(s"Illegal format for event identifier $id"))(_.nodeId) - protected final def store( divulgedContracts: Map[(ContractId, v1.ContractInst), Set[Party]], offsetAndTx: (Offset, LedgerEntry.Transaction))( @@ -445,7 +441,7 @@ private[dao] trait JdbcLedgerDaoSuite extends AkkaBeforeAndAfterAll with JdbcLed submitterInfo = submitterInfo, workflowId = entry.workflowId, transactionId = entry.transactionId, - transaction = entry.transaction.mapNodeId(splitOrThrow), + transaction = entry.transaction.mapNodeId(TransactionIdWithIndex.assertFromString(_).nodeId), recordTime = entry.recordedAt, ledgerEffectiveTime = entry.ledgerEffectiveTime, offset = offset, diff --git a/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoTransactionTreesSpec.scala b/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoTransactionTreesSpec.scala index fa22ba730626..dd5b7347ede6 100644 --- a/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoTransactionTreesSpec.scala +++ b/ledger/sandbox/src/test/lib/scala/com/digitalasset/platform/store/dao/JdbcLedgerDaoTransactionTreesSpec.scala @@ -14,7 +14,7 @@ import com.daml.ledger.api.v1.transaction.TransactionTree import com.daml.ledger.api.v1.transaction_service.GetTransactionTreesResponse import com.daml.platform.ApiOffset import com.daml.platform.api.v1.event.EventOps.TreeEventOps -import com.daml.platform.events.EventIdFormatter.split +import com.daml.platform.events.TransactionIdWithIndex import com.daml.platform.store.entries.LedgerEntry import org.scalatest._ @@ -179,11 +179,15 @@ private[dao] trait JdbcLedgerDaoTransactionTreesSpec case Some(transaction) => val createEventId = tx.transaction.nodes.collectFirst { - case (eventId, _) if split(eventId).exists(_.nodeId.index == 2) => eventId + case (eventId, _) + if TransactionIdWithIndex.fromString(eventId).exists(_.nodeId.index == 2) => + eventId }.get val exerciseEventId = tx.transaction.nodes.collectFirst { - case (eventId, _) if split(eventId).exists(_.nodeId.index == 3) => eventId + case (eventId, _) + if TransactionIdWithIndex.fromString(eventId).exists(_.nodeId.index == 3) => + eventId }.get transaction.eventsById should have size 2 diff --git a/ledger/sandbox/src/test/suite/scala/com/digitalasset/platform/events/EventIdFormatterSpec.scala b/ledger/sandbox/src/test/suite/scala/com/digitalasset/platform/events/TransactionIdWithIndexSpec.scala similarity index 61% rename from ledger/sandbox/src/test/suite/scala/com/digitalasset/platform/events/EventIdFormatterSpec.scala rename to ledger/sandbox/src/test/suite/scala/com/digitalasset/platform/events/TransactionIdWithIndexSpec.scala index 233e2828a2a3..551d78a79a92 100644 --- a/ledger/sandbox/src/test/suite/scala/com/digitalasset/platform/events/EventIdFormatterSpec.scala +++ b/ledger/sandbox/src/test/suite/scala/com/digitalasset/platform/events/TransactionIdWithIndexSpec.scala @@ -5,28 +5,27 @@ package com.daml.platform.events import com.daml.lf.data.Ref import com.daml.lf.transaction.Transaction -import com.daml.platform.events.EventIdFormatter.TransactionIdWithIndex import org.scalatest.concurrent.ScalaFutures import org.scalatest.{Matchers, WordSpec} -class EventIdFormatterSpec extends WordSpec with Matchers with ScalaFutures { +class TransactionIdWithIndexSpec extends WordSpec with Matchers with ScalaFutures { - "EventIdFormatter" should { + "TransactionIdWithIndex" should { val transactionId: Ref.LedgerString = Ref.LedgerString.fromInt(42) val index: Transaction.NodeId = Transaction.NodeId(42) val referenceEventID = s"#$transactionId:${index.index}" "format an EventId from a TransactionId and an index" in { - EventIdFormatter.fromTransactionId(transactionId, index) should equal(referenceEventID) + TransactionIdWithIndex(transactionId, index).toLedgerString shouldBe referenceEventID } "split an eventId into a transactionId and an index" in { - EventIdFormatter.split(referenceEventID) should equal( - Some(TransactionIdWithIndex(transactionId, index))) + TransactionIdWithIndex.fromString(referenceEventID) shouldBe Right( + TransactionIdWithIndex(transactionId, index)) } "return None when parsing an invalid argument" in { - EventIdFormatter.split("some invalid event id") should equal(None) + TransactionIdWithIndex.fromString("some invalid event id") shouldBe 'left } } }