mirror of
https://github.com/corda/corda.git
synced 2025-01-31 00:24:59 +00:00
Merge pull request #12 from corda/andrius-txverify-refactor
This commit is contained in:
commit
84c127bfff
@ -49,15 +49,20 @@ sealed class TransactionType {
|
|||||||
/** Just uses the default [TransactionBuilder] with no special logic */
|
/** Just uses the default [TransactionBuilder] with no special logic */
|
||||||
class Builder(notary: Party?) : TransactionBuilder(General(), notary) {}
|
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) {
|
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
|
verifyNoNotaryChange(tx)
|
||||||
// are any inputs, all outputs must have the same notary.
|
verifyEncumbrances(tx)
|
||||||
// TODO: Is that the correct set of restrictions? May need to come back to this, see if we can be more
|
verifyContracts(tx)
|
||||||
// flexible on output notaries.
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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()) {
|
if (tx.notary != null && tx.inputs.isNotEmpty()) {
|
||||||
tx.outputs.forEach {
|
tx.outputs.forEach {
|
||||||
if (it.notary != tx.notary) {
|
if (it.notary != tx.notary) {
|
||||||
@ -65,25 +70,16 @@ sealed class TransactionType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val ctx = tx.toTransactionForContract()
|
private fun verifyEncumbrances(tx: LedgerTransaction) {
|
||||||
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate that all encumbrances exist within the set of input states.
|
// Validate that all encumbrances exist within the set of input states.
|
||||||
tx.inputs.filter { it.state.data.encumbrance != null }.forEach { encumberedInput ->
|
val encumberedInputs = tx.inputs.filter { it.state.data.encumbrance != null }
|
||||||
val isMissing = tx.inputs.none {
|
encumberedInputs.forEach { encumberedInput ->
|
||||||
|
val encumbranceStateExists = tx.inputs.any {
|
||||||
it.ref.txhash == encumberedInput.ref.txhash && it.ref.index == encumberedInput.state.data.encumbrance
|
it.ref.txhash == encumberedInput.ref.txhash && it.ref.index == encumberedInput.state.data.encumbrance
|
||||||
}
|
}
|
||||||
if (isMissing) {
|
if (!encumbranceStateExists) {
|
||||||
throw TransactionVerificationException.TransactionMissingEncumbranceException(
|
throw TransactionVerificationException.TransactionMissingEncumbranceException(
|
||||||
tx, encumberedInput.state.data.encumbrance!!,
|
tx, encumberedInput.state.data.encumbrance!!,
|
||||||
TransactionVerificationException.Direction.INPUT
|
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()
|
override fun getRequiredSigners(tx: LedgerTransaction) = tx.commands.flatMap { it.signers }.toSet()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user