mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 16:57:40 +03:00
LF: control of input value version in the engine (#6828)
CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
a890618782
commit
66ae38da6c
@ -20,7 +20,6 @@ import com.daml.lf.speedy.Speedy
|
|||||||
import com.daml.lf.speedy.SExpr
|
import com.daml.lf.speedy.SExpr
|
||||||
import com.daml.lf.speedy.SValue
|
import com.daml.lf.speedy.SValue
|
||||||
import com.daml.lf.speedy.SExpr.{LfDefRef, SDefinitionRef}
|
import com.daml.lf.speedy.SExpr.{LfDefRef, SDefinitionRef}
|
||||||
import com.daml.lf.transaction.TransactionVersions
|
|
||||||
import com.daml.lf.validation.Validation
|
import com.daml.lf.validation.Validation
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
|
|
||||||
@ -164,7 +163,8 @@ class Context(val contextId: Context.ContextId, languageVersion: LanguageVersion
|
|||||||
compiledPackages,
|
compiledPackages,
|
||||||
txSeeding,
|
txSeeding,
|
||||||
defn,
|
defn,
|
||||||
TransactionVersions.SupportedDevOutputVersions,
|
value.ValueVersions.DevOutputVersions,
|
||||||
|
transaction.TransactionVersions.DevOutputVersions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +155,11 @@ 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
|
||||||
}
|
}
|
||||||
|
@ -293,7 +293,8 @@ class Engine(private[lf] val config: EngineConfig = EngineConfig.Stable) {
|
|||||||
expr = SExpr.SEApp(sexpr, Array(SExpr.SEValue.Token)),
|
expr = SExpr.SEApp(sexpr, Array(SExpr.SEValue.Token)),
|
||||||
globalCids = globalCids,
|
globalCids = globalCids,
|
||||||
committers = submitters,
|
committers = submitters,
|
||||||
outputTransactionVersions = config.outputTransactionVersions,
|
inputValueVersions = config.allowedInputValueVersions,
|
||||||
|
outputTransactionVersions = config.allowedOutputTransactionVersions,
|
||||||
validating = validating,
|
validating = validating,
|
||||||
)
|
)
|
||||||
interpretLoop(machine, ledgerTime)
|
interpretLoop(machine, ledgerTime)
|
||||||
@ -428,13 +429,13 @@ class Engine(private[lf] val config: EngineConfig = EngineConfig.Stable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private[engine] def addPackage(pkgId: PackageId, pkg: Package): Result[Unit] =
|
private[engine] def addPackage(pkgId: PackageId, pkg: Package): Result[Unit] =
|
||||||
if (config.languageVersions.contains(pkg.languageVersion))
|
if (config.allowedLanguageVersions.contains(pkg.languageVersion))
|
||||||
compiledPackages.addPackage(pkgId, pkg)
|
compiledPackages.addPackage(pkgId, pkg)
|
||||||
else
|
else
|
||||||
ResultError(
|
ResultError(
|
||||||
Error(
|
Error(
|
||||||
s"Disallowed language version in package $pkgId: " +
|
s"Disallowed language version in package $pkgId: " +
|
||||||
s"Expected version between ${config.languageVersions.min} and ${config.languageVersions.max} but got ${pkg.languageVersion}"
|
s"Expected version between ${config.allowedLanguageVersions.min} and ${config.allowedLanguageVersions.max} but got ${pkg.languageVersion}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,45 +11,55 @@ import com.daml.lf.transaction.{TransactionVersions, TransactionVersion => TV}
|
|||||||
// Currently only outputTransactionVersions is used.
|
// Currently only outputTransactionVersions is used.
|
||||||
// languageVersions and outputTransactionVersions should be plug
|
// languageVersions and outputTransactionVersions should be plug
|
||||||
final case class EngineConfig(
|
final case class EngineConfig(
|
||||||
// constrains the version of language accepted by the engine
|
// constrains the versions of language accepted by the engine
|
||||||
languageVersions: VersionRange[LV],
|
allowedLanguageVersions: VersionRange[LV],
|
||||||
// constrains the version of output transactions
|
// constrains the versions of input transactions
|
||||||
inputTransactionVersions: VersionRange[TV],
|
allowedInputTransactionVersions: VersionRange[TV],
|
||||||
// constrains the version of output transactions
|
// constrains the versions of output transactions
|
||||||
outputTransactionVersions: VersionRange[TV],
|
allowedOutputTransactionVersions: VersionRange[TV],
|
||||||
)
|
) {
|
||||||
|
|
||||||
|
private[lf] val allowedInputValueVersions =
|
||||||
|
VersionRange(
|
||||||
|
TransactionVersions.assignValueVersion(allowedInputTransactionVersions.min),
|
||||||
|
TransactionVersions.assignValueVersion(allowedInputTransactionVersions.max),
|
||||||
|
)
|
||||||
|
|
||||||
|
private[lf] val allowedOutputValueVersions =
|
||||||
|
VersionRange(
|
||||||
|
TransactionVersions.assignValueVersion(allowedOutputTransactionVersions.min),
|
||||||
|
TransactionVersions.assignValueVersion(allowedOutputTransactionVersions.max),
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
object EngineConfig {
|
object EngineConfig {
|
||||||
|
|
||||||
// development configuration, should not be used in PROD.
|
// Development configuration, should not be used in PROD.
|
||||||
// accept all language and transaction versions supported by SDK_1_x plus development versions.
|
|
||||||
val Dev: EngineConfig = new EngineConfig(
|
val Dev: EngineConfig = new EngineConfig(
|
||||||
languageVersions = VersionRange(
|
allowedLanguageVersions = VersionRange(
|
||||||
LV(LV.Major.V1, LV.Minor.Stable("6")),
|
LV(LV.Major.V1, LV.Minor.Stable("6")),
|
||||||
LV(LV.Major.V1, LV.Minor.Dev),
|
LV(LV.Major.V1, LV.Minor.Dev),
|
||||||
),
|
),
|
||||||
inputTransactionVersions = VersionRange(
|
allowedInputTransactionVersions = VersionRange(
|
||||||
TV("10"),
|
TV("10"),
|
||||||
TransactionVersions.acceptedVersions.last
|
TransactionVersions.acceptedVersions.last
|
||||||
),
|
),
|
||||||
outputTransactionVersions = VersionRange(
|
allowedOutputTransactionVersions = TransactionVersions.DevOutputVersions
|
||||||
TV("10"),
|
|
||||||
TransactionVersions.acceptedVersions.last
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Legacy configuration, to be used by sandbox classic only
|
// Legacy configuration, to be used by sandbox classic only
|
||||||
@deprecated("Sandbox_Classic is to be used by sandbox classic only", since = "1.4.0")
|
@deprecated("Sandbox_Classic is to be used by sandbox classic only", since = "1.4.0")
|
||||||
val Sandbox_Classic: EngineConfig = new EngineConfig(
|
val Sandbox_Classic: EngineConfig = new EngineConfig(
|
||||||
languageVersions = VersionRange(
|
allowedLanguageVersions = VersionRange(
|
||||||
LV(LV.Major.V1, LV.Minor.Stable("1")),
|
LV(LV.Major.V1, LV.Minor.Stable("0")),
|
||||||
LV(LV.Major.V1, LV.Minor.Dev),
|
LV(LV.Major.V1, LV.Minor.Dev),
|
||||||
),
|
),
|
||||||
inputTransactionVersions = VersionRange(
|
allowedInputTransactionVersions = VersionRange(
|
||||||
TransactionVersions.acceptedVersions.head,
|
TransactionVersions.acceptedVersions.head,
|
||||||
TransactionVersions.acceptedVersions.last
|
TransactionVersions.acceptedVersions.last
|
||||||
),
|
),
|
||||||
outputTransactionVersions = VersionRange(
|
allowedOutputTransactionVersions = VersionRange(
|
||||||
TV("10"),
|
TV("10"),
|
||||||
TransactionVersions.acceptedVersions.last
|
TransactionVersions.acceptedVersions.last
|
||||||
)
|
)
|
||||||
@ -57,12 +67,12 @@ object EngineConfig {
|
|||||||
|
|
||||||
// recommended configuration
|
// recommended configuration
|
||||||
val Stable: EngineConfig = new EngineConfig(
|
val Stable: EngineConfig = new EngineConfig(
|
||||||
languageVersions = VersionRange(
|
allowedLanguageVersions = VersionRange(
|
||||||
LV(LV.Major.V1, LV.Minor.Stable("6")),
|
LV(LV.Major.V1, LV.Minor.Stable("6")),
|
||||||
LV(LV.Major.V1, LV.Minor.Stable("8")),
|
LV(LV.Major.V1, LV.Minor.Stable("8")),
|
||||||
),
|
),
|
||||||
inputTransactionVersions = VersionRange(TV("10"), TV("10")),
|
allowedInputTransactionVersions = VersionRange(TV("10"), TV("10")),
|
||||||
outputTransactionVersions = VersionRange(TV("10"), TV("10"))
|
allowedOutputTransactionVersions = VersionRange(TV("10"), TV("10"))
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,53 +1,85 @@
|
|||||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package com.daml.lf.engine
|
package com.daml.lf
|
||||||
|
package engine
|
||||||
import com.daml.lf.language.{LanguageVersion => LV}
|
|
||||||
import com.daml.lf.transaction.TransactionVersions
|
|
||||||
import com.daml.lf.value.ValueVersions
|
|
||||||
|
|
||||||
class EngineInfo(config: EngineConfig) {
|
class EngineInfo(config: EngineConfig) {
|
||||||
|
|
||||||
override lazy val toString: String = show
|
import language.{LanguageVersion => LV}
|
||||||
|
|
||||||
lazy val show: String =
|
override def toString: String = show
|
||||||
s"DAML LF Engine supports LF versions: $formatLfVersions; Input Transaction versions: $formatInputTransactionVersions; Input Value versions: $formatInputValueVersions; Output Transaction versions: $formatOutputTransactionVersions; Output Value versions: $formatOutputValueVersions"
|
def show: String = pretty.mkString(System.lineSeparator())
|
||||||
|
|
||||||
private[this] def formatInputTransactionVersions: String =
|
lazy val pretty: Iterable[String] = {
|
||||||
format(TransactionVersions.acceptedVersions.map(_.protoValue))
|
|
||||||
|
|
||||||
private[this] def formatOutputTransactionVersions: String =
|
val allLangVersions =
|
||||||
format(
|
for {
|
||||||
TransactionVersions.acceptedVersions
|
major <- LV.Major.All
|
||||||
.collect {
|
minor <- major.supportedMinorVersions
|
||||||
case v if config.outputTransactionVersions.contains(v) =>
|
} yield LV(major, minor)
|
||||||
v.protoValue
|
|
||||||
}
|
val allTransactionVersions =
|
||||||
|
transaction.TransactionVersions.acceptedVersions
|
||||||
|
|
||||||
|
val allValueVersions =
|
||||||
|
value.ValueVersions.acceptedVersions
|
||||||
|
|
||||||
|
val allOutputTransactionVersions =
|
||||||
|
allTransactionVersions.filter(transaction.TransactionVersions.DevOutputVersions.contains)
|
||||||
|
|
||||||
|
val allOutputValueVersions =
|
||||||
|
allOutputTransactionVersions.map(transaction.TransactionVersions.assignValueVersion)
|
||||||
|
|
||||||
|
val allowedLangVersions =
|
||||||
|
allLangVersions.filter(config.allowedLanguageVersions.contains)
|
||||||
|
|
||||||
|
val allowedInputTransactionVersions =
|
||||||
|
allTransactionVersions.filter(config.allowedInputTransactionVersions.contains)
|
||||||
|
|
||||||
|
val allowedInputValueVersions =
|
||||||
|
allValueVersions.filter(config.allowedInputValueVersions.contains)
|
||||||
|
|
||||||
|
val allowedOutputTransactionVersions =
|
||||||
|
allTransactionVersions.filter(config.allowedOutputTransactionVersions.contains)
|
||||||
|
|
||||||
|
val allowedOutputValueVersions =
|
||||||
|
allValueVersions.filter(config.allowedOutputValueVersions.contains)
|
||||||
|
|
||||||
|
List(
|
||||||
|
List(
|
||||||
|
formatLangVersions(allLangVersions),
|
||||||
|
formatTxVersions("input", allTransactionVersions),
|
||||||
|
formatValVersions("input", allValueVersions),
|
||||||
|
formatTxVersions("output", allOutputTransactionVersions),
|
||||||
|
formatValVersions("output", allOutputValueVersions)
|
||||||
|
).mkString("DAML LF Engine supports ", "; ", "."),
|
||||||
|
List(
|
||||||
|
formatLangVersions(allowedLangVersions),
|
||||||
|
formatTxVersions("input", allowedInputTransactionVersions),
|
||||||
|
formatValVersions("input", allowedInputValueVersions),
|
||||||
|
formatTxVersions("output", allowedOutputTransactionVersions),
|
||||||
|
formatValVersions("output", allowedOutputValueVersions)
|
||||||
|
).mkString("DAML LF Engine config allows ", "; ", ".")
|
||||||
)
|
)
|
||||||
|
|
||||||
private[this] def formatInputValueVersions: String =
|
|
||||||
format(ValueVersions.acceptedVersions.map(_.protoValue))
|
|
||||||
|
|
||||||
private[this] def formatOutputValueVersions: String = {
|
|
||||||
val outputValueVersions =
|
|
||||||
config.outputTransactionVersions.map(TransactionVersions.assignValueVersion)
|
|
||||||
format(ValueVersions.acceptedVersions.filter(outputValueVersions.contains).map(_.protoValue))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private def formatLfVersions: String = {
|
private[this] def formatLangVersions(versions: Iterable[LV]) = {
|
||||||
val allVersions: Iterable[String] =
|
val prettyVersions = versions.map {
|
||||||
LV.Major.All flatMap (mv => lfVersions(mv.pretty, mv.supportedMinorVersions))
|
case LV(major, minor) =>
|
||||||
format(allVersions)
|
val ap = minor.toProtoIdentifier
|
||||||
}
|
s"${major.pretty}${if (ap.isEmpty) "" else s".$ap"}"
|
||||||
|
|
||||||
private def lfVersions(
|
|
||||||
majorVersion: String,
|
|
||||||
minorVersions: Iterable[LV.Minor]): Iterable[String] =
|
|
||||||
minorVersions.map { a =>
|
|
||||||
val ap = a.toProtoIdentifier
|
|
||||||
s"$majorVersion${if (ap.isEmpty) "" else s".$ap"}"
|
|
||||||
}
|
}
|
||||||
|
s"LF versions: ${prettyVersions.mkString(", ")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def formatTxVersions(
|
||||||
|
prefix: String,
|
||||||
|
versions: List[transaction.TransactionVersion],
|
||||||
|
) =
|
||||||
|
s"$prefix transaction versions: ${versions.map(_.protoValue).mkString(", ")}"
|
||||||
|
|
||||||
|
private[this] def formatValVersions(prefix: String, versions: List[value.ValueVersion]) =
|
||||||
|
s"$prefix value versions: ${versions.map(_.protoValue).mkString(", ")}"
|
||||||
|
|
||||||
private def format(as: Iterable[String]): String = as.mkString(", ")
|
|
||||||
}
|
}
|
||||||
|
@ -18,14 +18,22 @@ class EngineInfoTest extends WordSpec with Matchers {
|
|||||||
|
|
||||||
"show supported LF, Transaction and Value versions" in {
|
"show supported LF, Transaction and Value versions" in {
|
||||||
|
|
||||||
engineInfoStable.show shouldBe
|
infos.foreach(
|
||||||
"DAML LF Engine supports LF versions: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.dev; Input Transaction versions: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; Input Value versions: 1, 2, 3, 4, 5, 6, 7; Output Transaction versions: 10; Output Value versions: 6"
|
_.pretty.toSeq(0) shouldBe
|
||||||
|
"DAML LF Engine supports LF versions: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.dev; input transaction versions: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; input value versions: 1, 2, 3, 4, 5, 6, 7; output transaction versions: 10, 11; output value versions: 6, 7."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
engineInfoDev.show shouldBe
|
"show allowed LF, Transaction and Value versions" in {
|
||||||
"DAML LF Engine supports LF versions: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.dev; Input Transaction versions: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; Input Value versions: 1, 2, 3, 4, 5, 6, 7; Output Transaction versions: 10, 11; Output Value versions: 6, 7"
|
|
||||||
|
|
||||||
engineInfoLegacy.show shouldBe
|
engineInfoStable.pretty.toSeq(1) shouldBe
|
||||||
"DAML LF Engine supports LF versions: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.dev; Input Transaction versions: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; Input Value versions: 1, 2, 3, 4, 5, 6, 7; Output Transaction versions: 10, 11; Output Value versions: 6, 7"
|
"DAML LF Engine config allows LF versions: 1.6, 1.7, 1.8; input transaction versions: 10; input value versions: 6; output transaction versions: 10; output value versions: 6."
|
||||||
|
|
||||||
|
engineInfoDev.pretty.toSeq(1) shouldBe
|
||||||
|
"DAML LF Engine config allows LF versions: 1.6, 1.7, 1.8, 1.dev; input transaction versions: 10, 11; input value versions: 6, 7; output transaction versions: 10, 11; output value versions: 6, 7."
|
||||||
|
|
||||||
|
engineInfoLegacy.pretty.toSeq(1) shouldBe
|
||||||
|
"DAML LF Engine config allows LF versions: 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.dev; input transaction versions: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11; input value versions: 1, 2, 3, 4, 5, 6, 7; output transaction versions: 10, 11; output value versions: 6, 7."
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import com.daml.lf.transaction.{
|
|||||||
Transaction => Tx,
|
Transaction => Tx,
|
||||||
TransactionVersions => TxVersions
|
TransactionVersions => TxVersions
|
||||||
}
|
}
|
||||||
import com.daml.lf.value.Value
|
import com.daml.lf.value.{Value, ValueVersion}
|
||||||
import Value._
|
import Value._
|
||||||
import com.daml.lf.speedy.{InitialSeeding, SValue, svalue}
|
import com.daml.lf.speedy.{InitialSeeding, SValue, svalue}
|
||||||
import com.daml.lf.speedy.SValue._
|
import com.daml.lf.speedy.SValue._
|
||||||
@ -1628,6 +1628,48 @@ class EngineTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"Engine#submit" should {
|
||||||
|
val cidV6 = toContractId("#cidV6")
|
||||||
|
val cidV7 = toContractId("#cidV7")
|
||||||
|
val contract = ValueRecord(
|
||||||
|
Some(Identifier(basicTestsPkgId, "BasicTests:Simple")),
|
||||||
|
ImmArray((Some[Name]("p"), ValueParty(party)))
|
||||||
|
)
|
||||||
|
val hello = Identifier(basicTestsPkgId, "BasicTests:Hello")
|
||||||
|
val templateId = TypeConName(basicTestsPkgId, "BasicTests:Simple")
|
||||||
|
val now = Time.Timestamp.now()
|
||||||
|
val submissionSeed = crypto.Hash.hashPrivateKey("engine check the version of input value")
|
||||||
|
def contracts = Map(
|
||||||
|
cidV6 -> ContractInst(templateId, VersionedValue(ValueVersion("6"), contract), ""),
|
||||||
|
cidV7 -> ContractInst(templateId, VersionedValue(ValueVersion("7"), contract), ""),
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(cid: ContractId) = {
|
||||||
|
val engine = new Engine(EngineConfig.Stable)
|
||||||
|
val cmds = Commands(
|
||||||
|
submitter = party,
|
||||||
|
commands = ImmArray(
|
||||||
|
ExerciseCommand(templateId, cid, "Hello", ValueRecord(Some(hello), ImmArray.empty))),
|
||||||
|
ledgerEffectiveTime = now,
|
||||||
|
commandsReference = "",
|
||||||
|
)
|
||||||
|
engine
|
||||||
|
.submit(cmds, participant, submissionSeed)
|
||||||
|
.consume(contracts.get, lookupPackage, lookupKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
"succeed if fed with allowed value version" in {
|
||||||
|
run(cidV6) shouldBe 'right
|
||||||
|
}
|
||||||
|
|
||||||
|
"fail if fed with disallowed value version" in {
|
||||||
|
val result = run(cidV7)
|
||||||
|
result shouldBe 'left
|
||||||
|
result.left.get.msg should include("Update failed due to disallowed value version")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
"Engine.addPackage" should {
|
"Engine.addPackage" should {
|
||||||
|
|
||||||
import com.daml.lf.language.{LanguageVersion => LV}
|
import com.daml.lf.language.{LanguageVersion => LV}
|
||||||
@ -1635,7 +1677,7 @@ class EngineTest
|
|||||||
def engine(min: LV.Minor, max: LV.Minor) =
|
def engine(min: LV.Minor, max: LV.Minor) =
|
||||||
new Engine(
|
new Engine(
|
||||||
EngineConfig.Dev.copy(
|
EngineConfig.Dev.copy(
|
||||||
languageVersions = VersionRange(LV(LV.Major.V1, min), LV(LV.Major.V1, max))
|
allowedLanguageVersions = VersionRange(LV(LV.Major.V1, min), LV(LV.Major.V1, max))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -345,7 +345,7 @@ private[lf] object Anf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case x: SEAbs => throw CompilationError(s"flatten: unexpected: $x")
|
case x: SEAbs => throw CompilationError(s"flatten: unexpected: $x")
|
||||||
case x: SEWronglyTypeContractId => throw CompilationError(s"flatten: unexpected: $x")
|
case x: SEDamlException => throw CompilationError(s"flatten: unexpected: $x")
|
||||||
case x: SEAppAtomicFun => throw CompilationError(s"flatten: unexpected: $x")
|
case x: SEAppAtomicFun => throw CompilationError(s"flatten: unexpected: $x")
|
||||||
case x: SEAppAtomicGeneral => throw CompilationError(s"flatten: unexpected: $x")
|
case x: SEAppAtomicGeneral => throw CompilationError(s"flatten: unexpected: $x")
|
||||||
case x: SEAppAtomicSaturatedBuiltin => throw CompilationError(s"flatten: unexpected: $x")
|
case x: SEAppAtomicSaturatedBuiltin => throw CompilationError(s"flatten: unexpected: $x")
|
||||||
|
@ -1126,8 +1126,8 @@ private[lf] final case class Compiler(
|
|||||||
case SELabelClosure(label, expr) =>
|
case SELabelClosure(label, expr) =>
|
||||||
SELabelClosure(label, closureConvert(remaps, expr))
|
SELabelClosure(label, closureConvert(remaps, expr))
|
||||||
|
|
||||||
case x: SEWronglyTypeContractId =>
|
case x: SEDamlException =>
|
||||||
throw CompilationError(s"unexpected SEWronglyTypeContractId: $x")
|
throw CompilationError(s"unexpected SEDamlException: $x")
|
||||||
|
|
||||||
case x: SEImportValue =>
|
case x: SEImportValue =>
|
||||||
throw CompilationError(s"unexpected SEImportValue: $x")
|
throw CompilationError(s"unexpected SEImportValue: $x")
|
||||||
@ -1200,8 +1200,8 @@ private[lf] final case class Compiler(
|
|||||||
go(body, bound, go(handler, bound, go(fin, bound, free)))
|
go(body, bound, go(handler, bound, go(fin, bound, free)))
|
||||||
case SELabelClosure(_, expr) =>
|
case SELabelClosure(_, expr) =>
|
||||||
go(expr, bound, free)
|
go(expr, bound, free)
|
||||||
case x: SEWronglyTypeContractId =>
|
case x: SEDamlException =>
|
||||||
throw CompilationError(s"unexpected SEWronglyTypeContractId: $x")
|
throw CompilationError(s"unexpected SEDamlException: $x")
|
||||||
case x: SEImportValue =>
|
case x: SEImportValue =>
|
||||||
throw CompilationError(s"unexpected SEImportValue: $x")
|
throw CompilationError(s"unexpected SEImportValue: $x")
|
||||||
|
|
||||||
@ -1302,8 +1302,8 @@ private[lf] final case class Compiler(
|
|||||||
go(body)
|
go(body)
|
||||||
case SELabelClosure(_, expr) =>
|
case SELabelClosure(_, expr) =>
|
||||||
go(expr)
|
go(expr)
|
||||||
case x: SEWronglyTypeContractId =>
|
case x: SEDamlException =>
|
||||||
throw CompilationError(s"unexpected SEWronglyTypeContractId: $x")
|
throw CompilationError(s"unexpected SEDamlException: $x")
|
||||||
case x: SEImportValue =>
|
case x: SEImportValue =>
|
||||||
throw CompilationError(s"unexpected SEImportValue: $x")
|
throw CompilationError(s"unexpected SEImportValue: $x")
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ 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._
|
||||||
@ -72,6 +73,12 @@ private[lf] object Pretty {
|
|||||||
text("Expected contract of type") & prettyTypeConName(expected) & text("but got") & prettyTypeConName(
|
text("Expected contract of type") & prettyTypeConName(expected) & text("but got") & prettyTypeConName(
|
||||||
actual,
|
actual,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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..
|
||||||
@ -578,7 +585,7 @@ private[lf] object Pretty {
|
|||||||
case x: SEBuiltinRecursiveDefinition => str(x)
|
case x: SEBuiltinRecursiveDefinition => str(x)
|
||||||
case x: SEImportValue => str(x)
|
case x: SEImportValue => str(x)
|
||||||
case x: SELabelClosure => str(x)
|
case x: SELabelClosure => str(x)
|
||||||
case x: SEWronglyTypeContractId => str(x)
|
case x: SEDamlException => str(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1019,14 +1019,20 @@ private[lf] object SBuiltin {
|
|||||||
templateId,
|
templateId,
|
||||||
machine.committers,
|
machine.committers,
|
||||||
cbMissing = _ => machine.tryHandleException(),
|
cbMissing = _ => machine.tryHandleException(),
|
||||||
cbPresent = { coinst =>
|
cbPresent = {
|
||||||
// Note that we cannot throw in this continuation -- instead
|
case V.ContractInst(actualTmplId, V.VersionedValue(version, arg), _) =>
|
||||||
// set the control appropriately which will crash the machine
|
// Note that we cannot throw in this continuation -- instead
|
||||||
// correctly later.
|
// set the control appropriately which will crash the machine
|
||||||
if (coinst.template != templateId)
|
// correctly later.
|
||||||
machine.ctrl = SEWronglyTypeContractId(coid, templateId, coinst.template)
|
machine.ctrl =
|
||||||
else
|
if (actualTmplId != templateId)
|
||||||
machine.ctrl = SEImportValue(coinst.arg.value)
|
SEDamlException(DamlEWronglyTypedContract(coid, templateId, actualTmplId))
|
||||||
|
else if (!machine.inputValueVersions.contains(version))
|
||||||
|
SEDamlException(
|
||||||
|
DamlEDisallowedInputValueVersion(machine.inputValueVersions, version),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
SEImportValue(arg)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -3,11 +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.transaction.{GlobalKey, NodeId, Transaction => Tx}
|
import com.daml.lf.transaction.{GlobalKey, NodeId, Transaction => Tx}
|
||||||
import com.daml.lf.value.Value
|
import com.daml.lf.value.{Value, ValueVersion}
|
||||||
import com.daml.lf.scenario.ScenarioLedger
|
import com.daml.lf.scenario.ScenarioLedger
|
||||||
import com.daml.lf.value.Value.ContractId
|
import com.daml.lf.value.Value.ContractId
|
||||||
|
|
||||||
@ -88,6 +89,14 @@ 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
|
||||||
|
|
||||||
/** A fetch or exercise was being made against a contract that has not
|
/** A fetch or exercise was being made against a contract that has not
|
||||||
* been disclosed to 'committer'. */
|
* been disclosed to 'committer'. */
|
||||||
final case class ScenarioErrorContractNotVisible(
|
final case class ScenarioErrorContractNotVisible(
|
||||||
|
@ -387,16 +387,12 @@ object SExpr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** When we fetch a contract id from upstream we cannot crash in the upstream
|
/** We cannot crash in the engine call back.
|
||||||
* calls. Rather, we set the control to this expression and then crash when executing.
|
* Rather, we set the control to this expression and then crash when executing.
|
||||||
*/
|
*/
|
||||||
final case class SEWronglyTypeContractId(
|
final case class SEDamlException(error: SErrorDamlException) extends SExpr {
|
||||||
acoid: V.ContractId,
|
|
||||||
expected: TypeConName,
|
|
||||||
actual: TypeConName,
|
|
||||||
) extends SExpr {
|
|
||||||
def execute(machine: Machine): Unit = {
|
def execute(machine: Machine): Unit = {
|
||||||
throw DamlEWronglyTypedContract(acoid, expected, actual)
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import com.daml.lf.speedy.SExpr._
|
|||||||
import com.daml.lf.speedy.SResult._
|
import com.daml.lf.speedy.SResult._
|
||||||
import com.daml.lf.speedy.SValue._
|
import com.daml.lf.speedy.SValue._
|
||||||
import com.daml.lf.transaction.{TransactionVersion, TransactionVersions}
|
import com.daml.lf.transaction.{TransactionVersion, TransactionVersions}
|
||||||
import com.daml.lf.value.{Value => V}
|
import com.daml.lf.value.{ValueVersion, ValueVersions, Value => V}
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
import scala.collection.JavaConverters._
|
import scala.collection.JavaConverters._
|
||||||
@ -98,8 +98,10 @@ private[lf] object Speedy {
|
|||||||
|
|
||||||
/** The speedy CEK machine. */
|
/** The speedy CEK machine. */
|
||||||
final class Machine(
|
final class Machine(
|
||||||
|
/* Transaction versions that the machine can read */
|
||||||
|
val inputValueVersions: VersionRange[ValueVersion],
|
||||||
/* Transaction versions that the machine can output */
|
/* Transaction versions that the machine can output */
|
||||||
val outputTransactionVersions: VersionRange[transaction.TransactionVersion],
|
val outputTransactionVersions: VersionRange[TransactionVersion],
|
||||||
/* Whether the current submission is validating the transaction, or interpreting
|
/* Whether the current submission is validating the transaction, or interpreting
|
||||||
* it. If this is false, the committers must be a singleton set.
|
* it. If this is false, the committers must be a singleton set.
|
||||||
*/
|
*/
|
||||||
@ -550,7 +552,6 @@ private[lf] object Speedy {
|
|||||||
// to speedy value and set the control of with the result.
|
// to speedy value and set the control of with the result.
|
||||||
// All the contract IDs contained in the value are considered global.
|
// All the contract IDs contained in the value are considered global.
|
||||||
// Raises an exception if missing a package.
|
// Raises an exception if missing a package.
|
||||||
|
|
||||||
private[speedy] def importValue(value: V[V.ContractId]): Unit = {
|
private[speedy] def importValue(value: V[V.ContractId]): Unit = {
|
||||||
def go(value0: V[V.ContractId]): SValue =
|
def go(value0: V[V.ContractId]): SValue =
|
||||||
value0 match {
|
value0 match {
|
||||||
@ -658,10 +659,12 @@ private[lf] object Speedy {
|
|||||||
expr: SExpr,
|
expr: SExpr,
|
||||||
globalCids: Set[V.ContractId],
|
globalCids: Set[V.ContractId],
|
||||||
committers: Set[Party],
|
committers: Set[Party],
|
||||||
outputTransactionVersions: VersionRange[transaction.TransactionVersion],
|
inputValueVersions: VersionRange[ValueVersion],
|
||||||
|
outputTransactionVersions: VersionRange[TransactionVersion],
|
||||||
validating: Boolean = false,
|
validating: Boolean = false,
|
||||||
): Machine =
|
): Machine =
|
||||||
new Machine(
|
new Machine(
|
||||||
|
inputValueVersions = inputValueVersions,
|
||||||
outputTransactionVersions = outputTransactionVersions,
|
outputTransactionVersions = outputTransactionVersions,
|
||||||
validating = validating,
|
validating = validating,
|
||||||
ctrl = expr,
|
ctrl = expr,
|
||||||
@ -693,6 +696,7 @@ private[lf] object Speedy {
|
|||||||
compiledPackages: CompiledPackages,
|
compiledPackages: CompiledPackages,
|
||||||
transactionSeed: crypto.Hash,
|
transactionSeed: crypto.Hash,
|
||||||
scenario: SExpr,
|
scenario: SExpr,
|
||||||
|
inputValueVersions: VersionRange[ValueVersion],
|
||||||
outputTransactionVersions: VersionRange[TransactionVersion],
|
outputTransactionVersions: VersionRange[TransactionVersion],
|
||||||
): Machine = Machine(
|
): Machine = Machine(
|
||||||
compiledPackages = compiledPackages,
|
compiledPackages = compiledPackages,
|
||||||
@ -701,6 +705,7 @@ private[lf] object Speedy {
|
|||||||
expr = SEApp(scenario, Array(SEValue.Token)),
|
expr = SEApp(scenario, Array(SEValue.Token)),
|
||||||
globalCids = Set.empty,
|
globalCids = Set.empty,
|
||||||
committers = Set.empty,
|
committers = Set.empty,
|
||||||
|
inputValueVersions: VersionRange[ValueVersion],
|
||||||
outputTransactionVersions = outputTransactionVersions,
|
outputTransactionVersions = outputTransactionVersions,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -711,12 +716,14 @@ private[lf] object Speedy {
|
|||||||
compiledPackages: CompiledPackages,
|
compiledPackages: CompiledPackages,
|
||||||
transactionSeed: crypto.Hash,
|
transactionSeed: crypto.Hash,
|
||||||
scenario: Expr,
|
scenario: Expr,
|
||||||
|
inputValueVersions: VersionRange[ValueVersion],
|
||||||
outputTransactionVersions: VersionRange[TransactionVersion],
|
outputTransactionVersions: VersionRange[TransactionVersion],
|
||||||
): Machine =
|
): Machine =
|
||||||
fromScenarioSExpr(
|
fromScenarioSExpr(
|
||||||
compiledPackages = compiledPackages,
|
compiledPackages = compiledPackages,
|
||||||
transactionSeed = transactionSeed,
|
transactionSeed = transactionSeed,
|
||||||
scenario = compiledPackages.compiler.unsafeCompile(scenario),
|
scenario = compiledPackages.compiler.unsafeCompile(scenario),
|
||||||
|
inputValueVersions = inputValueVersions,
|
||||||
outputTransactionVersions = outputTransactionVersions,
|
outputTransactionVersions = outputTransactionVersions,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -734,7 +741,8 @@ private[lf] object Speedy {
|
|||||||
expr = expr,
|
expr = expr,
|
||||||
globalCids = Set.empty,
|
globalCids = Set.empty,
|
||||||
committers = Set.empty,
|
committers = Set.empty,
|
||||||
outputTransactionVersions = TransactionVersions.SupportedDevOutputVersions,
|
inputValueVersions = ValueVersions.Empty,
|
||||||
|
outputTransactionVersions = TransactionVersions.Empty,
|
||||||
)
|
)
|
||||||
|
|
||||||
@throws[PackageNotFound]
|
@throws[PackageNotFound]
|
||||||
|
@ -22,7 +22,6 @@ import java.io.{File, PrintWriter, StringWriter}
|
|||||||
import java.nio.file.{Path, Paths}
|
import java.nio.file.{Path, Paths}
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
|
|
||||||
import com.daml.lf.transaction.TransactionVersions
|
|
||||||
import org.jline.builtins.Completers
|
import org.jline.builtins.Completers
|
||||||
import org.jline.reader.{History, LineReader, LineReaderBuilder}
|
import org.jline.reader.{History, LineReader, LineReaderBuilder}
|
||||||
import org.jline.reader.impl.completer.{AggregateCompleter, ArgumentCompleter, StringsCompleter}
|
import org.jline.reader.impl.completer.{AggregateCompleter, ArgumentCompleter, StringsCompleter}
|
||||||
@ -185,11 +184,17 @@ object Repl {
|
|||||||
|
|
||||||
private val seed = nextSeed()
|
private val seed = nextSeed()
|
||||||
|
|
||||||
val txVersions =
|
val (inputValueVersion, outputTransactionVersions) =
|
||||||
if (devMode)
|
if (devMode)
|
||||||
TransactionVersions.SupportedDevOutputVersions
|
(
|
||||||
|
value.ValueVersions.DevOutputVersions,
|
||||||
|
transaction.TransactionVersions.DevOutputVersions
|
||||||
|
)
|
||||||
else
|
else
|
||||||
TransactionVersions.SupportedStableOutputVersions
|
(
|
||||||
|
value.ValueVersions.StableOutputVersions,
|
||||||
|
transaction.TransactionVersions.StableOutputVersions,
|
||||||
|
)
|
||||||
|
|
||||||
def run(expr: Expr): (
|
def run(expr: Expr): (
|
||||||
Speedy.Machine,
|
Speedy.Machine,
|
||||||
@ -199,7 +204,8 @@ object Repl {
|
|||||||
compiledPackages,
|
compiledPackages,
|
||||||
seed,
|
seed,
|
||||||
expr,
|
expr,
|
||||||
txVersions,
|
inputValueVersion,
|
||||||
|
outputTransactionVersions,
|
||||||
)
|
)
|
||||||
(machine, ScenarioRunner(machine).run())
|
(machine, ScenarioRunner(machine).run())
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,8 @@ object ScenarioRunner {
|
|||||||
engine.compiledPackages(),
|
engine.compiledPackages(),
|
||||||
transactionSeed,
|
transactionSeed,
|
||||||
scenarioExpr,
|
scenarioExpr,
|
||||||
engine.config.outputTransactionVersions,
|
engine.config.allowedInputValueVersions,
|
||||||
|
engine.config.allowedOutputTransactionVersions,
|
||||||
)
|
)
|
||||||
ScenarioRunner(speedyMachine).run() match {
|
ScenarioRunner(speedyMachine).run() match {
|
||||||
case Left(e) =>
|
case Left(e) =>
|
||||||
|
@ -18,7 +18,6 @@ import com.daml.lf.speedy.Speedy.Machine
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import com.daml.lf.transaction.TransactionVersions
|
|
||||||
import org.openjdk.jmh.annotations._
|
import org.openjdk.jmh.annotations._
|
||||||
|
|
||||||
class CollectAuthority {
|
class CollectAuthority {
|
||||||
@ -57,7 +56,8 @@ class CollectAuthorityState {
|
|||||||
compiledPackages,
|
compiledPackages,
|
||||||
seeding(),
|
seeding(),
|
||||||
expr,
|
expr,
|
||||||
TransactionVersions.SupportedDevOutputVersions,
|
value.ValueVersions.DevOutputVersions,
|
||||||
|
transaction.TransactionVersions.DevOutputVersions,
|
||||||
)
|
)
|
||||||
the_sexpr = machine.ctrl
|
the_sexpr = machine.ctrl
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package com.daml.lf
|
package com.daml
|
||||||
|
package lf
|
||||||
package speedy
|
package speedy
|
||||||
|
|
||||||
import com.daml.lf.data.Ref
|
import com.daml.lf.data.Ref
|
||||||
import com.daml.lf.language.Ast
|
import com.daml.lf.language.Ast
|
||||||
import com.daml.lf.language.Ast.ScenarioGetParty
|
import org.scalatest.{AsyncWordSpec, Matchers}
|
||||||
import com.daml.lf.transaction.TransactionVersions
|
|
||||||
import org.scalatest._
|
|
||||||
import org.scalatest.concurrent.ScalaFutures
|
import org.scalatest.concurrent.ScalaFutures
|
||||||
|
|
||||||
class ScenarioRunnerTest extends AsyncWordSpec with Matchers with ScalaFutures {
|
class ScenarioRunnerTest extends AsyncWordSpec with Matchers with ScalaFutures {
|
||||||
@ -16,13 +15,14 @@ class ScenarioRunnerTest extends AsyncWordSpec with Matchers with ScalaFutures {
|
|||||||
"ScenarioRunner" can {
|
"ScenarioRunner" can {
|
||||||
"mangle party names correctly" in {
|
"mangle party names correctly" in {
|
||||||
val compiledPackages = PureCompiledPackages(Map.empty).right.get
|
val compiledPackages = PureCompiledPackages(Map.empty).right.get
|
||||||
val e = Ast.EScenario(ScenarioGetParty(Ast.EPrimLit(Ast.PLText(("foo-bar")))))
|
val e = Ast.EScenario(Ast.ScenarioGetParty(Ast.EPrimLit(Ast.PLText("foo-bar"))))
|
||||||
val txSeed = crypto.Hash.hashPrivateKey("ScenarioRunnerTest")
|
val txSeed = crypto.Hash.hashPrivateKey("ScenarioRunnerTest")
|
||||||
val m = Speedy.Machine.fromScenarioExpr(
|
val m = Speedy.Machine.fromScenarioExpr(
|
||||||
compiledPackages,
|
compiledPackages,
|
||||||
txSeed,
|
txSeed,
|
||||||
e,
|
e,
|
||||||
TransactionVersions.SupportedDevOutputVersions,
|
lf.value.ValueVersions.DevOutputVersions,
|
||||||
|
transaction.TransactionVersions.DevOutputVersions,
|
||||||
)
|
)
|
||||||
val sr = ScenarioRunner(m, _ + "-XXX")
|
val sr = ScenarioRunner(m, _ + "-XXX")
|
||||||
sr.run() match {
|
sr.run() match {
|
||||||
|
@ -62,9 +62,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
|||||||
.toSeq
|
.toSeq
|
||||||
val txVersion =
|
val txVersion =
|
||||||
VersionTimeline
|
VersionTimeline
|
||||||
.latestWhenAllPresent(
|
.latestWhenAllPresent(TransactionVersions.StableOutputVersions.min, nodesVersions: _*)
|
||||||
TransactionVersions.SupportedStableOutputVersions.min,
|
|
||||||
nodesVersions: _*)
|
|
||||||
VersionedTransaction(txVersion, GenTransaction(nodes.result(), roots.result()))
|
VersionedTransaction(txVersion, GenTransaction(nodes.result(), roots.result()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +78,7 @@ final class TransactionBuilder(pkgTxVersion: Ref.PackageId => TransactionVersion
|
|||||||
private[this] def pkgValVersion(pkgId: Ref.PackageId) = {
|
private[this] def pkgValVersion(pkgId: Ref.PackageId) = {
|
||||||
import VersionTimeline.Implicits._
|
import VersionTimeline.Implicits._
|
||||||
VersionTimeline.latestWhenAllPresent(
|
VersionTimeline.latestWhenAllPresent(
|
||||||
ValueVersions.SupportedStableVersions.min,
|
ValueVersions.StableOutputVersions.min,
|
||||||
pkgTxVersion(pkgId))
|
pkgTxVersion(pkgId))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +122,7 @@ object TransactionBuilder {
|
|||||||
private val KeyWithMaintainers = transaction.Node.KeyWithMaintainers
|
private val KeyWithMaintainers = transaction.Node.KeyWithMaintainers
|
||||||
|
|
||||||
def apply(): TransactionBuilder =
|
def apply(): TransactionBuilder =
|
||||||
TransactionBuilder(TransactionVersions.SupportedStableOutputVersions.min)
|
TransactionBuilder(TransactionVersions.StableOutputVersions.min)
|
||||||
|
|
||||||
def apply(txVersion: TransactionVersion): TransactionBuilder =
|
def apply(txVersion: TransactionVersion): TransactionBuilder =
|
||||||
new TransactionBuilder(_ => txVersion)
|
new TransactionBuilder(_ => txVersion)
|
||||||
@ -133,7 +131,7 @@ object TransactionBuilder {
|
|||||||
def pkgTxVersion(pkgId: Ref.PackageId) = {
|
def pkgTxVersion(pkgId: Ref.PackageId) = {
|
||||||
import VersionTimeline.Implicits._
|
import VersionTimeline.Implicits._
|
||||||
VersionTimeline.latestWhenAllPresent(
|
VersionTimeline.latestWhenAllPresent(
|
||||||
TransactionVersions.SupportedStableOutputVersions.min,
|
TransactionVersions.StableOutputVersions.min,
|
||||||
pkgLangVersion(pkgId)
|
pkgLangVersion(pkgId)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -240,7 +238,7 @@ object TransactionBuilder {
|
|||||||
// not valid transactions.
|
// not valid transactions.
|
||||||
val Empty: Tx.Transaction =
|
val Empty: Tx.Transaction =
|
||||||
VersionedTransaction(
|
VersionedTransaction(
|
||||||
TransactionVersions.SupportedStableOutputVersions.min,
|
TransactionVersions.StableOutputVersions.min,
|
||||||
GenTransaction(HashMap.empty, ImmArray.empty),
|
GenTransaction(HashMap.empty, ImmArray.empty),
|
||||||
)
|
)
|
||||||
val EmptySubmitted: SubmittedTransaction = SubmittedTransaction(Empty)
|
val EmptySubmitted: SubmittedTransaction = SubmittedTransaction(Empty)
|
||||||
|
@ -34,16 +34,18 @@ private[lf] object TransactionVersions
|
|||||||
private[transaction] val minContractKeyInFetch = TransactionVersion("10")
|
private[transaction] val minContractKeyInFetch = TransactionVersion("10")
|
||||||
|
|
||||||
// Older versions are deprecated https://github.com/digital-asset/daml/issues/5220
|
// Older versions are deprecated https://github.com/digital-asset/daml/issues/5220
|
||||||
// We force output of recent version, but keep reading older version as long as
|
val StableOutputVersions: VersionRange[TransactionVersion] =
|
||||||
// Sandbox is alive.
|
|
||||||
val SupportedStableOutputVersions =
|
|
||||||
VersionRange(TransactionVersion("10"), TransactionVersion("10"))
|
VersionRange(TransactionVersion("10"), TransactionVersion("10"))
|
||||||
|
|
||||||
val SupportedDevOutputVersions = SupportedStableOutputVersions.copy(max = acceptedVersions.last)
|
val DevOutputVersions: VersionRange[TransactionVersion] =
|
||||||
|
StableOutputVersions.copy(max = acceptedVersions.last)
|
||||||
|
|
||||||
|
val Empty: VersionRange[TransactionVersion] =
|
||||||
|
VersionRange(acceptedVersions.last, acceptedVersions.head)
|
||||||
|
|
||||||
def assignVersion(
|
def assignVersion(
|
||||||
a: GenTransaction.WithTxValue[_, Value.ContractId],
|
a: GenTransaction.WithTxValue[_, Value.ContractId],
|
||||||
supportedVersions: VersionRange[TransactionVersion] = SupportedDevOutputVersions,
|
supportedVersions: VersionRange[TransactionVersion] = DevOutputVersions,
|
||||||
): Either[String, TransactionVersion] = {
|
): Either[String, TransactionVersion] = {
|
||||||
require(a != null)
|
require(a != null)
|
||||||
import VersionTimeline.Implicits._
|
import VersionTimeline.Implicits._
|
||||||
@ -118,7 +120,7 @@ private[lf] object TransactionVersions
|
|||||||
|
|
||||||
def asVersionedTransaction(
|
def asVersionedTransaction(
|
||||||
tx: GenTransaction.WithTxValue[NodeId, Value.ContractId],
|
tx: GenTransaction.WithTxValue[NodeId, Value.ContractId],
|
||||||
supportedVersions: VersionRange[TransactionVersion] = SupportedDevOutputVersions,
|
supportedVersions: VersionRange[TransactionVersion] = DevOutputVersions,
|
||||||
): Either[String, Transaction.Transaction] =
|
): Either[String, Transaction.Transaction] =
|
||||||
for {
|
for {
|
||||||
v <- assignVersion(tx, supportedVersions)
|
v <- assignVersion(tx, supportedVersions)
|
||||||
@ -127,13 +129,13 @@ private[lf] object TransactionVersions
|
|||||||
@throws[IllegalArgumentException]
|
@throws[IllegalArgumentException]
|
||||||
def assertAsVersionedTransaction(
|
def assertAsVersionedTransaction(
|
||||||
tx: GenTransaction.WithTxValue[NodeId, Value.ContractId],
|
tx: GenTransaction.WithTxValue[NodeId, Value.ContractId],
|
||||||
supportedVersions: VersionRange[TransactionVersion] = SupportedDevOutputVersions,
|
supportedVersions: VersionRange[TransactionVersion] = DevOutputVersions,
|
||||||
): Transaction.Transaction =
|
): Transaction.Transaction =
|
||||||
data.assertRight(asVersionedTransaction(tx, supportedVersions))
|
data.assertRight(asVersionedTransaction(tx, supportedVersions))
|
||||||
|
|
||||||
private[lf] def assignValueVersion(transactionVersion: TransactionVersion): ValueVersion =
|
private[lf] def assignValueVersion(transactionVersion: TransactionVersion): ValueVersion =
|
||||||
latestWhenAllPresent(
|
latestWhenAllPresent(
|
||||||
ValueVersions.SupportedStableVersions.min,
|
ValueVersions.acceptedVersions.head,
|
||||||
transactionVersion,
|
transactionVersion,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -145,7 +147,7 @@ private[lf] object TransactionVersions
|
|||||||
val transactionVersion =
|
val transactionVersion =
|
||||||
VersionTimeline.latestWhenAllPresent(
|
VersionTimeline.latestWhenAllPresent(
|
||||||
supportedTxVersions.min,
|
supportedTxVersions.min,
|
||||||
(SupportedStableOutputVersions.min: SpecifiedVersion) +: as: _*,
|
(DevOutputVersions.min: SpecifiedVersion) +: as: _*,
|
||||||
)
|
)
|
||||||
|
|
||||||
Either.cond(
|
Either.cond(
|
||||||
|
@ -8,7 +8,7 @@ import com.daml.lf.transaction.VersionTimeline
|
|||||||
final case class VersionRange[V](
|
final case class VersionRange[V](
|
||||||
min: V,
|
min: V,
|
||||||
max: V,
|
max: V,
|
||||||
) {
|
)(implicit ev: VersionTimeline.SubVersion[V]) {
|
||||||
import VersionTimeline._
|
import VersionTimeline._
|
||||||
import VersionTimeline.Implicits._
|
import VersionTimeline.Implicits._
|
||||||
|
|
||||||
@ -19,13 +19,10 @@ final case class VersionRange[V](
|
|||||||
max = minVersion(this.max, that.max)
|
max = minVersion(this.max, that.max)
|
||||||
)
|
)
|
||||||
|
|
||||||
def nonEmpty(implicit ev: VersionTimeline.SubVersion[V]): Boolean =
|
def nonEmpty: Boolean =
|
||||||
!(max precedes min)
|
!(max precedes min)
|
||||||
|
|
||||||
def contains(v: V)(implicit ev: VersionTimeline.SubVersion[V]): Boolean =
|
def contains(v: V): Boolean =
|
||||||
!((max precedes v) || (v precedes min))
|
!((max precedes v) || (v precedes min))
|
||||||
|
|
||||||
def map[W](f: V => W): VersionRange[W] =
|
|
||||||
VersionRange(f(min), f(max))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,7 @@ object ValueCoder {
|
|||||||
private[value] def valueToBytes[Cid](
|
private[value] def valueToBytes[Cid](
|
||||||
encodeCid: EncodeCid[Cid],
|
encodeCid: EncodeCid[Cid],
|
||||||
v: Value[Cid],
|
v: Value[Cid],
|
||||||
supportedVersions: VersionRange[ValueVersion] = ValueVersions.SupportedDevVersions,
|
supportedVersions: VersionRange[ValueVersion] = ValueVersions.DevOutputVersions,
|
||||||
): Either[EncodeError, Array[Byte]] =
|
): Either[EncodeError, Array[Byte]] =
|
||||||
encodeVersionedValue(encodeCid, v, supportedVersions).map(_.toByteArray)
|
encodeVersionedValue(encodeCid, v, supportedVersions).map(_.toByteArray)
|
||||||
|
|
||||||
|
@ -30,15 +30,19 @@ private[lf] object ValueVersions
|
|||||||
private[value] val minContractIdV1 = ValueVersion("7")
|
private[value] val minContractIdV1 = ValueVersion("7")
|
||||||
|
|
||||||
// Older versions are deprecated https://github.com/digital-asset/daml/issues/5220
|
// Older versions are deprecated https://github.com/digital-asset/daml/issues/5220
|
||||||
// We force output of recent version, but keep reading older version as long as
|
val StableOutputVersions: VersionRange[ValueVersion] =
|
||||||
// Sandbox is alive.
|
VersionRange(ValueVersion("6"), ValueVersion("6"))
|
||||||
val SupportedStableVersions = VersionRange(ValueVersion("6"), ValueVersion("6"))
|
|
||||||
|
|
||||||
val SupportedDevVersions = SupportedStableVersions.copy(max = acceptedVersions.last)
|
val DevOutputVersions: VersionRange[ValueVersion] =
|
||||||
|
StableOutputVersions.copy(max = acceptedVersions.last)
|
||||||
|
|
||||||
|
// Empty range
|
||||||
|
val Empty: VersionRange[ValueVersion] =
|
||||||
|
VersionRange(acceptedVersions.last, acceptedVersions.head)
|
||||||
|
|
||||||
def assignVersion[Cid](
|
def assignVersion[Cid](
|
||||||
v0: Value[Cid],
|
v0: Value[Cid],
|
||||||
supportedVersions: VersionRange[ValueVersion] = SupportedDevVersions,
|
supportedVersions: VersionRange[ValueVersion] = StableOutputVersions,
|
||||||
): Either[String, ValueVersion] = {
|
): Either[String, ValueVersion] = {
|
||||||
import VersionTimeline.{maxVersion => maxVV}
|
import VersionTimeline.{maxVersion => maxVV}
|
||||||
import VersionTimeline.Implicits._
|
import VersionTimeline.Implicits._
|
||||||
@ -98,20 +102,20 @@ private[lf] object ValueVersions
|
|||||||
@throws[IllegalArgumentException]
|
@throws[IllegalArgumentException]
|
||||||
def assertAssignVersion[Cid](
|
def assertAssignVersion[Cid](
|
||||||
v0: Value[Cid],
|
v0: Value[Cid],
|
||||||
supportedVersions: VersionRange[ValueVersion] = SupportedDevVersions,
|
supportedVersions: VersionRange[ValueVersion] = DevOutputVersions,
|
||||||
): ValueVersion =
|
): ValueVersion =
|
||||||
data.assertRight(assignVersion(v0, supportedVersions))
|
data.assertRight(assignVersion(v0, supportedVersions))
|
||||||
|
|
||||||
def asVersionedValue[Cid](
|
def asVersionedValue[Cid](
|
||||||
value: Value[Cid],
|
value: Value[Cid],
|
||||||
supportedVersions: VersionRange[ValueVersion] = SupportedDevVersions,
|
supportedVersions: VersionRange[ValueVersion] = DevOutputVersions,
|
||||||
): Either[String, VersionedValue[Cid]] =
|
): Either[String, VersionedValue[Cid]] =
|
||||||
assignVersion(value, supportedVersions).map(VersionedValue(_, value))
|
assignVersion(value, supportedVersions).map(VersionedValue(_, value))
|
||||||
|
|
||||||
@throws[IllegalArgumentException]
|
@throws[IllegalArgumentException]
|
||||||
def assertAsVersionedValue[Cid](
|
def assertAsVersionedValue[Cid](
|
||||||
value: Value[Cid],
|
value: Value[Cid],
|
||||||
supportedVersions: VersionRange[ValueVersion] = SupportedDevVersions,
|
supportedVersions: VersionRange[ValueVersion] = DevOutputVersions,
|
||||||
): VersionedValue[Cid] =
|
): VersionedValue[Cid] =
|
||||||
data.assertRight(asVersionedValue(value, supportedVersions))
|
data.assertRight(asVersionedValue(value, supportedVersions))
|
||||||
}
|
}
|
||||||
|
@ -19,9 +19,9 @@ class TransactionVersionSpec extends WordSpec with Matchers with TableDrivenProp
|
|||||||
import VersionTimeline.maxVersion
|
import VersionTimeline.maxVersion
|
||||||
|
|
||||||
private[this] val supportedValVersions =
|
private[this] val supportedValVersions =
|
||||||
ValueVersions.SupportedDevVersions.copy(min = ValueVersion("1"))
|
ValueVersions.DevOutputVersions.copy(min = ValueVersion("1"))
|
||||||
private[this] val supportedTxVersions =
|
private[this] val supportedTxVersions =
|
||||||
TransactionVersions.SupportedDevOutputVersions.copy(min = TransactionVersion("1"))
|
TransactionVersions.DevOutputVersions.copy(min = TransactionVersion("1"))
|
||||||
|
|
||||||
"assignVersion" should {
|
"assignVersion" should {
|
||||||
"prefer picking an older version" in {
|
"prefer picking an older version" in {
|
||||||
@ -139,6 +139,18 @@ class TransactionVersionSpec extends WordSpec with Matchers with TableDrivenProp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"ValueVersions.Empty" should {
|
||||||
|
"be empty" in {
|
||||||
|
ValueVersions.Empty.nonEmpty shouldBe false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"TransactionVersions.Empty" should {
|
||||||
|
"be empty" in {
|
||||||
|
TransactionVersions.Empty.nonEmpty shouldBe false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private[this] def assignValueVersions[Nid, Cid <: ContractId](
|
private[this] def assignValueVersions[Nid, Cid <: ContractId](
|
||||||
t: GenTransaction[Nid, Cid, Value[Cid]],
|
t: GenTransaction[Nid, Cid, Value[Cid]],
|
||||||
): GenTransaction[Nid, Cid, VersionedValue[Cid]] =
|
): GenTransaction[Nid, Cid, VersionedValue[Cid]] =
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
package com.daml.lf.engine.script
|
package com.daml.lf
|
||||||
|
package engine
|
||||||
|
package script
|
||||||
|
|
||||||
import akka.actor.ActorSystem
|
import akka.actor.ActorSystem
|
||||||
import akka.http.scaladsl.Http
|
import akka.http.scaladsl.Http
|
||||||
@ -27,16 +29,12 @@ import spray.json._
|
|||||||
import com.daml.api.util.TimestampConversion
|
import com.daml.api.util.TimestampConversion
|
||||||
import com.daml.grpc.adapter.ExecutionSequencerFactory
|
import com.daml.grpc.adapter.ExecutionSequencerFactory
|
||||||
import com.daml.grpc.adapter.client.akka.ClientAdapter
|
import com.daml.grpc.adapter.client.akka.ClientAdapter
|
||||||
import com.daml.lf.CompiledPackages
|
|
||||||
import com.daml.lf.scenario.ScenarioLedger
|
import com.daml.lf.scenario.ScenarioLedger
|
||||||
import com.daml.lf.crypto
|
|
||||||
import com.daml.lf.data.Ref._
|
import com.daml.lf.data.Ref._
|
||||||
import com.daml.lf.data.{Ref, ImmArray}
|
import com.daml.lf.data.{Ref, ImmArray}
|
||||||
import com.daml.lf.data.{Time}
|
import com.daml.lf.data.{Time}
|
||||||
import com.daml.lf.iface.{EnvironmentInterface, InterfaceType}
|
import com.daml.lf.iface.{EnvironmentInterface, InterfaceType}
|
||||||
import com.daml.lf.language.Ast._
|
import com.daml.lf.language.Ast._
|
||||||
import com.daml.lf.speedy
|
|
||||||
import com.daml.lf.speedy.{InitialSeeding, PartialTransaction}
|
|
||||||
import com.daml.lf.transaction.Node.{NodeCreate, NodeExercises}
|
import com.daml.lf.transaction.Node.{NodeCreate, NodeExercises}
|
||||||
import com.daml.lf.speedy.ScenarioRunner
|
import com.daml.lf.speedy.ScenarioRunner
|
||||||
import com.daml.lf.speedy.Speedy.Machine
|
import com.daml.lf.speedy.Speedy.Machine
|
||||||
@ -321,12 +319,23 @@ class GrpcLedgerClient(val grpcClient: LedgerClient, val applicationId: Applicat
|
|||||||
|
|
||||||
// Client for the script service.
|
// Client for the script service.
|
||||||
class IdeClient(val compiledPackages: CompiledPackages) extends ScriptLedgerClient {
|
class IdeClient(val compiledPackages: CompiledPackages) extends ScriptLedgerClient {
|
||||||
|
private val txSeeding =
|
||||||
|
speedy.InitialSeeding.TransactionSeed(crypto.Hash.hashPrivateKey(s"script-service"))
|
||||||
|
|
||||||
// Machine for scenario expressions.
|
// Machine for scenario expressions.
|
||||||
val machine = Machine.fromPureSExpr(compiledPackages, SEValue(SUnit))
|
val machine = Machine(
|
||||||
|
compiledPackages,
|
||||||
|
submissionTime = Time.Timestamp.Epoch,
|
||||||
|
initialSeeding = txSeeding,
|
||||||
|
expr = null,
|
||||||
|
globalCids = Set.empty,
|
||||||
|
committers = Set.empty,
|
||||||
|
inputValueVersions = value.ValueVersions.DevOutputVersions,
|
||||||
|
outputTransactionVersions = transaction.TransactionVersions.DevOutputVersions,
|
||||||
|
)
|
||||||
|
(compiledPackages, SEValue(SUnit))
|
||||||
val scenarioRunner = ScenarioRunner(machine)
|
val scenarioRunner = ScenarioRunner(machine)
|
||||||
private val txSeeding = crypto.Hash.hashPrivateKey(s"script-service")
|
|
||||||
machine.ptx =
|
|
||||||
PartialTransaction.initial(Time.Timestamp.MinValue, InitialSeeding.TransactionSeed(txSeeding))
|
|
||||||
override def query(party: SParty, templateId: Identifier)(
|
override def query(party: SParty, templateId: Identifier)(
|
||||||
implicit ec: ExecutionContext,
|
implicit ec: ExecutionContext,
|
||||||
mat: Materializer): Future[Seq[ScriptLedgerClient.ActiveContract]] = {
|
mat: Materializer): Future[Seq[ScriptLedgerClient.ActiveContract]] = {
|
||||||
|
@ -123,7 +123,7 @@ private[daml] object ApiServices {
|
|||||||
private def createServices(ledgerId: LedgerId, ledgerConfigProvider: LedgerConfigProvider)(
|
private def createServices(ledgerId: LedgerId, ledgerConfigProvider: LedgerConfigProvider)(
|
||||||
implicit executionContext: ExecutionContext): List[BindableService] = {
|
implicit executionContext: ExecutionContext): List[BindableService] = {
|
||||||
|
|
||||||
logger.info(engine.info.show)
|
engine.info.pretty.foreach(logger.info(_))
|
||||||
|
|
||||||
val apiTransactionService =
|
val apiTransactionService =
|
||||||
ApiTransactionService.create(ledgerId, transactionsService)
|
ApiTransactionService.create(ledgerId, transactionsService)
|
||||||
|
Loading…
Reference in New Issue
Block a user