2017-11-30 20 views
0
내가 수집 서명하는 동안 문제가 발생하고

흐름 -현금 계약 검증

계약 검증이 실패 오류 메시지를 제공 : 실패 요구 사항 : 발행에서 참조 [01]에 대한 C가 미국 = , L = 뉴욕, O = PartyB 양의 균형! 300000-0 = 0, 계약 : [email protected]

사실 그 때문이다 나타납니다 입력 된 현금 금액은 출력 + 원장을 나가는 금액과 동일하지 않습니다.

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

그러나 나는 단순히 Cash.generateSpend() 함수를 사용하고있는 트랜잭션 내에서 현금 상태를 생성하는, 그래서 나는이 오류가 발생할 수 수 있는지 모르겠습니다. 사용되는 현금은 시뮬레이션이 시작될 때 자체 발행되며이 문제를 일으키는 플로우가 호출되기 전에 노드간에 이동되었을 수 있습니다.

현금 상태의 정확한 값을 볼 수는 없지만 2 가지 상태가 있음을 알 수 있습니다. 현금의 산출량은 지출 된 금액 (3102 달러)과 당 3,020 달러를 소비하는 다른 두 주 (97991898 달러와 97995000 달러 중 하나)입니다. 파티는 시뮬레이션 시작시 원래 98000000 달러가 발행되었으므로이 세 번째 출력 상태는 $ 97995000이므로 매우 이상하게 보입니다. $ 97991898 + $ 3102 = $ 97995000 이래로 두 입력 상태가 $ 97995000에 이르고이 파티가 이미 다른 흐름에서 $ 5000을 소비 했으므로이 세 번째 현금 출력은 97995000 달러로 보이지 않는 것처럼 보입니다.

이 문제는 Cash.generateSpend()에서 문제가 발생할 수 있습니까? 현금의 다른 입력 또는 출력 상태를 추가하지 않을 것입니다 (아래에 흐름을 첨부했습니다). 또한이 문제는 5000 달러를 지출하는 흐름을 허용하는 경우에만 발생합니다 (즉, 파티 A는 B 달러 5,000 원을 지불하고 원장에 기록한 다음 여기 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)) 

나는이 질문은 끝이 매우 열려 알고 있지만, 내가 잘못 갈 수있는 지역에있는 모든 포인터는 크게 감상 할 수있다.

답변

0

여기 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>과 함께 출력한다는 것입니다.흐름을 디버그하고 트랜잭션이 검증되기 전에 트랜잭션의 내용을 검사하는 경우,이 경우인지 여부를 판별 할 수 있어야합니다.

1

이 문제/비슷한 현금 확인 문제를 겪고있는 사람이라면 누구든지 중앙 현금 발행자 역할을하는 노드를 만들어서 시뮬레이션 초기에 현금을 발행하는 대신에 CashIssueAndPayment 플로우와 일정량의 현금을 각 노드에 보냅니다.

이 문제가 내 흐름 내에서 발생했거나 단일 당사자가 현금 상태의 발행자 및 리시버 였기 때문에 여전히 확신 할 수 없습니다. 누군가가이 정보를 입력하면이를 듣는 것이 좋을 것입니다.