Проверка кассового контракта


Я сталкиваюсь с проблемой во время потока сбора подписей, когда Проверка кассового контракта терпит неудачу, предоставляя сообщение об ошибке

Проверка контракта не удалась: не удалось требование: для справки [01] у эмитента C=US, L=New York, O=PartyB сумма баланса: 300000-0 != 0, контракт: нетто.корда.финансы.контракты.актив.Наличные@7d43e51b

По-видимому, это связано с тем, что входная сумма наличных денег не равна выходу + сумма, выходящая из гроссбух.

"for reference ${issuer.reference} at issuer ${issuer.party} the amounts balance: ${inputAmount.quantity} - ${amountExitingLedger.quantity} != ${outputAmount.quantity}" using
                            (inputAmount == outputAmount + amountExitingLedger)
Однако для создания наличных состояний в рамках транзакции я просто использую наличные деньги.функция generateSpend (), поэтому я не уверен, что эта ошибка может быть вызвана. Используемые денежные средства самостоятельно выдаются в начале наших симуляций и, возможно, были перемещены между узлами до того, как поток, вызывающий эту проблему, был вызван. Я не могу видеть точное значение вводимых состояний наличности, но я могу видеть, что есть 2 состояния. Выход наличных денег - это тогда сумма потрачено ($3102) плюс два других государства , возвращающиеся к партии, потратившей $3102, причем один из них стоит $97991898 и $97995000. Первоначально партия была выпущена $98000000 в начале моделирования - так что наличие этого третьего выходного состояния $97995000 кажется очень странным. Кажется вероятным, что два входных состояния составляют сумму $ 97995000, так как $97991898 + $3102 = $ 97995000, и что эта сторона уже потратила $ 5000 в другом потоке, что делает этот третий денежный выход $ 97995000, по-видимому, появляется из нигде.

Может ли эта проблема быть вызвана тем, что что-то идет не так с наличными деньгами?generateSpend ()? Я не добавляю никаких других состояний ввода или вывода денежных средств (я приложил поток ниже). Я также отметил, что эта проблема возникает только в том случае, если я позволяю потоку, делающему эти 5000 долларов, произойти (т. е. сторона а платит B 5000 долларов, которые завершаются и записываются в книгу, а затем пытается сделать еще один платеж B здесь в отдельном потоке).

//STEP 4: Build the transaction
val notary = serviceHub.networkMapCache.notaryIdentities.first()
val builder = TransactionBuilder(notary)
val builder2 = TermDeposit().generateRedeem(builder, TermDeposit)
//Add our required cash
val (tx, cashKeys) = Cash.generateSpend(serviceHub, builder2, Amount((TermDeposit.state.data.depositAmount.quantity * (100+TermDeposit.state.data.interestPercent)/100).toLong(), USD), flow.counterparty)
println("Redeem added cash ${Amount((TermDeposit.state.data.depositAmount.quantity * (100+TermDeposit.state.data.interestPercent)/100).toLong(), USD)}")

//STEP 5: Get the client to sign the transaction
println("Inputs ${tx.inputStates()}")
println("Outputs ${tx.outputStates()}")
val partSignedTxn = serviceHub.signInitialTransaction(tx, cashKeys)
println("Before collect sigs")
val otherPartySig = subFlow(CollectSignaturesFlow(partSignedTxn, listOf(flow), CollectSignaturesFlow.tracker()))
println("after collect sigs")

//STEP 6: Merge all signatures and commit this to the ledger
val twiceSignedTx = partSignedTxn.plus(otherPartySig.sigs) 
println("Redeem before finality flow")
return subFlow(FinalityFlow(twiceSignedTx))

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

2 2

2 ответа:

Вот соответствующая часть Cash.verify():

val groups = tx.groupStates { it: Cash.State -> it.amount.token }

for ((inputs, outputs, key) in groups) {
    val issuer = key.issuer
    val currency = key.product

    val inputAmount = inputs.sumCashOrNull() ?: throw IllegalArgumentException("there is at least one cash input for this group")
    val outputAmount = outputs.sumCashOrZero(Issued(issuer, currency))

    val exitKeys = inputs.flatMap { it.exitKeys }.toSet()
    val exitCommand = tx.commands.select<Commands.Exit>(parties = null, signers = exitKeys).filter { it.value.amount.token == key }.singleOrNull()
    val amountExitingLedger = exitCommand?.value?.amount ?: Amount(0, Issued(issuer, currency))

    requireThat {
        "for reference ${issuer.reference} at issuer ${issuer.party} the amounts balance: " +
            "${inputAmount.quantity} - ${amountExitingLedger.quantity} != ${outputAmount.quantity}" using
            (inputAmount == outputAmount + amountExitingLedger)
    }
}

groupStates возвращает список списков, где каждый список содержит входы и выходы, соответствующие заданному Issuer<Currency>.

Денежные состояния, связанные с различными состояниями Issuer<Currency>, не являются взаимозаменяемыми. Другими словами, транзакция должна выдавать столько наличных денег для каждого Issuer<Currency>, сколько она принимает (игнорируя выходы). Наиболее вероятная проблема здесь заключается в том, что вы вводите некоторую наличность и выводите ее с другим Issuer<Currency>. Если вы отладите свой поток и изучите содержание транзакции, прежде чем она будет проверена, вы должны быть в состоянии определить, так ли это.

Для тех, кто столкнулся с этой проблемой / аналогичными проблемами проверки наличности, я смог исправить это, создав узел, который будет действовать как центральный эмитент наличных денег, а затем вместо самостоятельного выпуска наличных денег в начале моделирования я использовал поток наличных денег и платежей и отправил определенное количество наличных денег в каждый узел.

Я до сих пор не уверен, была ли эта проблема вызвана чем-то в моих потоках или тем фактом, что одна сторона была эмитентом и получателем наличных государств - если кто-то имеет вклад по этому поводу было бы здорово услышать!