mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
LF: retire ValueVersion (#8303)
use TransactionVersion instead. This is part of #7788 CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
403990dfd7
commit
649f740efd
@ -186,11 +186,6 @@ final class Conversions(
|
|||||||
sys.error(
|
sys.error(
|
||||||
s"Got unexpected DamlEWronglyTypedContract error in scenario service: $wtc. Note that in the scenario service this error should never surface since contract fetches are all type checked.",
|
s"Got unexpected DamlEWronglyTypedContract error in scenario service: $wtc. Note that in the scenario service this error should never surface since contract fetches are all type checked.",
|
||||||
)
|
)
|
||||||
|
|
||||||
case divv: SError.DamlEDisallowedInputValueVersion =>
|
|
||||||
sys.error(
|
|
||||||
s"Got unexpected DamlEDisallowedInputVersion error in scenario service: $divv. Note that in the scenario service this error should never surface since its accept all stable versions.",
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
builder.build
|
builder.build
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,13 @@ import scala.Ordering.Implicits.infixOrderingOps
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* [[VersionRange]] represents a range of versions of
|
* [[VersionRange]] represents a range of versions of
|
||||||
* [[com.daml.lf.language.LanguageVersion]],
|
* [[com.daml.lf.language.LanguageVersion]] or
|
||||||
* [[com.daml.lf.transaction.TransactionVersion]], or
|
* [[com.daml.lf.transaction.TransactionVersion]].
|
||||||
* [[com.daml.lf.value.ValueVersion]].
|
|
||||||
*
|
*
|
||||||
* @param min the minimal version included in the range.
|
* @param min the minimal version included in the range.
|
||||||
* @param max the maximal version included in the range.
|
* @param max the maximal version included in the range.
|
||||||
* @tparam V either [[com.daml.lf.language.LanguageVersion]],
|
* @tparam V either [[com.daml.lf.language.LanguageVersion]] or
|
||||||
* [[com.daml.lf.transaction.TransactionVersion]], or
|
* [[com.daml.lf.transaction.TransactionVersion]].
|
||||||
* [[com.daml.lf.value.ValueVersion]].
|
|
||||||
*/
|
*/
|
||||||
final case class VersionRange[V](
|
final case class VersionRange[V](
|
||||||
min: V,
|
min: V,
|
||||||
|
@ -52,6 +52,7 @@ da_scala_test_suite(
|
|||||||
"//daml-lf/language",
|
"//daml-lf/language",
|
||||||
"//daml-lf/parser",
|
"//daml-lf/parser",
|
||||||
"//daml-lf/transaction",
|
"//daml-lf/transaction",
|
||||||
|
"//daml-lf/transaction-test-lib",
|
||||||
"@maven//:com_google_protobuf_protobuf_java",
|
"@maven//:com_google_protobuf_protobuf_java",
|
||||||
"@maven//:com_storm_enroute_scalameter_core_2_12",
|
"@maven//:com_storm_enroute_scalameter_core_2_12",
|
||||||
"@maven//:org_scalatest_scalatest_2_12",
|
"@maven//:org_scalatest_scalatest_2_12",
|
||||||
|
@ -7,8 +7,9 @@ import com.daml.lf.data._
|
|||||||
import com.daml.lf.engine.Engine
|
import com.daml.lf.engine.Engine
|
||||||
import com.daml.lf.testing.parser.Implicits._
|
import com.daml.lf.testing.parser.Implicits._
|
||||||
import com.daml.lf.transaction.GlobalKey
|
import com.daml.lf.transaction.GlobalKey
|
||||||
|
import com.daml.lf.transaction.test.TransactionBuilder
|
||||||
import com.daml.lf.value.Value.ContractId
|
import com.daml.lf.value.Value.ContractId
|
||||||
import com.daml.lf.value.{Value, ValueVersion}
|
import com.daml.lf.value.Value
|
||||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
import org.scalatest.wordspec.AnyWordSpec
|
import org.scalatest.wordspec.AnyWordSpec
|
||||||
@ -98,7 +99,7 @@ class ContractDiscriminatorFreshnessCheckSpec
|
|||||||
private def contractInstance(party: Ref.Party, idx: Int, cids: List[ContractId]) =
|
private def contractInstance(party: Ref.Party, idx: Int, cids: List[ContractId]) =
|
||||||
Value.ContractInst(
|
Value.ContractInst(
|
||||||
tmplId,
|
tmplId,
|
||||||
ValueVersion.assertAsVersionedValue(contractRecord(party, idx, cids)),
|
TransactionBuilder.assertAsVersionedValue(contractRecord(party, idx, cids)),
|
||||||
"Agreement",
|
"Agreement",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import com.daml.lf.speedy.{InitialSeeding, SValue, svalue}
|
|||||||
import com.daml.lf.speedy.SValue._
|
import com.daml.lf.speedy.SValue._
|
||||||
import com.daml.lf.command._
|
import com.daml.lf.command._
|
||||||
import com.daml.lf.transaction.Node.GenNode
|
import com.daml.lf.transaction.Node.GenNode
|
||||||
import com.daml.lf.value.ValueVersion.assertAsVersionedValue
|
import com.daml.lf.transaction.test.TransactionBuilder.assertAsVersionedValue
|
||||||
import org.scalactic.Equality
|
import org.scalactic.Equality
|
||||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||||
import org.scalatest.EitherValues
|
import org.scalatest.EitherValues
|
||||||
|
@ -8,7 +8,6 @@ import org.typelevel.paiges.Doc._
|
|||||||
import com.daml.lf.ledger.EventId
|
import com.daml.lf.ledger.EventId
|
||||||
import com.daml.lf.value.Value
|
import com.daml.lf.value.Value
|
||||||
import Value.{NodeId => _, _}
|
import Value.{NodeId => _, _}
|
||||||
import com.daml.lf.VersionRange
|
|
||||||
import com.daml.lf.transaction.Node._
|
import com.daml.lf.transaction.Node._
|
||||||
import com.daml.lf.ledger._
|
import com.daml.lf.ledger._
|
||||||
import com.daml.lf.data.Ref._
|
import com.daml.lf.data.Ref._
|
||||||
@ -99,12 +98,6 @@ private[lf] object Pretty {
|
|||||||
prettyTypeConName(tid) /
|
prettyTypeConName(tid) /
|
||||||
text("The provided key is") & prettyValue(true)(key)
|
text("The provided key is") & prettyValue(true)(key)
|
||||||
|
|
||||||
case DamlEDisallowedInputValueVersion(VersionRange(expectedMin, expectedMax), actual) =>
|
|
||||||
text("Update failed due to disallowed value version") /
|
|
||||||
text("Expected value version between") & text(expectedMin.protoValue) &
|
|
||||||
text("and") & text(expectedMax.protoValue) & text("but got") &
|
|
||||||
text(actual.protoValue)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A minimal pretty-print of an update transaction node, without recursing into child nodes..
|
// A minimal pretty-print of an update transaction node, without recursing into child nodes..
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
package com.daml.lf.speedy
|
package com.daml.lf.speedy
|
||||||
|
|
||||||
import com.daml.lf.VersionRange
|
|
||||||
import com.daml.lf.data.Ref._
|
import com.daml.lf.data.Ref._
|
||||||
import com.daml.lf.data.Time
|
import com.daml.lf.data.Time
|
||||||
import com.daml.lf.ledger.EventId
|
import com.daml.lf.ledger.EventId
|
||||||
import com.daml.lf.ledger.FailedAuthorization
|
import com.daml.lf.ledger.FailedAuthorization
|
||||||
import com.daml.lf.transaction.{GlobalKey, NodeId, Transaction => Tx}
|
import com.daml.lf.transaction.{GlobalKey, NodeId, Transaction => Tx}
|
||||||
import com.daml.lf.value.{Value, ValueVersion}
|
import com.daml.lf.value.Value
|
||||||
import com.daml.lf.value.Value.ContractId
|
import com.daml.lf.value.Value.ContractId
|
||||||
import com.daml.lf.scenario.ScenarioLedger
|
import com.daml.lf.scenario.ScenarioLedger
|
||||||
|
|
||||||
@ -110,14 +109,6 @@ object SError {
|
|||||||
actual: TypeConName,
|
actual: TypeConName,
|
||||||
) extends SErrorDamlException
|
) extends SErrorDamlException
|
||||||
|
|
||||||
/** We tried to fetch data with disallowed value version --
|
|
||||||
* see <https://github.com/digital-asset/daml/issues/5164>
|
|
||||||
*/
|
|
||||||
final case class DamlEDisallowedInputValueVersion(
|
|
||||||
allowed: VersionRange[ValueVersion],
|
|
||||||
actual: ValueVersion,
|
|
||||||
) extends SErrorDamlException
|
|
||||||
|
|
||||||
/** There was an authorization failure during execution. */
|
/** There was an authorization failure during execution. */
|
||||||
final case class DamlEFailedAuthorization(
|
final case class DamlEFailedAuthorization(
|
||||||
nid: NodeId,
|
nid: NodeId,
|
||||||
|
@ -194,17 +194,12 @@ object Repl {
|
|||||||
|
|
||||||
private val seed = nextSeed()
|
private val seed = nextSeed()
|
||||||
|
|
||||||
val (inputValueVersion, outputTransactionVersions) =
|
val transactionVersions =
|
||||||
if (compilerConfig.allowedLanguageVersions.contains(LV.v1_dev))
|
if (compilerConfig.allowedLanguageVersions.contains(LV.v1_dev)) {
|
||||||
(
|
transaction.TransactionVersion.DevVersions
|
||||||
value.ValueVersion.DevOutputVersions,
|
} else {
|
||||||
transaction.TransactionVersion.DevVersions,
|
transaction.TransactionVersion.StableVersions
|
||||||
)
|
}
|
||||||
else
|
|
||||||
(
|
|
||||||
value.ValueVersion.StableOutputVersions,
|
|
||||||
transaction.TransactionVersion.StableVersions,
|
|
||||||
)
|
|
||||||
|
|
||||||
def run(expr: Expr): (
|
def run(expr: Expr): (
|
||||||
Speedy.Machine,
|
Speedy.Machine,
|
||||||
|
@ -5,12 +5,13 @@ package com.daml.lf
|
|||||||
package transaction
|
package transaction
|
||||||
package test
|
package test
|
||||||
|
|
||||||
import com.daml.lf.data.{BackStack, ImmArray, Ref}
|
import com.daml.lf.data.{BackStack, FrontStack, FrontStackCons, ImmArray, Ref}
|
||||||
import com.daml.lf.transaction.{Transaction => Tx}
|
import com.daml.lf.transaction.{Transaction => Tx}
|
||||||
import com.daml.lf.value.Value.{ContractId, ContractInst}
|
import com.daml.lf.value.Value.{ContractId, ContractInst, VersionedValue}
|
||||||
import com.daml.lf.value.{Value => LfValue}
|
import com.daml.lf.value.{Value => LfValue}
|
||||||
|
|
||||||
import scala.Ordering.Implicits.infixOrderingOps
|
import scala.Ordering.Implicits.infixOrderingOps
|
||||||
|
import scala.annotation.tailrec
|
||||||
import scala.collection.immutable.HashMap
|
import scala.collection.immutable.HashMap
|
||||||
|
|
||||||
final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion = _ =>
|
final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion = _ =>
|
||||||
@ -74,14 +75,11 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
|||||||
|
|
||||||
def newCid: ContractId = ContractId.V1(newHash())
|
def newCid: ContractId = ContractId.V1(newHash())
|
||||||
|
|
||||||
private[this] def pkgValVersion(pkgId: Ref.PackageId) =
|
|
||||||
TransactionVersion.assignValueVersion(pkgTxVersion(pkgId))
|
|
||||||
|
|
||||||
def versionContract(contract: ContractInst[Value]): ContractInst[TxValue] =
|
def versionContract(contract: ContractInst[Value]): ContractInst[TxValue] =
|
||||||
ContractInst.map1[Value, TxValue](versionValue(contract.template))(contract)
|
ContractInst.map1[Value, TxValue](transactionValue(contract.template))(contract)
|
||||||
|
|
||||||
private[this] def versionValue(templateId: Ref.TypeConName): Value => TxValue =
|
private[this] def transactionValue(templateId: Ref.TypeConName): Value => TxValue =
|
||||||
value.Value.VersionedValue(pkgValVersion(templateId.packageId), _)
|
value.Value.VersionedValue(pkgTxVersion(templateId.packageId), _)
|
||||||
|
|
||||||
def create(
|
def create(
|
||||||
id: String,
|
id: String,
|
||||||
@ -247,4 +245,73 @@ object TransactionBuilder {
|
|||||||
val EmptySubmitted: SubmittedTransaction = SubmittedTransaction(Empty)
|
val EmptySubmitted: SubmittedTransaction = SubmittedTransaction(Empty)
|
||||||
val EmptyCommitted: CommittedTransaction = CommittedTransaction(Empty)
|
val EmptyCommitted: CommittedTransaction = CommittedTransaction(Empty)
|
||||||
|
|
||||||
|
def assignVersion[Cid](
|
||||||
|
v0: Value,
|
||||||
|
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.StableVersions
|
||||||
|
): Either[String, TransactionVersion] = {
|
||||||
|
@tailrec
|
||||||
|
def go(
|
||||||
|
currentVersion: TransactionVersion,
|
||||||
|
values0: FrontStack[Value],
|
||||||
|
): Either[String, TransactionVersion] = {
|
||||||
|
import LfValue._
|
||||||
|
if (currentVersion >= supportedVersions.max) {
|
||||||
|
Right(currentVersion)
|
||||||
|
} else {
|
||||||
|
values0 match {
|
||||||
|
case FrontStack() => Right(currentVersion)
|
||||||
|
case FrontStackCons(value, values) =>
|
||||||
|
value match {
|
||||||
|
// for things supported since version 1, we do not need to check
|
||||||
|
case ValueRecord(_, fs) => go(currentVersion, fs.map(v => v._2) ++: values)
|
||||||
|
case ValueVariant(_, _, arg) => go(currentVersion, arg +: values)
|
||||||
|
case ValueList(vs) => go(currentVersion, vs.toImmArray ++: values)
|
||||||
|
case ValueContractId(_) | ValueInt64(_) | ValueText(_) | ValueTimestamp(_) |
|
||||||
|
ValueParty(_) | ValueBool(_) | ValueDate(_) | ValueUnit | ValueNumeric(_) =>
|
||||||
|
go(currentVersion, values)
|
||||||
|
case ValueOptional(x) =>
|
||||||
|
go(currentVersion, x.fold(values)(_ +: values))
|
||||||
|
case ValueTextMap(map) =>
|
||||||
|
go(currentVersion, map.values ++: values)
|
||||||
|
case ValueEnum(_, _) =>
|
||||||
|
go(currentVersion, values)
|
||||||
|
// for things added after version 10, we raise the minimum if present
|
||||||
|
case ValueGenMap(entries) =>
|
||||||
|
val newValues = entries.iterator.foldLeft(values) {
|
||||||
|
case (acc, (key, value)) => key +: value +: acc
|
||||||
|
}
|
||||||
|
go(currentVersion max TransactionVersion.minGenMap, newValues)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go(supportedVersions.min, FrontStack(v0)) match {
|
||||||
|
case Right(inferredVersion) if supportedVersions.max < inferredVersion =>
|
||||||
|
Left(s"inferred version $inferredVersion is not supported")
|
||||||
|
case res =>
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@throws[IllegalArgumentException]
|
||||||
|
def assertAssignVersion(
|
||||||
|
v0: Value,
|
||||||
|
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.DevVersions,
|
||||||
|
): TransactionVersion =
|
||||||
|
data.assertRight(assignVersion(v0, supportedVersions))
|
||||||
|
|
||||||
|
def asVersionedValue(
|
||||||
|
value: Value,
|
||||||
|
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.DevVersions,
|
||||||
|
): Either[String, TxValue] =
|
||||||
|
assignVersion(value, supportedVersions).map(VersionedValue(_, value))
|
||||||
|
|
||||||
|
@throws[IllegalArgumentException]
|
||||||
|
def assertAsVersionedValue(
|
||||||
|
value: Value,
|
||||||
|
supportedVersions: VersionRange[TransactionVersion] = TransactionVersion.DevVersions,
|
||||||
|
): TxValue =
|
||||||
|
data.assertRight(asVersionedValue(value, supportedVersions))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import com.daml.lf.transaction.{
|
|||||||
VersionedTransaction,
|
VersionedTransaction,
|
||||||
Transaction => Tx
|
Transaction => Tx
|
||||||
}
|
}
|
||||||
|
import com.daml.lf.transaction.test.TransactionBuilder
|
||||||
import com.daml.lf.value.Value.{NodeId => _, _}
|
import com.daml.lf.value.Value.{NodeId => _, _}
|
||||||
import org.scalacheck.{Arbitrary, Gen}
|
import org.scalacheck.{Arbitrary, Gen}
|
||||||
import Arbitrary.arbitrary
|
import Arbitrary.arbitrary
|
||||||
@ -249,8 +250,8 @@ object ValueGenerators {
|
|||||||
def versionedValueGen: Gen[VersionedValue[ContractId]] =
|
def versionedValueGen: Gen[VersionedValue[ContractId]] =
|
||||||
for {
|
for {
|
||||||
value <- valueGen
|
value <- valueGen
|
||||||
minVersion = ValueVersion.assertAssignVersion(value)
|
minVersion = TransactionBuilder.assertAssignVersion(value)
|
||||||
version <- valueVersionGen(minVersion)
|
version <- transactionVersionGen(minVersion)
|
||||||
} yield VersionedValue(version, value)
|
} yield VersionedValue(version, value)
|
||||||
|
|
||||||
private[lf] val genMaybeEmptyParties: Gen[Set[Party]] = Gen.listOf(party).map(_.toSet)
|
private[lf] val genMaybeEmptyParties: Gen[Set[Party]] = Gen.listOf(party).map(_.toSet)
|
||||||
@ -289,7 +290,7 @@ object ValueGenerators {
|
|||||||
*/
|
*/
|
||||||
val malformedCreateNodeGen: Gen[NodeCreate[Value.ContractId]] = {
|
val malformedCreateNodeGen: Gen[NodeCreate[Value.ContractId]] = {
|
||||||
for {
|
for {
|
||||||
version <- transactionVersionGen
|
version <- transactionVersionGen()
|
||||||
coid <- coidGen
|
coid <- coidGen
|
||||||
coinst <- contractInstanceGen
|
coinst <- contractInstanceGen
|
||||||
signatories <- genNonEmptyParties
|
signatories <- genNonEmptyParties
|
||||||
@ -300,7 +301,7 @@ object ValueGenerators {
|
|||||||
|
|
||||||
val fetchNodeGen: Gen[NodeFetch[ContractId]] = {
|
val fetchNodeGen: Gen[NodeFetch[ContractId]] = {
|
||||||
for {
|
for {
|
||||||
version <- transactionVersionGen
|
version <- transactionVersionGen()
|
||||||
coid <- coidGen
|
coid <- coidGen
|
||||||
templateId <- idGen
|
templateId <- idGen
|
||||||
actingParties <- genNonEmptyParties
|
actingParties <- genNonEmptyParties
|
||||||
@ -324,7 +325,7 @@ object ValueGenerators {
|
|||||||
/** Makes exercise nodes with some random child IDs. */
|
/** Makes exercise nodes with some random child IDs. */
|
||||||
val danglingRefExerciseNodeGen: Gen[NodeExercises[NodeId, Value.ContractId]] = {
|
val danglingRefExerciseNodeGen: Gen[NodeExercises[NodeId, Value.ContractId]] = {
|
||||||
for {
|
for {
|
||||||
version <- transactionVersionGen
|
version <- transactionVersionGen()
|
||||||
targetCoid <- coidGen
|
targetCoid <- coidGen
|
||||||
templateId <- idGen
|
templateId <- idGen
|
||||||
choiceId <- nameGen
|
choiceId <- nameGen
|
||||||
@ -465,8 +466,8 @@ object ValueGenerators {
|
|||||||
def noDanglingRefGenVersionedTransaction: Gen[VersionedTransaction[NodeId, ContractId]] = {
|
def noDanglingRefGenVersionedTransaction: Gen[VersionedTransaction[NodeId, ContractId]] = {
|
||||||
for {
|
for {
|
||||||
tx <- noDanglingRefGenTransaction
|
tx <- noDanglingRefGenTransaction
|
||||||
txVer <- transactionVersionGen
|
txVer <- transactionVersionGen()
|
||||||
nodeVersionGen = transactionVersionGen.filterNot(_ < txVer)
|
nodeVersionGen = transactionVersionGen().filterNot(_ < txVer)
|
||||||
nodes <- tx.fold(Gen.const(HashMap.empty[NodeId, GenNode[NodeId, ContractId]])) {
|
nodes <- tx.fold(Gen.const(HashMap.empty[NodeId, GenNode[NodeId, ContractId]])) {
|
||||||
case (acc, (nodeId, node)) =>
|
case (acc, (nodeId, node)) =>
|
||||||
for {
|
for {
|
||||||
@ -500,14 +501,10 @@ object ValueGenerators {
|
|||||||
Gen.frequency((1, Gen.const("")), (10, g))
|
Gen.frequency((1, Gen.const("")), (10, g))
|
||||||
}
|
}
|
||||||
|
|
||||||
def valueVersionGen(minVersion: ValueVersion = ValueVersion.minVersion): Gen[ValueVersion] =
|
def transactionVersionGen(
|
||||||
Gen.oneOf(ValueVersion.acceptedVersions.filterNot(_ < minVersion).toSeq)
|
minVersion: TransactionVersion = TransactionVersion.minVersion,
|
||||||
|
): Gen[TransactionVersion] =
|
||||||
def unsupportedValueVersionGen: Gen[ValueVersion] =
|
Gen.oneOf(TransactionVersion.All.filterNot(_ < minVersion))
|
||||||
stringVersionGen.map(ValueVersion(_)).filterNot(ValueVersion.acceptedVersions.contains)
|
|
||||||
|
|
||||||
def transactionVersionGen: Gen[TransactionVersion] =
|
|
||||||
Gen.oneOf(TransactionVersion.Values)
|
|
||||||
|
|
||||||
object Implicits {
|
object Implicits {
|
||||||
implicit val vdateArb: Arbitrary[Time.Date] = Arbitrary(dateGen)
|
implicit val vdateArb: Arbitrary[Time.Date] = Arbitrary(dateGen)
|
||||||
|
@ -49,7 +49,7 @@ object Node {
|
|||||||
private[lf] def updateVersion(version: TransactionVersion): GenNode[Nid, Cid]
|
private[lf] def updateVersion(version: TransactionVersion): GenNode[Nid, Cid]
|
||||||
|
|
||||||
protected def versionValue[Cid2 >: Cid](v: Value[Cid2]): VersionedValue[Cid2] =
|
protected def versionValue[Cid2 >: Cid](v: Value[Cid2]): VersionedValue[Cid2] =
|
||||||
VersionedValue(TransactionVersion.assignValueVersion(version), v)
|
VersionedValue(version, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
object GenNode extends CidContainer2[GenNode] {
|
object GenNode extends CidContainer2[GenNode] {
|
||||||
|
@ -63,7 +63,7 @@ object TransactionCoder {
|
|||||||
cidEncoder: ValueCoder.EncodeCid[Cid],
|
cidEncoder: ValueCoder.EncodeCid[Cid],
|
||||||
value: VersionedValue[Cid],
|
value: VersionedValue[Cid],
|
||||||
): Either[EncodeError, ValueOuterClass.VersionedValue] =
|
): Either[EncodeError, ValueOuterClass.VersionedValue] =
|
||||||
ValueCoder.encodeVersionedValueWithCustomVersion(cidEncoder, value)
|
ValueCoder.encodeVersionedValue(cidEncoder, value)
|
||||||
|
|
||||||
def decodeValue[Cid](
|
def decodeValue[Cid](
|
||||||
cidDecoder: ValueCoder.DecodeCid[Cid],
|
cidDecoder: ValueCoder.DecodeCid[Cid],
|
||||||
|
@ -6,7 +6,7 @@ package transaction
|
|||||||
|
|
||||||
import com.daml.lf.data.ImmArray
|
import com.daml.lf.data.ImmArray
|
||||||
import com.daml.lf.language.LanguageVersion
|
import com.daml.lf.language.LanguageVersion
|
||||||
import com.daml.lf.value.{Value, ValueVersion}
|
import com.daml.lf.value.Value
|
||||||
|
|
||||||
import scala.collection.immutable.HashMap
|
import scala.collection.immutable.HashMap
|
||||||
|
|
||||||
@ -22,21 +22,28 @@ object TransactionVersion {
|
|||||||
case object V10 extends TransactionVersion("10", 10)
|
case object V10 extends TransactionVersion("10", 10)
|
||||||
case object VDev extends TransactionVersion("dev", Int.MaxValue)
|
case object VDev extends TransactionVersion("dev", Int.MaxValue)
|
||||||
|
|
||||||
val Values = List(V10, VDev)
|
val All = List(V10, VDev)
|
||||||
|
|
||||||
private[lf] implicit val Ordering: scala.Ordering[TransactionVersion] = scala.Ordering.by(_.index)
|
private[lf] implicit val Ordering: scala.Ordering[TransactionVersion] = scala.Ordering.by(_.index)
|
||||||
|
|
||||||
private[this] val stringMapping = Values.iterator.map(v => v.protoValue -> v).toMap
|
private[this] val stringMapping = All.iterator.map(v => v.protoValue -> v).toMap
|
||||||
|
|
||||||
def fromString(vs: String): Either[String, TransactionVersion] =
|
def fromString(vs: String): Either[String, TransactionVersion] =
|
||||||
stringMapping.get(vs).toRight(s"Unsupported transaction version $vs")
|
stringMapping.get(vs) match {
|
||||||
|
case Some(value) => Right(value)
|
||||||
|
case None =>
|
||||||
|
Left(s"Unsupported transaction version '$vs'")
|
||||||
|
}
|
||||||
|
|
||||||
def assertFromString(vs: String): TransactionVersion =
|
def assertFromString(vs: String): TransactionVersion =
|
||||||
data.assertRight(fromString(vs))
|
data.assertRight(fromString(vs))
|
||||||
|
|
||||||
val minVersion = Values.min
|
val minVersion: TransactionVersion = All.min
|
||||||
private[transaction] val minChoiceObservers = VDev
|
def maxVersion: TransactionVersion = VDev
|
||||||
private[transaction] val minNodeVersion = VDev
|
|
||||||
|
private[lf] val minGenMap = VDev
|
||||||
|
private[lf] val minChoiceObservers = VDev
|
||||||
|
private[lf] val minNodeVersion = VDev
|
||||||
|
|
||||||
private[lf] val assignNodeVersion: LanguageVersion => TransactionVersion = {
|
private[lf] val assignNodeVersion: LanguageVersion => TransactionVersion = {
|
||||||
import LanguageVersion._
|
import LanguageVersion._
|
||||||
@ -48,13 +55,6 @@ object TransactionVersion {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private[lf] val assignValueVersion: TransactionVersion => ValueVersion = {
|
|
||||||
Map(
|
|
||||||
V10 -> ValueVersion("6"),
|
|
||||||
VDev -> ValueVersion("dev"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private[lf] def asVersionedTransaction(
|
private[lf] def asVersionedTransaction(
|
||||||
roots: ImmArray[NodeId],
|
roots: ImmArray[NodeId],
|
||||||
nodes: HashMap[NodeId, Node.GenNode[NodeId, Value.ContractId]],
|
nodes: HashMap[NodeId, Node.GenNode[NodeId, Value.ContractId]],
|
||||||
|
@ -7,6 +7,7 @@ package value
|
|||||||
import com.daml.lf.crypto.Hash
|
import com.daml.lf.crypto.Hash
|
||||||
import com.daml.lf.data.Ref.{Identifier, Name}
|
import com.daml.lf.data.Ref.{Identifier, Name}
|
||||||
import com.daml.lf.data._
|
import com.daml.lf.data._
|
||||||
|
import com.daml.lf.transaction.TransactionVersion
|
||||||
import data.ScalazEqual._
|
import data.ScalazEqual._
|
||||||
|
|
||||||
import scala.annotation.tailrec
|
import scala.annotation.tailrec
|
||||||
@ -202,7 +203,7 @@ object Value extends CidContainer1[Value] {
|
|||||||
*/
|
*/
|
||||||
val MAXIMUM_NESTING: Int = 100
|
val MAXIMUM_NESTING: Int = 100
|
||||||
|
|
||||||
final case class VersionedValue[+Cid](version: ValueVersion, value: Value[Cid])
|
final case class VersionedValue[+Cid](version: TransactionVersion, value: Value[Cid])
|
||||||
extends CidContainer[VersionedValue[Cid]] {
|
extends CidContainer[VersionedValue[Cid]] {
|
||||||
|
|
||||||
override protected def self: this.type = this
|
override protected def self: this.type = this
|
||||||
|
@ -30,8 +30,6 @@ object ValueCoder {
|
|||||||
object DecodeError extends (String => DecodeError) {
|
object DecodeError extends (String => DecodeError) {
|
||||||
private[lf] def apply(version: TransactionVersion, isTooOldFor: String): DecodeError =
|
private[lf] def apply(version: TransactionVersion, isTooOldFor: String): DecodeError =
|
||||||
DecodeError(s"transaction version ${version.protoValue} is too old to support $isTooOldFor")
|
DecodeError(s"transaction version ${version.protoValue} is too old to support $isTooOldFor")
|
||||||
private[lf] def apply(version: ValueVersion, isTooOldFor: String): DecodeError =
|
|
||||||
DecodeError(s"value version ${version.protoValue} is too old to support $isTooOldFor")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,8 +41,6 @@ object ValueCoder {
|
|||||||
object EncodeError extends (String => EncodeError) {
|
object EncodeError extends (String => EncodeError) {
|
||||||
private[lf] def apply(version: TransactionVersion, isTooOldFor: String): EncodeError =
|
private[lf] def apply(version: TransactionVersion, isTooOldFor: String): EncodeError =
|
||||||
EncodeError(s"transaction version ${version.protoValue} is too old to support $isTooOldFor")
|
EncodeError(s"transaction version ${version.protoValue} is too old to support $isTooOldFor")
|
||||||
private[lf] def apply(version: ValueVersion, isTooOldFor: String): EncodeError =
|
|
||||||
EncodeError(s"value version ${version.protoValue} is too old to support $isTooOldFor")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class EncodeCid[-Cid] private[lf] {
|
abstract class EncodeCid[-Cid] private[lf] {
|
||||||
@ -129,20 +125,27 @@ object ValueCoder {
|
|||||||
|
|
||||||
} yield Identifier(pkgId, QualifiedName(module, name))
|
} yield Identifier(pkgId, QualifiedName(module, name))
|
||||||
|
|
||||||
private def decodeVersion(vs: String): Either[DecodeError, ValueVersion] =
|
// For backward compatibility reasons, V10 is encoded as "6" when used inside a
|
||||||
ValueVersion
|
// proto.VersionedValue
|
||||||
.isAcceptedVersion(vs)
|
private[this] def encodeValueVersion(version: TransactionVersion): String =
|
||||||
.fold[Either[DecodeError, ValueVersion]](Left(DecodeError(s"Unsupported value version $vs")))(
|
if (version == TransactionVersion.V10) {
|
||||||
v => Right(v),
|
"6"
|
||||||
)
|
} else {
|
||||||
|
version.protoValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def decodeValueVersion(vs: String): Either[DecodeError, TransactionVersion] =
|
||||||
|
vs match {
|
||||||
|
case "6" => Right(TransactionVersion.V10)
|
||||||
|
case "10" => Left(DecodeError("Unsupported value version 10"))
|
||||||
|
case _ => TransactionVersion.fromString(vs).left.map(DecodeError)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a serialized protobuf versioned value,
|
* Reads a serialized protobuf versioned value,
|
||||||
* checks if the value version is currently supported and
|
* checks if the value version is currently supported and
|
||||||
* converts the value to the type usable by engine/interpreter.
|
* converts the value to the type usable by engine/interpreter.
|
||||||
*
|
*
|
||||||
* Supported value versions configured in [[ValueVersions]].
|
|
||||||
*
|
|
||||||
* @param protoValue0 the value to be read
|
* @param protoValue0 the value to be read
|
||||||
* @param decodeCid a function to decode stringified contract ids
|
* @param decodeCid a function to decode stringified contract ids
|
||||||
* @tparam Cid ContractId type
|
* @tparam Cid ContractId type
|
||||||
@ -153,7 +156,7 @@ object ValueCoder {
|
|||||||
protoValue0: proto.VersionedValue,
|
protoValue0: proto.VersionedValue,
|
||||||
): Either[DecodeError, VersionedValue[Cid]] =
|
): Either[DecodeError, VersionedValue[Cid]] =
|
||||||
for {
|
for {
|
||||||
version <- decodeVersion(protoValue0.getVersion)
|
version <- decodeValueVersion(protoValue0.getVersion)
|
||||||
value <- decodeValue(decodeCid, version, protoValue0.getValue)
|
value <- decodeValue(decodeCid, version, protoValue0.getValue)
|
||||||
} yield VersionedValue(version, value)
|
} yield VersionedValue(version, value)
|
||||||
|
|
||||||
@ -163,46 +166,6 @@ object ValueCoder {
|
|||||||
): Either[DecodeError, Value[Cid]] =
|
): Either[DecodeError, Value[Cid]] =
|
||||||
decodeVersionedValue(decodeCid, protoValue0) map (_.value)
|
decodeVersionedValue(decodeCid, protoValue0) map (_.value)
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes [[Value]] to protobuf, library decides which [[ValueVersion]] to assign.
|
|
||||||
* See [[ValueVersion.assignVersion]].
|
|
||||||
*
|
|
||||||
* @param value value to be written
|
|
||||||
* @param encodeCid a function to stringify contractIds (it's better to be invertible)
|
|
||||||
* @tparam Cid ContractId type
|
|
||||||
* @return protocol buffer serialized values
|
|
||||||
*/
|
|
||||||
def encodeVersionedValue[Cid](
|
|
||||||
encodeCid: EncodeCid[Cid],
|
|
||||||
value: Value[Cid],
|
|
||||||
supportedVersions: VersionRange[ValueVersion],
|
|
||||||
): Either[EncodeError, proto.VersionedValue] =
|
|
||||||
ValueVersion
|
|
||||||
.assignVersion(value, supportedVersions)
|
|
||||||
.fold(
|
|
||||||
err => Left(EncodeError(err)),
|
|
||||||
version => encodeVersionedValueWithCustomVersion(encodeCid, VersionedValue(version, value)),
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes [[VersionedValue]] to protobuf, caller provides the [[ValueVersion]].
|
|
||||||
*
|
|
||||||
* @param versionedValue value to be written
|
|
||||||
* @param encodeCid a function to stringify contractIds (it's better to be invertible)
|
|
||||||
* @tparam Cid ContractId type
|
|
||||||
* @return protocol buffer serialized values
|
|
||||||
*/
|
|
||||||
def encodeVersionedValueWithCustomVersion[Cid](
|
|
||||||
encodeCid: EncodeCid[Cid],
|
|
||||||
versionedValue: VersionedValue[Cid],
|
|
||||||
): Either[EncodeError, proto.VersionedValue] =
|
|
||||||
for {
|
|
||||||
value <- encodeValue(encodeCid, versionedValue.version, versionedValue.value)
|
|
||||||
} yield {
|
|
||||||
val builder = proto.VersionedValue.newBuilder()
|
|
||||||
builder.setVersion(versionedValue.version.protoValue).setValue(value).build()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to read a serialized protobuf value
|
* Method to read a serialized protobuf value
|
||||||
* to engine/interpreter usable Value type
|
* to engine/interpreter usable Value type
|
||||||
@ -214,7 +177,7 @@ object ValueCoder {
|
|||||||
*/
|
*/
|
||||||
def decodeValue[Cid](
|
def decodeValue[Cid](
|
||||||
decodeCid: DecodeCid[Cid],
|
decodeCid: DecodeCid[Cid],
|
||||||
valueVersion: ValueVersion,
|
version: TransactionVersion,
|
||||||
protoValue0: proto.Value,
|
protoValue0: proto.Value,
|
||||||
): Either[DecodeError, Value[Cid]] = {
|
): Either[DecodeError, Value[Cid]] = {
|
||||||
case class Err(msg: String) extends Throwable(null, null, true, false)
|
case class Err(msg: String) extends Throwable(null, null, true, false)
|
||||||
@ -227,9 +190,9 @@ object ValueCoder {
|
|||||||
identity,
|
identity,
|
||||||
)
|
)
|
||||||
|
|
||||||
def assertSince(minVersion: ValueVersion, description: => String) =
|
def assertSince(minVersion: TransactionVersion, description: => String) =
|
||||||
if (valueVersion < minVersion)
|
if (version < minVersion)
|
||||||
throw Err(s"$description is not supported by value version $valueVersion")
|
throw Err(s"$description is not supported by value version $version")
|
||||||
|
|
||||||
def go(nesting: Int, protoValue: proto.Value): Value[Cid] = {
|
def go(nesting: Int, protoValue: proto.Value): Value[Cid] = {
|
||||||
if (nesting > MAXIMUM_NESTING) {
|
if (nesting > MAXIMUM_NESTING) {
|
||||||
@ -343,7 +306,7 @@ object ValueCoder {
|
|||||||
ValueTextMap(map)
|
ValueTextMap(map)
|
||||||
|
|
||||||
case proto.Value.SumCase.GEN_MAP =>
|
case proto.Value.SumCase.GEN_MAP =>
|
||||||
assertSince(ValueVersion.minGenMap, "Value.SumCase.MAP")
|
assertSince(TransactionVersion.minGenMap, "Value.SumCase.MAP")
|
||||||
val genMap = protoValue.getGenMap.getEntriesList.asScala.map(entry =>
|
val genMap = protoValue.getGenMap.getEntriesList.asScala.map(entry =>
|
||||||
go(newNesting, entry.getKey) -> go(newNesting, entry.getValue))
|
go(newNesting, entry.getKey) -> go(newNesting, entry.getValue))
|
||||||
ValueGenMap(ImmArray(genMap))
|
ValueGenMap(ImmArray(genMap))
|
||||||
@ -361,6 +324,32 @@ object ValueCoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes [[VersionedValue]] to protobuf.
|
||||||
|
*
|
||||||
|
* @param versionedValue value to be written
|
||||||
|
* @param encodeCid a function to stringify contractIds (it's better to be invertible)
|
||||||
|
* @tparam Cid ContractId type
|
||||||
|
* @return protocol buffer serialized values
|
||||||
|
*/
|
||||||
|
def encodeVersionedValue[Cid](
|
||||||
|
encodeCid: EncodeCid[Cid],
|
||||||
|
versionedValue: VersionedValue[Cid],
|
||||||
|
): Either[EncodeError, proto.VersionedValue] =
|
||||||
|
encodeVersionedValue(encodeCid, versionedValue.version, versionedValue.value)
|
||||||
|
|
||||||
|
def encodeVersionedValue[Cid](
|
||||||
|
encodeCid: EncodeCid[Cid],
|
||||||
|
version: TransactionVersion,
|
||||||
|
value: Value[Cid],
|
||||||
|
): Either[EncodeError, proto.VersionedValue] =
|
||||||
|
for {
|
||||||
|
protoValue <- encodeValue(encodeCid, version, value)
|
||||||
|
} yield {
|
||||||
|
val builder = proto.VersionedValue.newBuilder()
|
||||||
|
builder.setVersion(encodeValueVersion(version)).setValue(protoValue).build()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a Value to protobuf
|
* Serialize a Value to protobuf
|
||||||
*
|
*
|
||||||
@ -372,12 +361,12 @@ object ValueCoder {
|
|||||||
*/
|
*/
|
||||||
def encodeValue[Cid](
|
def encodeValue[Cid](
|
||||||
encodeCid: EncodeCid[Cid],
|
encodeCid: EncodeCid[Cid],
|
||||||
valueVersion: ValueVersion,
|
valueVersion: TransactionVersion,
|
||||||
v0: Value[Cid],
|
v0: Value[Cid],
|
||||||
): Either[EncodeError, proto.Value] = {
|
): Either[EncodeError, proto.Value] = {
|
||||||
case class Err(msg: String) extends Throwable(null, null, true, false)
|
case class Err(msg: String) extends Throwable(null, null, true, false)
|
||||||
|
|
||||||
def assertSince(minVersion: ValueVersion, description: => String) =
|
def assertSince(minVersion: TransactionVersion, description: => String) =
|
||||||
if (valueVersion < minVersion)
|
if (valueVersion < minVersion)
|
||||||
throw Err(s"$description is not supported by value version $valueVersion")
|
throw Err(s"$description is not supported by value version $valueVersion")
|
||||||
|
|
||||||
@ -469,7 +458,7 @@ object ValueCoder {
|
|||||||
builder.setMap(protoMap).build()
|
builder.setMap(protoMap).build()
|
||||||
|
|
||||||
case ValueGenMap(entries) =>
|
case ValueGenMap(entries) =>
|
||||||
assertSince(ValueVersion.minGenMap, "Value.SumCase.MAP")
|
assertSince(TransactionVersion.minGenMap, "Value.SumCase.MAP")
|
||||||
val protoMap = proto.GenMap.newBuilder()
|
val protoMap = proto.GenMap.newBuilder()
|
||||||
entries.foreach {
|
entries.foreach {
|
||||||
case (key, value) =>
|
case (key, value) =>
|
||||||
@ -494,18 +483,6 @@ object ValueCoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The codomain and domain of the below functions are subject to change
|
|
||||||
// without warning or type change; they are stable with respect to
|
|
||||||
// each other and nothing else. As such, they are unsafe for
|
|
||||||
// general usage
|
|
||||||
|
|
||||||
private[value] def valueToBytes[Cid](
|
|
||||||
encodeCid: EncodeCid[Cid],
|
|
||||||
v: Value[Cid],
|
|
||||||
supportedVersions: VersionRange[ValueVersion] = ValueVersion.DevOutputVersions,
|
|
||||||
): Either[EncodeError, Array[Byte]] =
|
|
||||||
encodeVersionedValue(encodeCid, v, supportedVersions).map(_.toByteArray)
|
|
||||||
|
|
||||||
private[value] def valueFromBytes[Cid](
|
private[value] def valueFromBytes[Cid](
|
||||||
decodeCid: DecodeCid[Cid],
|
decodeCid: DecodeCid[Cid],
|
||||||
bytes: Array[Byte],
|
bytes: Array[Byte],
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
package com.daml.lf
|
|
||||||
package value
|
|
||||||
|
|
||||||
import com.daml.lf.value.Value._
|
|
||||||
import com.daml.lf.data.{FrontStack, FrontStackCons, ImmArray}
|
|
||||||
import scalaz.NonEmptyList
|
|
||||||
|
|
||||||
import scala.Ordering.Implicits.infixOrderingOps
|
|
||||||
import scala.annotation.tailrec
|
|
||||||
|
|
||||||
final case class ValueVersion(protoValue: String)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Currently supported versions of the DAML-LF value specification.
|
|
||||||
*/
|
|
||||||
object ValueVersion
|
|
||||||
extends LfVersions(
|
|
||||||
versionsAscending = NonEmptyList(new ValueVersion("6"), new ValueVersion("dev")))(
|
|
||||||
_.protoValue,
|
|
||||||
) {
|
|
||||||
|
|
||||||
private[lf] implicit val Ordering: Ordering[ValueVersion] = mkOrdering
|
|
||||||
|
|
||||||
private[value] val minVersion = ValueVersion("6")
|
|
||||||
private[value] val minGenMap = ValueVersion("dev")
|
|
||||||
private[value] val minContractIdV1 = ValueVersion("dev")
|
|
||||||
|
|
||||||
// Older versions are deprecated https://github.com/digital-asset/daml/issues/5220
|
|
||||||
private[lf] val StableOutputVersions: VersionRange[ValueVersion] =
|
|
||||||
VersionRange(ValueVersion("6"), ValueVersion("6"))
|
|
||||||
|
|
||||||
private[lf] val DevOutputVersions: VersionRange[ValueVersion] =
|
|
||||||
StableOutputVersions.copy(max = acceptedVersions.last)
|
|
||||||
|
|
||||||
private[lf] def assignVersion[Cid](
|
|
||||||
v0: Value[Cid],
|
|
||||||
supportedVersions: VersionRange[ValueVersion] = StableOutputVersions,
|
|
||||||
): Either[String, ValueVersion] = {
|
|
||||||
@tailrec
|
|
||||||
def go(
|
|
||||||
currentVersion: ValueVersion,
|
|
||||||
values0: FrontStack[Value[Cid]],
|
|
||||||
): Either[String, ValueVersion] = {
|
|
||||||
if (currentVersion == maxVersion) {
|
|
||||||
Right(currentVersion)
|
|
||||||
} else {
|
|
||||||
values0 match {
|
|
||||||
case FrontStack() => Right(currentVersion)
|
|
||||||
case FrontStackCons(value, values) =>
|
|
||||||
value match {
|
|
||||||
// for things supported since version 1, we do not need to check
|
|
||||||
case ValueRecord(_, fs) => go(currentVersion, fs.map(v => v._2) ++: values)
|
|
||||||
case ValueVariant(_, _, arg) => go(currentVersion, arg +: values)
|
|
||||||
case ValueList(vs) => go(currentVersion, vs.toImmArray ++: values)
|
|
||||||
case ValueContractId(_) | ValueInt64(_) | ValueText(_) | ValueTimestamp(_) |
|
|
||||||
ValueParty(_) | ValueBool(_) | ValueDate(_) | ValueUnit =>
|
|
||||||
go(currentVersion, values)
|
|
||||||
case ValueNumeric(_) =>
|
|
||||||
go(currentVersion, values)
|
|
||||||
case ValueOptional(x) =>
|
|
||||||
go(currentVersion, ImmArray(x.toList) ++: values)
|
|
||||||
case ValueTextMap(map) =>
|
|
||||||
go(currentVersion, map.values ++: values)
|
|
||||||
// for things added after version 6, we raise the minimum if present
|
|
||||||
case ValueGenMap(entries) =>
|
|
||||||
val newValues = entries.iterator.foldLeft(values) {
|
|
||||||
case (acc, (key, value)) => key +: value +: acc
|
|
||||||
}
|
|
||||||
go(currentVersion max minGenMap, newValues)
|
|
||||||
case ValueEnum(_, _) =>
|
|
||||||
go(currentVersion, values)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
go(supportedVersions.min, FrontStack(v0)) match {
|
|
||||||
case Right(inferredVersion) if supportedVersions.max < inferredVersion =>
|
|
||||||
Left(s"inferred version $inferredVersion is not supported")
|
|
||||||
case res =>
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@throws[IllegalArgumentException]
|
|
||||||
private[lf] def assertAssignVersion[Cid](
|
|
||||||
v0: Value[Cid],
|
|
||||||
supportedVersions: VersionRange[ValueVersion] = DevOutputVersions,
|
|
||||||
): ValueVersion =
|
|
||||||
data.assertRight(assignVersion(v0, supportedVersions))
|
|
||||||
|
|
||||||
private[lf] def asVersionedValue[Cid](
|
|
||||||
value: Value[Cid],
|
|
||||||
supportedVersions: VersionRange[ValueVersion] = DevOutputVersions,
|
|
||||||
): Either[String, VersionedValue[Cid]] =
|
|
||||||
assignVersion(value, supportedVersions).map(VersionedValue(_, value))
|
|
||||||
|
|
||||||
@throws[IllegalArgumentException]
|
|
||||||
private[lf] def assertAsVersionedValue[Cid](
|
|
||||||
value: Value[Cid],
|
|
||||||
supportedVersions: VersionRange[ValueVersion] = DevOutputVersions,
|
|
||||||
): VersionedValue[Cid] =
|
|
||||||
data.assertRight(asVersionedValue(value, supportedVersions))
|
|
||||||
}
|
|
@ -48,7 +48,7 @@ class TransactionCoderSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
"do NodeCreate" in {
|
"do NodeCreate" in {
|
||||||
forAll(malformedCreateNodeGen, transactionVersionGen, transactionVersionGen) {
|
forAll(malformedCreateNodeGen, transactionVersionGen(), transactionVersionGen()) {
|
||||||
(createNode, version1, version2) =>
|
(createNode, version1, version2) =>
|
||||||
val (nodeVersion, txVersion) = inIncreasingOrder(version1, version2)
|
val (nodeVersion, txVersion) = inIncreasingOrder(version1, version2)
|
||||||
val versionedNode = createNode.updateVersion(nodeVersion)
|
val versionedNode = createNode.updateVersion(nodeVersion)
|
||||||
@ -76,7 +76,7 @@ class TransactionCoderSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
"do NodeFetch" in {
|
"do NodeFetch" in {
|
||||||
forAll(fetchNodeGen, transactionVersionGen, transactionVersionGen) {
|
forAll(fetchNodeGen, transactionVersionGen(), transactionVersionGen()) {
|
||||||
(fetchNode, version1, version2) =>
|
(fetchNode, version1, version2) =>
|
||||||
val (nodeVersion, txVersion) = inIncreasingOrder(version1, version2)
|
val (nodeVersion, txVersion) = inIncreasingOrder(version1, version2)
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ class TransactionCoderSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
"do NodeExercises" in {
|
"do NodeExercises" in {
|
||||||
forAll(danglingRefExerciseNodeGen, transactionVersionGen, transactionVersionGen) {
|
forAll(danglingRefExerciseNodeGen, transactionVersionGen(), transactionVersionGen()) {
|
||||||
(exerciseNode, version1, version2) =>
|
(exerciseNode, version1, version2) =>
|
||||||
val (nodeVersion, txVersion) = inIncreasingOrder(version1, version2)
|
val (nodeVersion, txVersion) = inIncreasingOrder(version1, version2)
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ class TransactionCoderSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
forAll(noDanglingRefGenTransaction, minSuccessful(50)) { tx =>
|
forAll(noDanglingRefGenTransaction, minSuccessful(50)) { tx =>
|
||||||
forAll(transactionVersionGen, transactionVersionGen, minSuccessful(20)) {
|
forAll(transactionVersionGen(), transactionVersionGen(), minSuccessful(20)) {
|
||||||
(txVer1, txVer2) =>
|
(txVer1, txVer2) =>
|
||||||
import scalaz.std.tuple._
|
import scalaz.std.tuple._
|
||||||
import scalaz.syntax.bifunctor._
|
import scalaz.syntax.bifunctor._
|
||||||
@ -242,7 +242,7 @@ class TransactionCoderSpec
|
|||||||
ValueCoder.CidDecoder,
|
ValueCoder.CidDecoder,
|
||||||
encodedTxWithBadTxVer,
|
encodedTxWithBadTxVer,
|
||||||
) shouldEqual Left(
|
) shouldEqual Left(
|
||||||
DecodeError(s"Unsupported transaction version $badTxVer"),
|
DecodeError(s"Unsupported transaction version '$badTxVer'"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +330,11 @@ class TransactionCoderSpec
|
|||||||
|
|
||||||
"fail if try to encode a node in a version newer than the transaction" in {
|
"fail if try to encode a node in a version newer than the transaction" in {
|
||||||
|
|
||||||
forAll(danglingRefGenNode, transactionVersionGen, transactionVersionGen, minSuccessful(10)) {
|
forAll(
|
||||||
|
danglingRefGenNode,
|
||||||
|
transactionVersionGen(),
|
||||||
|
transactionVersionGen(),
|
||||||
|
minSuccessful(10)) {
|
||||||
case ((nodeId, node), version1, version2) =>
|
case ((nodeId, node), version1, version2) =>
|
||||||
whenever(version1 != version2) {
|
whenever(version1 != version2) {
|
||||||
val (txVersion, nodeVersion) = inIncreasingOrder(version1, version2)
|
val (txVersion, nodeVersion) = inIncreasingOrder(version1, version2)
|
||||||
@ -386,8 +390,8 @@ class TransactionCoderSpec
|
|||||||
|
|
||||||
forAll(
|
forAll(
|
||||||
danglingRefGenNode,
|
danglingRefGenNode,
|
||||||
transactionVersionGen.filter(_ != V10),
|
transactionVersionGen().filter(_ != V10),
|
||||||
transactionVersionGen.filter(_ != V10),
|
transactionVersionGen().filter(_ != V10),
|
||||||
minSuccessful(10)) {
|
minSuccessful(10)) {
|
||||||
case ((nodeId, node), version1, version2) =>
|
case ((nodeId, node), version1, version2) =>
|
||||||
whenever(version1 != version2) {
|
whenever(version1 != version2) {
|
||||||
|
@ -158,7 +158,7 @@ class TransactionSpec extends AnyFreeSpec with Matchers with ScalaCheckDrivenPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
"fail if version is different" in {
|
"fail if version is different" in {
|
||||||
val versions = TransactionVersion.Values
|
val versions = TransactionVersion.All
|
||||||
def diffVersion(v: TransactionVersion) = {
|
def diffVersion(v: TransactionVersion) = {
|
||||||
val randomVersion = versions(Random.nextInt(versions.length - 1))
|
val randomVersion = versions(Random.nextInt(versions.length - 1))
|
||||||
if (randomVersion != v) randomVersion else versions.last
|
if (randomVersion != v) randomVersion else versions.last
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
package com.daml.lf
|
package com.daml.lf
|
||||||
package transaction
|
package transaction
|
||||||
|
|
||||||
import value.ValueVersion
|
|
||||||
import com.daml.lf.language.LanguageVersion
|
import com.daml.lf.language.LanguageVersion
|
||||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||||
import org.scalatest.matchers.should.Matchers
|
import org.scalatest.matchers.should.Matchers
|
||||||
@ -32,21 +31,4 @@ class TransactionVersionSpec extends AnyWordSpec with Matchers with TableDrivenP
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"TransactionVersion.assignValueVersion" should {
|
|
||||||
"be stable" in {
|
|
||||||
|
|
||||||
val testCases = Table(
|
|
||||||
"input" -> "output",
|
|
||||||
V10 -> ValueVersion("6"),
|
|
||||||
VDev -> ValueVersion("dev")
|
|
||||||
)
|
|
||||||
|
|
||||||
forEvery(testCases) { (input, expectedOutput) =>
|
|
||||||
TransactionVersion.assignValueVersion(input) shouldBe expectedOutput
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ package com.daml.lf.value
|
|||||||
import com.daml.lf.EitherAssertions
|
import com.daml.lf.EitherAssertions
|
||||||
import com.daml.lf.data.Ref.Party
|
import com.daml.lf.data.Ref.Party
|
||||||
import com.daml.lf.data._
|
import com.daml.lf.data._
|
||||||
|
import com.daml.lf.transaction.TransactionVersion
|
||||||
import com.daml.lf.value.Value._
|
import com.daml.lf.value.Value._
|
||||||
import com.daml.lf.value.ValueCoder.DecodeError
|
|
||||||
import com.daml.lf.value.{ValueOuterClass => proto}
|
import com.daml.lf.value.{ValueOuterClass => proto}
|
||||||
import org.scalacheck.Shrink
|
import org.scalacheck.Shrink
|
||||||
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
|
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
|
||||||
@ -25,13 +25,6 @@ class ValueCoderSpec
|
|||||||
|
|
||||||
implicit val noStringShrink: Shrink[String] = Shrink.shrinkAny[String]
|
implicit val noStringShrink: Shrink[String] = Shrink.shrinkAny[String]
|
||||||
|
|
||||||
private[this] val lastDecimalVersion = ValueVersion("5")
|
|
||||||
|
|
||||||
private[this] val firstNumericVersion = ValueVersion("6")
|
|
||||||
|
|
||||||
private[this] val defaultValueVersion = ValueVersion.acceptedVersions.lastOption getOrElse sys
|
|
||||||
.error("there are no allowed versions! impossible! but could it be?")
|
|
||||||
|
|
||||||
implicit override val generatorDrivenConfig: PropertyCheckConfiguration =
|
implicit override val generatorDrivenConfig: PropertyCheckConfiguration =
|
||||||
PropertyCheckConfiguration(minSuccessful = 1000)
|
PropertyCheckConfiguration(minSuccessful = 1000)
|
||||||
|
|
||||||
@ -39,38 +32,14 @@ class ValueCoderSpec
|
|||||||
"do Int" in {
|
"do Int" in {
|
||||||
forAll("Int64 (Long) invariant") { i: Long =>
|
forAll("Int64 (Long) invariant") { i: Long =>
|
||||||
val value = ValueInt64(i)
|
val value = ValueInt64(i)
|
||||||
testRoundTrip(value)
|
testRoundTrip(TransactionVersion.minVersion, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do Bool" in {
|
"do Bool" in {
|
||||||
forAll("Bool invariant") { b: Boolean =>
|
forAll("Bool invariant") { b: Boolean =>
|
||||||
val value = ValueBool(b)
|
val value = ValueBool(b)
|
||||||
testRoundTrip(value)
|
testRoundTrip(TransactionVersion.minVersion, value)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"do Decimal" in {
|
|
||||||
forAll("Decimal (BigDecimal) invariant") { d: BigDecimal =>
|
|
||||||
// we are filtering on decimals invariant under string conversion
|
|
||||||
whenever(Decimal.fromBigDecimal(d).isRight) {
|
|
||||||
val Right(dec) = Decimal.fromBigDecimal(d)
|
|
||||||
val value = ValueNumeric(dec)
|
|
||||||
val recoveredDecimal = ValueCoder.decodeValue[ContractId](
|
|
||||||
ValueCoder.CidDecoder,
|
|
||||||
lastDecimalVersion,
|
|
||||||
assertRight(
|
|
||||||
ValueCoder
|
|
||||||
.encodeValue[ContractId](ValueCoder.CidEncoder, lastDecimalVersion, value),
|
|
||||||
),
|
|
||||||
) match {
|
|
||||||
case Right(ValueNumeric(d)) => d
|
|
||||||
case x => fail(s"should have got a decimal back, got $x")
|
|
||||||
}
|
|
||||||
Numeric.toUnscaledString(value.value) shouldEqual Numeric.toUnscaledString(
|
|
||||||
recoveredDecimal,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +54,13 @@ class ValueCoderSpec
|
|||||||
val value = ValueNumeric(dec)
|
val value = ValueNumeric(dec)
|
||||||
val recoveredDecimal = ValueCoder.decodeValue[ContractId](
|
val recoveredDecimal = ValueCoder.decodeValue[ContractId](
|
||||||
ValueCoder.CidDecoder,
|
ValueCoder.CidDecoder,
|
||||||
firstNumericVersion,
|
TransactionVersion.minVersion,
|
||||||
assertRight(
|
assertRight(
|
||||||
ValueCoder
|
ValueCoder
|
||||||
.encodeValue[ContractId](ValueCoder.CidEncoder, firstNumericVersion, value),
|
.encodeValue[ContractId](
|
||||||
|
ValueCoder.CidEncoder,
|
||||||
|
TransactionVersion.minVersion,
|
||||||
|
value),
|
||||||
),
|
),
|
||||||
) match {
|
) match {
|
||||||
case Right(ValueNumeric(x)) => x
|
case Right(ValueNumeric(x)) => x
|
||||||
@ -104,98 +76,77 @@ class ValueCoderSpec
|
|||||||
"do Text" in {
|
"do Text" in {
|
||||||
forAll("Text (String) invariant") { t: String =>
|
forAll("Text (String) invariant") { t: String =>
|
||||||
val value = ValueText(t)
|
val value = ValueText(t)
|
||||||
testRoundTrip(value)
|
testRoundTrip(TransactionVersion.minVersion, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do Party" in {
|
"do Party" in {
|
||||||
forAll(party) { p: Party =>
|
forAll(party) { p: Party =>
|
||||||
val value = ValueParty(p)
|
val value = ValueParty(p)
|
||||||
testRoundTrip(value)
|
testRoundTrip(TransactionVersion.minVersion, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do TimeStamp" in {
|
"do TimeStamp" in {
|
||||||
forAll(timestampGen) { t: Time.Timestamp => // TODO: fails with Longs
|
forAll(timestampGen) { t: Time.Timestamp => // TODO: fails with Longs
|
||||||
testRoundTrip(ValueTimestamp(t))
|
testRoundTrip(TransactionVersion.minVersion, ValueTimestamp(t))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do Date" in {
|
"do Date" in {
|
||||||
forAll(dateGen) { d: Time.Date =>
|
forAll(dateGen) { d: Time.Date =>
|
||||||
testRoundTrip(ValueDate(d))
|
testRoundTrip(TransactionVersion.minVersion, ValueDate(d))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do ContractId" in {
|
"do ContractId" in {
|
||||||
forAll(coidValueGen) { v: Value[ContractId] =>
|
forAll(coidValueGen) { v: Value[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minVersion, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do ContractId V0 in any ValueVersion" in forAll(coidValueGen, valueVersionGen())(
|
"do ContractId V0 in any ValueVersion" in forAll(coidValueGen, transactionVersionGen())(
|
||||||
testRoundTripWithVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
"do ContractId in any ValueVersion" in forAll(
|
|
||||||
coidValueGen,
|
|
||||||
valueVersionGen(ValueVersion.minContractIdV1))(
|
|
||||||
testRoundTripWithVersion
|
testRoundTripWithVersion
|
||||||
)
|
)
|
||||||
|
|
||||||
"do lists" in {
|
"do lists" in {
|
||||||
forAll(valueListGen) { v: ValueList[ContractId] =>
|
forAll(valueListGen) { v: ValueList[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minVersion, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do optionals" in {
|
"do optionals" in {
|
||||||
forAll(valueOptionalGen) { v: ValueOptional[ContractId] =>
|
forAll(valueOptionalGen) { v: ValueOptional[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minVersion, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do maps" in {
|
"do maps" in {
|
||||||
forAll(valueMapGen) { v: ValueTextMap[ContractId] =>
|
forAll(valueMapGen) { v: ValueTextMap[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minVersion, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do genMaps" in {
|
"do genMaps" in {
|
||||||
forAll(valueGenMapGen) { v: ValueGenMap[ContractId] =>
|
forAll(valueGenMapGen) { v: ValueGenMap[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minGenMap, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do variant" in {
|
"do variant" in {
|
||||||
forAll(variantGen) { v: ValueVariant[ContractId] =>
|
forAll(variantGen) { v: ValueVariant[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minVersion, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do record" in {
|
"do record" in {
|
||||||
forAll(recordGen) { v: ValueRecord[ContractId] =>
|
forAll(recordGen) { v: ValueRecord[ContractId] =>
|
||||||
testRoundTrip(v)
|
testRoundTrip(TransactionVersion.minVersion, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do unit" in {
|
"do unit" in {
|
||||||
val recovered = ValueCoder.decodeValue(
|
testRoundTrip(TransactionVersion.minVersion, ValueUnit)
|
||||||
ValueCoder.CidDecoder,
|
|
||||||
defaultValueVersion,
|
|
||||||
assertRight(
|
|
||||||
ValueCoder.encodeValue[ContractId](ValueCoder.CidEncoder, defaultValueVersion, ValueUnit),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
val fromToBytes = ValueCoder.valueFromBytes(
|
|
||||||
ValueCoder.CidDecoder,
|
|
||||||
ValueCoder
|
|
||||||
.valueToBytes(ValueCoder.CidEncoder, ValueUnit)
|
|
||||||
.toOption
|
|
||||||
.get,
|
|
||||||
)
|
|
||||||
Right(ValueUnit) shouldEqual fromToBytes
|
|
||||||
recovered shouldEqual Right(ValueUnit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"do identifier" in {
|
"do identifier" in {
|
||||||
@ -204,81 +155,45 @@ class ValueCoderSpec
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
"do identifier with supported override version" in forAll(idGen, valueVersionGen()) { (i, _) =>
|
"do identifier with supported override version" in forAll(idGen, transactionVersionGen()) {
|
||||||
val ei = ValueCoder.encodeIdentifier(i)
|
(i, _) =>
|
||||||
ValueCoder.decodeIdentifier(ei) shouldEqual Right(i)
|
val ei = ValueCoder.encodeIdentifier(i)
|
||||||
|
ValueCoder.decodeIdentifier(ei) shouldEqual Right(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
"do versioned value with supported override version" in forAll(versionedValueGen) {
|
"do versioned value with supported override version" in forAll(versionedValueGen) {
|
||||||
case VersionedValue(version, value) => testRoundTripWithVersion(value, version)
|
case VersionedValue(version, value) => testRoundTripWithVersion(value, version)
|
||||||
}
|
}
|
||||||
|
|
||||||
"do versioned value with assigned version" in forAll(valueGen) { v: Value[ContractId] =>
|
|
||||||
testRoundTripWithVersion(v, ValueVersion.assertAssignVersion(v))
|
|
||||||
}
|
|
||||||
|
|
||||||
"versioned value should pass serialization if unsupported override version provided" in
|
|
||||||
forAll(valueGen, unsupportedValueVersionGen) {
|
|
||||||
(value: Value[ContractId], badVer: ValueVersion) =>
|
|
||||||
ValueVersion.acceptedVersions.contains(badVer) shouldBe false
|
|
||||||
|
|
||||||
val actual: proto.VersionedValue = assertRight(
|
|
||||||
ValueCoder
|
|
||||||
.encodeVersionedValueWithCustomVersion(
|
|
||||||
ValueCoder.CidEncoder,
|
|
||||||
VersionedValue(badVer, value),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
actual.getVersion shouldEqual badVer.protoValue
|
|
||||||
}
|
|
||||||
|
|
||||||
"versioned value should fail deserialization if version is not supported" in
|
|
||||||
forAll(valueGen, unsupportedValueVersionGen) {
|
|
||||||
(value: Value[ContractId], badVer: ValueVersion) =>
|
|
||||||
ValueVersion.acceptedVersions.contains(badVer) shouldBe false
|
|
||||||
|
|
||||||
val protoWithUnsupportedVersion: proto.VersionedValue =
|
|
||||||
assertRight(
|
|
||||||
ValueCoder.encodeVersionedValueWithCustomVersion(
|
|
||||||
ValueCoder.CidEncoder,
|
|
||||||
VersionedValue(badVer, value),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
protoWithUnsupportedVersion.getVersion shouldEqual badVer.protoValue
|
|
||||||
|
|
||||||
val actual: Either[DecodeError, VersionedValue[ContractId]] =
|
|
||||||
ValueCoder.decodeVersionedValue(ValueCoder.CidDecoder, protoWithUnsupportedVersion)
|
|
||||||
|
|
||||||
actual shouldEqual Left(DecodeError(s"Unsupported value version ${badVer.protoValue}"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def testRoundTrip(value: Value[ContractId]): Assertion = {
|
def testRoundTrip(version: TransactionVersion, value: Value[ContractId]): Assertion = {
|
||||||
val recovered = ValueCoder.decodeValue(
|
val recovered = ValueCoder.decodeValue(
|
||||||
ValueCoder.CidDecoder,
|
ValueCoder.CidDecoder,
|
||||||
defaultValueVersion,
|
version,
|
||||||
assertRight(
|
assertRight(ValueCoder.encodeValue[ContractId](ValueCoder.CidEncoder, version, value)),
|
||||||
ValueCoder.encodeValue[ContractId](ValueCoder.CidEncoder, defaultValueVersion, value)),
|
|
||||||
)
|
)
|
||||||
|
val bytes =
|
||||||
|
assertRight(
|
||||||
|
ValueCoder.encodeVersionedValue(
|
||||||
|
ValueCoder.CidEncoder,
|
||||||
|
VersionedValue(version, value),
|
||||||
|
)
|
||||||
|
).toByteArray
|
||||||
|
|
||||||
val fromToBytes = ValueCoder.valueFromBytes(
|
val fromToBytes = ValueCoder.valueFromBytes(
|
||||||
ValueCoder.CidDecoder,
|
ValueCoder.CidDecoder,
|
||||||
assertRight(
|
bytes,
|
||||||
ValueCoder
|
|
||||||
.valueToBytes[ContractId](ValueCoder.CidEncoder, value)),
|
|
||||||
)
|
)
|
||||||
Right(value) shouldEqual recovered
|
Right(value) shouldEqual recovered
|
||||||
Right(value) shouldEqual fromToBytes
|
Right(value) shouldEqual fromToBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
def testRoundTripWithVersion(value0: Value[ContractId], version: ValueVersion): Assertion = {
|
def testRoundTripWithVersion(
|
||||||
ValueVersion.acceptedVersions.contains(version) shouldBe true
|
value0: Value[ContractId],
|
||||||
|
version: TransactionVersion): Assertion = {
|
||||||
val encoded: proto.VersionedValue = assertRight(
|
val encoded: proto.VersionedValue = assertRight(
|
||||||
ValueCoder
|
ValueCoder
|
||||||
.encodeVersionedValueWithCustomVersion(
|
.encodeVersionedValue(ValueCoder.CidEncoder, VersionedValue(version, value0)),
|
||||||
ValueCoder.CidEncoder,
|
|
||||||
VersionedValue(version, value0)),
|
|
||||||
)
|
)
|
||||||
val decoded: VersionedValue[ContractId] = assertRight(
|
val decoded: VersionedValue[ContractId] = assertRight(
|
||||||
ValueCoder.decodeVersionedValue(ValueCoder.CidDecoder, encoded),
|
ValueCoder.decodeVersionedValue(ValueCoder.CidDecoder, encoded),
|
||||||
|
@ -7,6 +7,7 @@ package value
|
|||||||
import data.{Bytes, ImmArray, Ref}
|
import data.{Bytes, ImmArray, Ref}
|
||||||
import Value._
|
import Value._
|
||||||
import Ref.{Identifier, Name}
|
import Ref.{Identifier, Name}
|
||||||
|
import com.daml.lf.transaction.TransactionVersion
|
||||||
import test.ValueGenerators.{coidGen, idGen, nameGen}
|
import test.ValueGenerators.{coidGen, idGen, nameGen}
|
||||||
import test.TypedValueGenerators.{RNil, genAddend, ValueAddend => VA}
|
import test.TypedValueGenerators.{RNil, genAddend, ValueAddend => VA}
|
||||||
import com.daml.scalatest.Unnatural
|
import com.daml.scalatest.Unnatural
|
||||||
@ -57,10 +58,10 @@ class ValueSpec
|
|||||||
"does not bump version when" - {
|
"does not bump version when" - {
|
||||||
|
|
||||||
"ensureNoCid is used " in {
|
"ensureNoCid is used " in {
|
||||||
val value = VersionedValue[ContractId](ValueVersion.minVersion, ValueUnit)
|
val value = VersionedValue[ContractId](TransactionVersion.minVersion, ValueUnit)
|
||||||
val contract = ContractInst(tmplId, value, "agreed")
|
val contract = ContractInst(tmplId, value, "agreed")
|
||||||
value.ensureNoCid.map(_.version) shouldBe Right(ValueVersion.minVersion)
|
value.ensureNoCid.map(_.version) shouldBe Right(TransactionVersion.minVersion)
|
||||||
contract.ensureNoCid.map(_.arg.version) shouldBe Right(ValueVersion.minVersion)
|
contract.ensureNoCid.map(_.arg.version) shouldBe Right(TransactionVersion.minVersion)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ private[migration] final class V38__Update_value_versions extends BaseJavaMigrat
|
|||||||
|
|
||||||
private[this] val batchSize = 1000
|
private[this] val batchSize = 1000
|
||||||
|
|
||||||
private[this] val stableValueVersion = lf.value.ValueVersion("6")
|
private[this] val stableValueVersion = lf.transaction.TransactionVersion.V10
|
||||||
private[this] val stableValueVersionAsInt = stableValueVersion.protoValue.toInt
|
private[this] val stableValueVersionAsInt = stableValueVersion.protoValue.toInt
|
||||||
|
|
||||||
private[this] val SELECT_EVENTS =
|
private[this] val SELECT_EVENTS =
|
||||||
|
@ -17,7 +17,7 @@ private[migration] object ValueSerializer {
|
|||||||
|
|
||||||
private[translation] object DeprecatedValueVersionsError {
|
private[translation] object DeprecatedValueVersionsError {
|
||||||
val DeprecatedValueVersions = Set("1", "2", "3", "4", "5")
|
val DeprecatedValueVersions = Set("1", "2", "3", "4", "5")
|
||||||
val UnsupportedErrorMessage = """Unsupported value version (\d)""".r
|
val UnsupportedErrorMessage = """Unsupported transaction version '(\d)'""".r
|
||||||
|
|
||||||
def unapply[X](arg: Either[ValueCoder.DecodeError, X]): Option[String] =
|
def unapply[X](arg: Either[ValueCoder.DecodeError, X]): Option[String] =
|
||||||
arg match {
|
arg match {
|
||||||
|
@ -16,7 +16,7 @@ private[platform] object ValueSerializer {
|
|||||||
errorContext: => String,
|
errorContext: => String,
|
||||||
): Array[Byte] =
|
): Array[Byte] =
|
||||||
ValueCoder
|
ValueCoder
|
||||||
.encodeVersionedValueWithCustomVersion(ValueCoder.CidEncoder, value)
|
.encodeVersionedValue(ValueCoder.CidEncoder, value)
|
||||||
.fold(error => sys.error(s"$errorContext (${error.errorMessage})"), _.toByteArray)
|
.fold(error => sys.error(s"$errorContext (${error.errorMessage})"), _.toByteArray)
|
||||||
|
|
||||||
private def deserializeValueHelper(
|
private def deserializeValueHelper(
|
||||||
|
@ -11,7 +11,6 @@ import com.daml.lf.transaction.Node.{KeyWithMaintainers, NodeCreate, NodeExercis
|
|||||||
import com.daml.lf.transaction.TransactionVersion
|
import com.daml.lf.transaction.TransactionVersion
|
||||||
import com.daml.lf.transaction.test.TransactionBuilder
|
import com.daml.lf.transaction.test.TransactionBuilder
|
||||||
import com.daml.lf.value.Value.{ContractInst, ValueParty, VersionedValue}
|
import com.daml.lf.value.Value.{ContractInst, ValueParty, VersionedValue}
|
||||||
import com.daml.lf.value.ValueVersion
|
|
||||||
import com.daml.platform.store.entries.LedgerEntry
|
import com.daml.platform.store.entries.LedgerEntry
|
||||||
import org.scalatest.{Inside, LoneElement}
|
import org.scalatest.{Inside, LoneElement}
|
||||||
import org.scalatest.flatspec.AsyncFlatSpec
|
import org.scalatest.flatspec.AsyncFlatSpec
|
||||||
@ -138,7 +137,7 @@ private[dao] trait JdbcLedgerDaoDivulgenceSpec extends LoneElement with Inside {
|
|||||||
template = someContractInstance.template,
|
template = someContractInstance.template,
|
||||||
agreementText = someContractInstance.agreementText,
|
agreementText = someContractInstance.agreementText,
|
||||||
arg = VersionedValue(
|
arg = VersionedValue(
|
||||||
version = ValueVersion("6"),
|
version = TransactionVersion.V10,
|
||||||
value = someContractInstance.arg
|
value = someContractInstance.arg
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -10,11 +10,11 @@ import com.daml.lf.transaction.TransactionCoder.{
|
|||||||
encodeTransaction
|
encodeTransaction
|
||||||
}
|
}
|
||||||
import com.daml.lf.transaction.TransactionOuterClass.Transaction
|
import com.daml.lf.transaction.TransactionOuterClass.Transaction
|
||||||
import com.daml.lf.transaction.{NodeId, VersionedTransaction}
|
import com.daml.lf.transaction.{NodeId, TransactionVersion, VersionedTransaction}
|
||||||
import com.daml.lf.value.Value.ContractId
|
import com.daml.lf.value.Value.ContractId
|
||||||
import com.daml.lf.value.ValueCoder._
|
import com.daml.lf.value.ValueCoder._
|
||||||
import com.daml.lf.value.ValueOuterClass.VersionedValue
|
import com.daml.lf.value.ValueOuterClass.VersionedValue
|
||||||
import com.daml.lf.value.{Value, ValueVersion}
|
import com.daml.lf.value.Value
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
|
|
||||||
package object benchmark {
|
package object benchmark {
|
||||||
@ -32,7 +32,7 @@ package object benchmark {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the output of a successful call to
|
* This is the output of a successful call to
|
||||||
* [[com.daml.lf.value.ValueCoder.encodeValue]].
|
* [[com.daml.lf.value.ValueCoder.encodeVersionedValue]].
|
||||||
* It's the in-memory representation of the Protobuf message that
|
* It's the in-memory representation of the Protobuf message that
|
||||||
* describes a value, not its serialized form.
|
* describes a value, not its serialized form.
|
||||||
*/
|
*/
|
||||||
@ -89,6 +89,6 @@ package object benchmark {
|
|||||||
encodeTransaction(NidEncoder, CidEncoder, transaction)
|
encodeTransaction(NidEncoder, CidEncoder, transaction)
|
||||||
|
|
||||||
private def encode(value: DecodedValue): EncodeResult[EncodedValue] =
|
private def encode(value: DecodedValue): EncodeResult[EncodedValue] =
|
||||||
encodeVersionedValue(CidEncoder, value, ValueVersion.DevOutputVersions)
|
encodeVersionedValue(CidEncoder, TransactionVersion.VDev, value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user