You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Corda中隔离Acceptor Flow进行单元测试并验证无效交易处理?

如何单独测试Corda接收方流程(跳过发起方流程)

完全理解你的需求——当发起方流程会提前拦截无效交易时,确实需要直接针对接收方流程做单独测试,验证它能否正确拒绝合约验证失败的交易。下面是具体的实现步骤和代码示例:

1. 搭建基础测试环境

首先用Corda的TestDSL初始化测试节点,包括接收方节点和一个模拟的发起方节点(不需要启动它的流程,只是用来生成签名):

class AcceptorFlowTests : MockNetworkTest() {
    private lateinit var acceptorNode: StartedNode<MockNode>
    private lateinit var initiatorNode: StartedNode<MockNode>

    override fun setup() {
        super.setup()
        val nodes = network.createNodes(listOf(acceptorIdentity, initiatorIdentity))
        acceptorNode = nodes.single { it.info.legalIdentities.first() == acceptorIdentity }
        initiatorNode = nodes.single { it.info.legalIdentities.first() == initiatorIdentity }
    }
}

2. 手动构造无效的SignedTransaction

我们需要创建一个结构完整但合约验证失败的交易,然后让发起方节点对其签名(模拟发起方流程的签名步骤):

private fun createInvalidSignedTransaction(): SignedTransaction {
    // 1. 创建一个违反合约规则的输出状态
    val invalidState = MyState(
        value = -100, // 假设合约要求value必须大于0
        owner = acceptorIdentity,
        participants = listOf(initiatorIdentity, acceptorIdentity)
    )

    // 2. 构建交易组件
    val txBuilder = TransactionBuilder(notary)
        .addOutputState(invalidState, MY_CONTRACT_ID)
        .addCommand(MyContract.Commands.Action(), listOf(initiatorIdentity.owningKey, acceptorIdentity.owningKey))

    // 3. 发起方节点签名(模拟发起方完成的步骤)
    val partiallySignedTx = initiatorNode.services.signInitialTransaction(txBuilder)

    return partiallySignedTx
}

这里的关键是确保交易的结构是合法的(有正确的命令、参与者、公证人),但输出状态违反合约的验证规则——这样发起方流程如果正常运行会在verify()步骤报错,但我们手动跳过发起方流程,直接把这个部分签名的交易传给接收方。

3. 启动接收方流程并验证结果

现在直接在接收方节点上启动Acceptor Flow,传入这个无效的交易,然后断言流程是否按预期拒绝:

@Test
fun `acceptor flow should reject transaction with invalid contract state`() {
    val invalidStx = createInvalidSignedTransaction()

    // 启动接收方流程
    val flow = AcceptorFlow(invalidStx)
    val future = acceptorNode.startFlow(flow)
    network.runNetwork()

    // 断言流程抛出合约验证异常
    val exception = assertThrows<TransactionVerificationException> { future.get() }
    assert(exception.message?.contains("Contract verification failed") == true)
}

关键注意事项

  • 确保你的Acceptor Flow在处理交易时,会调用serviceHub.verifyTransaction(stx)或者在签名前执行合约验证——这是接收方拒绝无效交易的核心步骤。
  • 如果你的Acceptor Flow依赖发起方的某些消息(比如交易的提议),可以手动构造对应的消息对象传入,不需要依赖发起方流程的触发。
  • 测试时要覆盖不同类型的合约失败场景(比如输入状态验证失败、命令不匹配等),确保接收方流程都能正确处理。

内容的提问来源于stack exchange,提问作者BrianRice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:24:27