通过使用流扩展,运行相同CorDapp的节点可以包括额外的验证,以确保事务满足其特定要求。 合同内部的验证侧重于所有交易方必须遵守的规则。 因此,它们更为笼统,着重于确保没有人将无效的交易放在一起。 这省去了各个组织所需的任何检查。 通过在组织之间提供基本的CorDapp并具有添加更多检查的功能,他们可以各自定制CorDapp以满足他们的需求。 流扩展使这成为可能。 继续推动组织通过常见的CorDapps进行通信,同时仍提供足够的自定义设置来满足他们的每个特定要求。
该介绍可能引起了您的注意(无论如何,我希望它能引起注意),但是实现该目标的代码相对简单。 它遵循了我在从外部CorDapps扩展和覆盖流中编写的相同概念。 我一直在谈论的额外事务验证可以通过在流或响应器流中提供单个open
功能来实现。
我将跳过以下摘录中的许多信息,因为它们在来自外部CorDapps的扩展和覆盖流中进行了介绍 。 如果您现在还没有意识到这一点,我强烈建议您阅读该文章。
为了在启动流程中进行额外的验证,我相信您想要的是类似于以下示例的基本流程:
@InitiatingFlow open class SendMessageFlow( private val message: MessageState) :
FlowLogic<SignedTransaction>() {
open fun extraTransactionValidation(transaction: TransactionBuilder) {
// to be implemented by subtype flows - otherwise do nothing
}
@Suspendable
final override fun call(): SignedTransaction {
// build transaction
val tx = verifyAndSign(transaction)
// collect signatures
// save transaction
}
private fun verifyAndSign(transaction: TransactionBuilder): SignedTransaction {
extraTransactionValidation(transaction)
transaction.verify(serviceHub)
return serviceHub.signInitialTransaction(transaction)
} }
在运行任何共享的交易验证之前,在TransactionBuilder
的verify
函数之前调用extraTransactionValidation
强制提议的交易满足组织的个人要求。
扩展流提供了extraTransactionValidation
的实现。 它的实现可能如下所示:
class ExtraValidationSendMessageFlow(message: MessageState) :
SendMessageFlow(message) {
override fun extraTransactionValidation(transaction: TransactionBuilder) {
requireThat {
val messages = transaction.toLedgerTransaction(serviceHub).outputsOfType<MessageState>()
using (messages.size == 1 ) "There must be only one output message"
val message = messages.single()
using (message.contents.contains( "I love Corda" )) "Message must contain the secret passphrase"
}
} }
这与您在合同中看到的验证几乎相同。 这才是真正的重点。 验证以相同的方式完成,但是检查交易的规则是自定义的。
以类似于启动流程的方式。 基本响应者流程如下所示:
@InitiatedBy (SendMessageFlow:: class ) open class SendMessageResponder( private val session: FlowSession) : FlowLogic<SignedTransaction>() {
open fun extraTransactionValidation(stx: SignedTransaction) {
// to be implemented by subtype flows - otherwise do nothing
}
@Suspendable
final override fun call(): SignedTransaction {
val stx = subFlow(object : SignTransactionFlow(session) {
override fun checkTransaction(stx: SignedTransaction) {
extraTransactionValidation(stx)
}
})
// save transaction
} }
将extraTransactionValidation
添加到extraTransactionValidation
的主体中SignTransactionFlow.checkTransaction
。 在执行SignTransactionFlow
执行的常规合同验证之前,将运行checkTransaction
和随后的extraTransactionValidation
。
以下是扩展基本流程并实现extraTransactionValidation
的示例流程:
@InitiatedBy (SendMessageFlow:: class ) class ExtraValidationSendMessageResponder(session: FlowSession) :
SendMessageResponder(session) {
override fun extraTransactionValidation(stx: SignedTransaction) {
requireThat {
val messages = stx.coreTransaction.outputsOfType<MessageState>()
using (messages.size == 1 ) "There must be only one output message"
val message = messages.single()
using (message.contents.contains( "I love Corda" )) "Message must contain the secret passphrase"
}
} }
是的,此验证也包含在启动流程中。 这就是我在说的。 通过将此验证添加到发起流程和响应者流程中,组织可以确保通过其系统的任何事务都满足其精确的要求。
由于此验证的性质,可以将其移至流之间共享的函数中:
private fun validate(transaction: BaseTransaction) {
requireThat {
val messages = transaction.outputsOfType<MessageState>()
using (messages.size == 1 ) "There must be only one output message"
val message = messages.single()
using (message.contents.contains( "I love Corda" )) "Message must contain the secret passphrase"
} }
此Kotlin函数已移出类,使其成为静态函数。 然后可以在两个流中使用它。
在结束本文之前,我想进一步探讨的一点是启动流程中的其他验证。 一个组织进行的交易很可能会被同一组织认定为有效。 所以问题是,为什么要在流程中添加额外的检查? 可以在调用流之前完成类似的验证。 这是一个非常有效的地方。 使用第三方CorDapp时,可以实现将其添加到流中的好处。 随着CorDapp复杂性的增加,它变得更加复杂。 确定由复杂流创建的状态可能不是一件容易的事。 因此,创建并立即检查事务的内容是最安全的事情。
总而言之,将额外的验证放置在流中可确保事务处理组织在提交事务之前对事务的内容完全满意。 此外,它继续推动组织利用由第三方开发人员实施的CorDapp。 通过在CorDapps中提供足够的灵活性,使组织可以添加自己的规则。 由于保证交易满足网络中任何组织的要求,因此采用它们变得更加容易。
这篇文章中使用的其余代码可以在我的Github上找到。
如果您喜欢这篇文章或发现它对您有帮助(或两者都有),请随时在Twitter上@LankyDanDev关注我,并记住与可能对您有用的任何人分享!
翻译自: https://www.javacodegeeks.com/2019/07/extending-flows-customise-transaction-validation.html