From acdca6533ade26ed7c173ee813bab352eace6aad Mon Sep 17 00:00:00 2001 From: Remy Date: Tue, 9 Jun 2020 13:41:14 +0200 Subject: [PATCH] Indexer: Fix function newRoots in TransactionConversion. (#6272) * reduce complexity from quadratic to linear * output node in creating order * avoid useless allocation of GenTransaction * make it clearer CHANGELOG_BEGIN CHANGELOG_END --- .../index/TransactionConversion.scala | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) 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 453507a3f0..086ade195a 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 @@ -4,7 +4,7 @@ package com.daml.platform.index import com.daml.api.util.TimestampConversion -import com.daml.lf.data.{ImmArray, Ref} +import com.daml.lf.data.{BackStack, FrontStack, FrontStackCons, Ref} import com.daml.lf.data.Relation.Relation import com.daml.lf.engine.Blinding import com.daml.lf.transaction.GenTransaction @@ -18,8 +18,7 @@ import com.daml.ledger.api.v1.transaction.{ Transaction => ApiTransaction, TransactionTree => ApiTransactionTree } -import com.daml.platform.api.v1.event.EventOps.EventOps -import com.daml.platform.api.v1.event.EventOps.TreeEventOps +import com.daml.platform.api.v1.event.EventOps.{EventOps, TreeEventOps} import com.daml.platform.participant.util.LfEngineToApi.{ assertOrRuntimeEx, lfNodeCreateToEvent, @@ -145,23 +144,28 @@ object TransactionConversion { ) } - @tailrec private def newRoots( tx: Transaction, - disclosure: Relation[EventId, Ref.Party], - ): Seq[String] = { - val (replaced, roots) = - tx.roots.foldLeft((false, IndexedSeq.empty[EventId])) { - case ((replaced, roots), eventId) => - if (isCreateOrExercise(tx.nodes(eventId)) && disclosure.contains(eventId)) { - (replaced, roots :+ eventId) - } else - tx.nodes(eventId) match { - case e: Exercise => (true, roots ++ e.children.toIndexedSeq) - case _ => (true, roots) - } + disclosed: EventId => Boolean, + ) = { + + @tailrec + def go(toProcess: FrontStack[EventId], acc: BackStack[EventId]): Seq[EventId] = + toProcess match { + case FrontStackCons(head, tail) => + tx.nodes(head) match { + case _: Create | _: Exercise if disclosed(head) => + go(tail, acc :+ head) + case exe: Exercise => + go(exe.children ++: tail, acc) + case _ => + go(tail, acc) + } + case FrontStack() => + acc.toImmArray.toSeq } - if (replaced) newRoots(tx.copy(roots = ImmArray(roots)), disclosure) else roots + + go(FrontStack(tx.roots), BackStack.empty) } private def applyDisclosure( @@ -173,7 +177,7 @@ object TransactionConversion { case events if events.nonEmpty => ApiTransactionTree( eventsById = events.toMap, - rootEventIds = newRoots(tx, disclosure) + rootEventIds = newRoots(tx, disclosure.contains) ) }