mirror of
https://github.com/corda/corda.git
synced 2025-06-21 16:49:45 +00:00
CORDA-641: Remove special case handling of notary transactions (#1675)
Move special case handling of notary transactions into `SignedTransaction`
This commit is contained in:
@ -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}" }
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
Reference in New Issue
Block a user