Проверка кассового контракта
Я сталкиваюсь с проблемой во время потока сбора подписей, когда Проверка кассового контракта терпит неудачу, предоставляя сообщение об ошибке
Проверка контракта не удалась: не удалось требование: для справки [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 ответа:
Вот соответствующая часть
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>
. Если вы отладите свой поток и изучите содержание транзакции, прежде чем она будет проверена, вы должны быть в состоянии определить, так ли это.
Для тех, кто столкнулся с этой проблемой / аналогичными проблемами проверки наличности, я смог исправить это, создав узел, который будет действовать как центральный эмитент наличных денег, а затем вместо самостоятельного выпуска наличных денег в начале моделирования я использовал поток наличных денег и платежей и отправил определенное количество наличных денег в каждый узел.
Я до сих пор не уверен, была ли эта проблема вызвана чем-то в моих потоках или тем фактом, что одна сторона была эмитентом и получателем наличных государств - если кто-то имеет вклад по этому поводу было бы здорово услышать!