Как обновить элементы в хранилище?

#corda

#corda

Вопрос:

В настоящее время я обучаюсь, чтобы стать разработчиком corda.

Я создал простое CorDapp, в котором есть только 1 участник, вот созданное мной состояние:

 @BelongsToContract(UserContract::class)
class UserState(val name: String,
                val age: Int,
                val address: String,
                val gender: GenderEnums,
                val node: Party,
                val status: StatusEnums,
                override val linearId: UniqueIdentifier,
                override val participants : List<Party>
) : LinearState
 

Поэтому, когда я запускаю CorDapp, я получаю желаемый результат https://imgur.com/mOKhNpI

Но то, что я хочу сделать, это обновить хранилище. Я бы, например, хотел обновить адрес с «Пампанга» на «Манила», но я не знаю, с чего начать. Все, что я знаю, это то, что, поскольку состояния неизменяемы, вы должны сначала использовать состояние.

Я попытался создать поток:

 @InitiatingFlow
@StartableByRPC
class UpdateUserFlows(private val name :String,
                      private val age : Int,
                      private val address : String,
                      private val gender: GenderEnums,
                      private val status : StatusEnums,
                      private val counterParty: Party): FlowLogic<SignedTransaction>() {

    private fun userStates(): UserState {
        return UserState(
                name = name,
                age = age,
                address = address,
                gender = gender,
                status = status,
                node = ourIdentity,
                linearId = UniqueIdentifier(),
                participants = listOf(ourIdentity, counterParty)
        )
    }

    @Suspendable
    override fun call(): SignedTransaction {
        val transaction: TransactionBuilder = transaction()
        val signedTransaction: SignedTransaction = verifyAndSign(transaction)
        val sessions: List<FlowSession> = (userStates().participants - ourIdentity).map { initiateFlow(it) }.toSet().toList()
        val transactionSignedByAllParties: SignedTransaction = collectSignature(signedTransaction, sessions)
        return recordTransaction(transactionSignedByAllParties, sessions)
    }

    private fun transaction(): TransactionBuilder {
        val notary: Party = serviceHub.networkMapCache.notaryIdentities.first()
        val issueCommand = Command(UserContract.Commands.Issue(), userStates().participants.map { it.owningKey })
        val builder = TransactionBuilder(notary = notary)
        builder.addOutputState(userStates(), UserContract.ID)
        builder.addCommand(issueCommand)
        return builder
    }

    private fun verifyAndSign(transaction: TransactionBuilder): SignedTransaction {
        transaction.verify(serviceHub)
        return serviceHub.signInitialTransaction(transaction)
    }


    @Suspendable
    private fun collectSignature(
            transaction: SignedTransaction,
            sessions: List<FlowSession>
    ): SignedTransaction = subFlow(CollectSignaturesFlow(transaction, sessions))

    @Suspendable
    private fun recordTransaction(transaction: SignedTransaction, sessions: List<FlowSession>): SignedTransaction =
            subFlow(FinalityFlow(transaction, sessions))
}
 

Но это не работает.

Ответ №1:

  • Вы правы, состояния неизменяемы в Corda, и для имитации обновления вам в основном нужно создать транзакцию, в которой входными данными является ваша текущая версия состояния (т. Е. address = Pampanga), а на выходе будет новый экземпляр UserState , который имеет те же linearId и другие значения атрибутов, что и входные данные, нодругое значение адреса (например, Manila).
  • Таким образом, вы создаете новое состояние (выходные данные транзакции), но поскольку оно будет иметь то же linearId значение; это было бы так, как если бы вы обновили входные данные, чтобы они стали выходными, это позволит вам увидеть все предыдущие версии состояния, запрашивая хранилище по его linearId .
  • Вы не поделились кодом своего контракта, но вам нужно добавить новую команду (назовем ее Update ); а также вам нужно добавить правила проверки, которые применяются к нему.
  • Внутри вашего потока вы бы использовали эту команду (вместо Issue ).