Я получаю исключение при выполнении моего теста потока
net.corda.core.contracts.TransactionVerificationException$ContractRejection: Contract verification failed: Required com.example.contract.InvoiceContract.Commands command, contract: com.example.contract.InvoiceContract
У меня есть txn, который потребляет 4 различных типа линейных состояний, обновляет некоторые поля и добавляет их в выходное состояние.У txn есть одна команда, логика которой определена в вышеуказанных государственных контрактах.Ниже приведен мой код потока:
object SubmitDocuments {
@InitiatingFlow
@StartableByRPC
class SubmitDocumentsToBank(val locState: StateAndRef<LOCState>, val invoiceState: StateAndRef<InvoiceState>, val packingListState: StateAndRef<PackingListState>, val bolState: StateAndRef<BillOfLadingState>, val updatedlocState: LOCState, val bank: Party) : FlowLogic<SignedTransaction>(){
companion object{
object CREATING_BUILDER : ProgressTracker.Step("Creating a Transaction builder")
object ADDING_STATES : ProgressTracker.Step("Adding Purchase order State in the transation output")
object ADDING_COMMAND : ProgressTracker.Step("Adding a Create Command in the transaction")
object VERIFIYING_TX : ProgressTracker.Step("Verifying the txn")
object SIGNING_TX : ProgressTracker.Step("Signing the transaction")
object SENDING_TX : ProgressTracker.Step("Sending and committing the transaction")
fun tracker() = ProgressTracker(CREATING_BUILDER, ADDING_STATES, ADDING_COMMAND, SIGNING_TX, VERIFIYING_TX, SENDING_TX )
}
override val progressTracker: ProgressTracker = tracker()
@Suspendable
override fun call(): SignedTransaction {
val notary = serviceHub.networkMapCache.notaryIdentities.first()
progressTracker.currentStep = CREATING_BUILDER
val buider = TransactionBuilder(notary)
buider.setTimeWindow(Instant.now(), Duration.ofSeconds(60))
progressTracker.currentStep = ADDING_STATES
val newInvoiceState = invoiceState.state.data.copy(participants = listOf(invoiceState.state.data.seller, bank))
val newpackingListState = packingListState.state.data.copy(participants = listOf(invoiceState.state.data.seller, bank))
val newbolState = bolState.state.data.copy(owner = bank, participants = listOf(bank) )
buider.addInputState(invoiceState)
buider.addInputState(packingListState)
buider.addInputState(bolState)
buider.addInputState(locState)
buider.addOutputState(newInvoiceState, LOCContract.LOC_CONTRACT_ID)
buider.addOutputState(newpackingListState, LOCContract.LOC_CONTRACT_ID)
buider.addOutputState(newbolState, LOCContract.LOC_CONTRACT_ID)
buider.addOutputState(updatedlocState, LOCContract.LOC_CONTRACT_ID)
progressTracker.currentStep = ADDING_COMMAND
val verifyDocHashCommand = Command(LOCContract.Commands.VerifySubmittedDocuments(), listOf(serviceHub.myInfo.legalIdentities.first().owningKey))
buider.addCommand(verifyDocHashCommand)
progressTracker.currentStep = VERIFIYING_TX
buider.verify(serviceHub)
progressTracker.currentStep = SIGNING_TX
val stx = serviceHub.signInitialTransaction(buider)
progressTracker.currentStep = SENDING_TX
return subFlow(FinalityFlow(stx))
}
}
}
Ниже приведен код контракта, в котором указана логика для команды:
open class LOCContract: Contract {
companion object {
@JvmStatic
val LOC_CONTRACT_ID = "com.example.contract.LOCContract"
}
interface Commands: CommandData {
class IssueLoc(val referenceState: String): Commands
class VerifySubmittedDocuments: Commands
class EndorseDocuments(val caller: Party): Commands
class ReleaseDocuments: Commands
}
override fun verify(tx: LedgerTransaction) {
val time = Instant.now()
val command = tx.commands.requireSingleCommand<Commands>()
when (command.value) {
is LOCContract.Commands.VerifySubmittedDocuments -> {
val inputInvoiceState = tx.inputsOfType<InvoiceState>().single()
val inputplistState = tx.inputsOfType<PackingListState>().single()
val inputbolState = tx.inputsOfType<BillOfLadingState>().single()
val bolHash = inputbolState.props.billOfLadingAttachment.hash
val invoiceHash = inputInvoiceState.props.invoiceAttachmentHash.hash
val packinglistHash = inputplistState.props.packingListAttachment.hash
val nonContractAttachments:List<Attachment> = tx.attachments.filter { it !is ContractAttachment }
requireThat {
"Attachments are empty" using (nonContractAttachments.isNotEmpty())
var list: ImmutableList<SecureHash>? = null
nonContractAttachments.forEach((fun (data){
list!!.add(data.id)
}))
"transaction should have valid Bill of lading document hash" using (list!!.contains(bolHash))
"transaction should have valid Invoice document hash" using (list!!.contains(invoiceHash))
"transaction should have valid Packing List document hash" using (list!!.contains(packinglistHash))
}
}
}
}
}
Почему он жалуется на => Обязательная команда com.example.contract.InvoiceContract.Commands, контракт: com.example.contract.InvoiceContract, транзакция: я что-то пропустил при построении txn в потоке?