Skip to content

Commit

Permalink
KV: do not use "Effects" part of InputsAndEffects
Browse files Browse the repository at this point in the history
The PR is based #9429.

CHANGELOG_BEGIN
CHANGELOG_END
  • Loading branch information
remyhaemmerle-da authored and cocreature committed Apr 19, 2021
1 parent 6533de7 commit ec081be
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 215 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,24 @@ sealed abstract class HasTxNodes[Nid, +Cid] {
globalState
}

final def localContracts[Cid2 >: Cid]: Map[Cid2, Nid] =
fold(Map.empty[Cid2, Nid]) {
final def localContracts[Cid2 >: Cid]: Map[Cid2, (Nid, Node.NodeCreate[Cid2])] =
fold(Map.empty[Cid2, (Nid, Node.NodeCreate[Cid2])]) {
case (acc, (nid, create: Node.NodeCreate[Cid])) =>
acc.updated(create.coid, nid)
acc.updated(create.coid, nid -> create)
case (acc, _) => acc
}

/** Returns the IDs of all the consumed contracts.
* This includes transient contracts.
*/
final def consumedContracts[Cid2 >: Cid]: Set[Cid2] =
fold(Set.empty[Cid2]) {
case (acc, (_, exe: Node.NodeExercises[_, Cid])) if exe.consuming =>
acc + exe.targetCoid
case (acc, _) =>
acc
}

/** Returns the IDs of all input contracts that are used by this transaction.
*/
final def inputContracts[Cid2 >: Cid]: Set[Cid2] =
Expand Down Expand Up @@ -405,6 +416,31 @@ sealed abstract class HasTxNodes[Nid, +Cid] {
}
}

/** The contract keys created or updated as part of the transaction.
*/
final def updatedContractKeys(implicit
ev: HasTxNodes[Nid, Cid] <:< HasTxNodes[_, Value.ContractId]
): Map[GlobalKey, Option[Value.ContractId]] = {
ev(this).fold(Map.empty[GlobalKey, Option[Value.ContractId]]) {
case (acc, (_, node: Node.NodeCreate[Value.ContractId])) =>
node.key.fold(acc)(key =>
acc.updated(GlobalKey.assertBuild(node.templateId, key.key), Some(node.coid))
)
case (acc, (_, node: Node.NodeExercises[_, Value.ContractId])) if node.consuming =>
node.key.fold(acc)(key =>
acc.updated(GlobalKey.assertBuild(node.templateId, key.key), None)
)
case (
acc,
(_, _: Node.NodeExercises[_, _] | _: Node.NodeFetch[_] | _: Node.NodeLookupByKey[_]),
) =>
acc
case (_, (_, _: Node.NodeRollback[_])) =>
// TODO https://github.com/digital-asset/daml/issues/8020
sys.error("rollback nodes are not supported")
}
}

// This method visits to all nodes of the transaction in execution order.
// Exercise/rollback nodes are visited twice: when execution reaches them and when execution leaves their body.
// On the first visit of an execution/rollback node, the caller can prevent traversal of the children
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,18 @@ class TransactionSpec extends AnyFreeSpec with Matchers with ScalaCheckDrivenPro
builder.build().contractKeys shouldBe expectedResults
}
}

"consumedContract" - {
"return the IDs of all the consumed contracts" ignore {
// TODO https://github.com/digital-asset/daml/issues/8020
}
}


"updatedContractKeys" - {
"return all the udpdate contract keys" ignore {
// TODO https://github.com/digital-asset/daml/issues/8020
}
}

object TransactionSpec {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ import com.daml.ledger.participant.state.v1.{PackageId, SubmitterInfo}
import com.daml.lf.data.Ref.{Identifier, LedgerString, Party}
import com.daml.lf.data.Relation.Relation
import com.daml.lf.data.Time
import com.daml.lf.transaction.{GlobalKey, _}
import com.daml.lf.transaction.{
BlindingInfo,
GlobalKey,
NodeId,
Transaction,
TransactionCoder,
TransactionOuterClass,
}
import com.daml.lf.value.Value.{ContractId, VersionedValue}
import com.daml.lf.value.{Value, ValueCoder, ValueOuterClass}
import com.daml.lf.{crypto, data}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ class KeyValueSubmission(metrics: Metrics) {
*/
def transactionOutputs(tx: SubmittedTransaction): List[DamlStateKey] =
metrics.daml.kvutils.submission.conversion.transactionOutputs.time { () =>
val effects = InputsAndEffects.computeEffects(tx)
effects.createdContracts.map(_._1) ++ effects.consumedContracts
(tx.localContracts.keys ++ tx.consumedContracts).map(Conversions.contractIdToStateKey).toList
}

/** Prepare a transaction submission. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,17 @@ import com.daml.ledger.participant.state.kvutils.committer.Committer._
import com.daml.ledger.participant.state.kvutils.committer._
import com.daml.ledger.participant.state.kvutils.committer.transaction.TransactionCommitter.DamlTransactionEntrySummary
import com.daml.ledger.participant.state.kvutils.committer.transaction.keys.ContractKeysValidation.validateKeys
import com.daml.ledger.participant.state.kvutils.{Conversions, Err, InputsAndEffects}
import com.daml.ledger.participant.state.kvutils.{Conversions, Err}
import com.daml.ledger.participant.state.v1.{Configuration, RejectionReason, TimeModel}
import com.daml.lf.archive.Decode
import com.daml.lf.archive.Reader.ParseError
import com.daml.lf.crypto
import com.daml.lf.data.Ref.{Identifier, PackageId, Party, TypeConName}
import com.daml.lf.data.Ref.{PackageId, Party}
import com.daml.lf.data.Time.Timestamp
import com.daml.lf.engine.{Blinding, Engine, ReplayMismatch}
import com.daml.lf.language.Ast
import com.daml.lf.transaction.{
BlindingInfo,
GlobalKey,
GlobalKeyWithMaintainers,
Node,
NodeId,
Expand Down Expand Up @@ -448,30 +447,31 @@ private[kvutils] class TransactionCommitter(
blindingInfo: BlindingInfo,
commitContext: CommitContext,
): Unit = {
val effects = InputsAndEffects.computeEffects(transactionEntry.transaction)
val cid2nid: Value.ContractId => NodeId =
transactionEntry.transaction.localContracts
val localContracts = transactionEntry.transaction.localContracts
val consumedContracts = transactionEntry.transaction.consumedContracts
val contractKeys = transactionEntry.transaction.contractKeyUpdates
// Add contract state entries to mark contract activeness (checked by 'validateModelConformance').
for ((key, createNode) <- effects.createdContracts) {
localContracts.foreach { case (cid, (nid, createNode)) =>
val cs = DamlContractState.newBuilder
cs.setActiveAt(buildTimestamp(transactionEntry.ledgerEffectiveTime))
val localDisclosure =
blindingInfo.disclosure(cid2nid(decodeContractId(key.getContractId)))
val localDisclosure = blindingInfo.disclosure(nid)
cs.addAllLocallyDisclosedTo((localDisclosure: Iterable[String]).asJava)
cs.setContractInstance(
Conversions.encodeContractInstance(createNode.versionedCoinst)
)
createNode.key.foreach { keyWithMaintainers =>
cs.setContractKey(
Conversions.encodeGlobalKey(
globalKey(createNode.coinst.template, keyWithMaintainers.key)
)
Conversions.encodeContractKey(createNode.coinst.template, keyWithMaintainers.key)
)
}
commitContext.set(key, DamlStateValue.newBuilder.setContractState(cs).build)
commitContext.set(
Conversions.contractIdToStateKey(cid),
DamlStateValue.newBuilder.setContractState(cs).build,
)
}
// Update contract state entries to mark contracts as consumed (checked by 'validateModelConformance').
for (key <- effects.consumedContracts) {
consumedContracts.foreach { cid =>
val key = Conversions.contractIdToStateKey(cid)
val cs = getContractState(commitContext, key)
commitContext.set(
key,
Expand All @@ -497,9 +497,10 @@ private[kvutils] class TransactionCommitter(
}
// Update contract keys.
val ledgerEffectiveTime = transactionEntry.submission.getLedgerEffectiveTime
for ((key, contractKeyState) <- effects.updatedContractKeys) {
contractKeys.foreach { case (contractKey, contractKeyState) =>
val stateKey = Conversions.globalKeyToStateKey(contractKey)
val (k, v) =
updateContractKeyWithContractKeyState(ledgerEffectiveTime, key, contractKeyState)
updateContractKeyWithContractKeyState(ledgerEffectiveTime, stateKey, contractKeyState)
commitContext.set(k, v)
}
}
Expand Down Expand Up @@ -769,14 +770,4 @@ private[kvutils] object TransactionCommitter {
}
} yield parseTimestamp(dedupTimestamp).toInstant

private[committer] def damlContractKey(
templateId: TypeConName,
keyValue: Value[ContractId],
): DamlContractKey =
encodeGlobalKey(globalKey(templateId, keyValue))

private[transaction] def globalKey(tmplId: Identifier, key: Value[ContractId]) =
GlobalKey
.build(tmplId, key)
.fold(msg => throw Err.InternalError(msg), identity)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

package com.daml.ledger.participant.state.kvutils.committer.transaction.keys

import com.daml.ledger.participant.state.kvutils.Conversions
import com.daml.ledger.participant.state.kvutils.DamlKvutils.DamlContractKey
import com.daml.ledger.participant.state.kvutils.committer.transaction.TransactionCommitter.damlContractKey
import com.daml.ledger.participant.state.kvutils.committer.transaction.keys.ContractKeysValidation.{
Inconsistent,
KeyValidationState,
Expand Down Expand Up @@ -74,7 +74,7 @@ private[keys] object KeyConsistencyValidation {
case None => Right(keyValidationState)
case Some(submittedKeyWithMaintainers) =>
val submittedDamlContractKey =
damlContractKey(templateId, submittedKeyWithMaintainers.key)
Conversions.encodeContractKey(templateId, submittedKeyWithMaintainers.key)
val newKeyValidationState =
keyValidationState + ConsistencyKeyValidationState(
submittedContractKeysToContractIds = Map(
Expand Down
Loading

0 comments on commit ec081be

Please sign in to comment.