Corda事务可以将状态作为输入引用而不消耗它吗?

时间:2018-02-05 09:59:43

标签: corda

在Corda,有没有办法在不花钱的情况下参考交易中未花费的州?目的是允许合同使用被称为verify方法一部分的州内的一些信息。

2 个答案:

答案 0 :(得分:3)

参考状态将添加到Corda第4版中,该版本将于今年晚些时候发布。这样就解决了上述问题。参见:

https://github.com/corda/corda/blob/master/docs/source/design/reference-states/design.md

答案 1 :(得分:2)

目前Corda中没有对此模式的内置支持,但它将添加到Corda 4中(请参阅下面的Roger答案)。目前,您有几种选择:

编写州合同以允许此行为:

您可以向合同添加一个命令,该命令强制要求您希望引用的州类型的每个输入都有匹配的输出。这可以保证事务只引用状态,而不是修改它。这是一个例子:

class MyContract : Contract {
    override fun verify(tx: LedgerTransaction) {
        val command = tx.commands.requireSingleCommand<MyContract.Commands>()
        when (command.value) {
            is Commands.Reference -> requireThat {
                val inputs = tx.inputsOfType<MyState>()
                val outputs = tx.outputsOfType<MyState>()
                // Assuming `MyState.equals` has been overridden appropriately.
                "There must be a matching output state for each input state" using
                        (inputs.toSet() == outputs.toSet())
            }
        }
    }

    interface Commands : CommandData {
        class Reference: Commands
    }
}

将状态称为输入状态,输出状态或命令中的字段:

您可以将事务中的引用状态包含在输入状态,输出状态或命令的字段中。命令可能是最合适的:

interface Commands : CommandData {
    class Reference(val referenceState: MyState): Commands
}

然后,您可以在合同的验证方法中检查此状态的内容。例如:

class MyContract : Contract {
    override fun verify(tx: LedgerTransaction) {
        val command = tx.commands.requireSingleCommand<MyContract.Commands>()
        when (command.value) {
            is Commands.Reference -> requireThat {
                val commandData = command.value as Commands.Reference
                val referenceState = commandData.referenceStateAndRef.state.data
                val inputs = tx.inputsOfType<MyState>()
                "The input state contents must match the reference data" using
                        (inputs.all { it.contents == referenceState.contents })
            }
        }
    }

    interface Commands : CommandData {
        class Reference(val referenceStateAndRef: StateAndRef<MyState>): Commands
    }
}

使用这种方法,您还必须检查流程,即参考状态与分类帐上实际的状态相同(即,事务的提议者未添加伪状态对象作为参考)。例如:

val referenceCommand = ledgerTransaction.commandsOfType<Reference>().single()
val referenceStateAndRef = referenceCommand.value.referenceStateAndRef
val actualStateAndRefFromVault = serviceHub.toStateAndRef<MyState>(referenceStateRef)
if (referenceStateAndRef != actualStateAndRefFromVault) {
    throw FlowException("Referenced state does not match state in the vault.")
}