Благодаря использованию расширения потока узлы, работающие с одним и тем же CorDapp, могут включать дополнительную проверку, чтобы гарантировать, что транзакция соответствует их конкретным требованиям. Проверка внутри контрактов фокусируется на правилах, которые должны соблюдаться всеми сторонами сделки. Из-за этого они носят более общий характер и направлены на то, чтобы никто не собирал недействительные транзакции. Это исключает любые проверки, которые требуются отдельным организациям. Предоставляя базовый CorDapp между организациями с возможностью добавления дополнительных проверок, каждый из них может адаптировать CorDapp для удовлетворения своих потребностей. Расширение потока делает это возможным. Продолжая стремиться к общению организаций через общие CorDapps, при этом обеспечивая достаточную настройку для удовлетворения каждого из их конкретных требований.
Это введение, возможно, привлекло ваше внимание (я надеюсь, что оно все равно произошло), но код для достижения этого относительно прост. Он следует тем же концепциям, о которых я писал в Расширении и переопределении потоков из внешних CorDapps . Дополнительная проверка транзакций, о которой я говорил, может быть достигнута путем предоставления единственной open
функции внутри потока или потока ответчика.
Я пропущу много информации в следующих фрагментах, так как они были рассмотрены в Расширяющих и Переопределяющих потоках из внешних CorDapps . Если вы этого еще не поняли, я настоятельно рекомендую вам прочитать этот пост.
Для дополнительной проверки в инициирующем потоке, я считаю, что вам нужен базовый поток, который выглядит как пример ниже:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@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) } } |
Вызов extraTransactionValidation
перед функцией verify
TransactionBuilder
вынуждает предлагаемую транзакцию соответствовать личным требованиям организации перед выполнением любой общей проверки транзакции.
Реализация extraTransactionValidation
обеспечивается расширенным потоком. Его реализация может выглядеть так:
01
02
03
04
05
06
07
08
09
10
11
12
|
class ExtraValidationSendMessageFlow(message: MessageState) : SendMessageFlow(message) { override fun extraTransactionValidation(transaction: TransactionBuilder) { requireThat { val messages = transaction.toLedgerTransaction(serviceHub).outputsOfType<MessageState>() "There must be only one output message" using (messages.size == 1 ) val message = messages.single() "Message must contain the secret passphrase" using (message.contents.contains( "I love Corda" )) } } } |
Это почти то же самое, что и проверка в контракте. Это действительно так. Проверка выполняется аналогичным образом, но правила, по которым проверяется транзакция, настраиваются.
По аналогии с первоначальным потоком. Базовый поток респондента будет выглядеть следующим образом:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
@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
в тело SignTransactionFlow.checkTransaction
имеет смысл. checkTransaction
и впоследствии extraTransactionValidation
выполняется до общей проверки контракта, SignTransactionFlow
выполняет SignTransactionFlow
.
Ниже приведен пример потока, расширяющего базовый поток и реализующего extraTransactionValidation
:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@InitiatedBy (SendMessageFlow:: class ) class ExtraValidationSendMessageResponder(session: FlowSession) : SendMessageResponder(session) { override fun extraTransactionValidation(stx: SignedTransaction) { requireThat { val messages = stx.coreTransaction.outputsOfType<MessageState>() "There must be only one output message" using (messages.size == 1 ) val message = messages.single() "Message must contain the secret passphrase" using (message.contents.contains( "I love Corda" )) } } } |
Да, эта проверка также включена в исходный поток. Это то, о чем я говорю. Добавив эту проверку в поток инициации и ответчика, организация может гарантировать, что любые транзакции, проходящие через их систему, соответствуют их точным требованиям.
Из-за характера этой проверки ее можно переместить в функцию, совместно используемую потоками:
1
2
3
4
5
6
7
8
|
private fun validate(transaction: BaseTransaction) { requireThat { val messages = transaction.outputsOfType<MessageState>() "There must be only one output message" using (messages.size == 1 ) val message = messages.single() "Message must contain the secret passphrase" using (message.contents.contains( "I love Corda" )) } } |
Эта функция Kotlin была удалена из класса, что делает ее статической функцией. Затем его можно использовать в обоих потоках.
Прежде чем закончить этот пост, я хочу подробнее остановиться на дополнительной проверке в исходном потоке. Весьма вероятно, что сделка, составленная организацией, будет признана действительной той же самой организацией. Итак, вопрос в том, зачем добавлять дополнительные проверки в поток? Подобная проверка может быть выполнена до того, как поток был вызван. Что является вполне подходящим местом для этого. Преимущество добавления его в поток реализуется при использовании стороннего CorDapp. Это усложняется по мере увеличения сложности CorDapp. Определение состояний, создаваемых сложным потоком, может быть непростым делом. Поэтому создание и немедленная проверка содержимого транзакции — это самое безопасное.
В заключение, размещение дополнительной проверки внутри потоков гарантирует, что транзакционные организации полностью удовлетворены содержанием транзакций, прежде чем они совершат их. Кроме того, организация продолжает использовать CorDapps, разработанные сторонними разработчиками. Обеспечивая достаточную гибкость в CorDapps для организаций, чтобы добавлять свои собственные правила. Их становится легче принимать из-за гарантий того, что транзакции соответствуют требованиям любой организации в сети.
Остальной код, используемый в этом посте, можно найти на моем Github .
Если вам понравился этот пост или вы нашли его полезным (или и тем, и другим), пожалуйста, не стесняйтесь, следите за мной в Твиттере на @LankyDanDev и не забудьте поделиться с кем-либо, кто может найти это полезным!
Опубликовано на Java Code Geeks с разрешения Дэна Ньютона, партнера нашей программы JCG . См. Оригинальную статью здесь: Расширение потоков для настройки проверки транзакций. Мнения, высказанные участниками Java Code Geeks, являются их собственными. |