Skip to content

Commit

Permalink
Engine: Centralize the place where value version is inferred. (#6229)
Browse files Browse the repository at this point in the history
CHANGELOG_BEGIN
CHANGELOG_END
  • Loading branch information
remyhaemmerle-da authored Jun 5, 2020
1 parent cfa66ec commit 5e9490f
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class Conversions(
// We need the mapping for converting error message so we manually add it here.
private val ptxCoidToNodeId = machine.ptx.nodes
.collect {
case (nodeId, node: N.NodeCreate.WithTxValue[V.ContractId]) =>
case (nodeId, node: N.NodeCreate[V.ContractId, _]) =>
node.coid -> ledger.ptxNodeId(nodeId)
}

Expand Down Expand Up @@ -96,7 +96,7 @@ final class Conversions(
builder.setTemplatePrecondViolated(
uepvBuilder
.setTemplateId(convertIdentifier(tid))
.setArg(convertValue(arg.value))
.setArg(convertValue(arg))
.build,
)
case SError.DamlELocalContractNotActive(coid, tid, consumedBy) =>
Expand Down Expand Up @@ -374,7 +374,7 @@ final class Conversions(

def convertPartialTransaction(ptx: SPartialTransaction): PartialTransaction = {
val builder = PartialTransaction.newBuilder
.addAllNodes(ptx.nodes.map(Function.tupled(convertTxNode)).asJava)
.addAllNodes(ptx.nodes.map(convertNode(convertValue(_), _)).asJava)
.addAllRoots(
ptx.context.children.toImmArray.toSeq.sortBy(_.index).map(convertTxNodeId).asJava,
)
Expand All @@ -385,7 +385,7 @@ final class Conversions(
val ecBuilder = ExerciseContext.newBuilder
.setTargetId(mkContractRef(ctx.targetId, ctx.templateId))
.setChoiceId(ctx.choiceId)
.setChosenValue(convertValue(ctx.chosenValue.value))
.setChosenValue(convertValue(ctx.chosenValue))
ctx.optLocation.map(loc => ecBuilder.setExerciseLocation(convertLocation(loc)))
builder.setExerciseContext(ecBuilder.build)
}
Expand Down Expand Up @@ -471,46 +471,51 @@ final class Conversions(
lbk.optLocation.foreach(loc => builder.setLocation(convertLocation(loc)))
val lbkBuilder = Node.LookupByKey.newBuilder
.setTemplateId(convertIdentifier(lbk.templateId))
.setKeyWithMaintainers(convertKeyWithMaintainers(lbk.key))
.setKeyWithMaintainers(convertKeyWithMaintainers(convertVersionedValue, lbk.key))
lbk.result.foreach(cid => lbkBuilder.setContractId(coidToNodeId(cid)))
builder.setLookupByKey(lbkBuilder)

}
builder.build
}

def convertKeyWithMaintainers(
key: N.KeyWithMaintainers[V.VersionedValue[V.ContractId]],
def convertKeyWithMaintainers[Val](
convertValue: Val => Value,
key: N.KeyWithMaintainers[Val],
): KeyWithMaintainers = {
KeyWithMaintainers
.newBuilder()
.setKey(convertValue(key.key.value))
.setKey(convertValue(key.key))
.addAllMaintainers(key.maintainers.map(convertParty).asJava)
.build()
}

def convertTxNode( /*ptx: Tx.PartialTransaction, */ nodeId: Tx.NodeId, node: Tx.Node): Node = {
def convertNode[Val](
convertValue: Val => Value,
nodeWithId: (Tx.NodeId, N.GenNode[V.NodeId, V.ContractId, Val]),
): Node = {
val (nodeId, node) = nodeWithId
val builder = Node.newBuilder
builder
.setNodeId(NodeId.newBuilder.setId(nodeId.index.toString).build)
// FIXME(JM): consumedBy, parent, ...
node match {
case create: N.NodeCreate.WithTxValue[V.ContractId] =>
case create: N.NodeCreate[V.ContractId, Val] =>
val createBuilder =
Node.Create.newBuilder
.setContractInstance(
ContractInstance.newBuilder
.setTemplateId(convertIdentifier(create.coinst.template))
.setValue(convertValue(create.coinst.arg.value))
.setValue(convertValue(create.coinst.arg))
.build,
)
.addAllSignatories(create.signatories.map(convertParty).asJava)
.addAllStakeholders(create.stakeholders.map(convertParty).asJava)
create.key.foreach(key =>
createBuilder.setKeyWithMaintainers(convertKeyWithMaintainers(key)))
createBuilder.setKeyWithMaintainers(convertKeyWithMaintainers(convertValue, key)))
create.optLocation.map(loc => builder.setLocation(convertLocation(loc)))
builder.setCreate(createBuilder.build)
case fetch: N.NodeFetch.WithTxValue[V.ContractId] =>
case fetch: N.NodeFetch[V.ContractId, Val] =>
builder.setFetch(
Node.Fetch.newBuilder
.setContractId(coidToNodeId(fetch.coid))
Expand All @@ -519,7 +524,7 @@ final class Conversions(
.addAllStakeholders(fetch.stakeholders.map(convertParty).asJava)
.build,
)
case ex: N.NodeExercises.WithTxValue[Tx.NodeId, V.ContractId] =>
case ex: N.NodeExercises[V.NodeId, V.ContractId, Val] =>
ex.optLocation.map(loc => builder.setLocation(convertLocation(loc)))
builder.setExercise(
Node.Exercise.newBuilder
Expand All @@ -528,7 +533,7 @@ final class Conversions(
.setChoiceId(ex.choiceId)
.setConsuming(ex.consuming)
.addAllActingParties(ex.actingParties.map(convertParty).asJava)
.setChosenValue(convertValue(ex.chosenValue.value))
.setChosenValue(convertValue(ex.chosenValue))
.addAllSignatories(ex.signatories.map(convertParty).asJava)
.addAllStakeholders(ex.stakeholders.map(convertParty).asJava)
.addAllChildren(
Expand All @@ -540,11 +545,11 @@ final class Conversions(
.build,
)

case lookup: N.NodeLookupByKey.WithTxValue[V.ContractId] =>
case lookup: N.NodeLookupByKey[V.ContractId, Val] =>
lookup.optLocation.map(loc => builder.setLocation(convertLocation(loc)))
builder.setLookupByKey({
val builder = Node.LookupByKey.newBuilder
.setKeyWithMaintainers(convertKeyWithMaintainers(lookup.key))
.setKeyWithMaintainers(convertKeyWithMaintainers(convertValue, lookup.key))
lookup.result.foreach(cid => builder.setContractId(coidToNodeId(cid)))
builder.build
})
Expand Down Expand Up @@ -580,6 +585,9 @@ final class Conversions(

}

private def convertVersionedValue(value: V.VersionedValue[V.ContractId]): Value =
convertValue(value.value)

def convertValue(value: V[V.ContractId]): Value = {
val builder = Value.newBuilder
value match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ final class Engine {
}
}

machine.ptx.finish match {
machine.ptx.finish(machine.supportedValueVersions) match {
case Left(p) =>
ResultError(Error(s"Interpretation error: ended with partial result: $p"))
case Right(t) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ object Pretty {
case DamlETemplatePreconditionViolated(tid, optLoc @ _, arg) =>
text("Update failed due to precondition violation when creating") &
prettyTypeConName(tid) &
text("with") & prettyVersionedValue(true)(arg)
text("with") & prettyValue(true)(arg)

case DamlELocalContractNotActive(coid, tid, consumedBy) =>
text("Update failed due to fetch of an inactive contract") & prettyContractId(coid) &
Expand All @@ -62,7 +62,7 @@ object Pretty {
case None =>
(line + text("Recursive exercise of ") + prettyTypeConName(tid)).nested(4)
case Some(node) =>
(line + prettyTransactionNode(node)).nested(4)
(line + prettyPartialTransactionNode(node)).nested(4)
})

case DamlEWronglyTypedContract(coid, expected, actual) =>
Expand All @@ -73,18 +73,18 @@ object Pretty {
}

// A minimal pretty-print of an update transaction node, without recursing into child nodes..
def prettyTransactionNode(node: Transaction.Node): Doc =
def prettyPartialTransactionNode(node: PartialTransaction.Node): Doc =
node match {
case create: NodeCreate.WithTxValue[ContractId] =>
case create: NodeCreate[Value.ContractId, Value[Value.ContractId]] =>
"create" &: prettyContractInst(create.coinst)
case fetch: NodeFetch.WithTxValue[ContractId] =>
case fetch: NodeFetch[Value.ContractId, Value[Value.ContractId]] =>
"fetch" &: prettyContractId(fetch.coid)
case ex: NodeExercises.WithTxValue[Transaction.NodeId, ContractId] =>
case ex: NodeExercises[Value.NodeId, Value.ContractId, Value[Value.ContractId]] =>
intercalate(text(", "), ex.actingParties.map(p => text(p))) &
text("exercises") & text(ex.choiceId) + char(':') + prettyIdentifier(ex.templateId) &
text("on") & prettyContractId(ex.targetCoid) /
text("with") & prettyVersionedValue(false)(ex.chosenValue)
case lbk: NodeLookupByKey.WithTxValue[ContractId] =>
text("with") & prettyValue(false)(ex.chosenValue)
case lbk: NodeLookupByKey[Value.ContractId, Value[Value.ContractId]] =>
text("lookup by key") & prettyIdentifier(lbk.templateId) /
text("key") & prettyKeyWithMaintainers(lbk.key) /
(lbk.result match {
Expand Down Expand Up @@ -248,21 +248,26 @@ object Pretty {
text("mustFailAt") & prettyParty(amf.actor) & prettyLoc(amf.optLocation)
}

def prettyKeyWithMaintainers(key: KeyWithMaintainers[Transaction.Value[ContractId]]): Doc =
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 arrowRight(d: Doc) = text("└─>") & d
def meta(d: Doc) = text("") & d

val ni = l.ledgerData.nodeInfos(nodeId) /* Ekke Ekke Ekke Ekke Ptang Zoo Boing! */
val ppNode = ni.node match {
case create: NodeCreate[ContractId, Transaction.Value[ContractId]] =>
val d = "create" &: prettyContractInst(create.coinst)
val d = "create" &: prettyVersionedContractInst(create.coinst)
create.key match {
case None => d
case Some(key) => d / text("key") & prettyKeyWithMaintainers(key)
case Some(key) => d / text("key") & prettyVersionedKeyWithMaintainers(key)
}
case ea: NodeFetch[ContractId, Transaction.Value[ContractId]] =>
"ensure active" &: prettyContractId(ea.coid)
Expand All @@ -284,7 +289,7 @@ object Pretty {
.nested(4)
case lbk: NodeLookupByKey[ContractId, Transaction.Value[ContractId]] =>
text("lookup by key") & prettyIdentifier(lbk.templateId) /
text("key") & prettyKeyWithMaintainers(lbk.key) /
text("key") & prettyVersionedKeyWithMaintainers(lbk.key) /
(lbk.result match {
case None => text("not found")
case Some(coid) => text("found") & prettyContractId(coid)
Expand Down Expand Up @@ -332,7 +337,11 @@ object Pretty {
def prettyLedgerNodeId(n: L.ScenarioNodeId): Doc =
text(n)

def prettyContractInst(coinst: ContractInst[Transaction.Value[ContractId]]): Doc =
def prettyContractInst(coinst: ContractInst[Value[ContractId]]): Doc =
(prettyIdentifier(coinst.template) / text("with:") &
prettyValue(false)(coinst.arg)).nested(4)

def prettyVersionedContractInst(coinst: ContractInst[Transaction.Value[ContractId]]): Doc =
(prettyIdentifier(coinst.template) / text("with:") &
prettyVersionedValue(false)(coinst.arg)).nested(4)

Expand Down
Loading

0 comments on commit 5e9490f

Please sign in to comment.