Обновление исходного кода Corda3 для запуска на v4 - PullRequest
0 голосов
/ 07 мая 2019

Прежде всего, я только начал изучать корду 3 месяца назад, поэтому у меня есть кое-какие знания.

Я унаследовал некоторый код, который отлично работает под Corda v3.3, но клиенты хотят, чтобы он работал на v4. Я пытаюсь следовать инструкциям на основном сайте. У меня есть инициирующий поток, который вызывает подпоток, который, в свою очередь, вызывает поток транспондера.

Инициирующий поток:

@InitiatingFlow(version = 2)
@StartableByRPC
class TransferFlow(private val issuerName: String = "",
                   private val seller: String = "",
                   private val amount: BigDecimal = BigDecimal("0"),
                   private val buyer: String = "",
                   private val custodianNameOfBuyer: String = "",
                   private val notaryName: String = "") : FlowLogic<SignedTransaction>() {
    @Suspendable
    override fun call(): SignedTransaction {

        subFlow(UpdateStatusOfTransferFlow(
                sessions,
                tokenTransferAgreement.linearId,
                "Removed Tokens From Seller"))
  }
}

class UpdateStatusOfTransferFlow(
        private val sessions: Set<FlowSession>,
        private val tokenTransferAgreementID: UniqueIdentifier,
        private val newStatus: String) : FlowLogic<SignedTransaction>() {
    @Suspendable
    override fun call(): SignedTransaction {
        sessions.size
        val idQueryCriteria = QueryCriteria.LinearStateQueryCriteria(linearId = listOf(tokenTransferAgreementID))
        val states = serviceHub.vaultService.queryBy<TokenTransferAgreement>(idQueryCriteria).states

        if (states.size != 1) throw FlowException("Can not find a unique state for $tokenTransferAgreementID")

        val inputStateAndRef = states.single()
        val inputState = inputStateAndRef.state.data

        val notary = inputStateAndRef.state.notary

        val outputState = inputState.withNewStatus(newStatus)

        val cmd = Command(TokenContract.Commands.UpdateStatusOfTransfer(),
                inputState.participants.map { it.owningKey })


        val txBuilder = TransactionBuilder(notary = notary)
        txBuilder.addCommand(cmd)
        txBuilder.addInputState(inputStateAndRef)
        txBuilder.addOutputState(outputState, TokenContract.ID)

        txBuilder.verify(serviceHub)
        val ptx = serviceHub.signInitialTransaction(txBuilder)
        val sessions2 = (inputState.participants.toSet() - ourIdentity).map { initiateFlow(it) }

       return subFlow(CollectSignaturesFlow(ptx, sessions2))

    }

}

And the responder:

@InitiatedBy(TransferFlowResponder::class)
class UpdateStatusOfTransferFlowResponder(private val session: FlowSession) : FlowLogic<Unit>() {
    @Suspendable
    override fun call() {
        val tokenTransferAgreements = mutableListOf<TokenTransferAgreement>()
        var isBuyer = true
        var notary = CordaUtility.getNotary(serviceHub) ?: throw FlowException("An notary is expected!")

        val signedTransactionFlow = subFlow(object : SignTransactionFlow(session) {
            override fun checkTransaction(stx: SignedTransaction) = requireThat {
                "There must be one output!" using (stx.tx.outputStates.size == 1)

                val tokenTransferAgreement = stx.tx.outputStates.first() as TokenTransferAgreement
                tokenTransferAgreements.add(tokenTransferAgreement)

                notary = stx.notary ?: throw FlowException("An notary is expected!")

                if (ourIdentity == tokenTransferAgreement.issuer) {
                   //checks go here
                 }

        })
    }

}

Я полагаю, что в какой-то момент я должен добавить вызов к потоку ReceiveFinality, однако он принимает в качестве аргумента только 1 сеанс, а не список, как у меня здесь. Должен ли я сделать несколько звонков, по одному для каждой сессии? Я также не уверен, должны ли звонки идти в транспондере или в классе UpdateStatusOfTransferFlow.

Помощь здесь будет оценена.

1 Ответ

0 голосов
/ 07 мая 2019

FinalityFlow в основном отвечает за то, чтобы транзакции были нотариально заверены, соответственно распределены и сохранены в локальных хранилищах.

В предыдущих версиях Corda все узлы по умолчанию принимали входящие запросы на окончательность.

Начиная с версии V4, вам необходимо написать ReceiveFinalityFlow, чтобы написать собственную логику обработки до завершения.

То, как в настоящее время выполняется окончательность в Corda, является инициирующим узлом, в качестве промежуточного шага во время окончательности раздача нотариально заверенных транзакций всем остальным участникам. Каждый из участвующих узлов, которые он отправляет, будет ожидать только получения сеанса от этого узла.

Таким образом, если вы можете отправить несколько сеансов в инициирующий FinalityFlow, чтобы включить всех участников, отвечающие узлы будут когда-либо получать только один сеанс от инициатора.

В будущем мы можем рассмотреть вопрос о том, чтобы нотариус распространил нотариально заверенную транзакцию среди всех участников, но даже в этом случае ReceiveFinalityFlow будет ожидать только одного сеанса, на этот раз от нотариуса.

...