LF: control of input value version in the engine (#6828)

CHANGELOG_BEGIN
CHANGELOG_END
This commit is contained in:
Remy 2020-08-13 21:15:52 +02:00 committed by GitHub
parent a890618782
commit 66ae38da6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 313 additions and 160 deletions

View File

@ -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,
) )
} }

View File

@ -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
} }

View File

@ -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}"
) )
) )

View File

@ -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"))
) )
} }

View File

@ -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(", ")
} }

View File

@ -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."
} }

View File

@ -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))
) )
) )

View File

@ -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")

View File

@ -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")
} }

View File

@ -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)
} }
} }

View File

@ -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)
}, },
), ),
) )

View File

@ -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(

View File

@ -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
} }
} }

View File

@ -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]

View File

@ -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())
} }

View File

@ -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) =>

View File

@ -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

View File

@ -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 {

View File

@ -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)

View File

@ -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(

View File

@ -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))
} }

View File

@ -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)

View File

@ -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))
} }

View File

@ -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]] =

View File

@ -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]] = {

View File

@ -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)