mirror of
https://github.com/corda/corda.git
synced 2025-06-16 22:28:15 +00:00
Cleaned up ContractUpgradeFlow API (#1591)
This commit is contained in:
@ -8,7 +8,6 @@ import net.corda.confidential.SwapIdentitiesFlow
|
||||
import net.corda.confidential.SwapIdentitiesHandler
|
||||
import net.corda.core.concurrent.CordaFuture
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.flows.ContractUpgradeFlow.Acceptor
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
@ -35,6 +34,7 @@ import net.corda.core.utilities.debug
|
||||
import net.corda.node.internal.classloading.requireAnnotation
|
||||
import net.corda.node.internal.cordapp.CordappLoader
|
||||
import net.corda.node.internal.cordapp.CordappProvider
|
||||
import net.corda.node.services.ContractUpgradeHandler
|
||||
import net.corda.node.services.FinalityHandler
|
||||
import net.corda.node.services.NotaryChangeHandler
|
||||
import net.corda.node.services.api.*
|
||||
@ -372,7 +372,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
private fun installCoreFlows() {
|
||||
installCoreFlow(FinalityFlow::class, ::FinalityHandler)
|
||||
installCoreFlow(NotaryChangeFlow::class, ::NotaryChangeHandler)
|
||||
installCoreFlow(ContractUpgradeFlow.Initiator::class, ::Acceptor)
|
||||
installCoreFlow(ContractUpgradeFlow.Initiate::class, ::ContractUpgradeHandler)
|
||||
installCoreFlow(SwapIdentitiesFlow::class, ::SwapIdentitiesHandler)
|
||||
}
|
||||
|
||||
|
@ -54,8 +54,7 @@ class CordappLoader private constructor(private val cordappJarPaths: List<URL>)
|
||||
/**
|
||||
* Creates a dev mode CordappLoader intended to only be used in test environments.
|
||||
*
|
||||
* @param scanPackage Resolves the JARs that contain scanPackage and use them as the source for
|
||||
* the classpath scanning.
|
||||
* @param scanPackages list of packages to scan.
|
||||
*/
|
||||
fun createDevMode(scanPackages: String): CordappLoader {
|
||||
val paths = scanPackages.split(",").flatMap { scanPackage ->
|
||||
@ -123,7 +122,11 @@ class CordappLoader private constructor(private val cordappJarPaths: List<URL>)
|
||||
}
|
||||
|
||||
val found = scanResult.getClassesWithAnnotation(FlowLogic::class, StartableByRPC::class).filter { it.isUserInvokable() }
|
||||
val coreFlows = listOf(ContractUpgradeFlow.Initiator::class.java)
|
||||
val coreFlows = listOf(
|
||||
ContractUpgradeFlow.Initiate::class.java,
|
||||
ContractUpgradeFlow.Authorise::class.java,
|
||||
ContractUpgradeFlow.Deauthorise::class.java
|
||||
)
|
||||
return found + coreFlows
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,13 @@
|
||||
package net.corda.node.services
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.ContractState
|
||||
import net.corda.core.contracts.UpgradeCommand
|
||||
import net.corda.core.contracts.UpgradedContract
|
||||
import net.corda.core.contracts.requireThat
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.ContractUpgradeUtils
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
|
||||
// TODO: We should have a whitelist of contracts we're willing to accept at all, and reject if the transaction
|
||||
@ -41,3 +46,27 @@ class NotaryChangeHandler(otherSideSession: FlowSession) : AbstractStateReplacem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ContractUpgradeHandler(otherSide: FlowSession) : AbstractStateReplacementFlow.Acceptor<Class<out UpgradedContract<ContractState, *>>>(otherSide) {
|
||||
@Suspendable
|
||||
override fun verifyProposal(stx: SignedTransaction, proposal: AbstractStateReplacementFlow.Proposal<Class<out UpgradedContract<ContractState, *>>>) {
|
||||
// Retrieve signed transaction from our side, we will apply the upgrade logic to the transaction on our side, and
|
||||
// verify outputs matches the proposed upgrade.
|
||||
val ourSTX = serviceHub.validatedTransactions.getTransaction(proposal.stateRef.txhash)
|
||||
requireNotNull(ourSTX) { "We don't have a copy of the referenced state" }
|
||||
val oldStateAndRef = ourSTX!!.tx.outRef<ContractState>(proposal.stateRef.index)
|
||||
val authorisedUpgrade = serviceHub.contractUpgradeService.getAuthorisedContractUpgrade(oldStateAndRef.ref) ?:
|
||||
throw IllegalStateException("Contract state upgrade is unauthorised. State hash : ${oldStateAndRef.ref}")
|
||||
val proposedTx = stx.tx
|
||||
val expectedTx = ContractUpgradeUtils.assembleBareTx(oldStateAndRef, proposal.modification, proposedTx.privacySalt).toWireTransaction()
|
||||
requireThat {
|
||||
"The instigator is one of the participants" using (initiatingSession.counterparty in oldStateAndRef.state.data.participants)
|
||||
"The proposed upgrade ${proposal.modification.javaClass} is a trusted upgrade path" using (proposal.modification.name == authorisedUpgrade)
|
||||
"The proposed tx matches the expected tx for this upgrade" using (proposedTx == expectedTx)
|
||||
}
|
||||
ContractUpgradeFlow.verify(
|
||||
oldStateAndRef.state,
|
||||
expectedTx.outRef<ContractState>(0).state,
|
||||
expectedTx.toLedgerTransaction(serviceHub).commandsOfType<UpgradeCommand>().single())
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class CordappLoaderTest {
|
||||
val actualCordapp = actual.first()
|
||||
assertThat(actualCordapp.contractClassNames).isEqualTo(listOf("net.corda.finance.contracts.isolated.AnotherDummyContract"))
|
||||
assertThat(actualCordapp.initiatedFlows).isEmpty()
|
||||
assertThat(actualCordapp.rpcFlows).isEqualTo(listOf(loader.appClassLoader.loadClass("net.corda.core.flows.ContractUpgradeFlow\$Initiator").asSubclass(FlowLogic::class.java)))
|
||||
assertThat(actualCordapp.rpcFlows).contains(loader.appClassLoader.loadClass("net.corda.core.flows.ContractUpgradeFlow\$Initiate").asSubclass(FlowLogic::class.java))
|
||||
assertThat(actualCordapp.services).isEmpty()
|
||||
assertThat(actualCordapp.plugins).hasSize(1)
|
||||
assertThat(actualCordapp.plugins.first().javaClass.name).isEqualTo("net.corda.finance.contracts.isolated.DummyPlugin")
|
||||
|
Reference in New Issue
Block a user