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
serviceHub.recordTransactions(finalTx)
val newOutput = run {
if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub).outRef<T>(0)
} else {
stx.tx.outRef<T>(0)
}
}
return newOutput
return stx.resolveBaseTransaction(serviceHub).outRef<T>(0)
}
/**
@ -174,11 +166,7 @@ abstract class AbstractStateReplacementFlow {
}
val finalTx = stx + allSignatures
if (finalTx.isNotaryChangeTransaction()) {
finalTx.resolveNotaryChangeTransaction(serviceHub).verifyRequiredSignatures()
} else {
finalTx.verifyRequiredSignatures()
}
finalTx.resolveTransactionWithSignatures(serviceHub).verifyRequiredSignatures()
serviceHub.recordTransactions(finalTx)
}
@ -195,11 +183,7 @@ abstract class AbstractStateReplacementFlow {
// TODO Check the set of multiple identities?
val myKey = ourIdentity.owningKey
val requiredKeys = if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub).requiredSigningKeys
} else {
stx.tx.requiredSigningKeys
}
val requiredKeys = stx.resolveTransactionWithSignatures(serviceHub).requiredSigningKeys
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 {
if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub).verifySignaturesExcept(notaryParty.owningKey)
} else {
stx.verifySignaturesExcept(notaryParty.owningKey)
}
stx.resolveTransactionWithSignatures(serviceHub).verifySignaturesExcept(notaryParty.owningKey)
} catch (ex: SignatureException) {
throw NotaryException(NotaryError.TransactionInvalid(ex))
}

View File

@ -164,11 +164,7 @@ interface ServiceHub : ServicesForResolution {
@Throws(TransactionResolutionException::class)
fun <T : ContractState> toStateAndRef(stateRef: StateRef): StateAndRef<T> {
val stx = validatedTransactions.getTransaction(stateRef.txhash) ?: throw TransactionResolutionException(stateRef.txhash)
return if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(this).outRef(stateRef.index)
} else {
stx.tx.outRef(stateRef.index)
}
return stx.resolveBaseTransaction(this).outRef<T>(stateRef.index)
}
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
/**
* 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
* [NotaryChangeLedgerTransaction] so the signatures can be verified.

View File

@ -1,6 +1,8 @@
package net.corda.core.transactions
import net.corda.core.contracts.ContractState
import net.corda.core.contracts.NamedByHash
import net.corda.core.contracts.TransactionState
import net.corda.core.crypto.TransactionSignature
import net.corda.core.crypto.isFulfilledBy
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 notary = stx.notary
checkNotary(notary)
var timeWindow: TimeWindow? = null
val transactionWithSignatures = if (stx.isNotaryChangeTransaction()) {
stx.resolveNotaryChangeTransaction(serviceHub)
} else {
timeWindow = stx.tx.timeWindow
stx
}
val timeWindow: TimeWindow? = if (stx.isNotaryChangeTransaction())
null
else
stx.tx.timeWindow
val transactionWithSignatures = stx.resolveTransactionWithSignatures(serviceHub)
checkSignatures(transactionWithSignatures)
return TransactionParts(stx.id, stx.inputs, timeWindow, notary!!)
} catch (e: Exception) {

View File

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

View File

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