CORDA-641: Remove special case handling of notary transactions (#1675)

Move special case handling of notary transactions into `SignedTransaction`
This commit is contained in:
Ross Nicoll
2017-10-10 13:23:31 +01:00
committed by GitHub
parent 0e47e53b60
commit 242b019dc2
8 changed files with 44 additions and 46 deletions

View File

@ -70,15 +70,7 @@ abstract class AbstractStateReplacementFlow {
val finalTx = stx + signatures val finalTx = stx + signatures
serviceHub.recordTransactions(finalTx) serviceHub.recordTransactions(finalTx)
val newOutput = run { return stx.resolveBaseTransaction(serviceHub).outRef<T>(0)
if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub).outRef<T>(0)
} else {
stx.tx.outRef<T>(0)
}
}
return newOutput
} }
/** /**
@ -174,11 +166,7 @@ abstract class AbstractStateReplacementFlow {
} }
val finalTx = stx + allSignatures val finalTx = stx + allSignatures
if (finalTx.isNotaryChangeTransaction()) { finalTx.resolveTransactionWithSignatures(serviceHub).verifyRequiredSignatures()
finalTx.resolveNotaryChangeTransaction(serviceHub).verifyRequiredSignatures()
} else {
finalTx.verifyRequiredSignatures()
}
serviceHub.recordTransactions(finalTx) serviceHub.recordTransactions(finalTx)
} }
@ -195,11 +183,7 @@ abstract class AbstractStateReplacementFlow {
// TODO Check the set of multiple identities? // TODO Check the set of multiple identities?
val myKey = ourIdentity.owningKey val myKey = ourIdentity.owningKey
val requiredKeys = if (stx.isNotaryChangeTransaction()) { val requiredKeys = stx.resolveTransactionWithSignatures(serviceHub).requiredSigningKeys
stx.resolveNotaryChangeTransaction(serviceHub).requiredSigningKeys
} else {
stx.tx.requiredSigningKeys
}
require(myKey in requiredKeys) { "Party is not a participant for any of the input states of transaction ${stx.id}" } require(myKey in requiredKeys) { "Party is not a participant for any of the input states of transaction ${stx.id}" }
} }

View File

@ -54,11 +54,7 @@ class NotaryFlow {
} }
try { try {
if (stx.isNotaryChangeTransaction()) { stx.resolveTransactionWithSignatures(serviceHub).verifySignaturesExcept(notaryParty.owningKey)
stx.resolveNotaryChangeTransaction(serviceHub).verifySignaturesExcept(notaryParty.owningKey)
} else {
stx.verifySignaturesExcept(notaryParty.owningKey)
}
} catch (ex: SignatureException) { } catch (ex: SignatureException) {
throw NotaryException(NotaryError.TransactionInvalid(ex)) throw NotaryException(NotaryError.TransactionInvalid(ex))
} }

View File

@ -164,11 +164,7 @@ interface ServiceHub : ServicesForResolution {
@Throws(TransactionResolutionException::class) @Throws(TransactionResolutionException::class)
fun <T : ContractState> toStateAndRef(stateRef: StateRef): StateAndRef<T> { fun <T : ContractState> toStateAndRef(stateRef: StateRef): StateAndRef<T> {
val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash) val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash)
return if (stx.isNotaryChangeTransaction()) { return stx.resolveBaseTransaction(this).outRef<T>(stateRef.index)
stx.resolveNotaryChangeTransaction(this).outRef(stateRef.index)
} else {
stx.tx.outRef(stateRef.index)
}
} }
private val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentitiesAndCerts.first().owningKey private val legalIdentityKey: PublicKey get() = this.myInfo.legalIdentitiesAndCerts.first().owningKey

View File

@ -179,6 +179,32 @@ data class SignedTransaction(val txBits: SerializedBytes<CoreTransaction>,
fun isNotaryChangeTransaction() = transaction is NotaryChangeWireTransaction fun isNotaryChangeTransaction() = transaction is NotaryChangeWireTransaction
/**
* Resolves the underlying base transaction and then returns it, handling any special case transactions such as
* [NotaryChangeWireTransaction].
*/
fun resolveBaseTransaction(services: StateLoader): BaseTransaction {
return when (transaction) {
is NotaryChangeWireTransaction -> resolveNotaryChangeTransaction(services)
is WireTransaction -> this.tx
is FilteredTransaction -> throw IllegalStateException("Persistence of filtered transactions is not supported.")
else -> throw IllegalStateException("Unknown transaction type ${transaction::class.qualifiedName}")
}
}
/**
* Resolves the underlying transaction with signatures and then returns it, handling any special case transactions
* such as [NotaryChangeWireTransaction].
*/
fun resolveTransactionWithSignatures(services: ServiceHub): TransactionWithSignatures {
return when (transaction) {
is NotaryChangeWireTransaction -> resolveNotaryChangeTransaction(services)
is WireTransaction -> this
is FilteredTransaction -> throw IllegalStateException("Persistence of filtered transactions is not supported.")
else -> throw IllegalStateException("Unknown transaction type ${transaction::class.qualifiedName}")
}
}
/** /**
* If [transaction] is a [NotaryChangeWireTransaction], loads the input states and resolves it to a * If [transaction] is a [NotaryChangeWireTransaction], loads the input states and resolves it to a
* [NotaryChangeLedgerTransaction] so the signatures can be verified. * [NotaryChangeLedgerTransaction] so the signatures can be verified.

View File

@ -1,6 +1,8 @@
package net.corda.core.transactions package net.corda.core.transactions
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.NamedByHash import net.corda.core.contracts.NamedByHash
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.TransactionSignature import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.isFulfilledBy import net.corda.core.crypto.isFulfilledBy
import net.corda.core.transactions.SignedTransaction.SignaturesMissingException import net.corda.core.transactions.SignedTransaction.SignaturesMissingException

View File

@ -38,13 +38,11 @@ class MyValidatingNotaryFlow(otherSide: FlowSession, service: MyCustomValidating
val stx = subFlow(ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = false)) val stx = subFlow(ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = false))
val notary = stx.notary val notary = stx.notary
checkNotary(notary) checkNotary(notary)
var timeWindow: TimeWindow? = null val timeWindow: TimeWindow? = if (stx.isNotaryChangeTransaction())
val transactionWithSignatures = if (stx.isNotaryChangeTransaction()) { null
stx.resolveNotaryChangeTransaction(serviceHub) else
} else { stx.tx.timeWindow
timeWindow = stx.tx.timeWindow val transactionWithSignatures = stx.resolveTransactionWithSignatures(serviceHub)
stx
}
checkSignatures(transactionWithSignatures) checkSignatures(transactionWithSignatures)
return TransactionParts(stx.id, stx.inputs, timeWindow, notary!!) return TransactionParts(stx.id, stx.inputs, timeWindow, notary!!)
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -35,8 +35,6 @@ class StateLoaderImpl(private val validatedTransactions: TransactionStorage) : S
@Throws(TransactionResolutionException::class) @Throws(TransactionResolutionException::class)
override fun loadState(stateRef: StateRef): TransactionState<*> { override fun loadState(stateRef: StateRef): TransactionState<*> {
val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash) val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash)
return if (stx.isNotaryChangeTransaction()) { return stx.resolveBaseTransaction(this).outputs[stateRef.index]
stx.resolveNotaryChangeTransaction(this).outputs[stateRef.index]
} else stx.tx.outputs[stateRef.index]
} }
} }

View File

@ -25,13 +25,11 @@ class ValidatingNotaryFlow(otherSideSession: FlowSession, service: TrustedAuthor
val stx = subFlow(ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = false)) val stx = subFlow(ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = false))
val notary = stx.notary val notary = stx.notary
checkNotary(notary) checkNotary(notary)
var timeWindow: TimeWindow? = null val timeWindow: TimeWindow? = if (stx.isNotaryChangeTransaction())
val transactionWithSignatures = if (stx.isNotaryChangeTransaction()) { null
stx.resolveNotaryChangeTransaction(serviceHub) else
} else { stx.tx.timeWindow
timeWindow = stx.tx.timeWindow val transactionWithSignatures = stx.resolveTransactionWithSignatures(serviceHub)
stx
}
checkSignatures(transactionWithSignatures) checkSignatures(transactionWithSignatures)
return TransactionParts(stx.id, stx.inputs, timeWindow, notary!!) return TransactionParts(stx.id, stx.inputs, timeWindow, notary!!)
} catch (e: Exception) { } catch (e: Exception) {