mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 16:57:40 +03:00
LF: Simplify transaction versionning for interface (#11744)
We revert #11626, and just change the way transaction version is computed: - As before, Node version is calculated from the package of the template ID action. - Transaction version is the max of the version of all the nodes, instead of the root nodes. CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
4b59c5731c
commit
1bb2fc28a3
@ -14,40 +14,17 @@ import scala.Ordering.Implicits.infixOrderingOps
|
||||
* @tparam V either [[com.daml.lf.language.LanguageVersion]] or
|
||||
* [[com.daml.lf.transaction.TransactionVersion]].
|
||||
*/
|
||||
final case class VersionRange[V] private (
|
||||
final case class VersionRange[V](
|
||||
min: V,
|
||||
max: V,
|
||||
)(implicit ordering: Ordering[V])
|
||||
extends data.NoCopy {
|
||||
)(implicit ordering: Ordering[V]) {
|
||||
|
||||
def join(that: VersionRange[V]): VersionRange[V] =
|
||||
new VersionRange(
|
||||
min = this.min min that.min,
|
||||
max = this.max max that.max,
|
||||
)
|
||||
require(min <= max)
|
||||
|
||||
def join(version: V): VersionRange[V] = join(VersionRange(version))
|
||||
|
||||
private[lf] def map[W](f: V => W)(implicit ordering: Ordering[W]): VersionRange[W] =
|
||||
private[lf] def map[W](f: V => W)(implicit ordering: Ordering[W]) =
|
||||
VersionRange(f(min), f(max))
|
||||
|
||||
def contains(v: V): Boolean =
|
||||
min <= v && v <= max
|
||||
}
|
||||
|
||||
object VersionRange {
|
||||
|
||||
def apply[V](min: V, max: V)(implicit ordering: Ordering[V]): VersionRange[V] = {
|
||||
assert(min <= max)
|
||||
new VersionRange(min, max)
|
||||
}
|
||||
|
||||
def apply[V](version: V)(implicit ordering: Ordering[V]): VersionRange[V] =
|
||||
new VersionRange(version, version)
|
||||
|
||||
// We represent an empty Range by setting min and max to the max/min possible value
|
||||
// O(n)
|
||||
private[lf] def slowEmpty[V](allValues: Seq[V])(implicit ordering: Ordering[V]): VersionRange[V] =
|
||||
new VersionRange(allValues.max, allValues.min)
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import com.daml.lf.transaction.{
|
||||
SubmittedTransaction,
|
||||
Transaction => Tx,
|
||||
TransactionVersion => TxVersion,
|
||||
VersionedTransaction => VersionedTx,
|
||||
}
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.nameof.NameOf
|
||||
@ -85,28 +84,25 @@ private[lf] object PartialTransaction {
|
||||
*/
|
||||
final case class Context(
|
||||
info: ContextInfo,
|
||||
minChildVersion: TxVersion, // tracks the minimum version of any child within `children`
|
||||
children: BackStack[NodeId],
|
||||
// tracks the min and max version of any child within `children`
|
||||
childrenVersions: VersionRange[TxVersion],
|
||||
nextActionChildIdx: Int,
|
||||
) {
|
||||
// when we add a child node we must pass the minimum-version contained in that child
|
||||
def addActionChild(child: NodeId, childVersions: VersionRange[TxVersion]): Context =
|
||||
Context(info, children :+ child, childrenVersions join childVersions, nextActionChildIdx + 1)
|
||||
def addRollbackChild(
|
||||
child: NodeId,
|
||||
childVersions: VersionRange[TxVersion],
|
||||
nextActionChildIdx: Int,
|
||||
): Context =
|
||||
Context(info, children :+ child, childrenVersions join childVersions, nextActionChildIdx)
|
||||
def addActionChild(child: NodeId, version: TxVersion): Context = {
|
||||
Context(info, minChildVersion min version, children :+ child, nextActionChildIdx + 1)
|
||||
}
|
||||
def addRollbackChild(child: NodeId, version: TxVersion, nextActionChildIdx: Int): Context =
|
||||
Context(info, minChildVersion min version, children :+ child, nextActionChildIdx)
|
||||
// This function may be costly, it must be call at most once for each node.
|
||||
def nextActionChildSeed: crypto.Hash = info.actionChildSeed(nextActionChildIdx)
|
||||
}
|
||||
|
||||
object Context {
|
||||
|
||||
def apply(info: ContextInfo, nextActionChildIdx: Int = 0): Context =
|
||||
Context(info, BackStack.empty, TxVersion.NoVersions, nextActionChildIdx)
|
||||
def apply(info: ContextInfo): Context =
|
||||
// An empty context, with no children; minChildVersion is set to the max-int.
|
||||
Context(info, TxVersion.VDev, BackStack.empty, 0)
|
||||
|
||||
def apply(initialSeeds: InitialSeeding, committers: Set[Party]): Context =
|
||||
initialSeeds match {
|
||||
@ -376,7 +372,9 @@ private[speedy] case class PartialTransaction(
|
||||
val tx0 = Tx(nodes, roots)
|
||||
val (tx, seeds) = NormalizeRollbacks.normalizeTx(tx0)
|
||||
CompleteTransaction(
|
||||
SubmittedTransaction(VersionedTx(context.childrenVersions.max, tx.nodes, tx.roots)),
|
||||
SubmittedTransaction(
|
||||
TxVersion.asVersionedTransaction(tx)
|
||||
),
|
||||
locationInfo(),
|
||||
seeds.zip(actionNodeSeeds.toImmArray),
|
||||
)
|
||||
@ -432,7 +430,7 @@ private[speedy] case class PartialTransaction(
|
||||
val ptx = copy(
|
||||
actionNodeLocations = actionNodeLocations :+ optLocation,
|
||||
nextNodeIdx = nextNodeIdx + 1,
|
||||
context = context.addActionChild(nid, VersionRange(version)),
|
||||
context = context.addActionChild(nid, version),
|
||||
nodes = nodes.updated(nid, createNode),
|
||||
actionNodeSeeds = actionNodeSeeds :+ actionNodeSeed,
|
||||
localContracts = localContracts + cid,
|
||||
@ -609,14 +607,7 @@ private[speedy] case class PartialTransaction(
|
||||
case _ => keys
|
||||
},
|
||||
),
|
||||
).noteAuthFails(
|
||||
nid,
|
||||
CheckAuthorization.authorizeExercise(
|
||||
optLocation,
|
||||
makeExNode(ec, packageToTransactionVersion(templateId.packageId)),
|
||||
),
|
||||
auth,
|
||||
)
|
||||
).noteAuthFails(nid, CheckAuthorization.authorizeExercise(optLocation, makeExNode(ec)), auth)
|
||||
}
|
||||
|
||||
/** Close normally an exercise context.
|
||||
@ -626,14 +617,12 @@ private[speedy] case class PartialTransaction(
|
||||
context.info match {
|
||||
case ec: ExercisesContextInfo =>
|
||||
val result = normValue(ec.templateId, value)
|
||||
val exeVersions =
|
||||
context.childrenVersions join packageToTransactionVersion(ec.templateId.packageId)
|
||||
val exerciseNode =
|
||||
makeExNode(ec, exeVersions.max)
|
||||
.copy(children = context.children.toImmArray, exerciseResult = Some(result))
|
||||
makeExNode(ec).copy(children = context.children.toImmArray, exerciseResult = Some(result))
|
||||
val nodeId = ec.nodeId
|
||||
copy(
|
||||
context = ec.parent.addActionChild(nodeId, exeVersions),
|
||||
context =
|
||||
ec.parent.addActionChild(nodeId, exerciseNode.version min context.minChildVersion),
|
||||
nodes = nodes.updated(nodeId, exerciseNode),
|
||||
)
|
||||
case _ =>
|
||||
@ -649,16 +638,15 @@ private[speedy] case class PartialTransaction(
|
||||
def abortExercises: PartialTransaction =
|
||||
context.info match {
|
||||
case ec: ExercisesContextInfo =>
|
||||
val exeVersions =
|
||||
context.childrenVersions join packageToTransactionVersion(ec.templateId.packageId)
|
||||
val exerciseNode =
|
||||
makeExNode(ec, exeVersions.max).copy(children = context.children.toImmArray)
|
||||
val exerciseNode = makeExNode(ec).copy(children = context.children.toImmArray)
|
||||
val nodeId = ec.nodeId
|
||||
val actionNodeSeed = context.nextActionChildSeed
|
||||
copy(
|
||||
context = ec.parent.addActionChild(nodeId, exeVersions),
|
||||
context =
|
||||
ec.parent.addActionChild(nodeId, exerciseNode.version min context.minChildVersion),
|
||||
nodes = nodes.updated(nodeId, exerciseNode),
|
||||
actionNodeSeeds = actionNodeSeeds :+ actionNodeSeed,
|
||||
actionNodeSeeds =
|
||||
actionNodeSeeds :+ actionNodeSeed, //(NC) pushed by 'beginExercises'; why push again?
|
||||
)
|
||||
case _ =>
|
||||
InternalError.runtimeException(
|
||||
@ -667,7 +655,8 @@ private[speedy] case class PartialTransaction(
|
||||
)
|
||||
}
|
||||
|
||||
private[this] def makeExNode(ec: ExercisesContextInfo, version: TxVersion): Node.Exercise =
|
||||
private[this] def makeExNode(ec: ExercisesContextInfo): Node.Exercise = {
|
||||
val version = packageToTransactionVersion(ec.templateId.packageId)
|
||||
Node.Exercise(
|
||||
targetCoid = ec.targetId,
|
||||
templateId = ec.templateId,
|
||||
@ -685,6 +674,7 @@ private[speedy] case class PartialTransaction(
|
||||
byInterface = ec.byInterface,
|
||||
version = version,
|
||||
)
|
||||
}
|
||||
|
||||
/** Open a Try context.
|
||||
* Must be closed by `endTry`, `abortTry`, or `rollbackTry`.
|
||||
@ -694,7 +684,7 @@ private[speedy] case class PartialTransaction(
|
||||
val info = TryContextInfo(nid, context, activeState, authorizers = context.info.authorizers)
|
||||
copy(
|
||||
nextNodeIdx = nextNodeIdx + 1,
|
||||
context = Context(info, context.nextActionChildIdx),
|
||||
context = Context(info).copy(nextActionChildIdx = context.nextActionChildIdx),
|
||||
)
|
||||
}
|
||||
|
||||
@ -707,7 +697,6 @@ private[speedy] case class PartialTransaction(
|
||||
copy(
|
||||
context = info.parent.copy(
|
||||
children = info.parent.children :++ context.children.toImmArray,
|
||||
childrenVersions = context.childrenVersions,
|
||||
nextActionChildIdx = context.nextActionChildIdx,
|
||||
)
|
||||
)
|
||||
@ -730,10 +719,11 @@ private[speedy] case class PartialTransaction(
|
||||
*/
|
||||
def rollbackTry(ex: SValue.SAny): PartialTransaction = {
|
||||
// we must never create a rollback containing a node with a version pre-dating exceptions
|
||||
if (context.childrenVersions.min < TxVersion.minExceptions)
|
||||
if (context.minChildVersion < TxVersion.minExceptions) {
|
||||
throw SError.SErrorDamlException(
|
||||
interpretation.Error.UnhandledException(ex.ty, ex.value.toUnnormalizedValue)
|
||||
)
|
||||
}
|
||||
context.info match {
|
||||
case info: TryContextInfo =>
|
||||
// In the case of there being no children we could drop the entire rollback node.
|
||||
@ -741,7 +731,7 @@ private[speedy] case class PartialTransaction(
|
||||
val rollbackNode = Node.Rollback(context.children.toImmArray)
|
||||
copy(
|
||||
context = info.parent
|
||||
.addRollbackChild(info.nodeId, context.childrenVersions, context.nextActionChildIdx),
|
||||
.addRollbackChild(info.nodeId, context.minChildVersion, context.nextActionChildIdx),
|
||||
nodes = nodes.updated(info.nodeId, rollbackNode),
|
||||
).resetActiveState(info.beginState)
|
||||
case _ =>
|
||||
@ -796,7 +786,7 @@ private[speedy] case class PartialTransaction(
|
||||
copy(
|
||||
actionNodeLocations = actionNodeLocations :+ optLocation,
|
||||
nextNodeIdx = nextNodeIdx + 1,
|
||||
context = context.addActionChild(nid, VersionRange(version)),
|
||||
context = context.addActionChild(nid, version),
|
||||
nodes = nodes.updated(nid, node),
|
||||
)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
package com.daml.lf
|
||||
package speedy
|
||||
|
||||
import com.daml.lf.data._
|
||||
import com.daml.lf.data.ImmArray
|
||||
import com.daml.lf.ledger.Authorize
|
||||
import com.daml.lf.speedy.PartialTransaction._
|
||||
import com.daml.lf.speedy.SValue.{SValue => _, _}
|
||||
@ -17,23 +17,16 @@ import org.scalatest.wordspec.AnyWordSpec
|
||||
class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
|
||||
private[this] val transactionSeed = crypto.Hash.hashPrivateKey("PartialTransactionSpec")
|
||||
|
||||
private val templates: Map[TransactionVersion, Ref.Identifier] =
|
||||
TransactionVersion.All.view
|
||||
.map(v => v -> Ref.Identifier.assertFromString(s"pkg${v.protoValue}:Mod:Template"))
|
||||
.toMap
|
||||
private[this] val templateId = templates(TransactionVersion.StableVersions.max)
|
||||
private[this] val choiceId = Ref.Name.assertFromString("choice")
|
||||
private[this] val templateId = data.Ref.Identifier.assertFromString("pkg:Mod:Template")
|
||||
private[this] val choiceId = data.Ref.Name.assertFromString("choice")
|
||||
private[this] val cid = Value.ContractId.V1(crypto.Hash.hashPrivateKey("My contract"))
|
||||
private[this] val party = Ref.Party.assertFromString("Alice")
|
||||
private[this] val committers: Set[Ref.Party] = Set.empty
|
||||
|
||||
private[this] val pkg2TxVersion = templates.map { case (version, id) => id.packageId -> version }
|
||||
private[this] val party = data.Ref.Party.assertFromString("Alice")
|
||||
private[this] val committers: Set[data.Ref.Party] = Set.empty
|
||||
|
||||
private[this] val initialState = PartialTransaction.initial(
|
||||
pkg2TxVersion,
|
||||
_ => TransactionVersion.maxVersion,
|
||||
ContractKeyUniquenessMode.On,
|
||||
Time.Timestamp.Epoch,
|
||||
data.Time.Timestamp.Epoch,
|
||||
InitialSeeding.TransactionSeed(transactionSeed),
|
||||
committers,
|
||||
)
|
||||
@ -49,7 +42,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
|
||||
private[this] implicit class PartialTransactionExtra(val ptx: PartialTransaction) {
|
||||
|
||||
def insertCreate_(templateId: Ref.Identifier = templateId): PartialTransaction =
|
||||
def insertCreate_ : PartialTransaction =
|
||||
ptx
|
||||
.insertCreate(
|
||||
Authorize(Set(party)),
|
||||
@ -64,7 +57,7 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
)
|
||||
._2
|
||||
|
||||
def beginExercises_(templateId: Ref.Identifier = templateId): PartialTransaction =
|
||||
def beginExercises_ : PartialTransaction =
|
||||
ptx.beginExercises(
|
||||
Authorize(Set(party)),
|
||||
targetId = cid,
|
||||
@ -94,13 +87,13 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
private[this] val outputCids =
|
||||
contractIdsInOrder(
|
||||
initialState //
|
||||
.insertCreate_() // create the contract cid_0
|
||||
.beginExercises_() // open an exercise context
|
||||
.insertCreate_() // create the contract cid_1_0
|
||||
.insertCreate_() // create the contract cid_1_2
|
||||
.insertCreate_() // create the contract cid_1_3
|
||||
.insertCreate_ // create the contract cid_0
|
||||
.beginExercises_ // open an exercise context
|
||||
.insertCreate_ // create the contract cid_1_0
|
||||
.insertCreate_ // create the contract cid_1_2
|
||||
.insertCreate_ // create the contract cid_1_3
|
||||
.endExercises_ // close the exercise context normally
|
||||
.insertCreate_() // create the contract cid_2
|
||||
.insertCreate_ // create the contract cid_2
|
||||
)
|
||||
|
||||
val Seq(cid_0, cid_1_0, cid_1_1, cid_1_2, cid_2) = outputCids
|
||||
@ -109,29 +102,29 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
"be without effect when closed without exception" in {
|
||||
def run1 = contractIdsInOrder(
|
||||
initialState //
|
||||
.insertCreate_() // create the contract cid_0
|
||||
.beginExercises_() // open an exercise context
|
||||
.insertCreate_() // create the contract cid_1_0
|
||||
.insertCreate_ // create the contract cid_0
|
||||
.beginExercises_ // open an exercise context
|
||||
.insertCreate_ // create the contract cid_1_0
|
||||
.beginTry // open a try context
|
||||
.insertCreate_() // create the contract cid_1_1
|
||||
.insertCreate_ // create the contract cid_1_1
|
||||
.endTry // close the try context
|
||||
.insertCreate_() // create the contract cid_1_2
|
||||
.insertCreate_ // create the contract cid_1_2
|
||||
.endExercises_ // close the exercise context normally
|
||||
.insertCreate_() // create the contract cid_2
|
||||
.insertCreate_ // create the contract cid_2
|
||||
)
|
||||
|
||||
def run2 = contractIdsInOrder(
|
||||
// the double slashes below tricks scalafmt
|
||||
initialState //
|
||||
.insertCreate_() // create the contract cid_0
|
||||
.insertCreate_ // create the contract cid_0
|
||||
.beginTry // open a try context
|
||||
.beginExercises_() // open an exercise context
|
||||
.insertCreate_() // create the contract cid_1_0
|
||||
.insertCreate_() // create the contract cid_1_2
|
||||
.insertCreate_() // create the contract cid_1_3
|
||||
.beginExercises_ // open an exercise context
|
||||
.insertCreate_ // create the contract cid_1_0
|
||||
.insertCreate_ // create the contract cid_1_2
|
||||
.insertCreate_ // create the contract cid_1_3
|
||||
.endExercises_ // close the exercise context normally
|
||||
.endTry // close the try context
|
||||
.insertCreate_() // create the contract cid_2
|
||||
.insertCreate_ // create the contract cid_2
|
||||
)
|
||||
|
||||
run1 shouldBe outputCids
|
||||
@ -143,46 +136,46 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
def run1 = contractIdsInOrder(
|
||||
// the double slashes below tricks scalafmt
|
||||
initialState //
|
||||
.insertCreate_() // create the contract cid_0
|
||||
.insertCreate_ // create the contract cid_0
|
||||
.beginTry // open a first try context
|
||||
.beginExercises_() // open an exercise context
|
||||
.insertCreate_() // create the contract cid_1_0
|
||||
.insertCreate_() // create the contract cid_1_1
|
||||
.insertCreate_() // create the contract cid_1_2
|
||||
.beginExercises_ // open an exercise context
|
||||
.insertCreate_ // create the contract cid_1_0
|
||||
.insertCreate_ // create the contract cid_1_1
|
||||
.insertCreate_ // create the contract cid_1_2
|
||||
// an exception is thrown
|
||||
.abortExercises // close abruptly the exercise due to an uncaught exception
|
||||
.rollbackTry_ // the try context handles the exception
|
||||
.insertCreate_() // create the contract cid_2
|
||||
.insertCreate_ // create the contract cid_2
|
||||
)
|
||||
|
||||
def run2 = contractIdsInOrder(
|
||||
initialState //
|
||||
.insertCreate_() // create the contract cid_0
|
||||
.insertCreate_ // create the contract cid_0
|
||||
.beginTry // open a first try context
|
||||
.beginExercises_() // open an exercise context
|
||||
.insertCreate_() // create the contract cid_1_0
|
||||
.insertCreate_() // create the contract cid_1_1
|
||||
.beginExercises_ // open an exercise context
|
||||
.insertCreate_ // create the contract cid_1_0
|
||||
.insertCreate_ // create the contract cid_1_1
|
||||
.beginTry // open a second try context
|
||||
.insertCreate_() // create the contract cid_1_2
|
||||
.insertCreate_ // create the contract cid_1_2
|
||||
// an exception is thrown
|
||||
.abortTry // the second try context does not handle the exception
|
||||
.abortExercises // close abruptly the exercise due to an uncaught exception
|
||||
.rollbackTry_ // the first try context does handle the exception
|
||||
.insertCreate_() // create the contract cid_2
|
||||
.insertCreate_ // create the contract cid_2
|
||||
)
|
||||
|
||||
def run3 = contractIdsInOrder(
|
||||
// the double slashes below tricks scalafmt
|
||||
initialState //
|
||||
.insertCreate_() // create the contract cid_0
|
||||
.beginExercises_() // open an exercise context
|
||||
.insertCreate_() // create the contract cid_1_0
|
||||
.insertCreate_ // create the contract cid_0
|
||||
.beginExercises_ // open an exercise context
|
||||
.insertCreate_ // create the contract cid_1_0
|
||||
.beginTry // open a try context
|
||||
.insertCreate_() // create the contract cid_1_2
|
||||
.insertCreate_ // create the contract cid_1_2
|
||||
.rollbackTry_ // the try context does handle the exception
|
||||
.insertCreate_() // create the contract cid_1_3
|
||||
.insertCreate_ // create the contract cid_1_3
|
||||
.endExercises_ // close the exercise context normally
|
||||
.insertCreate_() // create the contract cid_2
|
||||
.insertCreate_ // create the contract cid_2
|
||||
)
|
||||
|
||||
run1 shouldBe Seq(cid_0, cid_1_0, cid_1_1, cid_1_2, cid_2)
|
||||
@ -191,59 +184,4 @@ class PartialTransactionSpec extends AnyWordSpec with Matchers with Inside {
|
||||
}
|
||||
}
|
||||
|
||||
"infers version as" should {
|
||||
|
||||
"be the max of the version of the children nodes" in {
|
||||
|
||||
import TransactionVersion._
|
||||
|
||||
def versionsInOrder(ptx: PartialTransaction) =
|
||||
inside(ptx.finish) { case CompleteTransaction(tx, _, _) =>
|
||||
tx.version -> tx.fold(Vector.empty[Option[TransactionVersion]])(_ :+ _._2.optVersion)
|
||||
}
|
||||
|
||||
versionsInOrder(
|
||||
initialState
|
||||
.insertCreate_(templates(V14))
|
||||
) shouldBe (V14 -> Seq(Some(V14)))
|
||||
|
||||
versionsInOrder(
|
||||
initialState
|
||||
.insertCreate_(templates(V12))
|
||||
.insertCreate_(templates(V13))
|
||||
) shouldBe (V13 -> Seq(Some(V12), Some(V13)))
|
||||
|
||||
versionsInOrder(
|
||||
initialState
|
||||
.beginExercises_(templates(V14))
|
||||
.insertCreate_(templates(V12))
|
||||
.insertCreate_(templates(V13))
|
||||
.endExercises_
|
||||
) shouldBe (V14 -> Seq(Some(V14), Some(V12), Some(V13)))
|
||||
|
||||
versionsInOrder(
|
||||
initialState
|
||||
.beginExercises_(templates(V11))
|
||||
.insertCreate_(templates(V12))
|
||||
.insertCreate_(templates(V13))
|
||||
.endExercises_
|
||||
) shouldBe (V13 -> Seq(Some(V13), Some(V12), Some(V13)))
|
||||
|
||||
versionsInOrder(
|
||||
initialState.beginTry
|
||||
.insertCreate_(templates(VDev))
|
||||
.insertCreate_(templates(V14))
|
||||
.endTry
|
||||
) shouldBe (VDev -> Seq(Some(VDev), Some(V14)))
|
||||
|
||||
versionsInOrder(
|
||||
initialState.beginTry
|
||||
.insertCreate_(templates(V14))
|
||||
.insertCreate_(templates(VDev))
|
||||
.rollbackTry_
|
||||
) shouldBe (VDev -> Seq(None, Some(V14), Some(VDev)))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ object LanguageVersion {
|
||||
|
||||
// All versions compatible with legacy contract ID scheme.
|
||||
val LegacyVersions: VersionRange[LanguageVersion] =
|
||||
VersionRange(StableVersions.min, max = v1_8)
|
||||
StableVersions.copy(max = v1_8)
|
||||
|
||||
// All the stable and preview versions
|
||||
// Equals `Stable` if no preview version is available
|
||||
@ -76,7 +76,7 @@ object LanguageVersion {
|
||||
|
||||
// All the versions
|
||||
val DevVersions: VersionRange[LanguageVersion] =
|
||||
VersionRange(StableVersions.min, v1_dev)
|
||||
StableVersions.copy(max = v1_dev)
|
||||
|
||||
val defaultV1: LanguageVersion = StableVersions.max
|
||||
|
||||
|
@ -26,8 +26,6 @@ object TransactionVersion {
|
||||
private[daml] implicit val Ordering: scala.Ordering[TransactionVersion] =
|
||||
scala.Ordering.by(_.index)
|
||||
|
||||
private[lf] val NoVersions: VersionRange[TransactionVersion] = VersionRange.slowEmpty(All)
|
||||
|
||||
private[this] val stringMapping = All.iterator.map(v => v.protoValue -> v).toMap
|
||||
|
||||
def fromString(vs: String): Either[String, TransactionVersion] =
|
||||
@ -69,15 +67,14 @@ object TransactionVersion {
|
||||
|
||||
private[lf] def asVersionedTransaction(
|
||||
tx: Transaction
|
||||
): VersionedTransaction = tx match {
|
||||
case Transaction(nodes, roots) =>
|
||||
val rootVersions = roots.iterator.map(nodeId =>
|
||||
nodes(nodeId) match {
|
||||
case action: Node.Action => action.version
|
||||
case _: Node.Rollback => minExceptions
|
||||
}
|
||||
)
|
||||
VersionedTransaction(rootVersions.max, nodes, roots)
|
||||
): VersionedTransaction = {
|
||||
import scala.Ordering.Implicits.infixOrderingOps
|
||||
|
||||
val txVersion = tx.nodes.valuesIterator.foldLeft(TransactionVersion.minVersion) {
|
||||
case (acc, action: Node.Action) => acc max action.version
|
||||
case (acc, _: Node.Rollback) => acc max minExceptions
|
||||
}
|
||||
VersionedTransaction(txVersion, tx.nodes, tx.roots)
|
||||
}
|
||||
|
||||
val StableVersions: VersionRange[TransactionVersion] =
|
||||
|
Loading…
Reference in New Issue
Block a user