mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 10:46:11 +03:00
LF: drop legacy logic to infer transaction versions. (#7856)
This advances the state of #7788 CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
7325499ff9
commit
23ba79ca6b
@ -19,10 +19,10 @@ import com.daml.lf.transaction.{
|
||||
Node,
|
||||
NodeId,
|
||||
SubmittedTransaction,
|
||||
TransactionVersion,
|
||||
VersionedTransaction,
|
||||
GenTransaction => GenTx,
|
||||
Transaction => Tx,
|
||||
TransactionVersion => TxVersion,
|
||||
TransactionVersions => TxVersions
|
||||
}
|
||||
import com.daml.lf.value.{Value, ValueVersion}
|
||||
@ -30,6 +30,7 @@ import Value._
|
||||
import com.daml.lf.speedy.{InitialSeeding, SValue, svalue}
|
||||
import com.daml.lf.speedy.SValue._
|
||||
import com.daml.lf.command._
|
||||
import com.daml.lf.transaction.TransactionVersions.UnversionedNode
|
||||
import com.daml.lf.value.ValueVersions.assertAsVersionedValue
|
||||
import org.scalactic.Equality
|
||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||
@ -1857,8 +1858,7 @@ class EngineTest
|
||||
val result = run(
|
||||
cidV6,
|
||||
EngineConfig.Stable.copy(
|
||||
allowedOutputTransactionVersions =
|
||||
VersionRange(TransactionVersion("9"), TransactionVersion("9"))))
|
||||
allowedOutputTransactionVersions = VersionRange(TxVersion("9"), TxVersion("9"))))
|
||||
result shouldBe 'left
|
||||
result.left.get.msg should include("inferred transaction version 10 is not allowed")
|
||||
}
|
||||
@ -1955,7 +1955,7 @@ object EngineTest {
|
||||
): Either[Error, (Tx.Transaction, Tx.Metadata)] = {
|
||||
type Acc =
|
||||
(
|
||||
HashMap[NodeId, Tx.Node],
|
||||
HashMap[NodeId, UnversionedNode],
|
||||
BackStack[NodeId],
|
||||
Boolean,
|
||||
BackStack[(NodeId, crypto.Hash)],
|
||||
@ -2025,7 +2025,13 @@ object EngineTest {
|
||||
tr = tr1.transaction.mapNodeId(nodeRenaming)
|
||||
} yield
|
||||
(
|
||||
nodes ++ tr.nodes,
|
||||
nodes ++ tr.nodes.mapValues(
|
||||
Node.GenNode.map3(
|
||||
identity[NodeId],
|
||||
identity[ContractId],
|
||||
(v: VersionedValue[ContractId]) => v.value,
|
||||
)
|
||||
),
|
||||
roots :++ tr.roots,
|
||||
dependsOnTime || meta1.dependsOnTime,
|
||||
nodeSeeds :++ meta1.nodeSeeds.map { case (nid, seed) => nodeRenaming(nid) -> seed },
|
||||
@ -2037,7 +2043,14 @@ object EngineTest {
|
||||
iterate.map {
|
||||
case (nodes, roots, dependsOnTime, nodeSeeds, _, _) =>
|
||||
(
|
||||
TxVersions.assertAsVersionedTransaction(GenTx(nodes, roots.toImmArray)),
|
||||
data.assertRight(
|
||||
TxVersions.asVersionedTransaction(
|
||||
TxVersions.DevOutputVersions,
|
||||
engine.compiledPackages().packageLanguageVersion,
|
||||
roots.toImmArray,
|
||||
nodes,
|
||||
)
|
||||
),
|
||||
Tx.Metadata(
|
||||
submissionSeed = None,
|
||||
submissionTime = txMeta.submissionTime,
|
||||
|
@ -24,7 +24,7 @@ private[lf] object TransactionVersions
|
||||
import VersionTimeline._
|
||||
import VersionTimeline.Implicits._
|
||||
|
||||
private[this] val minVersion = TransactionVersion("1")
|
||||
private[transaction] val minVersion = TransactionVersion("1")
|
||||
private[transaction] val minKeyOrLookupByKey = TransactionVersion("3")
|
||||
private[transaction] val minFetchActors = TransactionVersion("5")
|
||||
private[transaction] val minNoControllers = TransactionVersion("6")
|
||||
@ -44,96 +44,6 @@ private[lf] object TransactionVersions
|
||||
val Empty: VersionRange[TransactionVersion] =
|
||||
VersionRange(acceptedVersions.last, acceptedVersions.head)
|
||||
|
||||
def assignVersion(
|
||||
a: GenTransaction.WithTxValue[_, Value.ContractId],
|
||||
supportedVersions: VersionRange[TransactionVersion] = DevOutputVersions,
|
||||
): Either[String, TransactionVersion] = {
|
||||
require(a != null)
|
||||
import VersionTimeline.Implicits._
|
||||
|
||||
val inferredVersion =
|
||||
VersionTimeline.latestWhenAllPresent(
|
||||
supportedVersions.min,
|
||||
// latest version used by any value
|
||||
a.foldValues(ValueVersion("1")) { (z, vv) =>
|
||||
VersionTimeline.maxVersion(z, vv.version)
|
||||
},
|
||||
// a NodeCreate with defined `key` or a NodeLookupByKey
|
||||
// implies minimum version 3
|
||||
if (a.nodes.values.exists {
|
||||
case nc: Node.NodeCreate[_, _] => nc.key.isDefined
|
||||
case _: Node.NodeLookupByKey[_, _] => true
|
||||
case _: Node.NodeFetch[_, _] | _: Node.NodeExercises[_, _, _] => false
|
||||
}) minKeyOrLookupByKey
|
||||
else
|
||||
minVersion,
|
||||
// a NodeFetch with actingParties implies minimum version 5
|
||||
if (a.nodes.values
|
||||
.exists { case nf: Node.NodeFetch[_, _] => nf.actingParties.nonEmpty; case _ => false })
|
||||
minFetchActors
|
||||
else
|
||||
minVersion,
|
||||
if (a.nodes.values
|
||||
.exists {
|
||||
case ne: Node.NodeExercises[_, _, _] => ne.exerciseResult.isDefined
|
||||
case _ => false
|
||||
})
|
||||
minExerciseResult
|
||||
else
|
||||
minVersion,
|
||||
if (a.nodes.values
|
||||
.exists {
|
||||
case ne: Node.NodeExercises[_, _, _] => ne.key.isDefined
|
||||
case _ => false
|
||||
})
|
||||
minContractKeyInExercise
|
||||
else
|
||||
minVersion,
|
||||
if (a.nodes.values
|
||||
.exists {
|
||||
case ne: Node.NodeExercises[_, _, _] =>
|
||||
ne.key match {
|
||||
case Some(Node.KeyWithMaintainers(key @ _, maintainers)) => maintainers.nonEmpty
|
||||
case _ => false
|
||||
}
|
||||
case _ => false
|
||||
})
|
||||
minMaintainersInExercise
|
||||
else
|
||||
minVersion,
|
||||
if (a.nodes.values
|
||||
.exists {
|
||||
case nf: Node.NodeFetch[_, _] => nf.key.isDefined
|
||||
case _ => false
|
||||
})
|
||||
minContractKeyInFetch
|
||||
else
|
||||
minVersion,
|
||||
)
|
||||
|
||||
Either.cond(
|
||||
!(supportedVersions.max precedes inferredVersion),
|
||||
inferredVersion,
|
||||
s"inferred version $inferredVersion is not supported"
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
def asVersionedTransaction(
|
||||
tx: GenTransaction.WithTxValue[NodeId, Value.ContractId],
|
||||
supportedVersions: VersionRange[TransactionVersion] = DevOutputVersions,
|
||||
): Either[String, Transaction.Transaction] =
|
||||
for {
|
||||
v <- assignVersion(tx, supportedVersions)
|
||||
} yield VersionedTransaction(v, tx)
|
||||
|
||||
@throws[IllegalArgumentException]
|
||||
def assertAsVersionedTransaction(
|
||||
tx: GenTransaction.WithTxValue[NodeId, Value.ContractId],
|
||||
supportedVersions: VersionRange[TransactionVersion] = DevOutputVersions,
|
||||
): Transaction.Transaction =
|
||||
data.assertRight(asVersionedTransaction(tx, supportedVersions))
|
||||
|
||||
private[lf] def assignValueVersion(transactionVersion: TransactionVersion): ValueVersion =
|
||||
latestWhenAllPresent(
|
||||
ValueVersions.acceptedVersions.head,
|
||||
|
@ -294,8 +294,14 @@ class TransactionCoderSpec
|
||||
val nodes = ImmArray((1 to 10000).map { nid =>
|
||||
NodeId(nid) -> node
|
||||
})
|
||||
val tx = TransactionVersions.assertAsVersionedTransaction(
|
||||
GenTransaction(nodes = HashMap(nodes.toSeq: _*), roots = nodes.map(_._1)))
|
||||
|
||||
val versions = Table("version", TransactionVersion("10"), TransactionVersion("dev"))
|
||||
|
||||
forEvery(versions) { version =>
|
||||
val tx = VersionedTransaction(
|
||||
version,
|
||||
GenTransaction(nodes = HashMap(nodes.toSeq: _*), roots = nodes.map(_._1))
|
||||
)
|
||||
|
||||
tx shouldEqual TransactionCoder
|
||||
.decodeTransaction(
|
||||
@ -314,6 +320,7 @@ class TransactionCoderSpec
|
||||
.get
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"encode" should {
|
||||
// FIXME: https://github.com/digital-asset/daml/issues/7709
|
||||
|
@ -4,60 +4,12 @@
|
||||
package com.daml.lf
|
||||
package transaction
|
||||
|
||||
import data.ImmArray
|
||||
import value.{Value, ValueVersion, ValueVersions}
|
||||
import Value.{ContractId, ValueOptional, VersionedValue}
|
||||
import value.{ValueVersion, ValueVersions}
|
||||
import com.daml.lf.language.LanguageVersion
|
||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||
import org.scalatest.{Matchers, WordSpec}
|
||||
|
||||
import scala.collection.immutable.HashMap
|
||||
|
||||
class TransactionVersionSpec extends WordSpec with Matchers with TableDrivenPropertyChecks {
|
||||
import TransactionVersionSpec._
|
||||
|
||||
import VersionTimeline.maxVersion
|
||||
|
||||
private[this] val supportedValVersions =
|
||||
ValueVersions.DevOutputVersions.copy(min = ValueVersion("1"))
|
||||
private[this] val supportedTxVersions =
|
||||
TransactionVersions.DevOutputVersions.copy(min = TransactionVersion("1"))
|
||||
|
||||
"assignVersion" should {
|
||||
"prefer picking an older version" in {
|
||||
assignTxVersion(assignValueVersions(dummyCreateTransaction)) shouldBe Right(
|
||||
maxVersion(supportedTxVersions.min, TransactionVersion("1")))
|
||||
}
|
||||
|
||||
"pick version 2 when confronted with newer data" in {
|
||||
val usingOptional =
|
||||
dummyCreateTransaction map3 (identity, identity, v => ValueOptional(Some(v)))
|
||||
assignTxVersion(assignValueVersions(usingOptional)) shouldBe Right(
|
||||
maxVersion(supportedTxVersions.min, TransactionVersion("2")))
|
||||
}
|
||||
|
||||
"pick version 7 when confronted with exercise result" in {
|
||||
val hasExerciseResult =
|
||||
dummyExerciseWithResultTransaction map3 (identity, identity, v => ValueOptional(Some(v)))
|
||||
assignTxVersion(assignValueVersions(hasExerciseResult)) shouldBe Right(
|
||||
maxVersion(supportedTxVersions.min, TransactionVersion("7")))
|
||||
}
|
||||
|
||||
"pick version 2 when confronted with exercise result" in {
|
||||
val hasExerciseResult =
|
||||
dummyExerciseTransaction map3 (identity, identity, v => ValueOptional(Some(v)))
|
||||
assignTxVersion(assignValueVersions(hasExerciseResult)) shouldBe Right(
|
||||
maxVersion(supportedTxVersions.min, TransactionVersion("2")))
|
||||
}
|
||||
|
||||
"crash the picked version is more recent that the maximal supported version" in {
|
||||
val supportedVersions = VersionRange(TransactionVersion("1"), TransactionVersion("5"))
|
||||
val hasExerciseResult =
|
||||
dummyExerciseWithResultTransaction map3 (identity, identity, v => ValueOptional(Some(v)))
|
||||
TransactionVersions.assignVersion(assignValueVersions(hasExerciseResult), supportedVersions) shouldBe 'left
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
"TransactionVersions.assignVersions" should {
|
||||
|
||||
@ -151,33 +103,4 @@ class TransactionVersionSpec extends WordSpec with Matchers with TableDrivenProp
|
||||
}
|
||||
}
|
||||
|
||||
private[this] def assignValueVersions[Nid, Cid <: ContractId](
|
||||
t: GenTransaction[Nid, Cid, Value[Cid]],
|
||||
): GenTransaction[Nid, Cid, VersionedValue[Cid]] =
|
||||
t map3 (identity, identity, ValueVersions.assertAsVersionedValue(_, supportedValVersions))
|
||||
|
||||
private[this] def assignTxVersion[Nid, Cid <: ContractId](
|
||||
t: GenTransaction[Nid, Cid, VersionedValue[Cid]],
|
||||
): Either[String, TransactionVersion] =
|
||||
TransactionVersions.assignVersion(t, supportedTxVersions)
|
||||
|
||||
}
|
||||
|
||||
object TransactionVersionSpec {
|
||||
|
||||
import TransactionSpec._
|
||||
|
||||
private[this] val singleId = NodeId(0)
|
||||
private val dummyCreateTransaction =
|
||||
mkTransaction(HashMap(singleId -> dummyCreateNode("cid1")), ImmArray(singleId))
|
||||
private val dummyExerciseWithResultTransaction =
|
||||
mkTransaction(
|
||||
HashMap(singleId -> dummyExerciseNode("cid2", ImmArray.empty)),
|
||||
ImmArray(singleId))
|
||||
private val dummyExerciseTransaction =
|
||||
mkTransaction(
|
||||
HashMap(singleId -> dummyExerciseNode("cid3", ImmArray.empty, false)),
|
||||
ImmArray(singleId),
|
||||
)
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user