mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-19 16:57:40 +03:00
kvutils: Extract a SimplePackage class from TestHelpers. [KVL-759] (#8203)
* kvutils: Simplify KVTest a little. * kvutils: Split out a SimplePackage manager from TestHelpers. In an effort to clean up the TestHelpers and associated calls, I have extracted a class that takes the additional contract data type _once_. It also provides a useful place to move associated methods and values. CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
f7465f0646
commit
c588b5cc34
@ -12,10 +12,10 @@ import com.daml.ledger.participant.state.kvutils.KeyValueCommitting.PreExecution
|
||||
import com.daml.ledger.participant.state.v1._
|
||||
import com.daml.lf.command.{Command, Commands}
|
||||
import com.daml.lf.crypto
|
||||
import com.daml.lf.crypto.Hash
|
||||
import com.daml.lf.data.Time.Timestamp
|
||||
import com.daml.lf.data.{ImmArray, Ref}
|
||||
import com.daml.lf.engine.Engine
|
||||
import com.daml.lf.language.Ast
|
||||
import com.daml.lf.transaction.Transaction
|
||||
import com.daml.metrics.Metrics
|
||||
import scalaz.State
|
||||
@ -30,7 +30,12 @@ final case class KVTestState(
|
||||
recordTime: Timestamp,
|
||||
defaultConfig: Configuration,
|
||||
nextEntryId: Int,
|
||||
damlState: Map[DamlStateKey, DamlStateValue]) {}
|
||||
engine: Engine,
|
||||
keyValueSubmission: KeyValueSubmission,
|
||||
keyValueCommitting: KeyValueCommitting,
|
||||
uploadedPackages: Map[Ref.PackageId, Ast.Package],
|
||||
damlState: Map[DamlStateKey, DamlStateValue],
|
||||
)
|
||||
|
||||
object KVTest {
|
||||
|
||||
@ -39,38 +44,53 @@ object KVTest {
|
||||
|
||||
type KVTest[A] = State[KVTestState, A]
|
||||
|
||||
def initialTestState: KVTestState =
|
||||
private[this] val MinMaxRecordTimeDelta: Duration = Duration.ofSeconds(1)
|
||||
private[this] val DefaultAdditionalContractDataType: String = "Party"
|
||||
private[this] val DefaultSimplePackage: SimplePackage = new SimplePackage(
|
||||
DefaultAdditionalContractDataType)
|
||||
|
||||
private[kvutils] val metrics = new Metrics(new MetricRegistry)
|
||||
|
||||
private def initialTestState: KVTestState = {
|
||||
val engine = Engine.DevEngine()
|
||||
KVTestState(
|
||||
participantId = mkParticipantId(0),
|
||||
recordTime = Timestamp.Epoch.addMicros(1000000),
|
||||
defaultConfig = theDefaultConfig,
|
||||
nextEntryId = 0,
|
||||
damlState = Map.empty
|
||||
engine = engine,
|
||||
keyValueSubmission = new KeyValueSubmission(metrics),
|
||||
keyValueCommitting = new KeyValueCommitting(engine, metrics),
|
||||
uploadedPackages = Map.empty,
|
||||
damlState = Map.empty,
|
||||
)
|
||||
}
|
||||
|
||||
def runTest[A](test: KVTest[A]): A =
|
||||
test.eval(initialTestState)
|
||||
|
||||
def runTestWithPackage[A](additionalContractDataTy: String, parties: Party*)(test: KVTest[A]): A =
|
||||
def runTestWithPackage[A](simplePackage: SimplePackage, parties: Party*)(test: KVTest[A]): A =
|
||||
(for {
|
||||
_ <- uploadArchive(additionalContractDataTy)
|
||||
_ <- uploadArchive(simplePackage)
|
||||
_ <- parties.toList.traverse(p => allocateParty(p, p))
|
||||
r <- test
|
||||
} yield r).eval(initialTestState)
|
||||
|
||||
def runTestWithSimplePackage[A](parties: Party*)(test: KVTest[A]): A =
|
||||
runTestWithPackage(DefaultAdditionalContractDataTy, parties: _*)(test)
|
||||
def runTestWithSimplePackage[A](parties: Party*)(test: SimplePackage => KVTest[A]): A =
|
||||
runTestWithPackage(DefaultSimplePackage, parties: _*)(test(DefaultSimplePackage))
|
||||
|
||||
def uploadArchive(additionalContractDataTy: String): KVTest[Unit] =
|
||||
private def uploadArchive(simplePackage: SimplePackage): KVTest[Unit] =
|
||||
for {
|
||||
archiveLogEntry <- submitArchives(
|
||||
"simple-archive-submission",
|
||||
archiveWithContractData(additionalContractDataTy)).map(_._2)
|
||||
simplePackage.archive,
|
||||
).map(_._2)
|
||||
_ = assert(archiveLogEntry.getPayloadCase == DamlLogEntry.PayloadCase.PACKAGE_UPLOAD_ENTRY)
|
||||
_ <- modify[KVTestState](state =>
|
||||
state.copy(
|
||||
uploadedPackages = state.uploadedPackages + (simplePackage.packageId -> simplePackage.damlPackageWithContractData)))
|
||||
} yield ()
|
||||
|
||||
def uploadSimpleArchive: KVTest[Unit] = uploadArchive(DefaultAdditionalContractDataTy)
|
||||
|
||||
def freshEntryId: KVTest.KVTest[DamlLogEntryId] =
|
||||
for {
|
||||
s <- get
|
||||
@ -137,16 +157,15 @@ object KVTest {
|
||||
def runCommand(
|
||||
submitter: Party,
|
||||
submissionSeed: crypto.Hash,
|
||||
additionalContractDataTy: String,
|
||||
cmds: Command*,
|
||||
command: Command,
|
||||
): KVTest[(SubmittedTransaction, Transaction.Metadata)] =
|
||||
for {
|
||||
s <- get[KVTestState]
|
||||
(tx, meta) = engine
|
||||
(tx, meta) = s.engine
|
||||
.submit(
|
||||
cmds = Commands(
|
||||
submitters = Set(submitter),
|
||||
commands = ImmArray(cmds),
|
||||
commands = ImmArray(command),
|
||||
ledgerEffectiveTime = s.recordTime,
|
||||
commandsReference = "cmds-ref",
|
||||
),
|
||||
@ -154,17 +173,17 @@ object KVTest {
|
||||
submissionSeed = submissionSeed,
|
||||
)
|
||||
.consume(
|
||||
{ coid =>
|
||||
pcs = contractId =>
|
||||
s.damlState
|
||||
.get(Conversions.contractIdToStateKey(coid))
|
||||
.get(Conversions.contractIdToStateKey(contractId))
|
||||
.map { v =>
|
||||
Conversions.decodeContractInstance(v.getContractState.getContractInstance)
|
||||
}
|
||||
}, { _ =>
|
||||
Some(decodedPackageWithContractData(additionalContractDataTy))
|
||||
}, { _ =>
|
||||
sys.error("no keys")
|
||||
}
|
||||
},
|
||||
packages = s.uploadedPackages.get,
|
||||
keys = globalKey =>
|
||||
s.damlState
|
||||
.get(Conversions.globalKeyToStateKey(globalKey.globalKey))
|
||||
.map(value => Conversions.decodeContractId(value.getContractKeyState.getContractId)),
|
||||
)
|
||||
.getOrElse(sys.error("Engine.submit fail"))
|
||||
} yield tx -> meta
|
||||
@ -172,9 +191,9 @@ object KVTest {
|
||||
def runSimpleCommand(
|
||||
submitter: Party,
|
||||
submissionSeed: crypto.Hash,
|
||||
cmds: Command*,
|
||||
command: Command,
|
||||
): KVTest[(SubmittedTransaction, Transaction.Metadata)] =
|
||||
runCommand(submitter, submissionSeed, DefaultAdditionalContractDataTy, cmds: _*)
|
||||
runCommand(submitter, submissionSeed, command)
|
||||
|
||||
def submitTransaction(
|
||||
submitter: Party,
|
||||
@ -182,20 +201,16 @@ object KVTest {
|
||||
submissionSeed: crypto.Hash,
|
||||
letDelta: Duration = Duration.ZERO,
|
||||
commandId: CommandId = randomLedgerString,
|
||||
deduplicationTime: Duration = Duration.ofDays(1)): KVTest[(DamlLogEntryId, DamlLogEntry)] =
|
||||
for {
|
||||
testState <- get[KVTestState]
|
||||
submissionInfo = createSubmitterInfo(submitter, commandId, deduplicationTime, testState)
|
||||
(tx, txMetaData) = transaction
|
||||
submission = transactionToSubmission(
|
||||
submissionSeed,
|
||||
letDelta,
|
||||
testState,
|
||||
submissionInfo,
|
||||
tx,
|
||||
txMetaData)
|
||||
result <- submit(submission)
|
||||
} yield result
|
||||
deduplicationTime: Duration = Duration.ofDays(1),
|
||||
): KVTest[(DamlLogEntryId, DamlLogEntry)] =
|
||||
prepareTransactionSubmission(
|
||||
submitter,
|
||||
transaction,
|
||||
submissionSeed,
|
||||
letDelta,
|
||||
commandId,
|
||||
deduplicationTime,
|
||||
).flatMap(submit)
|
||||
|
||||
def preExecuteTransaction(
|
||||
submitter: Party,
|
||||
@ -203,21 +218,49 @@ object KVTest {
|
||||
submissionSeed: crypto.Hash,
|
||||
letDelta: Duration = Duration.ZERO,
|
||||
commandId: CommandId = randomLedgerString,
|
||||
deduplicationTime: Duration = Duration.ofDays(1))
|
||||
: KVTest[(DamlLogEntryId, PreExecutionResult)] =
|
||||
deduplicationTime: Duration = Duration.ofDays(1),
|
||||
): KVTest[(DamlLogEntryId, PreExecutionResult)] =
|
||||
prepareTransactionSubmission(
|
||||
submitter,
|
||||
transaction,
|
||||
submissionSeed,
|
||||
letDelta,
|
||||
commandId,
|
||||
deduplicationTime,
|
||||
).flatMap(preExecute)
|
||||
|
||||
def prepareTransactionSubmission(
|
||||
submitter: Party,
|
||||
transaction: (SubmittedTransaction, Transaction.Metadata),
|
||||
submissionSeed: crypto.Hash,
|
||||
letDelta: Duration,
|
||||
commandId: CommandId,
|
||||
deduplicationTime: Duration,
|
||||
): KVTest[DamlSubmission] = {
|
||||
val (tx, txMetaData) = transaction
|
||||
for {
|
||||
testState <- get[KVTestState]
|
||||
submitterInfo = createSubmitterInfo(submitter, commandId, deduplicationTime, testState)
|
||||
(tx, txMetaData) = transaction
|
||||
submission = transactionToSubmission(
|
||||
submissionSeed,
|
||||
letDelta,
|
||||
testState,
|
||||
submitterInfo,
|
||||
tx,
|
||||
txMetaData)
|
||||
result <- preExecute(submission)
|
||||
} yield result
|
||||
submitterInfo = createSubmitterInfo(
|
||||
submitter,
|
||||
commandId,
|
||||
deduplicationTime,
|
||||
testState.recordTime,
|
||||
)
|
||||
} yield
|
||||
testState.keyValueSubmission.transactionToSubmission(
|
||||
submitterInfo = submitterInfo,
|
||||
meta = TransactionMeta(
|
||||
ledgerEffectiveTime = testState.recordTime.addMicros(letDelta.toNanos / 1000),
|
||||
workflowId = None,
|
||||
submissionTime = txMetaData.submissionTime,
|
||||
submissionSeed = submissionSeed,
|
||||
optUsedPackages = Some(txMetaData.usedPackages),
|
||||
optNodeSeeds = None,
|
||||
optByKeyNodes = None,
|
||||
),
|
||||
tx = tx
|
||||
)
|
||||
}
|
||||
|
||||
def submitConfig(
|
||||
configModify: Configuration => Configuration,
|
||||
@ -258,18 +301,21 @@ object KVTest {
|
||||
def submitPartyAllocation(
|
||||
subId: String,
|
||||
hint: String,
|
||||
participantId: ParticipantId): KVTest[DamlLogEntry] =
|
||||
submit(
|
||||
createPartySubmission(subId, hint, participantId)
|
||||
).map(_._2)
|
||||
participantId: ParticipantId,
|
||||
): KVTest[DamlLogEntry] =
|
||||
get[KVTestState]
|
||||
.flatMap(testState => submit(createPartySubmission(subId, hint, participantId, testState)))
|
||||
.map(_._2)
|
||||
|
||||
def preExecutePartyAllocation(
|
||||
subId: String,
|
||||
hint: String,
|
||||
participantId: ParticipantId): KVTest[PreExecutionResult] =
|
||||
preExecute(
|
||||
createPartySubmission(subId, hint, participantId)
|
||||
).map(_._2)
|
||||
participantId: ParticipantId,
|
||||
): KVTest[PreExecutionResult] =
|
||||
get[KVTestState]
|
||||
.flatMap(testState =>
|
||||
preExecute(createPartySubmission(subId, hint, participantId, testState)))
|
||||
.map(_._2)
|
||||
|
||||
def allocateParty(subId: String, hint: String): KVTest[Party] =
|
||||
for {
|
||||
@ -284,7 +330,7 @@ object KVTest {
|
||||
for {
|
||||
testState <- get[KVTestState]
|
||||
entryId <- freshEntryId
|
||||
(logEntry, newState) = keyValueCommitting.processSubmission(
|
||||
(logEntry, newState) = testState.keyValueCommitting.processSubmission(
|
||||
entryId = entryId,
|
||||
recordTime = testState.recordTime,
|
||||
defaultConfig = testState.defaultConfig,
|
||||
@ -307,24 +353,19 @@ object KVTest {
|
||||
}
|
||||
|
||||
private def preExecute(
|
||||
damlSubmission: DamlSubmission): KVTest[(DamlLogEntryId, PreExecutionResult)] =
|
||||
damlSubmission: DamlSubmission,
|
||||
): KVTest[(DamlLogEntryId, PreExecutionResult)] =
|
||||
for {
|
||||
testState <- get[KVTestState]
|
||||
entryId <- freshEntryId
|
||||
inputKeys = damlSubmission.getInputDamlStateList.asScala
|
||||
preExecutionResult @ PreExecutionResult(
|
||||
readSet,
|
||||
successfulLogEntry,
|
||||
newState,
|
||||
outOfTimeBoundsLogEntry,
|
||||
_,
|
||||
_) = keyValueCommitting
|
||||
.preExecuteSubmission(
|
||||
defaultConfig = testState.defaultConfig,
|
||||
submission = damlSubmission,
|
||||
participantId = testState.participantId,
|
||||
inputState = createInputState(inputKeys, testState),
|
||||
)
|
||||
preExecutionResult = testState.keyValueCommitting.preExecuteSubmission(
|
||||
defaultConfig = testState.defaultConfig,
|
||||
submission = damlSubmission,
|
||||
participantId = testState.participantId,
|
||||
inputState = createInputState(inputKeys, testState),
|
||||
)
|
||||
PreExecutionResult(readSet, successfulLogEntry, newState, outOfTimeBoundsLogEntry, _, _) = preExecutionResult
|
||||
_ <- addDamlState(newState)
|
||||
} yield {
|
||||
assert(
|
||||
@ -343,13 +384,6 @@ object KVTest {
|
||||
entryId -> preExecutionResult
|
||||
}
|
||||
|
||||
private[this] val MinMaxRecordTimeDelta: Duration = Duration.ofSeconds(1)
|
||||
private[this] val DefaultAdditionalContractDataTy = "Party"
|
||||
private[this] val engine = Engine.DevEngine()
|
||||
private[kvutils] val metrics = new Metrics(new MetricRegistry)
|
||||
private[this] val keyValueCommitting = new KeyValueCommitting(engine, metrics)
|
||||
private[this] val keyValueSubmission = new KeyValueSubmission(metrics)
|
||||
|
||||
private[this] def createInputState(
|
||||
inputKeys: mutable.Buffer[DamlStateKey],
|
||||
testState: KVTestState): Map[DamlStateKey, Option[DamlStateValue]] = {
|
||||
@ -362,44 +396,26 @@ object KVTest {
|
||||
}.toMap
|
||||
}
|
||||
|
||||
private[this] def createSubmitterInfo(
|
||||
private def createSubmitterInfo(
|
||||
submitter: Party,
|
||||
commandId: CommandId,
|
||||
deduplicationTime: Duration,
|
||||
testState: KVTestState): SubmitterInfo =
|
||||
recordTime: Timestamp,
|
||||
): SubmitterInfo =
|
||||
SubmitterInfo.withSingleSubmitter(
|
||||
submitter = submitter,
|
||||
applicationId = Ref.LedgerString.assertFromString("test"),
|
||||
commandId = commandId,
|
||||
deduplicateUntil = testState.recordTime.addMicros(deduplicationTime.toNanos / 1000).toInstant,
|
||||
)
|
||||
|
||||
private[this] def transactionToSubmission(
|
||||
submissionSeed: Hash,
|
||||
letDelta: Duration,
|
||||
testState: KVTestState,
|
||||
submInfo: SubmitterInfo,
|
||||
tx: SubmittedTransaction,
|
||||
txMetaData: Transaction.Metadata): DamlSubmission =
|
||||
keyValueSubmission.transactionToSubmission(
|
||||
submitterInfo = submInfo,
|
||||
meta = TransactionMeta(
|
||||
ledgerEffectiveTime = testState.recordTime.addMicros(letDelta.toNanos / 1000),
|
||||
workflowId = None,
|
||||
submissionTime = txMetaData.submissionTime,
|
||||
submissionSeed = submissionSeed,
|
||||
optUsedPackages = Some(txMetaData.usedPackages),
|
||||
optNodeSeeds = None,
|
||||
optByKeyNodes = None,
|
||||
),
|
||||
tx = tx
|
||||
deduplicateUntil = recordTime.addMicros(deduplicationTime.toNanos / 1000).toInstant,
|
||||
)
|
||||
|
||||
private[this] def createPartySubmission(
|
||||
subId: String,
|
||||
hint: String,
|
||||
participantId: ParticipantId): DamlSubmission =
|
||||
keyValueSubmission.partyToSubmission(
|
||||
participantId: ParticipantId,
|
||||
testState: KVTestState,
|
||||
): DamlSubmission =
|
||||
testState.keyValueSubmission.partyToSubmission(
|
||||
Ref.LedgerString.assertFromString(subId),
|
||||
Some(hint),
|
||||
None,
|
||||
@ -410,8 +426,9 @@ object KVTest {
|
||||
submissionId: SubmissionId,
|
||||
minMaxRecordTimeDelta: Duration,
|
||||
testState: KVTestState,
|
||||
oldConf: Configuration): DamlSubmission =
|
||||
keyValueSubmission.configurationToSubmission(
|
||||
oldConf: Configuration,
|
||||
): DamlSubmission =
|
||||
testState.keyValueSubmission.configurationToSubmission(
|
||||
maxRecordTime = testState.recordTime.addMicros(minMaxRecordTimeDelta.toNanos / 1000),
|
||||
submissionId = submissionId,
|
||||
participantId = testState.participantId,
|
||||
@ -421,8 +438,9 @@ object KVTest {
|
||||
private[this] def createArchiveSubmission(
|
||||
submissionId: String,
|
||||
testState: KVTestState,
|
||||
archives: DamlLf.Archive*): DamlSubmission =
|
||||
keyValueSubmission.archivesToSubmission(
|
||||
archives: DamlLf.Archive*,
|
||||
): DamlSubmission =
|
||||
testState.keyValueSubmission.archivesToSubmission(
|
||||
submissionId = submissionId,
|
||||
archives = archives.toList,
|
||||
sourceDescription = "description",
|
||||
|
@ -0,0 +1,132 @@
|
||||
// Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.ledger.participant.state.kvutils
|
||||
|
||||
import com.daml.daml_lf_dev.DamlLf
|
||||
import com.daml.lf.archive.testing.Encode
|
||||
import com.daml.lf.command.{
|
||||
Command,
|
||||
CreateAndExerciseCommand,
|
||||
CreateCommand,
|
||||
ExerciseByKeyCommand,
|
||||
ExerciseCommand
|
||||
}
|
||||
import com.daml.lf.data.Ref.QualifiedName
|
||||
import com.daml.lf.data.{ImmArray, Ref}
|
||||
import com.daml.lf.language.{Ast, LanguageVersion}
|
||||
import com.daml.lf.testing.parser.Implicits._
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.lf.value.Value.{ValueParty, ValueUnit}
|
||||
|
||||
class SimplePackage(additionalContractDataType: String) {
|
||||
val damlPackageWithContractData: Ast.Package =
|
||||
p"""
|
||||
module DA.Types {
|
||||
record @serializable Tuple2 (a: *) (b: *) = { x1: a, x2: b } ;
|
||||
}
|
||||
|
||||
module Simple {
|
||||
record @serializable SimpleTemplate = { owner: Party, observer: Party, contractData: $additionalContractDataType } ;
|
||||
variant @serializable SimpleVariant = SV: Party ;
|
||||
template (this : SimpleTemplate) = {
|
||||
precondition True,
|
||||
signatories Cons @Party [Simple:SimpleTemplate {owner} this] (Nil @Party),
|
||||
observers Cons @Party [Simple:SimpleTemplate {observer} this] (Nil @Party),
|
||||
agreement "",
|
||||
choices {
|
||||
choice Consume (self) (x: Unit) : Unit, controllers Cons @Party [Simple:SimpleTemplate {owner} this] (Nil @Party) to upure @Unit ()
|
||||
},
|
||||
key @Party (Simple:SimpleTemplate {owner} this) (\ (p: Party) -> Cons @Party [p] (Nil @Party))
|
||||
} ;
|
||||
}
|
||||
"""
|
||||
|
||||
val packageId: Ref.PackageId =
|
||||
defaultParserParameters.defaultPackageId
|
||||
|
||||
val decodedPackage: Ast.Package = {
|
||||
val metadata = if (LanguageVersion.ordering
|
||||
.gteq(defaultParserParameters.languageVersion, LanguageVersion.Features.packageMetadata)) {
|
||||
Some(
|
||||
Ast.PackageMetadata(
|
||||
Ref.PackageName.assertFromString("kvutils-tests"),
|
||||
Ref.PackageVersion.assertFromString("1.0.0")))
|
||||
} else None
|
||||
damlPackageWithContractData.copy(metadata = metadata)
|
||||
}
|
||||
|
||||
val archive: DamlLf.Archive = {
|
||||
Encode.encodeArchive(
|
||||
packageId -> decodedPackage,
|
||||
defaultParserParameters.languageVersion,
|
||||
)
|
||||
}
|
||||
|
||||
val archiveHash: String =
|
||||
archive.getHash
|
||||
|
||||
def typeConstructorId(typeConstructor: String): Ref.Identifier =
|
||||
Ref.Identifier(packageId, QualifiedName.assertFromString(typeConstructor))
|
||||
|
||||
def createCmd(templateId: Ref.Identifier, templateArg: Value[Value.ContractId]): Command =
|
||||
CreateCommand(templateId, templateArg)
|
||||
|
||||
def exerciseCmd(
|
||||
contractId: Value.ContractId,
|
||||
templateId: Ref.Identifier,
|
||||
choiceName: Ref.ChoiceName,
|
||||
): Command =
|
||||
ExerciseCommand(templateId, contractId, choiceName, ValueUnit)
|
||||
|
||||
def exerciseByKeyCmd(
|
||||
partyKey: Ref.Party,
|
||||
templateId: Ref.Identifier,
|
||||
choiceName: Ref.ChoiceName,
|
||||
): Command =
|
||||
ExerciseByKeyCommand(templateId, ValueParty(partyKey), choiceName, ValueUnit)
|
||||
|
||||
def createAndExerciseCmd(
|
||||
templateId: Ref.Identifier,
|
||||
templateArg: Value[Value.ContractId],
|
||||
choiceName: Ref.ChoiceName,
|
||||
): Command =
|
||||
CreateAndExerciseCommand(templateId, templateArg, choiceName, ValueUnit)
|
||||
|
||||
private val simpleTemplateId: Ref.Identifier =
|
||||
Ref.Identifier(
|
||||
packageId,
|
||||
Ref.QualifiedName(
|
||||
Ref.ModuleName.assertFromString("Simple"),
|
||||
Ref.DottedName.assertFromString("SimpleTemplate")
|
||||
)
|
||||
)
|
||||
|
||||
private val simpleConsumeChoiceName: Ref.ChoiceName =
|
||||
Ref.ChoiceName.assertFromString("Consume")
|
||||
|
||||
def simpleCreateCmd(templateArg: Value[Value.ContractId]): Command =
|
||||
createCmd(simpleTemplateId, templateArg)
|
||||
|
||||
def simpleExerciseConsumeCmd(contractId: Value.ContractId): Command =
|
||||
exerciseCmd(contractId, simpleTemplateId, simpleConsumeChoiceName)
|
||||
|
||||
def simpleCreateAndExerciseConsumeCmd(templateArg: Value[Value.ContractId]): Command =
|
||||
createAndExerciseCmd(simpleTemplateId, templateArg, simpleConsumeChoiceName)
|
||||
|
||||
def mkSimpleTemplateArg(
|
||||
owner: String,
|
||||
observer: String,
|
||||
additionalContractValue: Value[Value.ContractId],
|
||||
): Value[Value.ContractId] =
|
||||
Value.ValueRecord(
|
||||
Some(simpleTemplateId),
|
||||
ImmArray(
|
||||
Some(Ref.Name.assertFromString("owner")) -> Value.ValueParty(
|
||||
Ref.Party.assertFromString(owner)),
|
||||
Some(Ref.Name.assertFromString("observer")) -> Value.ValueParty(
|
||||
Ref.Party.assertFromString(observer)),
|
||||
Some(Ref.Name.assertFromString("contractData")) -> additionalContractValue
|
||||
)
|
||||
)
|
||||
}
|
@ -10,103 +10,20 @@ import com.daml.daml_lf_dev.DamlLf
|
||||
import com.daml.ledger.participant.state.kvutils.DamlKvutils.DamlLogEntryId
|
||||
import com.daml.ledger.participant.state.kvutils.committer.CommitContext
|
||||
import com.daml.ledger.participant.state.v1.{Configuration, ParticipantId, TimeModel}
|
||||
import com.daml.lf.archive.Decode
|
||||
import com.daml.lf.archive.testing.Encode
|
||||
import com.daml.lf.data.Ref.{IdString, QualifiedName}
|
||||
import com.daml.lf.data.Ref
|
||||
import com.daml.lf.data.Time.Timestamp
|
||||
import com.daml.lf.data.{ImmArray, Ref}
|
||||
import com.daml.lf.language.{Ast, LanguageVersion}
|
||||
import com.daml.lf.testing.parser.Implicits._
|
||||
import com.daml.lf.value.Value
|
||||
import com.google.protobuf.ByteString
|
||||
|
||||
object TestHelpers {
|
||||
|
||||
def damlPackageWithContractData(additionalContractDataType: String): Ast.Package =
|
||||
p"""
|
||||
module DA.Types {
|
||||
record @serializable Tuple2 (a: *) (b: *) = { x1: a, x2: b } ;
|
||||
}
|
||||
|
||||
module Simple {
|
||||
record @serializable SimpleTemplate = { owner: Party, observer: Party, contractData: $additionalContractDataType } ;
|
||||
variant @serializable SimpleVariant = SV: Party ;
|
||||
template (this : SimpleTemplate) = {
|
||||
precondition True,
|
||||
signatories Cons @Party [Simple:SimpleTemplate {owner} this] (Nil @Party),
|
||||
observers Cons @Party [Simple:SimpleTemplate {observer} this] (Nil @Party),
|
||||
agreement "",
|
||||
choices {
|
||||
choice Consume (self) (x: Unit) : Unit, controllers Cons @Party [Simple:SimpleTemplate {owner} this] (Nil @Party) to upure @Unit ()
|
||||
},
|
||||
key @Party (Simple:SimpleTemplate {owner} this) (\ (p: Party) -> Cons @Party [p] (Nil @Party))
|
||||
} ;
|
||||
}
|
||||
"""
|
||||
|
||||
def archiveWithContractData(additionalContractDataType: String): DamlLf.Archive = {
|
||||
val metadata = if (LanguageVersion.ordering
|
||||
.gteq(defaultParserParameters.languageVersion, LanguageVersion.Features.packageMetadata)) {
|
||||
Some(
|
||||
Ast.PackageMetadata(
|
||||
Ref.PackageName.assertFromString("kvutils-tests"),
|
||||
Ref.PackageVersion.assertFromString("1.0.0")))
|
||||
} else None
|
||||
val pkg = damlPackageWithContractData(additionalContractDataType).copy(metadata = metadata)
|
||||
|
||||
Encode.encodeArchive(
|
||||
defaultParserParameters.defaultPackageId -> pkg,
|
||||
defaultParserParameters.languageVersion)
|
||||
}
|
||||
|
||||
def packageIdWithContractData(additionalContractDataType: String): IdString.PackageId =
|
||||
Ref.PackageId.assertFromString(archiveWithContractData(additionalContractDataType).getHash)
|
||||
|
||||
def typeConstructorId(ty: String, typeConstructor: String): Ref.Identifier =
|
||||
Ref.Identifier(packageIdWithContractData(ty), QualifiedName.assertFromString(typeConstructor))
|
||||
|
||||
def typeConstructorId(ty: String): Ref.Identifier = typeConstructorId(ty, ty)
|
||||
|
||||
def name(value: String): Ref.Name = Ref.Name.assertFromString(value)
|
||||
|
||||
def party(value: String): Ref.Party = Ref.Party.assertFromString(value)
|
||||
|
||||
def decodedPackageWithContractData(additionalContractDataType: String): Ast.Package =
|
||||
Decode.decodeArchive(archiveWithContractData(additionalContractDataType))._2
|
||||
|
||||
val badArchive: DamlLf.Archive =
|
||||
DamlLf.Archive.newBuilder
|
||||
.setHash("blablabla")
|
||||
.build
|
||||
|
||||
val simpleConsumeChoiceid: Ref.ChoiceName =
|
||||
Ref.ChoiceName.assertFromString("Consume")
|
||||
|
||||
def mkTemplateArg(
|
||||
owner: String,
|
||||
observer: String,
|
||||
additionalContractDataType: String,
|
||||
additionalContractValue: Value[Value.ContractId]): Value[Value.ContractId] =
|
||||
Value.ValueRecord(
|
||||
Some(templateIdWith(additionalContractDataType)),
|
||||
ImmArray(
|
||||
Some(Ref.Name.assertFromString("owner")) -> Value.ValueParty(
|
||||
Ref.Party.assertFromString(owner)),
|
||||
Some(Ref.Name.assertFromString("observer")) -> Value.ValueParty(
|
||||
Ref.Party.assertFromString(observer)),
|
||||
Some(Ref.Name.assertFromString("contractData")) -> additionalContractValue
|
||||
)
|
||||
)
|
||||
|
||||
def templateIdWith(additionalContractDataType: String): Ref.Identifier =
|
||||
Ref.Identifier(
|
||||
packageIdWithContractData(additionalContractDataType),
|
||||
Ref.QualifiedName(
|
||||
Ref.ModuleName.assertFromString("Simple"),
|
||||
Ref.DottedName.assertFromString("SimpleTemplate")
|
||||
)
|
||||
)
|
||||
|
||||
val theRecordTime: Timestamp = Timestamp.Epoch
|
||||
val theDefaultConfig: Configuration = Configuration(
|
||||
generation = 0,
|
||||
|
@ -158,7 +158,7 @@ class KVUtilsConfigSpec extends AnyWordSpec with Matchers {
|
||||
}
|
||||
}
|
||||
|
||||
"update metrics" in KVTest.runTestWithSimplePackage() {
|
||||
"update metrics" in KVTest.runTest {
|
||||
for {
|
||||
//Submit config twice to force one acceptance and one rejection on duplicate
|
||||
_ <- submitConfig({ c =>
|
||||
|
@ -12,6 +12,7 @@ import com.daml.ledger.participant.state.kvutils.DamlKvutils.{
|
||||
DamlPackageUploadRejectionEntry
|
||||
}
|
||||
import com.daml.lf.archive.DarReader
|
||||
import com.daml.lf.data.Ref
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
@ -25,9 +26,11 @@ class KVUtilsPackageSpec extends AnyWordSpec with Matchers with BazelRunfiles {
|
||||
private val darReader = DarReader { case (_, is) => Try(DamlLf.Archive.parseFrom(is)) }
|
||||
|
||||
private def darFile = new File(rlocation("ledger/test-common/model-tests.dar"))
|
||||
|
||||
private val testStablePackages = darReader.readArchiveFromFile(darFile).get
|
||||
|
||||
private val simpleArchive = archiveWithContractData("Party")
|
||||
private val simplePackage = new SimplePackage("Party")
|
||||
private val simpleArchive = simplePackage.archive
|
||||
|
||||
"packages" should {
|
||||
"be able to submit simple package" in KVTest.runTest {
|
||||
@ -35,7 +38,7 @@ class KVUtilsPackageSpec extends AnyWordSpec with Matchers with BazelRunfiles {
|
||||
// NOTE(JM): 'runTest' always uploads 'simpleArchive' by default.
|
||||
logEntry <- submitArchives("simple-archive-submission-1", simpleArchive).map(_._2)
|
||||
archiveState <- getDamlState(
|
||||
Conversions.packageStateKey(packageIdWithContractData("Party")))
|
||||
Conversions.packageStateKey(Ref.PackageId.assertFromString(simplePackage.archiveHash)))
|
||||
|
||||
// Submit again and verify that the uploaded archive didn't appear again.
|
||||
logEntry2 <- submitArchives("simple-archive-submission-2", simpleArchive)
|
||||
@ -97,7 +100,7 @@ class KVUtilsPackageSpec extends AnyWordSpec with Matchers with BazelRunfiles {
|
||||
}
|
||||
}
|
||||
|
||||
"update metrics" in KVTest.runTestWithSimplePackage() {
|
||||
"update metrics" in KVTest.runTest {
|
||||
for {
|
||||
//Submit archive twice to force one acceptance and one rejection on duplicate
|
||||
_ <- submitArchives("simple-archive-submission-1", simpleArchive).map(_._2)
|
||||
|
@ -84,7 +84,7 @@ class KVUtilsPartySpec extends AnyWordSpec with Matchers {
|
||||
}
|
||||
}
|
||||
|
||||
"update metrics" in KVTest.runTestWithSimplePackage() {
|
||||
"update metrics" in KVTest.runTest {
|
||||
for {
|
||||
//Submit party twice to force one acceptance and one rejection on duplicate
|
||||
_ <- submitPartyAllocation("submission-1", "alice", p0)
|
||||
|
@ -9,9 +9,9 @@ import com.daml.ledger.participant.state.kvutils.DamlKvutils.{
|
||||
}
|
||||
import com.daml.ledger.participant.state.kvutils.TestHelpers._
|
||||
import com.daml.ledger.participant.state.v1.Update
|
||||
import com.daml.lf.command.{Command, CreateAndExerciseCommand, CreateCommand, ExerciseCommand}
|
||||
import com.daml.lf.command.Command
|
||||
import com.daml.lf.crypto
|
||||
import com.daml.lf.data.{FrontStack, Ref, SortedLookupList}
|
||||
import com.daml.lf.data.{FrontStack, SortedLookupList}
|
||||
import com.daml.lf.transaction.Node.NodeCreate
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.lf.value.Value.{
|
||||
@ -38,21 +38,33 @@ class KVUtilsTransactionSpec extends AnyWordSpec with Matchers {
|
||||
val eve = party("Eve")
|
||||
val bobValue = ValueParty(bob)
|
||||
|
||||
val templateArgs: Map[String, Value[ContractId]] = Map(
|
||||
"Party" -> bobValue,
|
||||
"Option Party" -> ValueOptional(Some(bobValue)),
|
||||
"List Party" -> ValueList(FrontStack(bobValue)),
|
||||
"TextMap Party" -> ValueTextMap(SortedLookupList(Map("bob" -> bobValue))),
|
||||
"Simple:SimpleVariant" ->
|
||||
ValueVariant(Some(typeConstructorId("Simple:SimpleVariant")), name("SV"), bobValue),
|
||||
"DA.Types:Tuple2 Party Unit" ->
|
||||
ValueRecord(
|
||||
Some(typeConstructorId("DA.Types:Tuple2 Party Unit", "DA.Types:Tuple2")),
|
||||
FrontStack(
|
||||
Some(name("x1")) -> bobValue,
|
||||
Some(name("x2")) -> ValueUnit
|
||||
).toImmArray
|
||||
),
|
||||
def simpleCreateCmd(simplePackage: SimplePackage): Command =
|
||||
simplePackage.simpleCreateCmd(mkSimpleCreateArg(simplePackage))
|
||||
|
||||
def mkSimpleCreateArg(simplePackage: SimplePackage): Value[ContractId] =
|
||||
simplePackage.mkSimpleTemplateArg("Alice", "Eve", bobValue)
|
||||
|
||||
val templateArgs: Map[String, SimplePackage => Value[ContractId]] = Map(
|
||||
"Party" -> (_ => bobValue),
|
||||
"Option Party" -> (_ => ValueOptional(Some(bobValue))),
|
||||
"List Party" -> (_ => ValueList(FrontStack(bobValue))),
|
||||
"TextMap Party" -> (_ => ValueTextMap(SortedLookupList(Map("bob" -> bobValue)))),
|
||||
"Simple:SimpleVariant" -> (
|
||||
simplePackage =>
|
||||
ValueVariant(
|
||||
Some(simplePackage.typeConstructorId("Simple:SimpleVariant")),
|
||||
name("SV"),
|
||||
bobValue,
|
||||
)),
|
||||
"DA.Types:Tuple2 Party Unit" -> (
|
||||
simplePackage =>
|
||||
ValueRecord(
|
||||
Some(simplePackage.typeConstructorId("DA.Types:Tuple2")),
|
||||
FrontStack(
|
||||
Some(name("x1")) -> bobValue,
|
||||
Some(name("x2")) -> ValueUnit
|
||||
).toImmArray,
|
||||
)),
|
||||
// Not yet supported in DAML:
|
||||
//
|
||||
// "<party: Party>" -> Value.ValueStruct(FrontStack(Ref.Name.assertFromString("party") -> bobValue).toImmArray),
|
||||
@ -60,90 +72,75 @@ class KVUtilsTransactionSpec extends AnyWordSpec with Matchers {
|
||||
// "GenMap Unit Party" -> Value.ValueGenMap(FrontStack(ValueUnit -> bobValue).toImmArray),
|
||||
)
|
||||
|
||||
def createCmd(templateId: Ref.Identifier, templateArg: Value[Value.ContractId]): Command =
|
||||
CreateCommand(templateId, templateArg)
|
||||
|
||||
val simpleTemplateId = templateIdWith("Party")
|
||||
val simpleTemplateArg = mkTemplateArg("Alice", "Eve", "Party", bobValue)
|
||||
val simpleCreateCmd = createCmd(simpleTemplateId, simpleTemplateArg)
|
||||
|
||||
def exerciseCmd(coid: String, templateId: Ref.Identifier): Command =
|
||||
ExerciseCommand(
|
||||
templateId,
|
||||
Value.ContractId.assertFromString(coid),
|
||||
simpleConsumeChoiceid,
|
||||
ValueUnit)
|
||||
|
||||
def createAndExerciseCmd(
|
||||
templateId: Ref.Identifier,
|
||||
templateArg: Value[Value.ContractId]): Command =
|
||||
CreateAndExerciseCommand(templateId, templateArg, simpleConsumeChoiceid, ValueUnit)
|
||||
|
||||
val p0 = mkParticipantId(0)
|
||||
val p1 = mkParticipantId(1)
|
||||
|
||||
"be able to submit a transaction" in KVTest.runTestWithSimplePackage(alice, bob, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
logEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed).map(_._2)
|
||||
} yield {
|
||||
logEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
logEntry.getTransactionEntry.hasBlindingInfo shouldBe true
|
||||
}
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
logEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed).map(_._2)
|
||||
} yield {
|
||||
logEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
logEntry.getTransactionEntry.hasBlindingInfo shouldBe true
|
||||
}
|
||||
}
|
||||
|
||||
"be able to pre-execute a transaction" in KVTest.runTestWithSimplePackage(alice, bob, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
preExecutionResult <- preExecuteTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed).map(_._2)
|
||||
} yield {
|
||||
preExecutionResult.successfulLogEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
preExecutionResult.successfulLogEntry.getTransactionEntry.hasBlindingInfo shouldBe true
|
||||
}
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
preExecutionResult <- preExecuteTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed,
|
||||
).map(_._2)
|
||||
} yield {
|
||||
preExecutionResult.successfulLogEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
preExecutionResult.successfulLogEntry.getTransactionEntry.hasBlindingInfo shouldBe true
|
||||
}
|
||||
}
|
||||
|
||||
"reject transaction with out of bounds LET" in KVTest.runTestWithSimplePackage(alice, bob, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
conf <- getDefaultConfiguration
|
||||
logEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed,
|
||||
letDelta = conf.timeModel.maxSkew.plusMillis(1))
|
||||
.map(_._2)
|
||||
} yield {
|
||||
logEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
logEntry.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.INVALID_LEDGER_TIME
|
||||
}
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
conf <- getDefaultConfiguration
|
||||
logEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed,
|
||||
letDelta = conf.timeModel.maxSkew.plusMillis(1))
|
||||
.map(_._2)
|
||||
} yield {
|
||||
logEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
logEntry.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.INVALID_LEDGER_TIME
|
||||
}
|
||||
}
|
||||
|
||||
"be able to exercise and rejects double spends" in KVTest.runTestWithSimplePackage(
|
||||
alice,
|
||||
bob,
|
||||
eve) {
|
||||
eve) { simplePackage =>
|
||||
val seeds =
|
||||
Stream
|
||||
.from(0)
|
||||
.map(i => crypto.Hash.hashPrivateKey(this.getClass.getName + i.toString))
|
||||
for {
|
||||
transaction1 <- runSimpleCommand(alice, seeds.head, simpleCreateCmd)
|
||||
transaction1 <- runSimpleCommand(alice, seeds.head, simpleCreateCmd(simplePackage))
|
||||
result <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction1,
|
||||
submissionSeed = seeds.head)
|
||||
(entryId, logEntry) = result
|
||||
update = KeyValueConsumption.logEntryToUpdate(entryId, logEntry).head
|
||||
coid = update
|
||||
contractId = update
|
||||
.asInstanceOf[Update.TransactionAccepted]
|
||||
.transaction
|
||||
.nodes
|
||||
@ -152,7 +149,11 @@ class KVUtilsTransactionSpec extends AnyWordSpec with Matchers {
|
||||
.asInstanceOf[NodeCreate[ContractId, _]]
|
||||
.coid
|
||||
|
||||
transaction2 <- runSimpleCommand(alice, seeds(1), exerciseCmd(coid.coid, simpleTemplateId))
|
||||
transaction2 <- runSimpleCommand(
|
||||
alice,
|
||||
seeds(1),
|
||||
simplePackage.simpleExerciseConsumeCmd(contractId),
|
||||
)
|
||||
logEntry2 <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction2,
|
||||
@ -172,106 +173,112 @@ class KVUtilsTransactionSpec extends AnyWordSpec with Matchers {
|
||||
}
|
||||
|
||||
"reject transactions by unallocated submitters" in KVTest.runTestWithSimplePackage(bob, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
configEntry <- submitConfig { c =>
|
||||
c.copy(generation = c.generation + 1)
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
configEntry <- submitConfig { c =>
|
||||
c.copy(generation = c.generation + 1)
|
||||
}
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
txEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed).map(_._2)
|
||||
} yield {
|
||||
configEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.CONFIGURATION_ENTRY
|
||||
txEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
txEntry.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.PARTY_NOT_KNOWN_ON_LEDGER
|
||||
}
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
txEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed).map(_._2)
|
||||
} yield {
|
||||
configEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.CONFIGURATION_ENTRY
|
||||
txEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
txEntry.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.PARTY_NOT_KNOWN_ON_LEDGER
|
||||
}
|
||||
}
|
||||
|
||||
for ((additionalContractDataType, additionalContractValue) <- templateArgs) {
|
||||
val command = createCmd(
|
||||
templateIdWith(additionalContractDataType),
|
||||
mkTemplateArg("Alice", "Eve", additionalContractDataType, additionalContractValue))
|
||||
s"accept transactions with unallocated parties in values: $additionalContractDataType" in KVTest
|
||||
.runTestWithPackage(additionalContractDataType, alice, eve) {
|
||||
s"accept transactions with unallocated parties in values: $additionalContractDataType" in {
|
||||
val simplePackage = new SimplePackage(additionalContractDataType)
|
||||
val command = simplePackage.simpleCreateCmd(
|
||||
simplePackage.mkSimpleTemplateArg("Alice", "Eve", additionalContractValue(simplePackage)))
|
||||
KVTest.runTestWithPackage(simplePackage, alice, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runCommand(alice, seed, additionalContractDataType, command)
|
||||
transaction <- runCommand(alice, seed, command)
|
||||
txEntry <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed)
|
||||
.map(_._2)
|
||||
submissionSeed = seed,
|
||||
).map(_._2)
|
||||
} yield {
|
||||
txEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"reject transactions with unallocated informee" in KVTest.runTestWithSimplePackage(alice, bob) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
txEntry1 <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed)
|
||||
.map(_._2)
|
||||
} yield {
|
||||
txEntry1.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
txEntry1.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.PARTY_NOT_KNOWN_ON_LEDGER
|
||||
}
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
txEntry1 <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed)
|
||||
.map(_._2)
|
||||
} yield {
|
||||
txEntry1.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
txEntry1.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.PARTY_NOT_KNOWN_ON_LEDGER
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: review this test
|
||||
"reject transactions for unhosted parties" in KVTest.runTestWithSimplePackage(bob, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
configEntry <- submitConfig { c =>
|
||||
c.copy(generation = c.generation + 1)
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
configEntry <- submitConfig { c =>
|
||||
c.copy(generation = c.generation + 1)
|
||||
}
|
||||
createTx <- withParticipantId(p1)(
|
||||
runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage)))
|
||||
|
||||
newParty <- withParticipantId(p1)(allocateParty("unhosted", alice))
|
||||
txEntry1 <- withParticipantId(p0)(
|
||||
submitTransaction(submitter = newParty, createTx, seed).map(_._2))
|
||||
txEntry2 <- withParticipantId(p1)(
|
||||
submitTransaction(submitter = newParty, transaction = createTx, submissionSeed = seed)
|
||||
.map(_._2))
|
||||
|
||||
} yield {
|
||||
configEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.CONFIGURATION_ENTRY
|
||||
txEntry1.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
txEntry1.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.SUBMITTER_CANNOT_ACT_VIA_PARTICIPANT
|
||||
txEntry2.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
|
||||
}
|
||||
createTx <- withParticipantId(p1)(runSimpleCommand(alice, seed, simpleCreateCmd))
|
||||
|
||||
newParty <- withParticipantId(p1)(allocateParty("unhosted", alice))
|
||||
txEntry1 <- withParticipantId(p0)(
|
||||
submitTransaction(submitter = newParty, createTx, seed).map(_._2))
|
||||
txEntry2 <- withParticipantId(p1)(
|
||||
submitTransaction(submitter = newParty, transaction = createTx, submissionSeed = seed)
|
||||
.map(_._2))
|
||||
|
||||
} yield {
|
||||
configEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.CONFIGURATION_ENTRY
|
||||
txEntry1.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
txEntry1.getTransactionRejectionEntry.getReasonCase shouldEqual DamlTransactionRejectionEntry.ReasonCase.SUBMITTER_CANNOT_ACT_VIA_PARTICIPANT
|
||||
txEntry2.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_ENTRY
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
"reject unauthorized transactions" in KVTest.runTestWithSimplePackage(alice, eve) {
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
// Submit a creation of a contract with owner 'Alice', but submit it as 'Bob'.
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
bob <- allocateParty("bob", bob)
|
||||
txEntry <- submitTransaction(
|
||||
submitter = bob,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed)
|
||||
.map(_._2)
|
||||
} yield {
|
||||
txEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
val disputed = DamlTransactionRejectionEntry.ReasonCase.DISPUTED
|
||||
txEntry.getTransactionRejectionEntry.getReasonCase shouldEqual disputed
|
||||
}
|
||||
simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
// Submit a creation of a contract with owner 'Alice', but submit it as 'Bob'.
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
bob <- allocateParty("bob", bob)
|
||||
txEntry <- submitTransaction(
|
||||
submitter = bob,
|
||||
transaction = transaction,
|
||||
submissionSeed = seed)
|
||||
.map(_._2)
|
||||
} yield {
|
||||
txEntry.getPayloadCase shouldEqual DamlLogEntry.PayloadCase.TRANSACTION_REJECTION_ENTRY
|
||||
val disputed = DamlTransactionRejectionEntry.ReasonCase.DISPUTED
|
||||
txEntry.getTransactionRejectionEntry.getReasonCase shouldEqual disputed
|
||||
}
|
||||
}
|
||||
|
||||
"update metrics" in KVTest.runTestWithSimplePackage(alice, eve) {
|
||||
"update metrics" in KVTest.runTestWithSimplePackage(alice, eve) { simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
// Submit a creation of a contract with owner 'Alice', but submit it as 'Bob'.
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
bob <- allocateParty("bob", bob)
|
||||
_ <- submitTransaction(submitter = bob, transaction = transaction, submissionSeed = seed)
|
||||
.map(_._2)
|
||||
@ -289,13 +296,14 @@ class KVUtilsTransactionSpec extends AnyWordSpec with Matchers {
|
||||
"properly archive transient contracts and keys" in KVTest.runTestWithSimplePackage(
|
||||
alice,
|
||||
bob,
|
||||
eve) {
|
||||
eve) { simplePackage =>
|
||||
val seeds =
|
||||
Stream
|
||||
.from(0)
|
||||
.map(i => crypto.Hash.hashPrivateKey(this.getClass.getName + i.toString))
|
||||
|
||||
val simpleCreateAndExerciseCmd = createAndExerciseCmd(simpleTemplateId, simpleTemplateArg)
|
||||
val simpleCreateAndExerciseCmd =
|
||||
simplePackage.simpleCreateAndExerciseConsumeCmd(mkSimpleCreateArg(simplePackage))
|
||||
|
||||
for {
|
||||
tx1 <- runSimpleCommand(alice, seeds.head, simpleCreateAndExerciseCmd)
|
||||
@ -330,10 +338,10 @@ class KVUtilsTransactionSpec extends AnyWordSpec with Matchers {
|
||||
"allow for missing submitter info in log entries" in KVTest.runTestWithSimplePackage(
|
||||
alice,
|
||||
bob,
|
||||
eve) {
|
||||
eve) { simplePackage =>
|
||||
val seed = hash(this.getClass.getName)
|
||||
for {
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd)
|
||||
transaction <- runSimpleCommand(alice, seed, simpleCreateCmd(simplePackage))
|
||||
result <- submitTransaction(
|
||||
submitter = alice,
|
||||
transaction = transaction,
|
||||
|
Loading…
Reference in New Issue
Block a user