Fix TransactionCommitter.trimUnnecessaryNodes for rollback nodes (#9536)

* Fix TransactionCommitter.trimUnnecessaryNodes for rollback nodes

changelog_begin
changelog_end

* Update ledger/participant-state/kvutils/src/test/suite/scala/com/daml/ledger/participant/state/kvutils/committer/transaction/TransactionCommitterSpec.scala

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>

* switch error code

changelog_begin
changelog_end

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>
This commit is contained in:
Moritz Kiefer 2021-04-30 14:17:58 +02:00 committed by GitHub
parent b25c904fc8
commit a937a66463
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 4 deletions

View File

@ -36,6 +36,7 @@ import com.daml.logging.{ContextualizedLogger, LoggingContext}
import com.daml.metrics.Metrics
import com.google.protobuf.{Timestamp => ProtoTimestamp}
import scala.annotation.tailrec
import scala.jdk.CollectionConverters._
// The parameter inStaticTimeMode indicates that the ledger is running in static time mode.
@ -387,9 +388,29 @@ private[kvutils] class TransactionCommitter(
)(implicit loggingContext: LoggingContext): StepResult[DamlTransactionEntrySummary] = {
val transaction = transactionEntry.submission.getTransaction
val nodes = transaction.getNodesList.asScala
val nodesToKeep = nodes.iterator.collect {
case node if node.hasCreate || node.hasExercise => node.getNodeId
}.toSet
val nodeMap: Map[String, TransactionOuterClass.Node] =
nodes.view.map(n => n.getNodeId -> n).toMap
@tailrec
def goNodesToKeep(todo: List[String], result: Set[String]): Set[String] = todo match {
case Nil => result
case head :: tail =>
import TransactionOuterClass.Node.NodeTypeCase
val node = nodeMap
.get(head)
.getOrElse(throw Err.InternalError(s"Invalid transaction node id $head"))
node.getNodeTypeCase match {
case NodeTypeCase.CREATE =>
goNodesToKeep(tail, result + head)
case NodeTypeCase.EXERCISE =>
goNodesToKeep(node.getExercise.getChildrenList.asScala.toList ++ tail, result + head)
case NodeTypeCase.ROLLBACK | NodeTypeCase.FETCH | NodeTypeCase.LOOKUP_BY_KEY |
NodeTypeCase.NODETYPE_NOT_SET =>
goNodesToKeep(tail, result)
}
}
val nodesToKeep = goNodesToKeep(transaction.getRootsList.asScala.toList, Set.empty)
val filteredRoots = transaction.getRootsList.asScala.filter(nodesToKeep)

View File

@ -99,6 +99,13 @@ class TransactionCommitterSpec extends AnyWordSpec with Matchers with MockitoSug
)
)
),
createNode("Rollback-1")(
_.setRollback(
rollbackNodeBuilder.addAllChildren(Seq("RollbackChild-1", "RollbackChild-2").asJava)
)
),
createNode("RollbackChild-1")(_.setCreate(createNodeBuilder)),
createNode("RollbackChild-2")(_.setFetch(fetchNodeBuilder)),
)
val tx = TransactionOuterClass.Transaction
.newBuilder()
@ -122,13 +129,16 @@ class TransactionCommitterSpec extends AnyWordSpec with Matchers with MockitoSug
private def exerciseNodeBuilder =
TransactionOuterClass.NodeExercise.newBuilder()
private def rollbackNodeBuilder =
TransactionOuterClass.NodeRollback.newBuilder()
private def createNodeBuilder = TransactionOuterClass.NodeCreate.newBuilder()
private def lookupByKeyNodeBuilder =
TransactionOuterClass.NodeLookupByKey.newBuilder()
"trimUnnecessaryNodes" should {
"remove `Fetch` and `LookupByKey` nodes from transaction tree" in {
"remove `Fetch`, `LookupByKey`, and `Rollback` nodes from the transaction tree" in {
val context = createCommitContext(recordTime = None)
val actual = transactionCommitter.trimUnnecessaryNodes(