在哪里检查合同约束
Where to check contract constraints
从 Corda 的 release-M13 开始,在 CordApp-Tutorial 示例中,在流程本身中进行了一些约束检查 (ExampleFlow.Acceptor)。我的问题是,我可以在流程上检查哪些约束,以及合同中的哪些约束?或者这只是一个组织问题?
这是一个很好的问题。我相信你指的是:
@InitiatedBy(Initiator::class)
class Acceptor(val otherParty: Party) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val signTransactionFlow = object : SignTransactionFlow(otherParty) {
override fun checkTransaction(stx: SignedTransaction) = requireThat {
val output = stx.tx.outputs.single().data
"This must be an IOU transaction." using (output is IOUState)
val iou = output as IOUState
"The IOU's value can't be too high." using (iou.iou.value < 100)
}
}
return subFlow(signTransactionFlow)
}
}
CollectSignaturesFlow
及其对应物,SignTransactionFlow
自动收集任何类型交易的签名。这种自动化非常有用,因为开发人员不必再手动编写签名收集流程了!但是,开发人员必须注意,给定任何 有效 交易 - 根据交易中引用的合同代码 - 交易对方将始终签名!这是因为交易是独立验证的,与某些预期的外部值无关。
让我举两个例子:
- 如果我可以从之前的交易中访问你未花费的现金状态之一,那么也许我可以创建一个现金支出交易(从你到我)并要求你通过
CollectSignaturesFlow
签名。如果交易有效,则无需任何额外检查,您将在其上签名,这将导致您向我发送现金。显然你不想要这个!
- 合约代码只能用于验证交易的一部分。如果你想检查交易是否代表你想进入的交易,例如price < some amount 那么你将不得不做一些额外的检查。合同代码无法就什么构成对您而言具有商业可行性的交易发表意见。此检查必须通过覆盖
signTransaction
作为 SignTransactionFlow
的一部分来完成
在生产 CorDapp 中,人们可能希望在是否签署交易和达成交易方面听从人类的判断。或者,可以通过 HTTP API 或 MQ 联系一些外部参考数据系统来自动执行此过程,以确定交易是否应该进行。
在上面的代码示例中,我们添加了两个简单的约束:
- 防止借款人创建过大(大于 100)的欠条状态
- 确保交易确实包含 IOU 状态而不是我们不期望的其他状态
请注意,这两个约束不能放在合约代码中。合同代码更适合定义管理资产或协议应如何随时间演变的约束。例如,关于欠条:
- 发行必须由贷方和借款人签署
- 问题的值必须大于零
- 兑换必须涉及正确货币的现金支付
- 借据必须在到期日之前赎回
- 此处提供更多示例:https://github.com/roger3cev/iou-cordapp-v2/blob/master/src/main/kotlin/net/corda/iou/contract/IOUContract.kt
请记住,Corda 是为潜在的相互不信任的各方就共享事实达成共识而设计的。因此,节点不能隐含地相信他们通过网络从对方那里收到的东西,因此我们总是必须检查我们收到的是我们期望收到的。
希望这是有道理的!
从 Corda 的 release-M13 开始,在 CordApp-Tutorial 示例中,在流程本身中进行了一些约束检查 (ExampleFlow.Acceptor)。我的问题是,我可以在流程上检查哪些约束,以及合同中的哪些约束?或者这只是一个组织问题?
这是一个很好的问题。我相信你指的是:
@InitiatedBy(Initiator::class)
class Acceptor(val otherParty: Party) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val signTransactionFlow = object : SignTransactionFlow(otherParty) {
override fun checkTransaction(stx: SignedTransaction) = requireThat {
val output = stx.tx.outputs.single().data
"This must be an IOU transaction." using (output is IOUState)
val iou = output as IOUState
"The IOU's value can't be too high." using (iou.iou.value < 100)
}
}
return subFlow(signTransactionFlow)
}
}
CollectSignaturesFlow
及其对应物,SignTransactionFlow
自动收集任何类型交易的签名。这种自动化非常有用,因为开发人员不必再手动编写签名收集流程了!但是,开发人员必须注意,给定任何 有效 交易 - 根据交易中引用的合同代码 - 交易对方将始终签名!这是因为交易是独立验证的,与某些预期的外部值无关。
让我举两个例子:
- 如果我可以从之前的交易中访问你未花费的现金状态之一,那么也许我可以创建一个现金支出交易(从你到我)并要求你通过
CollectSignaturesFlow
签名。如果交易有效,则无需任何额外检查,您将在其上签名,这将导致您向我发送现金。显然你不想要这个! - 合约代码只能用于验证交易的一部分。如果你想检查交易是否代表你想进入的交易,例如price < some amount 那么你将不得不做一些额外的检查。合同代码无法就什么构成对您而言具有商业可行性的交易发表意见。此检查必须通过覆盖
signTransaction
作为
SignTransactionFlow
的一部分来完成
在生产 CorDapp 中,人们可能希望在是否签署交易和达成交易方面听从人类的判断。或者,可以通过 HTTP API 或 MQ 联系一些外部参考数据系统来自动执行此过程,以确定交易是否应该进行。
在上面的代码示例中,我们添加了两个简单的约束:
- 防止借款人创建过大(大于 100)的欠条状态
- 确保交易确实包含 IOU 状态而不是我们不期望的其他状态
请注意,这两个约束不能放在合约代码中。合同代码更适合定义管理资产或协议应如何随时间演变的约束。例如,关于欠条:
- 发行必须由贷方和借款人签署
- 问题的值必须大于零
- 兑换必须涉及正确货币的现金支付
- 借据必须在到期日之前赎回
- 此处提供更多示例:https://github.com/roger3cev/iou-cordapp-v2/blob/master/src/main/kotlin/net/corda/iou/contract/IOUContract.kt
请记住,Corda 是为潜在的相互不信任的各方就共享事实达成共识而设计的。因此,节点不能隐含地相信他们通过网络从对方那里收到的东西,因此我们总是必须检查我们收到的是我们期望收到的。
希望这是有道理的!