Corda 交易可以在不消耗状态的情况下将状态作为输入引用吗?
Can a Corda transaction reference a state as an input without consuming it?
在 Corda 中,有没有一种方法可以在不花费的情况下引用交易中未花费的状态?目的是允许合约使用状态中的某些信息作为 verify
方法的一部分。
目前 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.")
}
将在今年晚些时候发布的 Corda 版本 4 中添加参考状态。这解决了上面的问题。参见:
https://github.com/corda/corda/blob/master/docs/source/design/reference-states/design.md
在 Corda 中,有没有一种方法可以在不花费的情况下引用交易中未花费的状态?目的是允许合约使用状态中的某些信息作为 verify
方法的一部分。
目前 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.")
}
将在今年晚些时候发布的 Corda 版本 4 中添加参考状态。这解决了上面的问题。参见:
https://github.com/corda/corda/blob/master/docs/source/design/reference-states/design.md