mirror of
https://github.com/corda/corda.git
synced 2024-12-19 04:57:58 +00:00
Minor transaction verification logic refactoring
This commit is contained in:
parent
053dd9a1fe
commit
cef2c906ab
@ -49,15 +49,20 @@ sealed class TransactionType {
|
||||
/** Just uses the default [TransactionBuilder] with no special logic */
|
||||
class Builder(notary: Party?) : TransactionBuilder(General(), notary) {}
|
||||
|
||||
/**
|
||||
* Check the transaction is contract-valid by running the verify() for each input and output state contract.
|
||||
* If any contract fails to verify, the whole transaction is considered to be invalid.
|
||||
*/
|
||||
override fun verifyTransaction(tx: LedgerTransaction) {
|
||||
// Make sure the notary has stayed the same. As we can't tell how inputs and outputs connect, if there
|
||||
// are any inputs, all outputs must have the same notary.
|
||||
// TODO: Is that the correct set of restrictions? May need to come back to this, see if we can be more
|
||||
// flexible on output notaries.
|
||||
verifyNoNotaryChange(tx)
|
||||
verifyEncumbrances(tx)
|
||||
verifyContracts(tx)
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the notary has stayed the same. As we can't tell how inputs and outputs connect, if there
|
||||
* are any inputs, all outputs must have the same notary.
|
||||
*
|
||||
* TODO: Is that the correct set of restrictions? May need to come back to this, see if we can be more
|
||||
* flexible on output notaries.
|
||||
*/
|
||||
private fun verifyNoNotaryChange(tx: LedgerTransaction) {
|
||||
if (tx.notary != null && tx.inputs.isNotEmpty()) {
|
||||
tx.outputs.forEach {
|
||||
if (it.notary != tx.notary) {
|
||||
@ -65,25 +70,16 @@ sealed class TransactionType {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val ctx = tx.toTransactionForContract()
|
||||
|
||||
// TODO: This will all be replaced in future once the sandbox and contract constraints work is done.
|
||||
val contracts = (ctx.inputs.map { it.contract } + ctx.outputs.map { it.contract }).toSet()
|
||||
for (contract in contracts) {
|
||||
try {
|
||||
contract.verify(ctx)
|
||||
} catch(e: Throwable) {
|
||||
throw TransactionVerificationException.ContractRejection(tx, contract, e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun verifyEncumbrances(tx: LedgerTransaction) {
|
||||
// Validate that all encumbrances exist within the set of input states.
|
||||
tx.inputs.filter { it.state.data.encumbrance != null }.forEach { encumberedInput ->
|
||||
val isMissing = tx.inputs.none {
|
||||
val encumberedInputs = tx.inputs.filter { it.state.data.encumbrance != null }
|
||||
encumberedInputs.forEach { encumberedInput ->
|
||||
val encumbranceStateExists = tx.inputs.any {
|
||||
it.ref.txhash == encumberedInput.ref.txhash && it.ref.index == encumberedInput.state.data.encumbrance
|
||||
}
|
||||
if (isMissing) {
|
||||
if (!encumbranceStateExists) {
|
||||
throw TransactionVerificationException.TransactionMissingEncumbranceException(
|
||||
tx, encumberedInput.state.data.encumbrance!!,
|
||||
TransactionVerificationException.Direction.INPUT
|
||||
@ -103,6 +99,23 @@ sealed class TransactionType {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the transaction is contract-valid by running the verify() for each input and output state contract.
|
||||
* If any contract fails to verify, the whole transaction is considered to be invalid.
|
||||
*/
|
||||
private fun verifyContracts(tx: LedgerTransaction) {
|
||||
val ctx = tx.toTransactionForContract()
|
||||
// TODO: This will all be replaced in future once the sandbox and contract constraints work is done.
|
||||
val contracts = (ctx.inputs.map { it.contract } + ctx.outputs.map { it.contract }).toSet()
|
||||
for (contract in contracts) {
|
||||
try {
|
||||
contract.verify(ctx)
|
||||
} catch(e: Throwable) {
|
||||
throw TransactionVerificationException.ContractRejection(tx, contract, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getRequiredSigners(tx: LedgerTransaction) = tx.commands.flatMap { it.signers }.toSet()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user