(R3 Corda 4.8) 选定的输出约束:net.corda.core.contracts.WhitelistedByZoneAttachmentConstraint@1f102389 不满足

(R3 Corda 4.8) Selected output constraint: net.corda.core.contracts.WhitelistedByZoneAttachmentConstraint@1f102389 not satisfying

我克隆了 cordapp-kotlin-template 。我定义了一个名为 LoadState 的状态,如下所示:

@BelongsToContract(LoadContract::class)
data class LoadState(
    val loadId: String,
    val transporterName: String? = null,
    val vehicleModel: String? = null,
    val regLicenseNo: String? = null,
    val totalWeight: Int? = null,
    val notes: String? = null,
    val suppliers: MutableList<SupplierDetailsModel> = mutableListOf(),
    val recycler: Party,
    override val participants: List<AbstractParty> = listOf(recycler)
) : QueryableState {
    override fun generateMappedObject(schema: MappedSchema): PersistentState {
        if (schema is LoadSchemaV1) {
            return PersistentLoadState(this.loadId)
        } else {
            throw IllegalArgumentException("Unsupported Schema.")
        }
    }

    override fun supportedSchemas(): Iterable<MappedSchema> {
        return listOf(LoadSchemaV1())
    }
}

当我第一次使用该应用程序并发出 LoadState 时说 LO123 它工作正常。状态也被发布并记录在保险库中。 这就是我的 LoadState 问题流程的样子:

@Suspendable
    override fun call(): SignedTransaction {
        val notary = serviceHub.networkMapCache.getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"))
        progressTracker.currentStep = TX_COMPONENTS

        val recyclerName = CordaX500Name(
            organisation = "MyRecycler",
            locality = "Mumbai",
            country = "IN"
        )

        val recycler = serviceHub.identityService.wellKnownPartyFromX500Name(recyclerName)
            ?: throw IllegalArgumentException("Could not find party Recycler.")

        val outputState = LoadState(
            loadId = req.loadId,
            loadDate = req.loadDate,
            transporterName = req.transporterName,
            vehicleModel = req.vehicleModel,
            regLicenseNo = req.regLicenseNo,
            totalWeight = req.totalWeight,
            assets = req.assets,
            suppliers = req.suppliers,
            recycler = recycler,
            notes = req.notes
        )

        val command = Command(LoadContract.Commands.Create(), listOf(ourIdentity.owningKey))

        progressTracker.currentStep = TX_BUILDING

        val txBuilder = TransactionBuilder(notary = notary)
            .addOutputState(outputState, LoadContract.ID)
            .addCommand(command)

        // signing the transaction
        progressTracker.currentStep = TX_SIGNING
        val signedTx = serviceHub.signInitialTransaction(txBuilder)

        // verifying the transaction
        progressTracker.currentStep = TX_VERIFICATION
        txBuilder.verify(serviceHub)

        // We finalise the transaction and then send it to the counterparty.
        progressTracker.currentStep = FINALIZATION

        val recyclerSession = initiateFlow(recycler)

        return subFlow(FinalityFlow(signedTx, listOf()))
    }

现在需要向我们的 LoadState 添加一个新字段:

val myNewField: String? = null

将这个新字段添加到 LoadState 后,我 运行 deployNodes 命令。生成构建文件夹后,我将 Node/cordapps 文件夹的内容复制到我的旧构建 Node/cordapps 文件夹。

现在,在启动节点时,我正在 运行 迁移命令(核心架构和应用程序架构)。一旦迁移过程完成并且节点启动,我将调用一个 api 端点,它调用一个以 L0123 作为输入的流,复制它,并修改一些参数并创建一个类型为 LoadState 的新输出状态。错误抛出在: txBuilder.verify(serviceHub) 在我的 UpdateLoadFlow 中。这就是我的更新流程:

@Suspendable
    override fun call(): SignedTransaction {
        val notary = serviceHub.networkMapCache.getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"))

        progressTracker.currentStep = TX_COMPONENTS

        val recyclerName = CordaX500Name(
            organisation = "MyRecycler",
            locality = "Mumbai",
            country = "IN"
        )

        val recycler = serviceHub.identityService.wellKnownPartyFromX500Name(recyclerName)
            ?: throw IllegalArgumentException("Could not find party Recycler.")

        val inputState = QueryVault().queryLoadById(req.loadId, Vault.StateStatus.UNCONSUMED, serviceHub.vaultService)
            ?: throw Exception("Load ${req.loadId} not found.")

        val vaultData = inputState.state.data
        var outputState = vaultData.copy(myNewField = "some new value");
        
        val command = Command(LoadContract.Commands.Update(), listOf(ourIdentity.owningKey))

        progressTracker.currentStep = TX_BUILDING

        val txBuilder = TransactionBuilder(notary = notary)
            .addInputState(inputState)
            .addOutputState(outputState, LoadContract.ID)
            .addCommand(command)

        txBuilder.verify(serviceHub)
        // signing the transaction
        progressTracker.currentStep = TX_SIGNING
        val signedTx = serviceHub.signInitialTransaction(txBuilder)
        // verifying the transaction
        progressTracker.currentStep = TX_VERIFICATION

        // We finalise the transaction and then send it to the counterparty.
        progressTracker.currentStep = FINALIZATION
        val recyclerSession = initiateFlow(recycler)
        return subFlow(FinalityFlow(signedTx, listOf()))
    }

请帮我解决这个问题。

经过我们在上述评论部分的讨论,您的状态似乎是使用白名单区域约束发布的。

另外查看代码,很明显您没有为您的州明确添加白名单区域约束。 然后还有两种可能性,使用白名单区域约束发布状态。

一个是您使用的是 4 之前的某个 Corda 版本,或者您已经包含必要的配置以在指定的网络引导程序中包含白名单区域约束 here。 您有两个选择 - 从头开始​​并确保使用 Corda 4。

如果您不能从头开始,请按照此路径首先将白名单区域约束迁移到签名约束,然后 运行 您的 UpdateLoadFlow。您可以参考this 博客中关于约束迁移的内容。