diff --git a/client/src/integration-test/kotlin/net/corda/client/NodeMonitorModelTest.kt b/client/src/integration-test/kotlin/net/corda/client/NodeMonitorModelTest.kt index 294c969d0d..303ab00583 100644 --- a/client/src/integration-test/kotlin/net/corda/client/NodeMonitorModelTest.kt +++ b/client/src/integration-test/kotlin/net/corda/client/NodeMonitorModelTest.kt @@ -7,24 +7,24 @@ import net.corda.core.contracts.Amount import net.corda.core.contracts.Issued import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.USD +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.NodeInfo import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.StateMachineTransactionMapping import net.corda.core.node.services.Vault -import net.corda.core.protocols.StateMachineRunId import net.corda.core.serialization.OpaqueBytes import net.corda.core.transactions.SignedTransaction +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow import net.corda.node.driver.driver import net.corda.node.services.User import net.corda.node.services.config.configureTestSSL import net.corda.node.services.messaging.ArtemisMessagingComponent import net.corda.node.services.messaging.StateMachineUpdate import net.corda.node.services.network.NetworkMapService -import net.corda.node.services.startProtocolPermission +import net.corda.node.services.startFlowPermission import net.corda.node.services.transactions.SimpleNotaryService -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol import net.corda.testing.expect import net.corda.testing.expectEvents import net.corda.testing.sequence @@ -56,7 +56,7 @@ class NodeMonitorModelTest { val driverStarted = CountDownLatch(1) driverThread = thread { driver { - val cashUser = User("user1", "test", permissions = setOf(startProtocolPermission())) + val cashUser = User("user1", "test", permissions = setOf(startFlowPermission())) val aliceNodeFuture = startNode("Alice", rpcUsers = listOf(cashUser)) val notaryNodeFuture = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))) diff --git a/client/src/main/kotlin/net/corda/client/mock/EventGenerator.kt b/client/src/main/kotlin/net/corda/client/mock/EventGenerator.kt index 962cd81a3c..427f62da5c 100644 --- a/client/src/main/kotlin/net/corda/client/mock/EventGenerator.kt +++ b/client/src/main/kotlin/net/corda/client/mock/EventGenerator.kt @@ -5,7 +5,7 @@ import net.corda.core.contracts.* import net.corda.core.crypto.Party import net.corda.core.serialization.OpaqueBytes import net.corda.core.transactions.TransactionBuilder -import net.corda.protocols.CashCommand +import net.corda.flows.CashCommand /** * [Generator]s for incoming/outgoing events to/from the [WalletMonitorService]. Internally it keeps track of owned diff --git a/client/src/main/kotlin/net/corda/client/model/GatheredTransactionDataModel.kt b/client/src/main/kotlin/net/corda/client/model/GatheredTransactionDataModel.kt index 14c30f7499..ff33e51d72 100644 --- a/client/src/main/kotlin/net/corda/client/model/GatheredTransactionDataModel.kt +++ b/client/src/main/kotlin/net/corda/client/model/GatheredTransactionDataModel.kt @@ -1,18 +1,18 @@ package net.corda.client.model +import javafx.beans.property.SimpleObjectProperty +import javafx.beans.value.ObservableValue +import javafx.collections.ObservableList +import javafx.collections.ObservableMap import net.corda.client.fxutils.* import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateRef import net.corda.core.crypto.SecureHash +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.services.StateMachineTransactionMapping -import net.corda.core.protocols.StateMachineRunId import net.corda.core.transactions.SignedTransaction import net.corda.node.services.messaging.StateMachineUpdate -import javafx.beans.property.SimpleObjectProperty -import javafx.beans.value.ObservableValue -import javafx.collections.ObservableList -import javafx.collections.ObservableMap import org.fxmisc.easybind.EasyBind data class GatheredTransactionData( @@ -59,7 +59,7 @@ sealed class TransactionCreateStatus(val message: String?) { override fun toString(): String = message ?: javaClass.simpleName } -data class ProtocolStatus( +data class FlowStatus( val status: String ) @@ -71,12 +71,12 @@ sealed class StateMachineStatus(val stateMachineName: String) { data class StateMachineData( val id: StateMachineRunId, - val protocolStatus: ObservableValue, + val flowStatus: ObservableValue, val stateMachineStatus: ObservableValue ) /** - * This model provides an observable list of transactions and what state machines/protocols recorded them + * This model provides an observable list of transactions and what state machines/flows recorded them */ class GatheredTransactionDataModel { @@ -92,7 +92,7 @@ class GatheredTransactionDataModel { when (update) { is StateMachineUpdate.Added -> { val added: SimpleObjectProperty = - SimpleObjectProperty(StateMachineStatus.Added(update.stateMachineInfo.protocolLogicClassName)) + SimpleObjectProperty(StateMachineStatus.Added(update.stateMachineInfo.flowLogicClassName)) map[update.id] = added } is StateMachineUpdate.Removed -> { @@ -103,7 +103,7 @@ class GatheredTransactionDataModel { } } private val stateMachineDataList = LeftOuterJoinedMap(stateMachineStatus, progressEvents) { id, status, progress -> - StateMachineData(id, progress.map { it?.let { ProtocolStatus(it.message) } }, status) + StateMachineData(id, progress.map { it?.let { FlowStatus(it.message) } }, status) }.getObservableValues() private val stateMachineDataMap = stateMachineDataList.associateBy(StateMachineData::id) private val smTxMappingList = stateMachineTransactionMapping.recordInSequence() diff --git a/client/src/main/kotlin/net/corda/client/model/NodeMonitorModel.kt b/client/src/main/kotlin/net/corda/client/model/NodeMonitorModel.kt index 08d61b9ba1..5949f8aa8c 100644 --- a/client/src/main/kotlin/net/corda/client/model/NodeMonitorModel.kt +++ b/client/src/main/kotlin/net/corda/client/model/NodeMonitorModel.kt @@ -3,18 +3,18 @@ package net.corda.client.model import com.google.common.net.HostAndPort import javafx.beans.property.SimpleObjectProperty import net.corda.client.CordaRPCClient +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.StateMachineTransactionMapping import net.corda.core.node.services.Vault -import net.corda.core.protocols.StateMachineRunId import net.corda.core.transactions.SignedTransaction +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow import net.corda.node.services.config.NodeSSLConfiguration import net.corda.node.services.messaging.CordaRPCOps import net.corda.node.services.messaging.StateMachineInfo import net.corda.node.services.messaging.StateMachineUpdate -import net.corda.node.services.messaging.startProtocol -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol +import net.corda.node.services.messaging.startFlow import rx.Observable import rx.subjects.PublishSubject @@ -63,7 +63,7 @@ class NodeMonitorModel { val proxy = client.proxy() val (stateMachines, stateMachineUpdates) = proxy.stateMachinesAndUpdates() - // Extract the protocol tracking stream + // Extract the flow tracking stream // TODO is there a nicer way of doing this? Stream of streams in general results in code like this... val currentProgressTrackerUpdates = stateMachines.mapNotNull { stateMachine -> ProgressTrackingEvent.createStreamFromStateMachineInfo(stateMachine) @@ -100,7 +100,7 @@ class NodeMonitorModel { // Client -> Service clientToServiceSource.subscribe { - proxy.startProtocol(::CashProtocol, it) + proxy.startFlow(::CashFlow, it) } proxyObservable.set(proxy) } diff --git a/core/src/main/kotlin/net/corda/core/contracts/Structures.kt b/core/src/main/kotlin/net/corda/core/contracts/Structures.kt index 563858def6..663a89d0eb 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/Structures.kt @@ -4,9 +4,9 @@ import net.corda.core.contracts.clauses.Clause import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.flows.FlowLogicRef +import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.node.services.ServiceType -import net.corda.core.protocols.ProtocolLogicRef -import net.corda.core.protocols.ProtocolLogicRefFactory import net.corda.core.serialization.OpaqueBytes import net.corda.core.serialization.serialize import net.corda.core.transactions.TransactionBuilder @@ -206,16 +206,16 @@ data class ScheduledStateRef(val ref: StateRef, override val scheduledAt: Instan /** * This class represents the lifecycle activity that a contract state of type [LinearState] would like to perform at a given point in time. - * e.g. run a fixing protocol. + * e.g. run a fixing flow. * - * Note the use of [ProtocolLogicRef] to represent a safe way to transport a [ProtocolLogic] out of the contract sandbox. + * Note the use of [FlowLogicRef] to represent a safe way to transport a [FlowLogic] out of the contract sandbox. * - * Currently we support only protocol based activities as we expect there to be a transaction generated off the back of + * Currently we support only flow based activities as we expect there to be a transaction generated off the back of * the activity, otherwise we have to start tracking secondary state on the platform of which scheduled activities * for a particular [ContractState] have been processed/fired etc. If the activity is not "on ledger" then the * scheduled activity shouldn't be either. */ -data class ScheduledActivity(val logicRef: ProtocolLogicRef, override val scheduledAt: Instant) : Scheduled +data class ScheduledActivity(val logicRef: FlowLogicRef, override val scheduledAt: Instant) : Scheduled /** * A state that evolves by superseding itself, all of which share the common "linearId". @@ -261,16 +261,16 @@ interface SchedulableState : ContractState { * [ContractState], what that activity is and at what point in time it should be initiated. * This can be used to implement deadlines for payment or processing of financial instruments according to a schedule. * - * The state has no reference to it's own StateRef, so supply that for use as input to any ProtocolLogic constructed. + * The state has no reference to it's own StateRef, so supply that for use as input to any FlowLogic constructed. * * @return null if there is no activity to schedule. */ - fun nextScheduledActivity(thisStateRef: StateRef, protocolLogicRefFactory: ProtocolLogicRefFactory): ScheduledActivity? + fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? } /** * Interface representing an agreement that exposes various attributes that are common. Implementing it simplifies - * implementation of general protocols that manipulate many agreement types. + * implementation of general flows that manipulate many agreement types. */ interface DealState : LinearState { /** Human readable well known reference (e.g. trade reference) */ @@ -293,7 +293,7 @@ interface DealState : LinearState { /** * Generate a partial transaction representing an agreement (command) to this deal, allowing a general - * deal/agreement protocol to generate the necessary transaction for potential implementations. + * deal/agreement flow to generate the necessary transaction for potential implementations. * * TODO: Currently this is the "inception" transaction but in future an offer of some description might be an input state ref * diff --git a/core/src/main/kotlin/net/corda/core/protocols/ProtocolLogic.kt b/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt similarity index 63% rename from core/src/main/kotlin/net/corda/core/protocols/ProtocolLogic.kt rename to core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt index f9afee6d53..3a9e7186b0 100644 --- a/core/src/main/kotlin/net/corda/core/protocols/ProtocolLogic.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt @@ -1,4 +1,4 @@ -package net.corda.core.protocols +package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.Party @@ -9,9 +9,9 @@ import org.slf4j.Logger import rx.Observable /** - * A sub-class of [ProtocolLogic] implements a protocol flow using direct, straight line blocking code. Thus you - * can write complex protocol logic in an ordinary fashion, without having to think about callbacks, restarting after - * a node crash, how many instances of your protocol there are running and so on. + * A sub-class of [FlowLogic] implements a flow using direct, straight line blocking code. Thus you + * can write complex flow logic in an ordinary fashion, without having to think about callbacks, restarting after + * a node crash, how many instances of your flow there are running and so on. * * Invoking the network will cause the call stack to be suspended onto the heap and then serialized to a database using * the Quasar fibers framework. Because of this, if you need access to data that might change over time, you should @@ -19,32 +19,32 @@ import rx.Observable * service across calls to send/receive/sendAndReceive because the world might change in arbitrary ways out from * underneath you, for instance, if the node is restarted or reconfigured! * - * Additionally, be aware of what data you pin either via the stack or in your [ProtocolLogic] implementation. Very large + * Additionally, be aware of what data you pin either via the stack or in your [FlowLogic] implementation. Very large * objects or datasets will hurt performance by increasing the amount of data stored in each checkpoint. * - * If you'd like to use another ProtocolLogic class as a component of your own, construct it on the fly and then pass - * it to the [subProtocol] method. It will return the result of that protocol when it completes. + * If you'd like to use another FlowLogic class as a component of your own, construct it on the fly and then pass + * it to the [subFlow] method. It will return the result of that flow when it completes. */ -abstract class ProtocolLogic { +abstract class FlowLogic { /** Reference to the [Fiber] instance that is the top level controller for the entire flow. */ - lateinit var psm: ProtocolStateMachine<*> + lateinit var fsm: FlowStateMachine<*> /** This is where you should log things to. */ - val logger: Logger get() = psm.logger + val logger: Logger get() = fsm.logger /** * Provides access to big, heavy classes that may be reconstructed from time to time, e.g. across restarts. It is - * only available once the protocol has started, which means it cannnot be accessed in the constructor. Either + * only available once the flow has started, which means it cannnot be accessed in the constructor. Either * access this lazily or from inside [call]. */ - val serviceHub: ServiceHub get() = psm.serviceHub + val serviceHub: ServiceHub get() = fsm.serviceHub - private var sessionProtocol: ProtocolLogic<*> = this + private var sessionFlow: FlowLogic<*> = this /** - * Return the marker [Class] which [party] has used to register the counterparty protocol that is to execute on the - * other side. The default implementation returns the class object of this ProtocolLogic, but any [Class] instance + * Return the marker [Class] which [party] has used to register the counterparty flow that is to execute on the + * other side. The default implementation returns the class object of this FlowLogic, but any [Class] instance * will do as long as the other side registers with it. */ open fun getCounterpartyMarker(party: Party): Class<*> = javaClass @@ -56,44 +56,44 @@ abstract class ProtocolLogic { @Suspendable fun sendAndReceive(otherParty: Party, payload: Any, receiveType: Class): UntrustworthyData { - return psm.sendAndReceive(otherParty, payload, receiveType, sessionProtocol) + return fsm.sendAndReceive(otherParty, payload, receiveType, sessionFlow) } inline fun receive(otherParty: Party): UntrustworthyData = receive(otherParty, T::class.java) @Suspendable fun receive(otherParty: Party, receiveType: Class): UntrustworthyData { - return psm.receive(otherParty, receiveType, sessionProtocol) + return fsm.receive(otherParty, receiveType, sessionFlow) } @Suspendable fun send(otherParty: Party, payload: Any) { - psm.send(otherParty, payload, sessionProtocol) + fsm.send(otherParty, payload, sessionFlow) } /** - * Invokes the given subprotocol by simply passing through this [ProtocolLogic]s reference to the - * [ProtocolStateMachine] and then calling the [call] method. - * @param shareParentSessions In certain situations the need arises to use the same sessions the parent protocol has - * already established. However this also prevents the subprotocol from creating new sessions with those parties. + * Invokes the given subflow by simply passing through this [FlowLogic]s reference to the + * [FlowStateMachine] and then calling the [call] method. + * @param shareParentSessions In certain situations the need arises to use the same sessions the parent flow has + * already established. However this also prevents the subflow from creating new sessions with those parties. * For this reason the default value is false. */ // TODO Rethink the default value for shareParentSessions // TODO shareParentSessions is a bit too low-level and perhaps can be expresed in a better way @Suspendable - fun subProtocol(subLogic: ProtocolLogic, shareParentSessions: Boolean = false): R { - subLogic.psm = psm + fun subFlow(subLogic: FlowLogic, shareParentSessions: Boolean = false): R { + subLogic.fsm = fsm maybeWireUpProgressTracking(subLogic) if (shareParentSessions) { - subLogic.sessionProtocol = this + subLogic.sessionFlow = this } val result = subLogic.call() - // It's easy to forget this when writing protocols so we just step it to the DONE state when it completes. + // It's easy to forget this when writing flows so we just step it to the DONE state when it completes. subLogic.progressTracker?.currentStep = ProgressTracker.DONE return result } - private fun maybeWireUpProgressTracking(subLogic: ProtocolLogic<*>) { + private fun maybeWireUpProgressTracking(subLogic: FlowLogic<*>) { val ours = progressTracker val theirs = subLogic.progressTracker @@ -108,11 +108,11 @@ abstract class ProtocolLogic { /** * Override this to provide a [ProgressTracker]. If one is provided and stepped, the framework will do something - * helpful with the progress reports. If this protocol is invoked as a sub-protocol of another, then the - * tracker will be made a child of the current step in the parent. If it's null, this protocol doesn't track + * helpful with the progress reports. If this flow is invoked as a sub-flow of another, then the + * tracker will be made a child of the current step in the parent. If it's null, this flow doesn't track * progress. * - * Note that this has to return a tracker before the protocol is invoked. You can't change your mind half way + * Note that this has to return a tracker before the flow is invoked. You can't change your mind half way * through. */ open val progressTracker: ProgressTracker? = null diff --git a/core/src/main/kotlin/net/corda/core/protocols/ProtocolLogicRef.kt b/core/src/main/kotlin/net/corda/core/flows/FlowLogicRef.kt similarity index 58% rename from core/src/main/kotlin/net/corda/core/protocols/ProtocolLogicRef.kt rename to core/src/main/kotlin/net/corda/core/flows/FlowLogicRef.kt index 7869aa948c..08acb753cb 100644 --- a/core/src/main/kotlin/net/corda/core/protocols/ProtocolLogicRef.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FlowLogicRef.kt @@ -1,13 +1,10 @@ -package net.corda.core.protocols +package net.corda.core.flows import com.google.common.primitives.Primitives -import net.corda.core.contracts.StateRef import net.corda.core.crypto.SecureHash import net.corda.core.serialization.SingletonSerializeAsToken -import net.corda.protocols.TwoPartyDealProtocol import java.lang.reflect.ParameterizedType import java.lang.reflect.Type -import java.time.Duration import java.util.* import kotlin.reflect.KFunction import kotlin.reflect.KParameter @@ -15,63 +12,63 @@ import kotlin.reflect.jvm.javaType import kotlin.reflect.primaryConstructor /** - * A class for conversion to and from [ProtocolLogic] and [ProtocolLogicRef] instances. + * A class for conversion to and from [FlowLogic] and [FlowLogicRef] instances. * * Validation of types is performed on the way in and way out in case this object is passed between JVMs which might have differing * whitelists. * - * TODO: Ways to populate whitelist of "blessed" protocols per node/party + * TODO: Ways to populate whitelist of "blessed" flows per node/party * TODO: Ways to populate argument types whitelist. Per node/party or global? - * TODO: Align with API related logic for passing in ProtocolLogic references (ProtocolRef) + * TODO: Align with API related logic for passing in FlowLogic references (FlowRef) * TODO: Actual support for AppContext / AttachmentsClassLoader */ -class ProtocolLogicRefFactory(private val protocolWhitelist: Map>) : SingletonSerializeAsToken() { +class FlowLogicRefFactory(private val flowWhitelist: Map>) : SingletonSerializeAsToken() { constructor() : this(mapOf()) // Pending real dependence on AppContext for class loading etc @Suppress("UNUSED_PARAMETER") - private fun validateProtocolClassName(className: String, appContext: AppContext) { + private fun validateFlowClassName(className: String, appContext: AppContext) { // TODO: make this specific to the attachments in the [AppContext] by including [SecureHash] in whitelist check - require(protocolWhitelist.containsKey(className)) { "${ProtocolLogic::class.java.simpleName} of ${ProtocolLogicRef::class.java.simpleName} must have type on the whitelist: $className" } + require(flowWhitelist.containsKey(className)) { "${FlowLogic::class.java.simpleName} of ${FlowLogicRef::class.java.simpleName} must have type on the whitelist: $className" } } // Pending real dependence on AppContext for class loading etc @Suppress("UNUSED_PARAMETER") private fun validateArgClassName(className: String, argClassName: String, appContext: AppContext) { - // TODO: consider more carefully what to whitelist and how to secure protocols + // TODO: consider more carefully what to whitelist and how to secure flows // For now automatically accept standard java.lang.* and kotlin.* types. - // All other types require manual specification at ProtocolLogicRefFactory construction time. + // All other types require manual specification at FlowLogicRefFactory construction time. if (argClassName.startsWith("java.lang.") || argClassName.startsWith("kotlin.")) { return } // TODO: make this specific to the attachments in the [AppContext] by including [SecureHash] in whitelist check - require(protocolWhitelist[className]!!.contains(argClassName)) { "Args to $className must have types on the args whitelist: $argClassName, but it has ${protocolWhitelist[className]}" } + require(flowWhitelist[className]!!.contains(argClassName)) { "Args to $className must have types on the args whitelist: $argClassName, but it has ${flowWhitelist[className]}" } } /** - * Create a [ProtocolLogicRef] for the Kotlin primary constructor of a named [ProtocolLogic] + * Create a [FlowLogicRef] for the Kotlin primary constructor of a named [FlowLogic] */ - fun createKotlin(protocolLogicClassName: String, args: Map, attachments: List = emptyList()): ProtocolLogicRef { + fun createKotlin(flowLogicClassName: String, args: Map, attachments: List = emptyList()): FlowLogicRef { val context = AppContext(attachments) - validateProtocolClassName(protocolLogicClassName, context) + validateFlowClassName(flowLogicClassName, context) for(arg in args.values.filterNotNull()) { - validateArgClassName(protocolLogicClassName, arg.javaClass.name, context) + validateArgClassName(flowLogicClassName, arg.javaClass.name, context) } - val clazz = Class.forName(protocolLogicClassName) - require(ProtocolLogic::class.java.isAssignableFrom(clazz)) { "$protocolLogicClassName is not a ProtocolLogic" } + val clazz = Class.forName(flowLogicClassName) + require(FlowLogic::class.java.isAssignableFrom(clazz)) { "$flowLogicClassName is not a FlowLogic" } @Suppress("UNCHECKED_CAST") - val logic = clazz as Class>> + val logic = clazz as Class>> return createKotlin(logic, args) } /** - * Create a [ProtocolLogicRef] for the Kotlin primary constructor or Java constructor and the given args. + * Create a [FlowLogicRef] for the Kotlin primary constructor or Java constructor and the given args. */ - fun create(type: Class>, vararg args: Any?): ProtocolLogicRef { + fun create(type: Class>, vararg args: Any?): FlowLogicRef { val constructor = type.kotlin.primaryConstructor ?: return createJava(type, *args) if (constructor.parameters.size < args.size) { - throw IllegalProtocolLogicException(type, "due to too many arguments supplied to kotlin primary constructor") + throw IllegalFlowLogicException(type, "due to too many arguments supplied to kotlin primary constructor") } // Build map of args from array val argsMap = args.zip(constructor.parameters).map { Pair(it.second.name!!, it.first) }.toMap() @@ -79,24 +76,24 @@ class ProtocolLogicRefFactory(private val protocolWhitelist: Map>, args: Map): ProtocolLogicRef { + fun createKotlin(type: Class>, args: Map): FlowLogicRef { // TODO: we need to capture something about the class loader or "application context" into the ref, // perhaps as some sort of ThreadLocal style object. For now, just create an empty one. val appContext = AppContext(emptyList()) - validateProtocolClassName(type.name, appContext) + validateFlowClassName(type.name, appContext) // Check we can find a constructor and populate the args to it, but don't call it createConstructor(appContext, type, args) - return ProtocolLogicRef(type.name, appContext, args) + return FlowLogicRef(type.name, appContext, args) } /** - * Create a [ProtocolLogicRef] by trying to find a Java constructor that matches the given args. + * Create a [FlowLogicRef] by trying to find a Java constructor that matches the given args. */ - private fun createJava(type: Class>, vararg args: Any?): ProtocolLogicRef { + private fun createJava(type: Class>, vararg args: Any?): FlowLogicRef { // Build map for each val argsMap = HashMap(args.size) var index = 0 @@ -104,22 +101,22 @@ class ProtocolLogicRefFactory(private val protocolWhitelist: Map { - validateProtocolClassName(ref.protocolLogicClassName, ref.appContext) - val klass = Class.forName(ref.protocolLogicClassName, true, ref.appContext.classLoader).asSubclass(ProtocolLogic::class.java) + fun toFlowLogic(ref: FlowLogicRef): FlowLogic<*> { + validateFlowClassName(ref.flowLogicClassName, ref.appContext) + val klass = Class.forName(ref.flowLogicClassName, true, ref.appContext.classLoader).asSubclass(FlowLogic::class.java) return createConstructor(ref.appContext, klass, ref.args)() } - private fun createConstructor(appContext: AppContext, clazz: Class>, args: Map): () -> ProtocolLogic<*> { + private fun createConstructor(appContext: AppContext, clazz: Class>, args: Map): () -> FlowLogic<*> { for (constructor in clazz.kotlin.constructors) { val params = buildParams(appContext, clazz, constructor, args) ?: continue // If we get here then we matched every parameter return { constructor.callBy(params) } } - throw IllegalProtocolLogicException(clazz, "as could not find matching constructor for: $args") + throw IllegalFlowLogicException(clazz, "as could not find matching constructor for: $args") } - private fun buildParams(appContext: AppContext, clazz: Class>, constructor: KFunction>, args: Map): HashMap? { + private fun buildParams(appContext: AppContext, clazz: Class>, constructor: KFunction>, args: Map): HashMap? { val params = hashMapOf() val usedKeys = hashSetOf() for (parameter in constructor.parameters) { @@ -164,15 +161,15 @@ class ProtocolLogicRefFactory(private val protocolWhitelist: Map, msg: String) : IllegalArgumentException("${ProtocolLogicRef::class.java.simpleName} cannot be constructed for ${ProtocolLogic::class.java.simpleName} of type ${type.name} $msg") +class IllegalFlowLogicException(type: Class<*>, msg: String) : IllegalArgumentException("${FlowLogicRef::class.java.simpleName} cannot be constructed for ${FlowLogic::class.java.simpleName} of type ${type.name} $msg") /** - * A class representing a [ProtocolLogic] instance which would be possible to safely pass out of the contract sandbox. + * A class representing a [FlowLogic] instance which would be possible to safely pass out of the contract sandbox. * - * Only allows a String reference to the ProtocolLogic class, and only allows restricted argument types as per [ProtocolLogicRefFactory]. + * Only allows a String reference to the FlowLogic class, and only allows restricted argument types as per [FlowLogicRefFactory]. */ -// TODO: align this with the existing [ProtocolRef] in the bank-side API (probably replace some of the API classes) -data class ProtocolLogicRef internal constructor(val protocolLogicClassName: String, val appContext: AppContext, val args: Map) +// TODO: align this with the existing [FlowRef] in the bank-side API (probably replace some of the API classes) +data class FlowLogicRef internal constructor(val flowLogicClassName: String, val appContext: AppContext, val args: Map) /** * This is just some way to track what attachments need to be in the class loader, but may later include some app diff --git a/core/src/main/kotlin/net/corda/core/protocols/ProtocolStateMachine.kt b/core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt similarity index 63% rename from core/src/main/kotlin/net/corda/core/protocols/ProtocolStateMachine.kt rename to core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt index 190cb655ab..f8e6d8c9b4 100644 --- a/core/src/main/kotlin/net/corda/core/protocols/ProtocolStateMachine.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt @@ -1,4 +1,4 @@ -package net.corda.core.protocols +package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable import com.google.common.util.concurrent.ListenableFuture @@ -19,25 +19,25 @@ data class StateMachineRunId private constructor(val uuid: UUID) { } /** - * A ProtocolStateMachine instance is a suspendable fiber that delegates all actual logic to a [ProtocolLogic] instance. - * For any given flow there is only one PSM, even if that protocol invokes subprotocols. + * A FlowStateMachine instance is a suspendable fiber that delegates all actual logic to a [FlowLogic] instance. + * For any given flow there is only one PSM, even if that flow invokes subflows. * - * These classes are created by the [StateMachineManager] when a new protocol is started at the topmost level. If - * a protocol invokes a sub-protocol, then it will pass along the PSM to the child. The call method of the topmost + * These classes are created by the [StateMachineManager] when a new flow is started at the topmost level. If + * a flow invokes a sub-flow, then it will pass along the PSM to the child. The call method of the topmost * logic element gets to return the value that the entire state machine resolves to. */ -interface ProtocolStateMachine { +interface FlowStateMachine { @Suspendable fun sendAndReceive(otherParty: Party, payload: Any, receiveType: Class, - sessionProtocol: ProtocolLogic<*>): UntrustworthyData + sessionFlow: FlowLogic<*>): UntrustworthyData @Suspendable - fun receive(otherParty: Party, receiveType: Class, sessionProtocol: ProtocolLogic<*>): UntrustworthyData + fun receive(otherParty: Party, receiveType: Class, sessionFlow: FlowLogic<*>): UntrustworthyData @Suspendable - fun send(otherParty: Party, payload: Any, sessionProtocol: ProtocolLogic<*>) + fun send(otherParty: Party, payload: Any, sessionFlow: FlowLogic<*>) val serviceHub: ServiceHub val logger: Logger @@ -48,4 +48,4 @@ interface ProtocolStateMachine { val resultFuture: ListenableFuture } -class ProtocolSessionException(message: String) : Exception(message) +class FlowSessionException(message: String) : Exception(message) diff --git a/core/src/main/kotlin/net/corda/core/messaging/Messaging.kt b/core/src/main/kotlin/net/corda/core/messaging/Messaging.kt index b76c041517..7f7a01a710 100644 --- a/core/src/main/kotlin/net/corda/core/messaging/Messaging.kt +++ b/core/src/main/kotlin/net/corda/core/messaging/Messaging.kt @@ -66,7 +66,7 @@ interface MessagingService { * available via type casting. Once this function returns the message is queued for delivery but not necessarily * delivered: if the recipients are offline then the message could be queued hours or days later. * - * There is no way to know if a message has been received. If your protocol requires this, you need the recipient + * There is no way to know if a message has been received. If your flow requires this, you need the recipient * to send an ACK message back. */ fun send(message: Message, target: MessageRecipients) diff --git a/core/src/main/kotlin/net/corda/core/node/CordaPluginRegistry.kt b/core/src/main/kotlin/net/corda/core/node/CordaPluginRegistry.kt index c0e227c9be..b3b434c586 100644 --- a/core/src/main/kotlin/net/corda/core/node/CordaPluginRegistry.kt +++ b/core/src/main/kotlin/net/corda/core/node/CordaPluginRegistry.kt @@ -22,19 +22,19 @@ abstract class CordaPluginRegistry { open val staticServeDirs: Map = emptyMap() /** - * A Map with an entry for each consumed protocol used by the webAPIs. - * The key of each map entry should contain the ProtocolLogic class name. - * The associated map values are the union of all concrete class names passed to the protocol constructor. + * A Map with an entry for each consumed flow used by the webAPIs. + * The key of each map entry should contain the FlowLogic class name. + * The associated map values are the union of all concrete class names passed to the flow constructor. * Standard java.lang.* and kotlin.* types do not need to be included explicitly. - * This is used to extend the white listed protocols that can be initiated from the ServiceHub invokeProtocolAsync method. + * This is used to extend the white listed flows that can be initiated from the ServiceHub invokeFlowAsync method. */ - open val requiredProtocols: Map> = emptyMap() + open val requiredFlows: Map> = emptyMap() /** * List of additional long lived services to be hosted within the node. * They are expected to have a single parameter constructor that takes a [PluginServiceHub] as input. * The [PluginServiceHub] will be fully constructed before the plugin service is created and will - * allow access to the protocol factory and protocol initiation entry points there. + * allow access to the flow factory and flow initiation entry points there. */ open val servicePlugins: List> = emptyList() diff --git a/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt b/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt index b0efa7d82c..c81f002e3e 100644 --- a/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt +++ b/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt @@ -7,7 +7,7 @@ import net.corda.core.node.services.ServiceType /** * Information for an advertised service including the service specific identity information. - * The identity can be used in protocols and is distinct from the Node's legalIdentity + * The identity can be used in flows and is distinct from the Node's legalIdentity */ data class ServiceEntry(val info: ServiceInfo, val identity: Party) diff --git a/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt b/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt index be66cc5a3c..f8a2398e58 100644 --- a/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt +++ b/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt @@ -1,7 +1,7 @@ package net.corda.core.node import net.corda.core.crypto.Party -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import kotlin.reflect.KClass /** @@ -9,22 +9,22 @@ import kotlin.reflect.KClass */ interface PluginServiceHub : ServiceHub { /** - * Register the protocol factory we wish to use when a initiating party attempts to communicate with us. The + * Register the flow factory we wish to use when a initiating party attempts to communicate with us. The * registration is done against a marker [KClass] which is sent in the session handshake by the other party. If this - * marker class has been registered then the corresponding factory will be used to create the protocol which will + * marker class has been registered then the corresponding factory will be used to create the flow which will * communicate with the other side. If there is no mapping then the session attempt is rejected. * @param markerClass The marker [KClass] present in a session initiation attempt, which is a 1:1 mapping to a [Class] - * using the
::class
construct. Conventionally this is a [ProtocolLogic] subclass, however any class can - * be used, with the default being the class of the initiating protocol. This enables the registration to be of the - * form: registerProtocolInitiator(InitiatorProtocol::class, ::InitiatedProtocol) - * @param protocolFactory The protocol factory generating the initiated protocol. + * using the
::class
construct. Conventionally this is a [FlowLogic] subclass, however any class can + * be used, with the default being the class of the initiating flow. This enables the registration to be of the + * form: registerFlowInitiator(InitiatorFlow::class, ::InitiatedFlow) + * @param flowFactory The flow factory generating the initiated flow. */ // TODO: remove dependency on Kotlin relfection (Kotlin KClass -> Java Class). - fun registerProtocolInitiator(markerClass: KClass<*>, protocolFactory: (Party) -> ProtocolLogic<*>) + fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) /** - * Return the protocol factory that has been registered with [markerClass], or null if no factory is found. + * Return the flow factory that has been registered with [markerClass], or null if no factory is found. */ - fun getProtocolFactory(markerClass: Class<*>): ((Party) -> ProtocolLogic<*>)? + fun getFlowFactory(markerClass: Class<*>): ((Party) -> FlowLogic<*>)? } diff --git a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt index 2479d13763..515f33adf0 100644 --- a/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt +++ b/core/src/main/kotlin/net/corda/core/node/ServiceHub.kt @@ -3,10 +3,10 @@ package net.corda.core.node import net.corda.core.contracts.StateRef import net.corda.core.contracts.TransactionResolutionException import net.corda.core.contracts.TransactionState +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowStateMachine import net.corda.core.messaging.MessagingService import net.corda.core.node.services.* -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolStateMachine import net.corda.core.transactions.SignedTransaction import java.security.KeyPair import java.time.Clock @@ -16,7 +16,7 @@ import java.time.Clock * mocked out. This class is useful to pass to chunks of pluggable code that might have need of many different kinds of * functionality and you don't want to hard-code which types in the interface. * - * Any services exposed to protocols (public view) need to implement [SerializeAsToken] or similar to avoid their internal + * Any services exposed to flows (public view) need to implement [SerializeAsToken] or similar to avoid their internal * state from being serialized in checkpoints. */ interface ServiceHub { @@ -49,16 +49,16 @@ interface ServiceHub { } /** - * Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the protocol. + * Will check [logicType] and [args] against a whitelist and if acceptable then construct and initiate the flow. * - * @throws IllegalProtocolLogicException or IllegalArgumentException if there are problems with the [logicType] or [args]. + * @throws IllegalFlowLogicException or IllegalArgumentException if there are problems with the [logicType] or [args]. */ - fun invokeProtocolAsync(logicType: Class>, vararg args: Any?): ProtocolStateMachine + fun invokeFlowAsync(logicType: Class>, vararg args: Any?): FlowStateMachine /** * Helper property to shorten code for fetching the Node's KeyPair associated with the * public legalIdentity Party from the key management service. - * Typical use is during signing in protocols and for unit test signing. + * Typical use is during signing in flows and for unit test signing. * * TODO: legalIdentity can now be composed of multiple keys, should we return a list of keyPairs here? Right now * the logic assumes the legal identity has a composite key with only one node @@ -70,7 +70,7 @@ interface ServiceHub { * public notaryIdentity Party from the key management service. It is assumed that this is only * used in contexts where the Node knows it is hosting a Notary Service. Otherwise, it will throw * an IllegalArgumentException. - * Typical use is during signing in protocols and for unit test signing. + * Typical use is during signing in flows and for unit test signing. */ val notaryIdentityKey: KeyPair get() = this.keyManagementService.toKeyPair(this.myInfo.notaryIdentity.owningKey.keys) diff --git a/core/src/main/kotlin/net/corda/core/node/services/Services.kt b/core/src/main/kotlin/net/corda/core/node/services/Services.kt index 8fc6ec804e..ece53304f7 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/Services.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/Services.kt @@ -220,7 +220,7 @@ interface KeyManagementService { /** * A sketch of an interface to a simple key/value storage system. Intended for persistence of simple blobs like - * transactions, serialised protocol state machines and so on. Again, this isn't intended to imply lack of SQL or + * transactions, serialised flow state machines and so on. Again, this isn't intended to imply lack of SQL or * anything like that, this interface is only big enough to support the prototyping work. */ interface StorageService { diff --git a/core/src/main/kotlin/net/corda/core/node/services/StateMachineRecordedTransactionMappingStorage.kt b/core/src/main/kotlin/net/corda/core/node/services/StateMachineRecordedTransactionMappingStorage.kt index 24ddf16937..ca960282ce 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/StateMachineRecordedTransactionMappingStorage.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/StateMachineRecordedTransactionMappingStorage.kt @@ -1,14 +1,14 @@ package net.corda.core.node.services import net.corda.core.crypto.SecureHash -import net.corda.core.protocols.StateMachineRunId +import net.corda.core.flows.StateMachineRunId import rx.Observable data class StateMachineTransactionMapping(val stateMachineRunId: StateMachineRunId, val transactionId: SecureHash) /** * This is the interface to storage storing state machine -> recorded tx mappings. Any time a transaction is recorded - * during a protocol run [addMapping] should be called. + * during a flow run [addMapping] should be called. */ interface StateMachineRecordedTransactionMappingStorage { fun addMapping(stateMachineRunId: StateMachineRunId, transactionId: SecureHash) diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt index f7114e9bdc..9b88a50a79 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -58,7 +58,7 @@ open class TransactionBuilder( /** * Places a [TimestampCommand] in this transaction, removing any existing command if there is one. * The command requires a signature from the Notary service, which acts as a Timestamp Authority. - * The signature can be obtained using [NotaryProtocol]. + * The signature can be obtained using [NotaryFlow]. * * The window of time in which the final timestamp may lie is defined as [time] +/- [timeTolerance]. * If you want a non-symmetrical time window you must add the command via [addCommand] yourself. The tolerance diff --git a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt index 82ac236968..548883b9b4 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt @@ -69,7 +69,7 @@ class WireTransaction( /** * Looks up identities and attachments from storage to generate a [LedgerTransaction]. A transaction is expected to - * have been fully resolved using the resolution protocol by this point. + * have been fully resolved using the resolution flow by this point. * * @throws FileNotFoundException if a required attachment was not found in storage. * @throws TransactionResolutionException if an input points to a transaction not found in storage. diff --git a/core/src/main/kotlin/net/corda/protocols/AbstractStateReplacementProtocol.kt b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt similarity index 92% rename from core/src/main/kotlin/net/corda/protocols/AbstractStateReplacementProtocol.kt rename to core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt index ac75a7f434..7d9e1acae2 100644 --- a/core/src/main/kotlin/net/corda/protocols/AbstractStateReplacementProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.ContractState @@ -8,26 +8,26 @@ import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.Party import net.corda.core.crypto.signWithECDSA +import net.corda.core.flows.FlowLogic import net.corda.core.node.recordTransactions -import net.corda.core.protocols.ProtocolLogic import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.UntrustworthyData -import net.corda.protocols.AbstractStateReplacementProtocol.Acceptor -import net.corda.protocols.AbstractStateReplacementProtocol.Instigator +import net.corda.flows.AbstractStateReplacementFlow.Acceptor +import net.corda.flows.AbstractStateReplacementFlow.Instigator /** - * Abstract protocol to be used for replacing one state with another, for example when changing the notary of a state. + * Abstract flow to be used for replacing one state with another, for example when changing the notary of a state. * Notably this requires a one to one replacement of states, states cannot be split, merged or issued as part of these - * protocols. + * flows. * * The [Instigator] assembles the transaction for state replacement and sends out change proposals to all participants * ([Acceptor]) of that state. If participants agree to the proposed change, they each sign the transaction. * Finally, [Instigator] sends the transaction containing all signatures back to each participant so they can record it and * use the new updated state for future transactions. */ -abstract class AbstractStateReplacementProtocol { +abstract class AbstractStateReplacementFlow { interface Proposal { val stateRef: StateRef val modification: T @@ -36,7 +36,7 @@ abstract class AbstractStateReplacementProtocol { abstract class Instigator(val originalState: StateAndRef, val modification: T, - override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic>() { + override val progressTracker: ProgressTracker = tracker()) : FlowLogic>() { companion object { object SIGNING : ProgressTracker.Step("Requesting signatures from other parties") @@ -107,12 +107,12 @@ abstract class AbstractStateReplacementProtocol { @Suspendable private fun getNotarySignature(stx: SignedTransaction): DigitalSignature.WithKey { progressTracker.currentStep = NOTARY - return subProtocol(NotaryProtocol.Client(stx)) + return subFlow(NotaryFlow.Client(stx)) } } abstract class Acceptor(val otherSide: Party, - override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic() { + override val progressTracker: ProgressTracker = tracker()) : FlowLogic() { companion object { object VERIFYING : ProgressTracker.Step("Verifying state replacement proposal") @@ -194,7 +194,7 @@ abstract class AbstractStateReplacementProtocol { @Suspendable private fun checkDependenciesValid(stx: SignedTransaction) { - subProtocol(ResolveTransactionsProtocol(stx.tx, otherSide)) + subFlow(ResolveTransactionsFlow(stx.tx, otherSide)) } private fun sign(stx: SignedTransaction): DigitalSignature.WithKey { @@ -203,7 +203,7 @@ abstract class AbstractStateReplacementProtocol { } } - // TODO: similar classes occur in other places (NotaryProtocol), need to consolidate + // TODO: similar classes occur in other places (NotaryFlow), need to consolidate data class Result private constructor(val sig: DigitalSignature.WithKey?, val error: StateReplacementRefused?) { companion object { fun withError(error: StateReplacementRefused) = Result(null, error) diff --git a/core/src/main/kotlin/net/corda/protocols/BroadcastTransactionProtocol.kt b/core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt similarity index 79% rename from core/src/main/kotlin/net/corda/protocols/BroadcastTransactionProtocol.kt rename to core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt index 3cf2d78dea..952bb80afb 100644 --- a/core/src/main/kotlin/net/corda/protocols/BroadcastTransactionProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt @@ -1,22 +1,22 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.recordTransactions -import net.corda.core.protocols.ProtocolLogic import net.corda.core.transactions.SignedTransaction /** * Notify all involved parties about a transaction, including storing a copy. Normally this would be called via - * [FinalityProtocol]. + * [FinalityFlow]. * * @param notarisedTransaction transaction which has been notarised (if needed) and is ready to notify nodes about. * @param participants a list of participants involved in the transaction. * @return a list of participants who were successfully notified of the transaction. */ -class BroadcastTransactionProtocol(val notarisedTransaction: SignedTransaction, - val participants: Set) : ProtocolLogic() { +class BroadcastTransactionFlow(val notarisedTransaction: SignedTransaction, + val participants: Set) : FlowLogic() { data class NotifyTxRequest(val tx: SignedTransaction) diff --git a/core/src/main/kotlin/net/corda/protocols/FetchAttachmentsProtocol.kt b/core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt similarity index 84% rename from core/src/main/kotlin/net/corda/protocols/FetchAttachmentsProtocol.kt rename to core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt index 8541408941..e562a0a94e 100644 --- a/core/src/main/kotlin/net/corda/protocols/FetchAttachmentsProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import net.corda.core.contracts.Attachment import net.corda.core.crypto.Party @@ -11,8 +11,8 @@ import java.io.InputStream * Given a set of hashes either loads from from local storage or requests them from the other peer. Downloaded * attachments are saved to local storage automatically. */ -class FetchAttachmentsProtocol(requests: Set, - otherSide: Party) : FetchDataProtocol(requests, otherSide) { +class FetchAttachmentsFlow(requests: Set, + otherSide: Party) : FetchDataFlow(requests, otherSide) { override fun load(txid: SecureHash): Attachment? = serviceHub.storageService.attachments.openAttachment(txid) diff --git a/core/src/main/kotlin/net/corda/protocols/FetchDataProtocol.kt b/core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt similarity index 88% rename from core/src/main/kotlin/net/corda/protocols/FetchDataProtocol.kt rename to core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt index 01c7e876d8..63c4e2f1fa 100644 --- a/core/src/main/kotlin/net/corda/protocols/FetchDataProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt @@ -1,17 +1,17 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.NamedByHash import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import net.corda.core.utilities.UntrustworthyData -import net.corda.protocols.FetchDataProtocol.DownloadedVsRequestedDataMismatch -import net.corda.protocols.FetchDataProtocol.HashNotFound +import net.corda.flows.FetchDataFlow.DownloadedVsRequestedDataMismatch +import net.corda.flows.FetchDataFlow.HashNotFound import java.util.* /** - * An abstract protocol for fetching typed data from a remote peer. + * An abstract flow for fetching typed data from a remote peer. * * Given a set of hashes (IDs), either loads them from local disk or asks the remote peer to provide them. * @@ -26,9 +26,9 @@ import java.util.* * @param T The ultimate type of the data being fetched. * @param W The wire type of the data being fetched, for when it isn't the same as the ultimate type. */ -abstract class FetchDataProtocol( +abstract class FetchDataFlow( protected val requests: Set, - protected val otherSide: Party) : ProtocolLogic>() { + protected val otherSide: Party) : FlowLogic>() { open class BadAnswer : Exception() class HashNotFound(val requested: SecureHash) : BadAnswer() @@ -88,7 +88,7 @@ abstract class FetchDataProtocol( } val answers = response.requireNoNulls().map { convert(it) } // Check transactions actually hash to what we requested, if this fails the remote node - // is a malicious protocol violator or buggy. + // is a malicious flow violator or buggy. for ((index, item) in answers.withIndex()) if (item.id != requests[index]) throw DownloadedVsRequestedDataMismatch(requests[index], item.id) diff --git a/core/src/main/kotlin/net/corda/protocols/FetchTransactionsProtocol.kt b/core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt similarity index 58% rename from core/src/main/kotlin/net/corda/protocols/FetchTransactionsProtocol.kt rename to core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt index d4405c90e4..a8a1913ea0 100644 --- a/core/src/main/kotlin/net/corda/protocols/FetchTransactionsProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash @@ -8,12 +8,12 @@ import net.corda.core.transactions.SignedTransaction * Given a set of tx hashes (IDs), either loads them from local disk or asks the remote peer to provide them. * * A malicious response in which the data provided by the remote peer does not hash to the requested hash results in - * [FetchDataProtocol.DownloadedVsRequestedDataMismatch] being thrown. If the remote peer doesn't have an entry, it - * results in a [FetchDataProtocol.HashNotFound] exception. Note that returned transactions are not inserted into + * [FetchDataFlow.DownloadedVsRequestedDataMismatch] being thrown. If the remote peer doesn't have an entry, it + * results in a [FetchDataFlow.HashNotFound] exception. Note that returned transactions are not inserted into * the database, because it's up to the caller to actually verify the transactions are valid. */ -class FetchTransactionsProtocol(requests: Set, otherSide: Party) : - FetchDataProtocol(requests, otherSide) { +class FetchTransactionsFlow(requests: Set, otherSide: Party) : + FetchDataFlow(requests, otherSide) { override fun load(txid: SecureHash): SignedTransaction? = serviceHub.storageService.validatedTransactions.getTransaction(txid) } diff --git a/core/src/main/kotlin/net/corda/protocols/FinalityProtocol.kt b/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt similarity index 79% rename from core/src/main/kotlin/net/corda/protocols/FinalityProtocol.kt rename to core/src/main/kotlin/net/corda/flows/FinalityFlow.kt index 2f7eb11f78..9f4df48ba2 100644 --- a/core/src/main/kotlin/net/corda/protocols/FinalityProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt @@ -1,8 +1,8 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.Party -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker @@ -14,9 +14,9 @@ import net.corda.core.utilities.ProgressTracker * @param participants a list of participants involved in the transaction. * @return a list of participants who were successfully notified of the transaction. */ -class FinalityProtocol(val transaction: SignedTransaction, - val participants: Set, - override val progressTracker: ProgressTracker = tracker()): ProtocolLogic() { +class FinalityFlow(val transaction: SignedTransaction, + val participants: Set, + override val progressTracker: ProgressTracker = tracker()) : FlowLogic() { companion object { object NOTARISING : ProgressTracker.Step("Requesting signature by notary service") object BROADCASTING : ProgressTracker.Step("Broadcasting transaction to participants") @@ -31,7 +31,7 @@ class FinalityProtocol(val transaction: SignedTransaction, progressTracker.currentStep = NOTARISING // Notarise the transaction if needed val notarisedTransaction = if (needsNotarySignature(transaction)) { - val notarySig = subProtocol(NotaryProtocol.Client(transaction)) + val notarySig = subFlow(NotaryFlow.Client(transaction)) transaction.withAdditionalSignature(notarySig) } else { transaction @@ -39,7 +39,7 @@ class FinalityProtocol(val transaction: SignedTransaction, // Let everyone else know about the transaction progressTracker.currentStep = BROADCASTING - subProtocol(BroadcastTransactionProtocol(notarisedTransaction, participants)) + subFlow(BroadcastTransactionFlow(notarisedTransaction, participants)) } private fun needsNotarySignature(stx: SignedTransaction) = stx.tx.notary != null && hasNoNotarySignature(stx) diff --git a/core/src/main/kotlin/net/corda/protocols/NotaryChangeProtocol.kt b/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt similarity index 84% rename from core/src/main/kotlin/net/corda/protocols/NotaryChangeProtocol.kt rename to core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt index ebec7b84d5..89fe318cf8 100644 --- a/core/src/main/kotlin/net/corda/protocols/NotaryChangeProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.ContractState @@ -10,11 +10,11 @@ import net.corda.core.crypto.Party import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.UntrustworthyData -import net.corda.protocols.NotaryChangeProtocol.Acceptor -import net.corda.protocols.NotaryChangeProtocol.Instigator +import net.corda.flows.NotaryChangeFlow.Acceptor +import net.corda.flows.NotaryChangeFlow.Instigator /** - * A protocol to be used for changing a state's Notary. This is required since all input states to a transaction + * A flow to be used for changing a state's Notary. This is required since all input states to a transaction * must point to the same notary. * * The [Instigator] assembles the transaction for notary replacement and sends out change proposals to all participants @@ -22,18 +22,18 @@ import net.corda.protocols.NotaryChangeProtocol.Instigator * Finally, [Instigator] sends the transaction containing all signatures back to each participant so they can record it and * use the new updated state for future transactions. */ -object NotaryChangeProtocol: AbstractStateReplacementProtocol() { +object NotaryChangeFlow : AbstractStateReplacementFlow() { data class Proposal(override val stateRef: StateRef, override val modification: Party, - override val stx: SignedTransaction) : AbstractStateReplacementProtocol.Proposal + override val stx: SignedTransaction) : AbstractStateReplacementFlow.Proposal class Instigator(originalState: StateAndRef, newNotary: Party, progressTracker: ProgressTracker = tracker()) - : AbstractStateReplacementProtocol.Instigator(originalState, newNotary, progressTracker) { + : AbstractStateReplacementFlow.Instigator(originalState, newNotary, progressTracker) { - override fun assembleProposal(stateRef: StateRef, modification: Party, stx: SignedTransaction): AbstractStateReplacementProtocol.Proposal + override fun assembleProposal(stateRef: StateRef, modification: Party, stx: SignedTransaction): AbstractStateReplacementFlow.Proposal = Proposal(stateRef, modification, stx) override fun assembleTx(): Pair> { @@ -51,7 +51,7 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol() { class Acceptor(otherSide: Party, override val progressTracker: ProgressTracker = tracker()) - : AbstractStateReplacementProtocol.Acceptor(otherSide) { + : AbstractStateReplacementFlow.Acceptor(otherSide) { /** * Check the notary change proposal. @@ -61,7 +61,7 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol() { * TODO: In more difficult cases this should call for human attention to manually verify and approve the proposal */ @Suspendable - override fun verifyProposal(maybeProposal: UntrustworthyData>): AbstractStateReplacementProtocol.Proposal { + override fun verifyProposal(maybeProposal: UntrustworthyData>): AbstractStateReplacementFlow.Proposal { return maybeProposal.unwrap { proposal -> val newNotary = proposal.modification val isNotary = serviceHub.networkMapCache.notaryNodes.any { it.notaryIdentity == newNotary } diff --git a/core/src/main/kotlin/net/corda/protocols/NotaryProtocol.kt b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt similarity index 95% rename from core/src/main/kotlin/net/corda/protocols/NotaryProtocol.kt rename to core/src/main/kotlin/net/corda/flows/NotaryFlow.kt index 1376266bad..30e9f868ba 100644 --- a/core/src/main/kotlin/net/corda/protocols/NotaryProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt @@ -1,28 +1,28 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.* +import net.corda.core.flows.FlowLogic import net.corda.core.node.services.TimestampChecker import net.corda.core.node.services.UniquenessException import net.corda.core.node.services.UniquenessProvider -import net.corda.core.protocols.ProtocolLogic import net.corda.core.serialization.serialize import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.UntrustworthyData -object NotaryProtocol { +object NotaryFlow { /** - * A protocol to be used for obtaining a signature from a [NotaryService] ascertaining the transaction + * A flow to be used for obtaining a signature from a [NotaryService] ascertaining the transaction * timestamp is correct and none of its inputs have been used in another completed transaction. * * @throws NotaryException in case the any of the inputs to the transaction have been consumed * by another transaction or the timestamp is invalid. */ open class Client(private val stx: SignedTransaction, - override val progressTracker: ProgressTracker = Client.tracker()) : ProtocolLogic() { + override val progressTracker: ProgressTracker = Client.tracker()) : FlowLogic() { companion object { @@ -91,7 +91,7 @@ object NotaryProtocol { */ open class Service(val otherSide: Party, val timestampChecker: TimestampChecker, - val uniquenessProvider: UniquenessProvider) : ProtocolLogic() { + val uniquenessProvider: UniquenessProvider) : FlowLogic() { @Suspendable override fun call() { diff --git a/core/src/main/kotlin/net/corda/protocols/ResolveTransactionsProtocol.kt b/core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt similarity index 87% rename from core/src/main/kotlin/net/corda/protocols/ResolveTransactionsProtocol.kt rename to core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt index b2d5b7afb7..091e558f5e 100644 --- a/core/src/main/kotlin/net/corda/protocols/ResolveTransactionsProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt @@ -1,22 +1,22 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.checkedAdd import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.flows.FlowLogic import net.corda.core.node.recordTransactions -import net.corda.core.protocols.ProtocolLogic import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction import java.util.* -// TODO: This code is currently unit tested by TwoPartyTradeProtocolTests, it should have its own tests. +// TODO: This code is currently unit tested by TwoPartyTradeFlowTests, it should have its own tests. // TODO: It may be a clearer API if we make the primary c'tor private here, and only allow a single tx to be "resolved". /** - * This protocol is used to verify the validity of a transaction by recursively checking the validity of all the + * This flow is used to verify the validity of a transaction by recursively checking the validity of all the * dependencies. Once a transaction is checked it's inserted into local storage so it can be relayed and won't be * checked again. * @@ -24,12 +24,12 @@ import java.util.* * transaction are resolved and then the transaction itself is verified. Again, if successful, the results are inserted * into the database as long as a [SignedTransaction] was provided. If only the [WireTransaction] form was provided * then this isn't enough to put into the local database, so only the dependencies are checked and inserted. This way - * to use the protocol is helpful when resolving and verifying a finished but partially signed transaction. + * to use the flow is helpful when resolving and verifying a finished but partially signed transaction. * - * The protocol returns a list of verified [LedgerTransaction] objects, in a depth-first order. + * The flow returns a list of verified [LedgerTransaction] objects, in a depth-first order. */ -class ResolveTransactionsProtocol(private val txHashes: Set, - private val otherSide: Party) : ProtocolLogic>() { +class ResolveTransactionsFlow(private val txHashes: Set, + private val otherSide: Party) : FlowLogic>() { companion object { private fun dependencyIDs(wtx: WireTransaction) = wtx.inputs.map { it.txhash }.toSet() @@ -75,7 +75,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set, private var wtx: WireTransaction? = null // TODO: Figure out a more appropriate DOS limit here, 5000 is simply a very bad guess. - /** The maximum number of transactions this protocol will try to download before bailing out. */ + /** The maximum number of transactions this flow will try to download before bailing out. */ var transactionCountLimit = 5000 /** @@ -110,7 +110,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set, result += ltx } - // If this protocol is resolving a specific transaction, make sure we have its attachments and then verify + // If this flow is resolving a specific transaction, make sure we have its attachments and then verify // it as well, but don't insert to the database. Note that when we were given a SignedTransaction (stx != null) // we *could* insert, because successful verification implies we have everything we need here, and it might // be a clearer API if we do that. But for consistency with the other c'tor we currently do not. @@ -134,7 +134,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set, // // TODO: This approach has two problems. Analyze and resolve them: // - // (1) This protocol leaks private data. If you download a transaction and then do NOT request a + // (1) This flow leaks private data. If you download a transaction and then do NOT request a // dependency, it means you already have it, which in turn means you must have been involved with it before // somehow, either in the tx itself or in any following spend of it. If there were no following spends, then // your peer knows for sure that you were involved ... this is bad! The only obvious ways to fix this are @@ -162,7 +162,7 @@ class ResolveTransactionsProtocol(private val txHashes: Set, break // Request the standalone transaction data (which may refer to things we don't yet have). - val downloads: List = subProtocol(FetchTransactionsProtocol(notAlreadyFetched, otherSide)).downloaded + val downloads: List = subFlow(FetchTransactionsFlow(notAlreadyFetched, otherSide)).downloaded fetchMissingAttachments(downloads.map { it.tx }) @@ -192,6 +192,6 @@ class ResolveTransactionsProtocol(private val txHashes: Set, wtx.attachments.filter { serviceHub.storageService.attachments.openAttachment(it) == null } } if (missingAttachments.isNotEmpty()) - subProtocol(FetchAttachmentsProtocol(missingAttachments.toSet(), otherSide)) + subFlow(FetchAttachmentsFlow(missingAttachments.toSet(), otherSide)) } } diff --git a/core/src/main/kotlin/net/corda/protocols/ServiceRequestMessage.kt b/core/src/main/kotlin/net/corda/flows/ServiceRequestMessage.kt similarity index 97% rename from core/src/main/kotlin/net/corda/protocols/ServiceRequestMessage.kt rename to core/src/main/kotlin/net/corda/flows/ServiceRequestMessage.kt index 3863b51902..4b7f19bc40 100644 --- a/core/src/main/kotlin/net/corda/protocols/ServiceRequestMessage.kt +++ b/core/src/main/kotlin/net/corda/flows/ServiceRequestMessage.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import com.google.common.util.concurrent.ListenableFuture import net.corda.core.messaging.MessagingService diff --git a/core/src/main/kotlin/net/corda/protocols/TwoPartyDealProtocol.kt b/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt similarity index 91% rename from core/src/main/kotlin/net/corda/protocols/TwoPartyDealProtocol.kt rename to core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt index 2e37d5161d..290e677588 100644 --- a/core/src/main/kotlin/net/corda/protocols/TwoPartyDealProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt @@ -1,14 +1,14 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.ContractState import net.corda.core.contracts.DealState import net.corda.core.contracts.StateRef import net.corda.core.crypto.* +import net.corda.core.flows.FlowLogic import net.corda.core.node.NodeInfo import net.corda.core.node.recordTransactions import net.corda.core.node.services.ServiceType -import net.corda.core.protocols.ProtocolLogic import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -21,14 +21,14 @@ import java.security.KeyPair /** * Classes for manipulating a two party deal or agreement. * - * TODO: The subclasses should probably be broken out into individual protocols rather than making this an ever expanding collection of subclasses. + * TODO: The subclasses should probably be broken out into individual flows rather than making this an ever expanding collection of subclasses. * * TODO: Also, the term Deal is used here where we might prefer Agreement. * - * TODO: Consider whether we can merge this with [TwoPartyTradeProtocol] + * TODO: Consider whether we can merge this with [TwoPartyTradeFlow] * */ -object TwoPartyDealProtocol { +object TwoPartyDealFlow { class DealMismatchException(val expectedDeal: ContractState, val actualDeal: ContractState) : Exception() { override fun toString() = "The submitted deal didn't match the expected: $expectedDeal vs $actualDeal" @@ -38,7 +38,7 @@ object TwoPartyDealProtocol { override fun toString() = "The submitted deal didn't match the expected: $expectedDeal vs $actualDeal" } - // This object is serialised to the network and is the first protocol message the seller sends to the buyer. + // This object is serialised to the network and is the first flow message the seller sends to the buyer. data class Handshake(val payload: T, val publicKey: CompositeKey) class SignaturesFromPrimary(val sellerSig: DigitalSignature.WithKey, val notarySig: DigitalSignature.WithKey) @@ -47,15 +47,15 @@ object TwoPartyDealProtocol { * [Primary] at the end sends the signed tx to all the regulator parties. This a seperate workflow which needs a * sepearate session with the regulator. This interface is used to do that in [Primary.getCounterpartyMarker]. */ - interface MarkerForBogusRegulatorProtocol + interface MarkerForBogusRegulatorFlow /** - * Abstracted bilateral deal protocol participant that initiates communication/handshake. + * Abstracted bilateral deal flow participant that initiates communication/handshake. * - * There's a good chance we can push at least some of this logic down into core protocol logic + * There's a good chance we can push at least some of this logic down into core flow logic * and helper methods etc. */ - abstract class Primary(override val progressTracker: ProgressTracker = Primary.tracker()) : ProtocolLogic() { + abstract class Primary(override val progressTracker: ProgressTracker = Primary.tracker()) : FlowLogic() { companion object { object AWAITING_PROPOSAL : ProgressTracker.Step("Handshaking and awaiting transaction proposal") @@ -76,7 +76,7 @@ object TwoPartyDealProtocol { override fun getCounterpartyMarker(party: Party): Class<*> { return if (serviceHub.networkMapCache.regulators.any { it.legalIdentity == party }) { - MarkerForBogusRegulatorProtocol::class.java + MarkerForBogusRegulatorFlow::class.java } else { super.getCounterpartyMarker(party) } @@ -86,7 +86,7 @@ object TwoPartyDealProtocol { fun getPartialTransaction(): UntrustworthyData { progressTracker.currentStep = AWAITING_PROPOSAL - // Make the first message we'll send to kick off the protocol. + // Make the first message we'll send to kick off the flow. val hello = Handshake(payload, myKeyPair.public.composite) val maybeSTX = sendAndReceive(otherParty, hello) @@ -117,7 +117,7 @@ object TwoPartyDealProtocol { // once we implement state pairing. // // but the goal of this code is not to be fully secure (yet), but rather, just to find good ways to - // express protocol state machines on top of the messaging layer. + // express flow state machines on top of the messaging layer. return stx } @@ -128,7 +128,7 @@ object TwoPartyDealProtocol { // Download and check all the transactions that this transaction depends on, but do not check this // transaction itself. val dependencyTxIDs = stx.tx.inputs.map { it.txhash }.toSet() - subProtocol(ResolveTransactionsProtocol(dependencyTxIDs, otherParty)) + subFlow(ResolveTransactionsFlow(dependencyTxIDs, otherParty)) } @Suspendable @@ -162,7 +162,7 @@ object TwoPartyDealProtocol { @Suspendable private fun getNotarySignature(stx: SignedTransaction): DigitalSignature.WithKey { progressTracker.currentStep = NOTARY - return subProtocol(NotaryProtocol.Client(stx)) + return subFlow(NotaryFlow.Client(stx)) } open fun computeOurSignature(partialTX: SignedTransaction): DigitalSignature.WithKey { @@ -185,12 +185,12 @@ object TwoPartyDealProtocol { /** - * Abstracted bilateral deal protocol participant that is recipient of initial communication. + * Abstracted bilateral deal flow participant that is recipient of initial communication. * - * There's a good chance we can push at least some of this logic down into core protocol logic + * There's a good chance we can push at least some of this logic down into core flow logic * and helper methods etc. */ - abstract class Secondary(override val progressTracker: ProgressTracker = Secondary.tracker()) : ProtocolLogic() { + abstract class Secondary(override val progressTracker: ProgressTracker = Secondary.tracker()) : FlowLogic() { companion object { object RECEIVING : ProgressTracker.Step("Waiting for deal info") @@ -267,7 +267,7 @@ object TwoPartyDealProtocol { /** - * One side of the protocol for inserting a pre-agreed deal. + * One side of the flow for inserting a pre-agreed deal. */ open class Instigator(override val otherParty: Party, override val payload: AutoOffer, @@ -279,7 +279,7 @@ object TwoPartyDealProtocol { } /** - * One side of the protocol for inserting a pre-agreed deal. + * One side of the flow for inserting a pre-agreed deal. */ open class Acceptor(override val otherParty: Party, override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary() { diff --git a/core/src/main/kotlin/net/corda/protocols/ValidatingNotaryProtocol.kt b/core/src/main/kotlin/net/corda/flows/ValidatingNotaryFlow.kt similarity index 76% rename from core/src/main/kotlin/net/corda/protocols/ValidatingNotaryProtocol.kt rename to core/src/main/kotlin/net/corda/flows/ValidatingNotaryFlow.kt index e91e0ece99..5a10bfd575 100644 --- a/core/src/main/kotlin/net/corda/protocols/ValidatingNotaryProtocol.kt +++ b/core/src/main/kotlin/net/corda/flows/ValidatingNotaryFlow.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.TransactionVerificationException @@ -10,15 +10,15 @@ import net.corda.core.transactions.WireTransaction import java.security.SignatureException /** - * A notary commit protocol that makes sure a given transaction is valid before committing it. This does mean that the calling + * A notary commit flow that makes sure a given transaction is valid before committing it. This does mean that the calling * party has to reveal the whole transaction history; however, we avoid complex conflict resolution logic where a party * has its input states "blocked" by a transaction from another party, and needs to establish whether that transaction was * indeed valid. */ -class ValidatingNotaryProtocol(otherSide: Party, - timestampChecker: TimestampChecker, - uniquenessProvider: UniquenessProvider) : - NotaryProtocol.Service(otherSide, timestampChecker, uniquenessProvider) { +class ValidatingNotaryFlow(otherSide: Party, + timestampChecker: TimestampChecker, + uniquenessProvider: UniquenessProvider) : + NotaryFlow.Service(otherSide, timestampChecker, uniquenessProvider) { @Suspendable override fun beforeCommit(stx: SignedTransaction, reqIdentity: Party) { @@ -46,6 +46,6 @@ class ValidatingNotaryProtocol(otherSide: Party, @Suspendable private fun resolveTransaction(reqIdentity: Party, wtx: WireTransaction) { - subProtocol(ResolveTransactionsProtocol(wtx, reqIdentity)) + subFlow(ResolveTransactionsFlow(wtx, reqIdentity)) } } diff --git a/core/src/test/java/net/corda/core/protocols/ProtocolLogicRefFromJavaTest.java b/core/src/test/java/net/corda/core/flows/FlowLogicRefFromJavaTest.java similarity index 54% rename from core/src/test/java/net/corda/core/protocols/ProtocolLogicRefFromJavaTest.java rename to core/src/test/java/net/corda/core/flows/FlowLogicRefFromJavaTest.java index 68d100e126..95ac1e92ce 100644 --- a/core/src/test/java/net/corda/core/protocols/ProtocolLogicRefFromJavaTest.java +++ b/core/src/test/java/net/corda/core/flows/FlowLogicRefFromJavaTest.java @@ -1,4 +1,4 @@ -package net.corda.core.protocols; +package net.corda.core.flows; import org.junit.Test; @@ -7,7 +7,7 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -public class ProtocolLogicRefFromJavaTest { +public class FlowLogicRefFromJavaTest { private static class ParamType1 { final int value; @@ -25,9 +25,9 @@ public class ProtocolLogicRefFromJavaTest { } } - private static class JavaProtocolLogic extends ProtocolLogic { + private static class JavaFlowLogic extends FlowLogic { - public JavaProtocolLogic(ParamType1 A, ParamType2 b) { + public JavaFlowLogic(ParamType1 A, ParamType2 b) { } @Override @@ -36,9 +36,9 @@ public class ProtocolLogicRefFromJavaTest { } } - private static class JavaNoArgProtocolLogic extends ProtocolLogic { + private static class JavaNoArgFlowLogic extends FlowLogic { - public JavaNoArgProtocolLogic() { + public JavaNoArgFlowLogic() { } @Override @@ -53,16 +53,16 @@ public class ProtocolLogicRefFromJavaTest { Set argsList = new HashSet<>(); argsList.add(ParamType1.class.getName()); argsList.add(ParamType2.class.getName()); - whiteList.put(JavaProtocolLogic.class.getName(), argsList); - ProtocolLogicRefFactory factory = new ProtocolLogicRefFactory(whiteList); - factory.create(JavaProtocolLogic.class, new ParamType1(1), new ParamType2("Hello Jack")); + whiteList.put(JavaFlowLogic.class.getName(), argsList); + FlowLogicRefFactory factory = new FlowLogicRefFactory(whiteList); + factory.create(JavaFlowLogic.class, new ParamType1(1), new ParamType2("Hello Jack")); } @Test public void testNoArg() { Map> whiteList = new HashMap<>(); - whiteList.put(JavaNoArgProtocolLogic.class.getName(), new HashSet<>()); - ProtocolLogicRefFactory factory = new ProtocolLogicRefFactory(whiteList); - factory.create(JavaNoArgProtocolLogic.class); + whiteList.put(JavaNoArgFlowLogic.class.getName(), new HashSet<>()); + FlowLogicRefFactory factory = new FlowLogicRefFactory(whiteList); + factory.create(JavaNoArgFlowLogic.class); } } diff --git a/core/src/test/kotlin/net/corda/core/protocols/BroadcastTransactionProtocolTest.kt b/core/src/test/kotlin/net/corda/core/flows/BroadcastTransactionFlowTest.kt similarity index 89% rename from core/src/test/kotlin/net/corda/core/protocols/BroadcastTransactionProtocolTest.kt rename to core/src/test/kotlin/net/corda/core/flows/BroadcastTransactionFlowTest.kt index 8fae2f3398..e6b8dbe758 100644 --- a/core/src/test/kotlin/net/corda/core/protocols/BroadcastTransactionProtocolTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/BroadcastTransactionFlowTest.kt @@ -1,4 +1,4 @@ -package net.corda.core.protocols +package net.corda.core.flows import com.esotericsoftware.kryo.io.Input import com.pholser.junit.quickcheck.From @@ -10,12 +10,12 @@ import com.pholser.junit.quickcheck.runner.JUnitQuickcheck import net.corda.contracts.testing.SignedTransactionGenerator import net.corda.core.serialization.createKryo import net.corda.core.serialization.serialize -import net.corda.protocols.BroadcastTransactionProtocol.NotifyTxRequest +import net.corda.flows.BroadcastTransactionFlow.NotifyTxRequest import org.junit.runner.RunWith import kotlin.test.assertEquals @RunWith(JUnitQuickcheck::class) -class BroadcastTransactionProtocolTest { +class BroadcastTransactionFlowTest { class NotifyTxRequestMessageGenerator : Generator(NotifyTxRequest::class.java) { override fun generate(random: SourceOfRandomness, status: GenerationStatus): NotifyTxRequest { diff --git a/core/src/test/kotlin/net/corda/core/protocols/ProtocolLogicRefTest.kt b/core/src/test/kotlin/net/corda/core/flows/FlowLogicRefTest.kt similarity index 59% rename from core/src/test/kotlin/net/corda/core/protocols/ProtocolLogicRefTest.kt rename to core/src/test/kotlin/net/corda/core/flows/FlowLogicRefTest.kt index 341836d2e3..60bfd4880a 100644 --- a/core/src/test/kotlin/net/corda/core/protocols/ProtocolLogicRefTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/FlowLogicRefTest.kt @@ -1,17 +1,17 @@ -package net.corda.core.protocols +package net.corda.core.flows import net.corda.core.days import org.junit.Before import org.junit.Test import java.time.Duration -class ProtocolLogicRefTest { +class FlowLogicRefTest { data class ParamType1(val value: Int) data class ParamType2(val value: String) @Suppress("UNUSED_PARAMETER", "unused") // Things are used via reflection. - class KotlinProtocolLogic(A: ParamType1, b: ParamType2) : ProtocolLogic() { + class KotlinFlowLogic(A: ParamType1, b: ParamType2) : FlowLogic() { constructor() : this(ParamType1(1), ParamType2("2")) constructor(C: ParamType2) : this(ParamType1(1), C) @@ -25,71 +25,71 @@ class ProtocolLogicRefTest { override fun call() = Unit } - class KotlinNoArgProtocolLogic : ProtocolLogic() { + class KotlinNoArgFlowLogic : FlowLogic() { override fun call() = Unit } @Suppress("UNUSED_PARAMETER") // We will never use A or b - class NotWhiteListedKotlinProtocolLogic(A: Int, b: String) : ProtocolLogic() { + class NotWhiteListedKotlinFlowLogic(A: Int, b: String) : FlowLogic() { override fun call() = Unit } - lateinit var factory: ProtocolLogicRefFactory + lateinit var factory: FlowLogicRefFactory @Before fun setup() { // We have to allow Java boxed primitives but Kotlin warns we shouldn't be using them - factory = ProtocolLogicRefFactory(mapOf(Pair(KotlinProtocolLogic::class.java.name, setOf(ParamType1::class.java.name, ParamType2::class.java.name)), - Pair(KotlinNoArgProtocolLogic::class.java.name, setOf()))) + factory = FlowLogicRefFactory(mapOf(Pair(KotlinFlowLogic::class.java.name, setOf(ParamType1::class.java.name, ParamType2::class.java.name)), + Pair(KotlinNoArgFlowLogic::class.java.name, setOf()))) } @Test fun testCreateKotlinNoArg() { - factory.create(KotlinNoArgProtocolLogic::class.java) + factory.create(KotlinNoArgFlowLogic::class.java) } @Test fun testCreateKotlin() { val args = mapOf(Pair("A", ParamType1(1)), Pair("b", ParamType2("Hello Jack"))) - factory.createKotlin(KotlinProtocolLogic::class.java, args) + factory.createKotlin(KotlinFlowLogic::class.java, args) } @Test fun testCreatePrimary() { - factory.create(KotlinProtocolLogic::class.java, ParamType1(1), ParamType2("Hello Jack")) + factory.create(KotlinFlowLogic::class.java, ParamType1(1), ParamType2("Hello Jack")) } @Test(expected = IllegalArgumentException::class) fun testCreateNotWhiteListed() { - factory.create(NotWhiteListedKotlinProtocolLogic::class.java, ParamType1(1), ParamType2("Hello Jack")) + factory.create(NotWhiteListedKotlinFlowLogic::class.java, ParamType1(1), ParamType2("Hello Jack")) } @Test fun testCreateKotlinVoid() { - factory.createKotlin(KotlinProtocolLogic::class.java, emptyMap()) + factory.createKotlin(KotlinFlowLogic::class.java, emptyMap()) } @Test fun testCreateKotlinNonPrimary() { val args = mapOf(Pair("C", ParamType2("Hello Jack"))) - factory.createKotlin(KotlinProtocolLogic::class.java, args) + factory.createKotlin(KotlinFlowLogic::class.java, args) } @Test(expected = IllegalArgumentException::class) fun testCreateArgNotWhiteListed() { val args = mapOf(Pair("illegal", 1.days)) - factory.createKotlin(KotlinProtocolLogic::class.java, args) + factory.createKotlin(KotlinFlowLogic::class.java, args) } @Test fun testCreateJavaPrimitiveNoRegistrationRequired() { val args = mapOf(Pair("primitive", "A string")) - factory.createKotlin(KotlinProtocolLogic::class.java, args) + factory.createKotlin(KotlinFlowLogic::class.java, args) } @Test fun testCreateKotlinPrimitiveNoRegistrationRequired() { val args = mapOf(Pair("kotlinType", 3)) - factory.createKotlin(KotlinProtocolLogic::class.java, args) + factory.createKotlin(KotlinFlowLogic::class.java, args) } } diff --git a/core/src/test/kotlin/net/corda/core/protocols/ResolveTransactionsProtocolTest.kt b/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt similarity index 82% rename from core/src/test/kotlin/net/corda/core/protocols/ResolveTransactionsProtocolTest.kt rename to core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt index e1f5dfde48..fc80266d86 100644 --- a/core/src/test/kotlin/net/corda/core/protocols/ResolveTransactionsProtocolTest.kt +++ b/core/src/test/kotlin/net/corda/core/flows/ResolveTransactionsFlowTest.kt @@ -1,4 +1,4 @@ -package net.corda.core.protocols +package net.corda.core.flows import net.corda.core.contracts.DummyContract import net.corda.core.crypto.NullSignature @@ -8,8 +8,8 @@ import net.corda.core.node.recordTransactions import net.corda.core.serialization.opaque import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.DUMMY_NOTARY_KEY +import net.corda.flows.ResolveTransactionsFlow import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.ResolveTransactionsProtocol import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.MINI_CORP_PUBKEY @@ -24,7 +24,7 @@ import kotlin.test.assertFailsWith import kotlin.test.assertNotNull import kotlin.test.assertNull -class ResolveTransactionsProtocolTest { +class ResolveTransactionsFlowTest { lateinit var net: MockNetwork lateinit var a: MockNetwork.MockNode lateinit var b: MockNetwork.MockNode @@ -48,8 +48,8 @@ class ResolveTransactionsProtocolTest { @Test fun `resolve from two hashes`() { val (stx1, stx2) = makeTransactions() - val p = ResolveTransactionsProtocol(setOf(stx2.id), a.info.legalIdentity) - val future = b.services.startProtocol(p).resultFuture + val p = ResolveTransactionsFlow(setOf(stx2.id), a.info.legalIdentity) + val future = b.services.startFlow(p).resultFuture net.runNetwork() val results = future.get() assertEquals(listOf(stx1.id, stx2.id), results.map { it.id }) @@ -62,8 +62,8 @@ class ResolveTransactionsProtocolTest { @Test fun `dependency with an error`() { val stx = makeTransactions(signFirstTX = false).second - val p = ResolveTransactionsProtocol(setOf(stx.id), a.info.legalIdentity) - val future = b.services.startProtocol(p).resultFuture + val p = ResolveTransactionsFlow(setOf(stx.id), a.info.legalIdentity) + val future = b.services.startFlow(p).resultFuture net.runNetwork() assertFailsWith(SignatureException::class) { rootCauseExceptions { future.get() } @@ -73,8 +73,8 @@ class ResolveTransactionsProtocolTest { @Test fun `resolve from a signed transaction`() { val (stx1, stx2) = makeTransactions() - val p = ResolveTransactionsProtocol(stx2, a.info.legalIdentity) - val future = b.services.startProtocol(p).resultFuture + val p = ResolveTransactionsFlow(stx2, a.info.legalIdentity) + val future = b.services.startFlow(p).resultFuture net.runNetwork() future.get() databaseTransaction(b.database) { @@ -99,11 +99,11 @@ class ResolveTransactionsProtocolTest { } cursor = stx } - val p = ResolveTransactionsProtocol(setOf(cursor.id), a.info.legalIdentity) + val p = ResolveTransactionsFlow(setOf(cursor.id), a.info.legalIdentity) p.transactionCountLimit = 40 - val future = b.services.startProtocol(p).resultFuture + val future = b.services.startFlow(p).resultFuture net.runNetwork() - assertFailsWith { + assertFailsWith { rootCauseExceptions { future.get() } } } @@ -128,8 +128,8 @@ class ResolveTransactionsProtocolTest { a.services.recordTransactions(stx2, stx3) } - val p = ResolveTransactionsProtocol(setOf(stx3.id), a.info.legalIdentity) - val future = b.services.startProtocol(p).resultFuture + val p = ResolveTransactionsFlow(setOf(stx3.id), a.info.legalIdentity) + val future = b.services.startFlow(p).resultFuture net.runNetwork() future.get() } @@ -138,8 +138,8 @@ class ResolveTransactionsProtocolTest { fun attachment() { val id = a.services.storageService.attachments.importAttachment("Some test file".toByteArray().opaque().open()) val stx2 = makeTransactions(withAttachment = id).second - val p = ResolveTransactionsProtocol(stx2, a.info.legalIdentity) - val future = b.services.startProtocol(p).resultFuture + val p = ResolveTransactionsFlow(stx2, a.info.legalIdentity) + val future = b.services.startFlow(p).resultFuture net.runNetwork() future.get() assertNotNull(b.services.storageService.attachments.openAttachment(id)) diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt index 364d14693f..27cb6bf166 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/ClientRpcTutorial.kt @@ -12,16 +12,16 @@ import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.services.ServiceInfo import net.corda.core.serialization.OpaqueBytes import net.corda.core.transactions.SignedTransaction +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow import net.corda.node.driver.driver import net.corda.node.services.User import net.corda.node.services.config.FullNodeConfiguration import net.corda.node.services.config.NodeSSLConfiguration import net.corda.node.services.messaging.CordaRPCOps -import net.corda.node.services.messaging.startProtocol -import net.corda.node.services.startProtocolPermission +import net.corda.node.services.messaging.startFlow +import net.corda.node.services.startFlowPermission import net.corda.node.services.transactions.ValidatingNotaryService -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol import org.graphstream.graph.Edge import org.graphstream.graph.Node import org.graphstream.graph.implementations.MultiGraph @@ -47,7 +47,7 @@ fun main(args: Array) { val printOrVisualise = PrintOrVisualise.valueOf(args[0]) val baseDirectory = Paths.get("build/rpc-api-tutorial") - val user = User("user", "password", permissions = setOf(startProtocolPermission())) + val user = User("user", "password", permissions = setOf(startFlowPermission())) driver(driverDirectory = baseDirectory) { startNode("Notary", advertisedServices = setOf(ServiceInfo(ValidatingNotaryService.type))) @@ -125,14 +125,14 @@ fun generateTransactions(proxy: CordaRPCOps) { val n = random.nextDouble() if (ownedQuantity > 10000 && n > 0.8) { val quantity = Math.abs(random.nextLong()) % 2000 - proxy.startProtocol(::CashProtocol, CashCommand.ExitCash(Amount(quantity, USD), issueRef)) + proxy.startFlow(::CashFlow, CashCommand.ExitCash(Amount(quantity, USD), issueRef)) ownedQuantity -= quantity } else if (ownedQuantity > 1000 && n < 0.7) { val quantity = Math.abs(random.nextLong() % Math.min(ownedQuantity, 2000)) - proxy.startProtocol(::CashProtocol, CashCommand.PayCash(Amount(quantity, Issued(meAndRef, USD)), me)) + proxy.startFlow(::CashFlow, CashCommand.PayCash(Amount(quantity, Issued(meAndRef, USD)), me)) } else { val quantity = Math.abs(random.nextLong() % 1000) - proxy.startProtocol(::CashProtocol, CashCommand.IssueCash(Amount(quantity, USD), issueRef, me, notary)) + proxy.startFlow(::CashFlow, CashCommand.IssueCash(Amount(quantity, USD), issueRef, me, notary)) ownedQuantity += quantity } } diff --git a/finance/src/main/kotlin/net/corda/protocols/CashProtocol.kt b/finance/src/main/kotlin/net/corda/flows/CashFlow.kt similarity index 80% rename from finance/src/main/kotlin/net/corda/protocols/CashProtocol.kt rename to finance/src/main/kotlin/net/corda/flows/CashFlow.kt index 16764b2f32..09c6d81385 100644 --- a/finance/src/main/kotlin/net/corda/protocols/CashProtocol.kt +++ b/finance/src/main/kotlin/net/corda/flows/CashFlow.kt @@ -1,4 +1,4 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.contracts.asset.Cash @@ -6,8 +6,8 @@ import net.corda.core.contracts.* import net.corda.core.crypto.Party import net.corda.core.crypto.keys import net.corda.core.crypto.toStringShort -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.StateMachineRunId +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.StateMachineRunId import net.corda.core.serialization.OpaqueBytes import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -15,14 +15,14 @@ import java.security.KeyPair import java.util.* /** - * Initiates a protocol that produces an Issue/Move or Exit Cash transaction. + * Initiates a flow that produces an Issue/Move or Exit Cash transaction. * * @param command Indicates what Cash transaction to create with what parameters. */ -class CashProtocol(val command: CashCommand): ProtocolLogic() { +class CashFlow(val command: CashCommand) : FlowLogic() { @Suspendable - override fun call(): CashProtocolResult { + override fun call(): CashFlowResult { return when (command) { is CashCommand.IssueCash -> issueCash(command) is CashCommand.PayCash -> initiatePayment(command) @@ -32,7 +32,7 @@ class CashProtocol(val command: CashCommand): ProtocolLogic( // TODO check with the recipient if they want to accept the cash. @Suspendable - private fun initiatePayment(req: CashCommand.PayCash): CashProtocolResult { + private fun initiatePayment(req: CashCommand.PayCash): CashFlowResult { val builder: TransactionBuilder = TransactionType.General.Builder(null) // TODO: Have some way of restricting this to states the caller controls try { @@ -45,20 +45,20 @@ class CashProtocol(val command: CashCommand): ProtocolLogic( } val tx = spendTX.toSignedTransaction(checkSufficientSignatures = false) - val protocol = FinalityProtocol(tx, setOf(req.recipient)) - subProtocol(protocol) - return CashProtocolResult.Success( - psm.id, + val flow = FinalityFlow(tx, setOf(req.recipient)) + subFlow(flow) + return CashFlowResult.Success( + fsm.id, tx, "Cash payment transaction generated" ) } catch(ex: InsufficientBalanceException) { - return CashProtocolResult.Failed(ex.message ?: "Insufficient balance") + return CashFlowResult.Failed(ex.message ?: "Insufficient balance") } } @Suspendable - private fun exitCash(req: CashCommand.ExitCash): CashProtocolResult { + private fun exitCash(req: CashCommand.ExitCash): CashFlowResult { val builder: TransactionBuilder = TransactionType.General.Builder(null) try { val issuer = PartyAndReference(serviceHub.myInfo.legalIdentity, req.issueRef) @@ -81,19 +81,19 @@ class CashProtocol(val command: CashCommand): ProtocolLogic( // Commit the transaction val tx = builder.toSignedTransaction(checkSufficientSignatures = false) - subProtocol(FinalityProtocol(tx, participants)) - return CashProtocolResult.Success( - psm.id, + subFlow(FinalityFlow(tx, participants)) + return CashFlowResult.Success( + fsm.id, tx, "Cash destruction transaction generated" ) } catch (ex: InsufficientBalanceException) { - return CashProtocolResult.Failed(ex.message ?: "Insufficient balance") + return CashFlowResult.Failed(ex.message ?: "Insufficient balance") } } @Suspendable - private fun issueCash(req: CashCommand.IssueCash): CashProtocolResult { + private fun issueCash(req: CashCommand.IssueCash): CashFlowResult { val builder: TransactionBuilder = TransactionType.General.Builder(notary = null) val issuer = PartyAndReference(serviceHub.myInfo.legalIdentity, req.issueRef) Cash().generateIssue(builder, req.amount.issuedBy(issuer), req.recipient.owningKey, req.notary) @@ -101,9 +101,9 @@ class CashProtocol(val command: CashCommand): ProtocolLogic( builder.signWith(myKey) val tx = builder.toSignedTransaction(checkSufficientSignatures = true) // Issuance transactions do not need to be notarised, so we can skip directly to broadcasting it - subProtocol(BroadcastTransactionProtocol(tx, setOf(req.recipient))) - return CashProtocolResult.Success( - psm.id, + subFlow(BroadcastTransactionFlow(tx, setOf(req.recipient))) + return CashFlowResult.Success( + fsm.id, tx, "Cash issuance completed" ) @@ -113,7 +113,7 @@ class CashProtocol(val command: CashCommand): ProtocolLogic( } /** - * A command to initiate the Cash protocol with. + * A command to initiate the Cash flow with. */ sealed class CashCommand { /** @@ -147,11 +147,11 @@ sealed class CashCommand { class ExitCash(val amount: Amount, val issueRef: OpaqueBytes) : CashCommand() } -sealed class CashProtocolResult { +sealed class CashFlowResult { /** - * @param transaction the transaction created as a result, in the case where the protocol completed successfully. + * @param transaction the transaction created as a result, in the case where the flow completed successfully. */ - class Success(val id: StateMachineRunId, val transaction: SignedTransaction?, val message: String?) : CashProtocolResult() { + class Success(val id: StateMachineRunId, val transaction: SignedTransaction?, val message: String?) : CashFlowResult() { override fun toString() = "Success($message)" } @@ -159,7 +159,7 @@ sealed class CashProtocolResult { * State indicating the action undertaken failed, either directly (it is not something which requires a * state machine), or before a state machine was started. */ - class Failed(val message: String?) : CashProtocolResult() { + class Failed(val message: String?) : CashFlowResult() { override fun toString() = "Failed($message)" } } diff --git a/finance/src/main/kotlin/net/corda/protocols/TwoPartyTradeProtocol.kt b/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt similarity index 91% rename from finance/src/main/kotlin/net/corda/protocols/TwoPartyTradeProtocol.kt rename to finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt index 5af861e562..b14e4cc419 100644 --- a/finance/src/main/kotlin/net/corda/protocols/TwoPartyTradeProtocol.kt +++ b/finance/src/main/kotlin/net/corda/flows/TwoPartyTradeFlow.kt @@ -1,11 +1,11 @@ -package net.corda.protocols +package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.contracts.asset.sumCashBy import net.corda.core.contracts.* import net.corda.core.crypto.* +import net.corda.core.flows.FlowLogic import net.corda.core.node.NodeInfo -import net.corda.core.protocols.ProtocolLogic import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -16,7 +16,7 @@ import java.security.KeyPair import java.util.* /** - * This asset trading protocol implements a "delivery vs payment" type swap. It has two parties (B and S for buyer + * This asset trading flow implements a "delivery vs payment" type swap. It has two parties (B and S for buyer * and seller) and the following steps: * * 1. S sends the [StateAndRef] pointing to what they want to sell to B, along with info about the price they require @@ -26,28 +26,28 @@ import java.util.* * it lacks a signature from S authorising movement of the asset. * 3. S signs it and hands the now finalised SignedWireTransaction back to B. * - * Assuming no malicious termination, they both end the protocol being in posession of a valid, signed transaction + * Assuming no malicious termination, they both end the flow being in posession of a valid, signed transaction * that represents an atomic asset swap. * * Note that it's the *seller* who initiates contact with the buyer, not vice-versa as you might imagine. * - * To initiate the protocol, use either the [runBuyer] or [runSeller] methods, depending on which side of the trade + * To initiate the flow, use either the [runBuyer] or [runSeller] methods, depending on which side of the trade * your node is taking. These methods return a future which will complete once the trade is over and a fully signed - * transaction is available: you can either block your thread waiting for the protocol to complete by using + * transaction is available: you can either block your thread waiting for the flow to complete by using * [ListenableFuture.get] or more usefully, register a callback that will be invoked when the time comes. * * To see an example of how to use this class, look at the unit tests. */ // TODO: Common elements in multi-party transaction consensus and signing should be refactored into a superclass of this -// and [AbstractStateReplacementProtocol]. -object TwoPartyTradeProtocol { +// and [AbstractStateReplacementFlow]. +object TwoPartyTradeFlow { class UnacceptablePriceException(val givenPrice: Amount) : Exception("Unacceptable price: $givenPrice") class AssetMismatchException(val expectedTypeName: String, val typeName: String) : Exception() { override fun toString() = "The submitted asset didn't match the expected type: $expectedTypeName vs $typeName" } - // This object is serialised to the network and is the first protocol message the seller sends to the buyer. + // This object is serialised to the network and is the first flow message the seller sends to the buyer. data class SellerTradeInfo( val assetForSale: StateAndRef, val price: Amount, @@ -62,7 +62,7 @@ object TwoPartyTradeProtocol { val assetToSell: StateAndRef, val price: Amount, val myKeyPair: KeyPair, - override val progressTracker: ProgressTracker = Seller.tracker()) : ProtocolLogic() { + override val progressTracker: ProgressTracker = Seller.tracker()) : FlowLogic() { companion object { object AWAITING_PROPOSAL : ProgressTracker.Step("Awaiting transaction proposal") @@ -92,7 +92,7 @@ object TwoPartyTradeProtocol { @Suspendable private fun getNotarySignature(stx: SignedTransaction): DigitalSignature.WithKey { progressTracker.currentStep = NOTARY - return subProtocol(NotaryProtocol.Client(stx)) + return subFlow(NotaryFlow.Client(stx)) } @Suspendable @@ -100,7 +100,7 @@ object TwoPartyTradeProtocol { progressTracker.currentStep = AWAITING_PROPOSAL val myPublicKey = myKeyPair.public.composite - // Make the first message we'll send to kick off the protocol. + // Make the first message we'll send to kick off the flow. val hello = SellerTradeInfo(assetToSell, price, myPublicKey) val maybeSTX = sendAndReceive(otherParty, hello) @@ -116,7 +116,7 @@ object TwoPartyTradeProtocol { // Download and check all the things that this transaction depends on and verify it is contract-valid, // even though it is missing signatures. - subProtocol(ResolveTransactionsProtocol(wtx, otherParty)) + subFlow(ResolveTransactionsFlow(wtx, otherParty)) if (wtx.outputs.map { it.data }.sumCashBy(myPublicKey).withoutIssuer() != price) throw IllegalArgumentException("Transaction is not sending us the right amount of cash") @@ -129,7 +129,7 @@ object TwoPartyTradeProtocol { // once we implement state pairing. // // but the goal of this code is not to be fully secure (yet), but rather, just to find good ways to - // express protocol state machines on top of the messaging layer. + // express flow state machines on top of the messaging layer. return it } @@ -156,7 +156,7 @@ object TwoPartyTradeProtocol { open class Buyer(val otherParty: Party, val notary: Party, val acceptablePrice: Amount, - val typeToBuy: Class) : ProtocolLogic() { + val typeToBuy: Class) : FlowLogic() { object RECEIVING : ProgressTracker.Step("Waiting for seller trading info") @@ -207,7 +207,7 @@ object TwoPartyTradeProtocol { // Check the transaction that contains the state which is being resolved. // We only have a hash here, so if we don't know it already, we have to ask for it. - subProtocol(ResolveTransactionsProtocol(setOf(it.assetForSale.ref.txhash), otherParty)) + subFlow(ResolveTransactionsFlow(setOf(it.assetForSale.ref.txhash), otherParty)) return it } diff --git a/node/src/integration-test/kotlin/net/corda/node/services/DistributedNotaryTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/DistributedNotaryTests.kt index 521a6e3c0f..66a108ccde 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/DistributedNotaryTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/DistributedNotaryTests.kt @@ -14,6 +14,9 @@ import net.corda.core.node.services.ServiceInfo import net.corda.core.random63BitValue import net.corda.core.serialization.serialize import net.corda.core.utilities.LogHelper +import net.corda.flows.NotaryError +import net.corda.flows.NotaryException +import net.corda.flows.NotaryFlow import net.corda.node.internal.AbstractNode import net.corda.node.internal.Node import net.corda.node.services.config.ConfigHelper @@ -21,9 +24,6 @@ import net.corda.node.services.config.FullNodeConfiguration import net.corda.node.services.network.NetworkMapService import net.corda.node.services.transactions.RaftValidatingNotaryService import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.NotaryError -import net.corda.protocols.NotaryException -import net.corda.protocols.NotaryProtocol import net.corda.testing.freeLocalHostAndPort import org.junit.After import org.junit.Before @@ -76,12 +76,12 @@ class DistributedNotaryTests { tx.toSignedTransaction(false) } - val buildProtocol = { NotaryProtocol.Client(stx) } + val buildFlow = { NotaryFlow.Client(stx) } - val firstSpend = alice.services.startProtocol(buildProtocol()) + val firstSpend = alice.services.startFlow(buildFlow()) firstSpend.resultFuture.get() - val secondSpend = alice.services.startProtocol(buildProtocol()) + val secondSpend = alice.services.startFlow(buildFlow()) val ex = assertFailsWith(ExecutionException::class) { secondSpend.resultFuture.get() } val error = (ex.cause as NotaryException).error as NotaryError.Conflict diff --git a/node/src/main/kotlin/net/corda/node/api/APIServer.kt b/node/src/main/kotlin/net/corda/node/api/APIServer.kt index 1aa078d367..95911fe7b7 100644 --- a/node/src/main/kotlin/net/corda/node/api/APIServer.kt +++ b/node/src/main/kotlin/net/corda/node/api/APIServer.kt @@ -91,31 +91,31 @@ interface APIServer { fun commitTransaction(tx: SerializedBytes, signatures: List): SecureHash /** - * This method would not return until the protocol is finished (hence the "Sync"). + * This method would not return until the flow is finished (hence the "Sync"). * - * Longer term we'd add an Async version that returns some kind of ProtocolInvocationRef that could be queried and + * Longer term we'd add an Async version that returns some kind of FlowInvocationRef that could be queried and * would appear on some kind of event message that is broadcast informing of progress. * - * Will throw exception if protocol fails. + * Will throw exception if flow fails. */ - fun invokeProtocolSync(type: ProtocolRef, args: Map): Any? + fun invokeFlowSync(type: FlowRef, args: Map): Any? - // fun invokeProtocolAsync(type: ProtocolRef, args: Map): ProtocolInstanceRef + // fun invokeFlowAsync(type: FlowRef, args: Map): FlowInstanceRef /** - * Fetch protocols that require a response to some prompt/question by a human (on the "bank" side). + * Fetch flows that require a response to some prompt/question by a human (on the "bank" side). */ - fun fetchProtocolsRequiringAttention(query: StatesQuery): Map + fun fetchFlowsRequiringAttention(query: StatesQuery): Map /** - * Provide the response that a protocol is waiting for. + * Provide the response that a flow is waiting for. * - * @param protocol Should refer to a previously supplied ProtocolRequiringAttention. - * @param stepId Which step of the protocol are we referring too. - * @param choice Should be one of the choices presented in the ProtocolRequiringAttention. + * @param flow Should refer to a previously supplied FlowRequiringAttention. + * @param stepId Which step of the flow are we referring too. + * @param choice Should be one of the choices presented in the FlowRequiringAttention. * @param args Any arguments required. */ - fun provideProtocolResponse(protocol: ProtocolInstanceRef, choice: SecureHash, args: Map) + fun provideFlowResponse(flow: FlowInstanceRef, choice: SecureHash, args: Map) } @@ -131,20 +131,20 @@ data class ContractLedgerRef(val hash: SecureHash) : ContractDefRef /** - * Encapsulates the protocol to be instantiated. e.g. TwoPartyTradeProtocol.Buyer. + * Encapsulates the flow to be instantiated. e.g. TwoPartyTradeFlow.Buyer. */ -interface ProtocolRef { +interface FlowRef { } -data class ProtocolClassRef(val className: String) : ProtocolRef +data class FlowClassRef(val className: String) : FlowRef -data class ProtocolInstanceRef(val protocolInstance: SecureHash, val protocolClass: ProtocolClassRef, val protocolStepId: String) +data class FlowInstanceRef(val flowInstance: SecureHash, val flowClass: FlowClassRef, val flowStepId: String) /** - * Thinking that Instant is OK for short lived protocol deadlines. + * Thinking that Instant is OK for short lived flow deadlines. */ -data class ProtocolRequiringAttention(val ref: ProtocolInstanceRef, val prompt: String, val choiceIdsToMessages: Map, val dueBy: Instant) +data class FlowRequiringAttention(val ref: FlowInstanceRef, val prompt: String, val choiceIdsToMessages: Map, val dueBy: Instant) /** diff --git a/node/src/main/kotlin/net/corda/node/internal/APIServerImpl.kt b/node/src/main/kotlin/net/corda/node/internal/APIServerImpl.kt index 0009492bb6..f4835ed232 100644 --- a/node/src/main/kotlin/net/corda/node/internal/APIServerImpl.kt +++ b/node/src/main/kotlin/net/corda/node/internal/APIServerImpl.kt @@ -1,7 +1,10 @@ package net.corda.node.internal import com.google.common.util.concurrent.ListenableFuture -import net.corda.core.contracts.* +import net.corda.core.contracts.ContractState +import net.corda.core.contracts.DealState +import net.corda.core.contracts.StateRef +import net.corda.core.contracts.TransactionState import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.SecureHash import net.corda.core.node.services.linearHeadsOfType @@ -64,25 +67,25 @@ class APIServerImpl(val node: AbstractNode) : APIServer { throw UnsupportedOperationException() } - override fun invokeProtocolSync(type: ProtocolRef, args: Map): Any? { - return invokeProtocolAsync(type, args).get() + override fun invokeFlowSync(type: FlowRef, args: Map): Any? { + return invokeFlowAsync(type, args).get() } - private fun invokeProtocolAsync(type: ProtocolRef, args: Map): ListenableFuture { - if (type is ProtocolClassRef) { - val protocolLogicRef = node.services.protocolLogicRefFactory.createKotlin(type.className, args) - val protocolInstance = node.services.protocolLogicRefFactory.toProtocolLogic(protocolLogicRef) - return node.services.startProtocol(protocolInstance).resultFuture + private fun invokeFlowAsync(type: FlowRef, args: Map): ListenableFuture { + if (type is FlowClassRef) { + val flowLogicRef = node.services.flowLogicRefFactory.createKotlin(type.className, args) + val flowInstance = node.services.flowLogicRefFactory.toFlowLogic(flowLogicRef) + return node.services.startFlow(flowInstance).resultFuture } else { - throw UnsupportedOperationException("Unsupported ProtocolRef type: $type") + throw UnsupportedOperationException("Unsupported FlowRef type: $type") } } - override fun fetchProtocolsRequiringAttention(query: StatesQuery): Map { + override fun fetchFlowsRequiringAttention(query: StatesQuery): Map { throw UnsupportedOperationException() } - override fun provideProtocolResponse(protocol: ProtocolInstanceRef, choice: SecureHash, args: Map) { + override fun provideFlowResponse(flow: FlowInstanceRef, choice: SecureHash, args: Map) { throw UnsupportedOperationException() } diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 6527473eef..39bb1909f9 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -8,17 +8,20 @@ import com.google.common.util.concurrent.SettableFuture import net.corda.core.* import net.corda.core.crypto.Party import net.corda.core.crypto.X509Utilities +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.flows.FlowStateMachine import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.* import net.corda.core.node.services.* import net.corda.core.node.services.NetworkMapCache.MapChangeType -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolLogicRefFactory -import net.corda.core.protocols.ProtocolStateMachine import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize import net.corda.core.transactions.SignedTransaction +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow +import net.corda.flows.sendRequest import net.corda.node.api.APIServer import net.corda.node.services.api.* import net.corda.node.services.config.NodeConfiguration @@ -30,7 +33,7 @@ import net.corda.node.services.keys.PersistentKeyManagementService import net.corda.node.services.messaging.RPCOps import net.corda.node.services.network.InMemoryNetworkMapCache import net.corda.node.services.network.NetworkMapService -import net.corda.node.services.network.NetworkMapService.Companion.REGISTER_PROTOCOL_TOPIC +import net.corda.node.services.network.NetworkMapService.Companion.REGISTER_FLOW_TOPIC import net.corda.node.services.network.NetworkMapService.RegistrationResponse import net.corda.node.services.network.NodeRegistration import net.corda.node.services.network.PersistentNetworkMapService @@ -45,9 +48,6 @@ import net.corda.node.utilities.AddOrRemove import net.corda.node.utilities.AffinityExecutor import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol -import net.corda.protocols.sendRequest import org.jetbrains.exposed.sql.Database import org.slf4j.Logger import java.nio.file.FileAlreadyExistsException @@ -66,7 +66,7 @@ import net.corda.core.crypto.generateKeyPair as cryptoGenerateKeyPair * I/O), or a mock implementation suitable for unit test environments. * * Marked as SingletonSerializeAsToken to prevent the invisible reference to AbstractNode in the ServiceHub accidentally - * sweeping up the Node into the Kryo checkpoint serialization via any protocols holding a reference to ServiceHub. + * sweeping up the Node into the Kryo checkpoint serialization via any flows holding a reference to ServiceHub. */ // TODO: Where this node is the initial network map service, currently no networkMapService is provided. // In theory the NodeInfo for the node should be passed in, instead, however currently this is constructed by the @@ -95,7 +95,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo protected val _servicesThatAcceptUploads = ArrayList() val servicesThatAcceptUploads: List = _servicesThatAcceptUploads - private val protocolFactories = ConcurrentHashMap, (Party) -> ProtocolLogic<*>>() + private val flowFactories = ConcurrentHashMap, (Party) -> FlowLogic<*>>() protected val partyKeys = mutableSetOf() val services = object : ServiceHubInternal() { @@ -112,18 +112,18 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo // Internal only override val monitoringService: MonitoringService = MonitoringService(MetricRegistry()) - override val protocolLogicRefFactory: ProtocolLogicRefFactory get() = protocolLogicFactory + override val flowLogicRefFactory: FlowLogicRefFactory get() = flowLogicFactory - override fun startProtocol(logic: ProtocolLogic): ProtocolStateMachine = smm.add(logic) + override fun startFlow(logic: FlowLogic): FlowStateMachine = smm.add(logic) - override fun registerProtocolInitiator(markerClass: KClass<*>, protocolFactory: (Party) -> ProtocolLogic<*>) { - require(markerClass !in protocolFactories) { "${markerClass.java.name} has already been used to register a protocol" } - log.info("Registering protocol ${markerClass.java.name}") - protocolFactories[markerClass.java] = protocolFactory + override fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) { + require(markerClass !in flowFactories) { "${markerClass.java.name} has already been used to register a flow" } + log.info("Registering flow ${markerClass.java.name}") + flowFactories[markerClass.java] = flowFactory } - override fun getProtocolFactory(markerClass: Class<*>): ((Party) -> ProtocolLogic<*>)? { - return protocolFactories[markerClass] + override fun getFlowFactory(markerClass: Class<*>): ((Party) -> FlowLogic<*>)? { + return flowFactories[markerClass] } override fun recordTransactions(txs: Iterable) { @@ -149,7 +149,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo lateinit var netMapCache: NetworkMapCache lateinit var api: APIServer lateinit var scheduler: NodeSchedulerService - lateinit var protocolLogicFactory: ProtocolLogicRefFactory + lateinit var flowLogicFactory: FlowLogicRefFactory lateinit var schemas: SchemaService val customServices: ArrayList = ArrayList() protected val runOnStop: ArrayList = ArrayList() @@ -204,8 +204,8 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo // the identity key. But the infrastructure to make that easy isn't here yet. keyManagement = makeKeyManagementService() api = APIServerImpl(this@AbstractNode) - protocolLogicFactory = initialiseProtocolLogicFactory() - scheduler = NodeSchedulerService(database, services, protocolLogicFactory) + flowLogicFactory = initialiseFlowLogicFactory() + scheduler = NodeSchedulerService(database, services, flowLogicFactory) val tokenizableServices = mutableListOf(storage, net, vault, keyManagement, identity, platformClock, scheduler) @@ -309,31 +309,32 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo } } - private val defaultProtocolWhiteList: Map>, Set>> = mapOf( - CashProtocol::class.java to setOf( + private val defaultFlowWhiteList: Map>, Set>> = mapOf( + CashFlow::class.java to setOf( CashCommand.IssueCash::class.java, CashCommand.PayCash::class.java, CashCommand.ExitCash::class.java ) ) - private fun initialiseProtocolLogicFactory(): ProtocolLogicRefFactory { - val protocolWhitelist = HashMap>() - for ((protocolClass, extraArgumentTypes) in defaultProtocolWhiteList) { + private fun initialiseFlowLogicFactory(): FlowLogicRefFactory { + val flowWhitelist = HashMap>() + + for ((flowClass, extraArgumentTypes) in defaultFlowWhiteList) { val argumentWhitelistClassNames = HashSet(extraArgumentTypes.map { it.name }) - protocolClass.constructors.forEach { + flowClass.constructors.forEach { it.parameters.mapTo(argumentWhitelistClassNames) { it.type.name } } - protocolWhitelist.merge(protocolClass.name, argumentWhitelistClassNames, { x, y -> x + y }) + flowWhitelist.merge(flowClass.name, argumentWhitelistClassNames, { x, y -> x + y }) } for (plugin in pluginRegistries) { - for ((className, classWhitelist) in plugin.requiredProtocols) { - protocolWhitelist.merge(className, classWhitelist, { x, y -> x + y }) + for ((className, classWhitelist) in plugin.requiredFlows) { + flowWhitelist.merge(className, classWhitelist, { x, y -> x + y }) } } - return ProtocolLogicRefFactory(protocolWhitelist) + return FlowLogicRefFactory(flowWhitelist) } private fun buildPluginServices(tokenizableServices: MutableList): List { @@ -406,7 +407,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo val reg = NodeRegistration(info, instant.toEpochMilli(), type, expires) val legalIdentityKey = obtainLegalIdentityKey() val request = NetworkMapService.RegistrationRequest(reg.toWire(legalIdentityKey.private), net.myAddress) - return net.sendRequest(REGISTER_PROTOCOL_TOPIC, request, networkMapAddr) + return net.sendRequest(REGISTER_FLOW_TOPIC, request, networkMapAddr) } protected open fun makeKeyManagementService(): KeyManagementService = PersistentKeyManagementService(partyKeys) diff --git a/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt b/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt index 1cce20bbd1..f9d863496d 100644 --- a/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt +++ b/node/src/main/kotlin/net/corda/node/internal/CordaRPCOpsImpl.kt @@ -3,20 +3,18 @@ package net.corda.node.internal import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.keys -import net.corda.core.crypto.toStringShort +import net.corda.core.flows.FlowLogic import net.corda.core.node.NodeInfo import net.corda.core.node.ServiceHub import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.StateMachineTransactionMapping import net.corda.core.node.services.Vault -import net.corda.core.protocols.ProtocolLogic import net.corda.core.toObservable import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker import net.corda.node.services.messaging.* -import net.corda.node.services.startProtocolPermission -import net.corda.node.services.statemachine.ProtocolStateMachineImpl +import net.corda.node.services.startFlowPermission +import net.corda.node.services.statemachine.FlowStateMachineImpl import net.corda.node.services.statemachine.StateMachineManager import net.corda.node.utilities.databaseTransaction import org.jetbrains.exposed.sql.Database @@ -52,7 +50,7 @@ class CordaRPCOpsImpl( override fun stateMachinesAndUpdates(): Pair, Observable> { val (allStateMachines, changes) = smm.track() return Pair( - allStateMachines.map { StateMachineInfo.fromProtocolStateMachineImpl(it) }, + allStateMachines.map { StateMachineInfo.fromFlowStateMachineImpl(it) }, changes.map { StateMachineUpdate.fromStateMachineChange(it) } ) } @@ -79,11 +77,11 @@ class CordaRPCOpsImpl( } } - // TODO: Check that this protocol is annotated as being intended for RPC invocation - override fun startProtocolDynamic(logicType: Class>, vararg args: Any?): ProtocolHandle { - requirePermission(startProtocolPermission(logicType)) - val stateMachine = services.invokeProtocolAsync(logicType, *args) as ProtocolStateMachineImpl - return ProtocolHandle( + // TODO: Check that this flow is annotated as being intended for RPC invocation + override fun startFlowDynamic(logicType: Class>, vararg args: Any?): FlowHandle { + requirePermission(startFlowPermission(logicType)) + val stateMachine = services.invokeFlowAsync(logicType, *args) as FlowStateMachineImpl + return FlowHandle( id = stateMachine.id, progress = stateMachine.logic.progressTracker?.changes ?: Observable.empty(), returnValue = stateMachine.resultFuture.toObservable() diff --git a/node/src/main/kotlin/net/corda/node/internal/Node.kt b/node/src/main/kotlin/net/corda/node/internal/Node.kt index 0d370f3fbd..65dfc1c49e 100644 --- a/node/src/main/kotlin/net/corda/node/internal/Node.kt +++ b/node/src/main/kotlin/net/corda/node/internal/Node.kt @@ -61,7 +61,7 @@ class ConfigurationException(message: String) : Exception(message) * network map service, while bootstrapping a network. * @param advertisedServices The services this node advertises. This must be a subset of the services it runs, * but nodes are not required to advertise services they run (hence subset). - * @param clock The clock used within the node and by all protocols etc. + * @param clock The clock used within the node and by all flows etc. */ class Node(override val configuration: FullNodeConfiguration, networkMapAddress: SingleMessageRecipient?, advertisedServices: Set, clock: Clock = NodeClock()) : AbstractNode(configuration, networkMapAddress, advertisedServices, clock) { @@ -102,7 +102,7 @@ class Node(override val configuration: FullNodeConfiguration, networkMapAddress: // layer, which can then react to the backpressure. Artemis MQ in particular knows how to do flow control by paging // messages to disk rather than letting us run out of RAM. // - // The primary work done by the server thread is execution of protocol logics, and related + // The primary work done by the server thread is execution of flow logics, and related // serialisation/deserialisation work. override val serverThread = AffinityExecutor.ServiceAffinityExecutor("Node thread", 1) diff --git a/node/src/main/kotlin/net/corda/node/services/NotaryChangeService.kt b/node/src/main/kotlin/net/corda/node/services/NotaryChangeService.kt index 1b46765487..f6954cab6c 100644 --- a/node/src/main/kotlin/net/corda/node/services/NotaryChangeService.kt +++ b/node/src/main/kotlin/net/corda/node/services/NotaryChangeService.kt @@ -3,8 +3,7 @@ package net.corda.node.services import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.PluginServiceHub import net.corda.core.serialization.SingletonSerializeAsToken -import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.NotaryChangeProtocol +import net.corda.flows.NotaryChangeFlow object NotaryChange { class Plugin : CordaPluginRegistry() { @@ -13,11 +12,11 @@ object NotaryChange { /** * A service that monitors the network for requests for changing the notary of a state, - * and immediately runs the [NotaryChangeProtocol] if the auto-accept criteria are met. + * and immediately runs the [NotaryChangeFlow] if the auto-accept criteria are met. */ class Service(services: PluginServiceHub) : SingletonSerializeAsToken() { init { - services.registerProtocolInitiator(NotaryChangeProtocol.Instigator::class) { NotaryChangeProtocol.Acceptor(it) } + services.registerFlowInitiator(NotaryChangeFlow.Instigator::class) { NotaryChangeFlow.Acceptor(it) } } } } diff --git a/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt b/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt index d69c6c56e3..ae9e004258 100644 --- a/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt +++ b/node/src/main/kotlin/net/corda/node/services/RPCUserService.kt @@ -1,7 +1,7 @@ package net.corda.node.services import com.typesafe.config.Config -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import net.corda.node.services.config.getListOrElse /** @@ -41,5 +41,5 @@ data class User(val username: String, val password: String, val permissions: Set override fun toString(): String = "${javaClass.simpleName}($username, permissions=$permissions)" } -fun

> startProtocolPermission(clazz: Class

) = "StartProtocol.${clazz.name}" -inline fun > startProtocolPermission(): String = startProtocolPermission(P::class.java) +fun

> startFlowPermission(clazz: Class

) = "StartFlow.${clazz.name}" +inline fun > startFlowPermission(): String = startFlowPermission(P::class.java) diff --git a/node/src/main/kotlin/net/corda/node/services/api/AbstractNodeService.kt b/node/src/main/kotlin/net/corda/node/services/api/AbstractNodeService.kt index 9ea584162f..1640567e64 100644 --- a/node/src/main/kotlin/net/corda/node/services/api/AbstractNodeService.kt +++ b/node/src/main/kotlin/net/corda/node/services/api/AbstractNodeService.kt @@ -7,7 +7,7 @@ import net.corda.core.node.services.DEFAULT_SESSION_ID import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize -import net.corda.protocols.ServiceRequestMessage +import net.corda.flows.ServiceRequestMessage import javax.annotation.concurrent.ThreadSafe /** diff --git a/node/src/main/kotlin/net/corda/node/services/api/CheckpointStorage.kt b/node/src/main/kotlin/net/corda/node/services/api/CheckpointStorage.kt index abd67cfa94..c4042ed82e 100644 --- a/node/src/main/kotlin/net/corda/node/services/api/CheckpointStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/api/CheckpointStorage.kt @@ -2,7 +2,7 @@ package net.corda.node.services.api import net.corda.core.crypto.SecureHash import net.corda.core.serialization.SerializedBytes -import net.corda.node.services.statemachine.ProtocolStateMachineImpl +import net.corda.node.services.statemachine.FlowStateMachineImpl /** * Thread-safe storage of fiber checkpoints. @@ -30,7 +30,7 @@ interface CheckpointStorage { } // This class will be serialised, so everything it points to transitively must also be serialisable (with Kryo). -class Checkpoint(val serializedFiber: SerializedBytes>) { +class Checkpoint(val serializedFiber: SerializedBytes>) { val id: SecureHash get() = serializedFiber.hash diff --git a/node/src/main/kotlin/net/corda/node/services/api/ServiceHubInternal.kt b/node/src/main/kotlin/net/corda/node/services/api/ServiceHubInternal.kt index 28564a8614..1a9c5a9a48 100644 --- a/node/src/main/kotlin/net/corda/node/services/api/ServiceHubInternal.kt +++ b/node/src/main/kotlin/net/corda/node/services/api/ServiceHubInternal.kt @@ -1,14 +1,14 @@ package net.corda.node.services.api import com.google.common.util.concurrent.ListenableFuture +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.flows.FlowStateMachine import net.corda.core.messaging.MessagingService import net.corda.core.node.PluginServiceHub import net.corda.core.node.services.TxWritableStorageService -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolLogicRefFactory -import net.corda.core.protocols.ProtocolStateMachine import net.corda.core.transactions.SignedTransaction -import net.corda.node.services.statemachine.ProtocolStateMachineImpl +import net.corda.node.services.statemachine.FlowStateMachineImpl import org.slf4j.LoggerFactory interface MessagingServiceInternal : MessagingService { @@ -38,7 +38,7 @@ private val log = LoggerFactory.getLogger(ServiceHubInternal::class.java) abstract class ServiceHubInternal : PluginServiceHub { abstract val monitoringService: MonitoringService - abstract val protocolLogicRefFactory: ProtocolLogicRefFactory + abstract val flowLogicRefFactory: FlowLogicRefFactory abstract val schemaService: SchemaService abstract override val networkService: MessagingServiceInternal @@ -51,7 +51,7 @@ abstract class ServiceHubInternal : PluginServiceHub { * @param txs The transactions to record. */ internal fun recordTransactionsInternal(writableStorageService: TxWritableStorageService, txs: Iterable) { - val stateMachineRunId = ProtocolStateMachineImpl.currentStateMachine()?.id + val stateMachineRunId = FlowStateMachineImpl.currentStateMachine()?.id if (stateMachineRunId != null) { txs.forEach { storageService.stateMachineRecordedTransactionMapping.addMapping(stateMachineRunId, it.id) @@ -68,12 +68,12 @@ abstract class ServiceHubInternal : PluginServiceHub { * between SMM and the scheduler. That particular problem should also be resolved by the service manager work * itself, at which point this method would not be needed (by the scheduler). */ - abstract fun startProtocol(logic: ProtocolLogic): ProtocolStateMachine + abstract fun startFlow(logic: FlowLogic): FlowStateMachine - override fun invokeProtocolAsync(logicType: Class>, vararg args: Any?): ProtocolStateMachine { - val logicRef = protocolLogicRefFactory.create(logicType, *args) + override fun invokeFlowAsync(logicType: Class>, vararg args: Any?): FlowStateMachine { + val logicRef = flowLogicRefFactory.create(logicType, *args) @Suppress("UNCHECKED_CAST") - val logic = protocolLogicRefFactory.toProtocolLogic(logicRef) as ProtocolLogic - return startProtocol(logic) + val logic = flowLogicRefFactory.toFlowLogic(logicRef) as FlowLogic + return startFlow(logic) } } diff --git a/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt b/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt index 6e0316e6b2..9bc65d7d71 100644 --- a/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt +++ b/node/src/main/kotlin/net/corda/node/services/events/NodeSchedulerService.kt @@ -2,21 +2,21 @@ package net.corda.node.services.events import co.paralleluniverse.fibers.Suspendable import com.google.common.util.concurrent.SettableFuture +import kotlinx.support.jdk8.collections.compute import net.corda.core.ThreadBox import net.corda.core.contracts.SchedulableState import net.corda.core.contracts.ScheduledActivity import net.corda.core.contracts.ScheduledStateRef import net.corda.core.contracts.StateRef +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.node.services.SchedulerService -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolLogicRefFactory import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.loggerFor import net.corda.core.utilities.trace import net.corda.node.services.api.ServiceHubInternal import net.corda.node.utilities.* -import kotlinx.support.jdk8.collections.compute import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.statements.InsertStatement @@ -38,14 +38,14 @@ import javax.annotation.concurrent.ThreadSafe * but that starts to sound a lot like off-ledger state. * * @param services Core node services. - * @param protocolLogicRefFactory Factory for restoring [ProtocolLogic] instances from references. + * @param flowLogicRefFactory Factory for restoring [FlowLogic] instances from references. * @param schedulerTimerExecutor The executor the scheduler blocks on waiting for the clock to advance to the next - * activity. Only replace this for unit testing purposes. This is not the executor the [ProtocolLogic] is launched on. + * activity. Only replace this for unit testing purposes. This is not the executor the [FlowLogic] is launched on. */ @ThreadSafe class NodeSchedulerService(private val database: Database, private val services: ServiceHubInternal, - private val protocolLogicRefFactory: ProtocolLogicRefFactory, + private val flowLogicRefFactory: FlowLogicRefFactory, private val schedulerTimerExecutor: Executor = Executors.newSingleThreadExecutor()) : SchedulerService, SingletonSerializeAsToken() { @@ -87,7 +87,7 @@ class NodeSchedulerService(private val database: Database, private val mutex = ThreadBox(InnerState()) - // We need the [StateMachineManager] to be constructed before this is called in case it schedules a protocol. + // We need the [StateMachineManager] to be constructed before this is called in case it schedules a flow. fun start() { mutex.locked { recomputeEarliest() @@ -152,10 +152,10 @@ class NodeSchedulerService(private val database: Database, } private fun onTimeReached(scheduledState: ScheduledStateRef) { - services.startProtocol(RunScheduled(scheduledState, this@NodeSchedulerService)) + services.startFlow(RunScheduled(scheduledState, this@NodeSchedulerService)) } - class RunScheduled(val scheduledState: ScheduledStateRef, val scheduler: NodeSchedulerService) : ProtocolLogic() { + class RunScheduled(val scheduledState: ScheduledStateRef, val scheduler: NodeSchedulerService) : FlowLogic() { companion object { object RUNNING : ProgressTracker.Step("Running scheduled...") @@ -169,9 +169,9 @@ class NodeSchedulerService(private val database: Database, progressTracker.currentStep = RUNNING // Ensure we are still scheduled. - val scheduledLogic: ProtocolLogic<*>? = getScheduledLogic() + val scheduledLogic: FlowLogic<*>? = getScheduledLogic() if(scheduledLogic != null) { - subProtocol(scheduledLogic) + subFlow(scheduledLogic) } } @@ -180,16 +180,16 @@ class NodeSchedulerService(private val database: Database, val state = txState.data as SchedulableState return try { // This can throw as running contract code. - state.nextScheduledActivity(scheduledState.ref, scheduler.protocolLogicRefFactory) + state.nextScheduledActivity(scheduledState.ref, scheduler.flowLogicRefFactory) } catch(e: Exception) { logger.error("Attempt to run scheduled state $scheduledState resulted in error.", e) null } } - private fun getScheduledLogic(): ProtocolLogic<*>? { + private fun getScheduledLogic(): FlowLogic<*>? { val scheduledActivity = getScheduledaActivity() - var scheduledLogic: ProtocolLogic<*>? = null + var scheduledLogic: FlowLogic<*>? = null scheduler.mutex.locked { // need to remove us from those scheduled, but only if we are still next scheduledStates.compute(scheduledState.ref) { ref, value -> @@ -201,11 +201,11 @@ class NodeSchedulerService(private val database: Database, logger.info("Scheduled state $scheduledState has rescheduled to ${scheduledActivity.scheduledAt}.") ScheduledStateRef(scheduledState.ref, scheduledActivity.scheduledAt) } else { - // TODO: ProtocolLogicRefFactory needs to sort out the class loader etc - val logic = scheduler.protocolLogicRefFactory.toProtocolLogic(scheduledActivity.logicRef) - logger.trace { "Scheduler starting ProtocolLogic $logic" } - // ProtocolLogic will be checkpointed by the time this returns. - //scheduler.services.startProtocolAndForget(logic) + // TODO: FlowLogicRefFactory needs to sort out the class loader etc + val logic = scheduler.flowLogicRefFactory.toFlowLogic(scheduledActivity.logicRef) + logger.trace { "Scheduler starting FlowLogic $logic" } + // FlowLogic will be checkpointed by the time this returns. + //scheduler.services.startFlowAndForget(logic) scheduledLogic = logic null } diff --git a/node/src/main/kotlin/net/corda/node/services/events/ScheduledActivityObserver.kt b/node/src/main/kotlin/net/corda/node/services/events/ScheduledActivityObserver.kt index 70c81b07d9..5a2acb09d2 100644 --- a/node/src/main/kotlin/net/corda/node/services/events/ScheduledActivityObserver.kt +++ b/node/src/main/kotlin/net/corda/node/services/events/ScheduledActivityObserver.kt @@ -4,7 +4,7 @@ import net.corda.core.contracts.ContractState import net.corda.core.contracts.SchedulableState import net.corda.core.contracts.ScheduledStateRef import net.corda.core.contracts.StateAndRef -import net.corda.core.protocols.ProtocolLogicRefFactory +import net.corda.core.flows.FlowLogicRefFactory import net.corda.node.services.api.ServiceHubInternal /** @@ -15,14 +15,14 @@ class ScheduledActivityObserver(val services: ServiceHubInternal) { init { services.vaultService.updates.subscribe { update -> update.consumed.forEach { services.schedulerService.unscheduleStateActivity(it) } - update.produced.forEach { scheduleStateActivity(it, services.protocolLogicRefFactory) } + update.produced.forEach { scheduleStateActivity(it, services.flowLogicRefFactory) } } } - private fun scheduleStateActivity(produced: StateAndRef, protocolLogicRefFactory: ProtocolLogicRefFactory) { + private fun scheduleStateActivity(produced: StateAndRef, flowLogicRefFactory: FlowLogicRefFactory) { val producedState = produced.state.data if (producedState is SchedulableState) { - val scheduledAt = sandbox { producedState.nextScheduledActivity(produced.ref, protocolLogicRefFactory)?.scheduledAt } ?: return + val scheduledAt = sandbox { producedState.nextScheduledActivity(produced.ref, flowLogicRefFactory)?.scheduledAt } ?: return services.schedulerService.scheduleStateActivity(ScheduledStateRef(produced.ref, scheduledAt)) } } diff --git a/node/src/main/kotlin/net/corda/node/services/keys/E2ETestKeyManagementService.kt b/node/src/main/kotlin/net/corda/node/services/keys/E2ETestKeyManagementService.kt index 870094ba28..67f48ec567 100644 --- a/node/src/main/kotlin/net/corda/node/services/keys/E2ETestKeyManagementService.kt +++ b/node/src/main/kotlin/net/corda/node/services/keys/E2ETestKeyManagementService.kt @@ -15,7 +15,7 @@ import javax.annotation.concurrent.ThreadSafe * * - Probably be accessed via the network layer as an internal node service i.e. via a message queue, so it can run * on a separate/firewalled service. - * - Use the protocol framework so requests to fetch keys can be suspended whilst a human signs off on the request. + * - Use the flow framework so requests to fetch keys can be suspended whilst a human signs off on the request. * - Use deterministic key derivation. * - Possibly have some sort of TREZOR-like two-factor authentication ability. * diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt index b6e098030e..9948d215a9 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt @@ -158,7 +158,7 @@ class ArtemisMessagingServer(override val config: NodeConfiguration, log.error("Queue created for a peer that we don't know from the network map: $queueName") } } catch (e: AddressFormatException) { - log.error("Protocol violation: Could not parse queue name as Base 58: $queueName") + log.error("Flow violation: Could not parse queue name as Base 58: $queueName") } } } diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/CordaRPCOps.kt b/node/src/main/kotlin/net/corda/node/services/messaging/CordaRPCOps.kt index d5e4f4b856..c9afdd6117 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/CordaRPCOps.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/CordaRPCOps.kt @@ -3,29 +3,29 @@ package net.corda.node.services.messaging import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.crypto.SecureHash +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.NodeInfo import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.StateMachineTransactionMapping import net.corda.core.node.services.Vault -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.StateMachineRunId import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker -import net.corda.node.services.statemachine.ProtocolStateMachineImpl +import net.corda.node.services.statemachine.FlowStateMachineImpl import net.corda.node.services.statemachine.StateMachineManager import net.corda.node.utilities.AddOrRemove import rx.Observable data class StateMachineInfo( val id: StateMachineRunId, - val protocolLogicClassName: String, + val flowLogicClassName: String, val progressTrackerStepAndUpdates: Pair>? ) { companion object { - fun fromProtocolStateMachineImpl(psm: ProtocolStateMachineImpl<*>): StateMachineInfo { + fun fromFlowStateMachineImpl(psm: FlowStateMachineImpl<*>): StateMachineInfo { return StateMachineInfo( id = psm.id, - protocolLogicClassName = psm.logic.javaClass.simpleName, + flowLogicClassName = psm.logic.javaClass.simpleName, progressTrackerStepAndUpdates = psm.logic.track() ) } @@ -42,7 +42,7 @@ sealed class StateMachineUpdate(val id: StateMachineRunId) { AddOrRemove.ADD -> { val stateMachineInfo = StateMachineInfo( id = change.id, - protocolLogicClassName = change.logic.javaClass.simpleName, + flowLogicClassName = change.logic.javaClass.simpleName, progressTrackerStepAndUpdates = change.logic.track() ) StateMachineUpdate.Added(stateMachineInfo) @@ -92,11 +92,11 @@ interface CordaRPCOps : RPCOps { fun networkMapUpdates(): Pair, Observable> /** - * Start the given protocol with the given arguments, returning an [Observable] with a single observation of the - * result of running the protocol. + * Start the given flow with the given arguments, returning an [Observable] with a single observation of the + * result of running the flow. */ @RPCReturnsObservables - fun startProtocolDynamic(logicType: Class>, vararg args: Any?): ProtocolHandle + fun startFlowDynamic(logicType: Class>, vararg args: Any?): FlowHandle /** * Returns Node's identity, assuming this will not change while the node is running. @@ -115,46 +115,50 @@ interface CordaRPCOps : RPCOps { } /** - * These allow type safe invocations of protocols from Kotlin, e.g.: + * These allow type safe invocations of flows from Kotlin, e.g.: * * val rpc: CordaRPCOps = (..) - * rpc.startProtocol(::ResolveTransactionsProtocol, setOf(), aliceIdentity) + * rpc.startFlow(::ResolveTransactionsFlow, setOf(), aliceIdentity) * * Note that the passed in constructor function is only used for unification of other type parameters and reification of - * the Class instance of the protocol. This could be changed to use the constructor function directly. + * the Class instance of the flow. This could be changed to use the constructor function directly. */ -inline fun > CordaRPCOps.startProtocol( +inline fun > CordaRPCOps.startFlow( @Suppress("UNUSED_PARAMETER") - protocolConstructor: () -> R -) = startProtocolDynamic(R::class.java) -inline fun > CordaRPCOps.startProtocol( + flowConstructor: () -> R +) = startFlowDynamic(R::class.java) + +inline fun > CordaRPCOps.startFlow( @Suppress("UNUSED_PARAMETER") - protocolConstructor: (A) -> R, + flowConstructor: (A) -> R, arg0: A -) = startProtocolDynamic(R::class.java, arg0) -inline fun > CordaRPCOps.startProtocol( +) = startFlowDynamic(R::class.java, arg0) + +inline fun > CordaRPCOps.startFlow( @Suppress("UNUSED_PARAMETER") - protocolConstructor: (A, B) -> R, + flowConstructor: (A, B) -> R, arg0: A, arg1: B -) = startProtocolDynamic(R::class.java, arg0, arg1) -inline fun > CordaRPCOps.startProtocol( +) = startFlowDynamic(R::class.java, arg0, arg1) + +inline fun > CordaRPCOps.startFlow( @Suppress("UNUSED_PARAMETER") - protocolConstructor: (A, B, C) -> R, + flowConstructor: (A, B, C) -> R, arg0: A, arg1: B, arg2: C -) = startProtocolDynamic(R::class.java, arg0, arg1, arg2) -inline fun > CordaRPCOps.startProtocol( +) = startFlowDynamic(R::class.java, arg0, arg1, arg2) + +inline fun > CordaRPCOps.startFlow( @Suppress("UNUSED_PARAMETER") - protocolConstructor: (A, B, C, D) -> R, + flowConstructor: (A, B, C, D) -> R, arg0: A, arg1: B, arg2: C, arg3: D -) = startProtocolDynamic(R::class.java, arg0, arg1, arg2, arg3) +) = startFlowDynamic(R::class.java, arg0, arg1, arg2, arg3) -data class ProtocolHandle( +data class FlowHandle( val id: StateMachineRunId, val progress: Observable, val returnValue: Observable diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt b/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt index a3dd5b8415..380d4b7e8c 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/RPCStructures.kt @@ -19,14 +19,14 @@ import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.* import net.corda.core.node.services.* -import net.corda.core.protocols.StateMachineRunId import net.corda.core.serialization.* import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction +import net.corda.flows.CashFlowResult import net.corda.node.services.User -import net.corda.protocols.CashProtocolResult import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.EdDSAPublicKey import org.apache.activemq.artemis.api.core.SimpleString @@ -181,8 +181,8 @@ private class RPCKryo(observableSerializer: Serializer>? = null) register(Cash.Clauses.ConserveAmount::class.java) register(listOf(Unit).javaClass) // SingletonList register(setOf(Unit).javaClass) // SingletonSet - register(CashProtocolResult.Success::class.java) - register(CashProtocolResult.Failed::class.java) + register(CashFlowResult.Success::class.java) + register(CashFlowResult.Failed::class.java) register(ServiceEntry::class.java) register(NodeInfo::class.java) register(PhysicalLocation::class.java) @@ -215,7 +215,7 @@ private class RPCKryo(observableSerializer: Serializer>? = null) register(Array::class.java, read = { kryo, input -> emptyArray() }, write = { kryo, output, o -> }) register(Collections.unmodifiableList(emptyList()).javaClass) register(PermissionException::class.java) - register(ProtocolHandle::class.java) + register(FlowHandle::class.java) register(KryoException::class.java) register(StringBuffer::class.java) pluginRegistries.forEach { it.registerRPCKryoTypes(this) } diff --git a/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt b/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt index f78f1ece4c..a6dd063489 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt @@ -22,12 +22,12 @@ import net.corda.core.randomOrNull import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize -import net.corda.node.services.network.NetworkMapService.Companion.FETCH_PROTOCOL_TOPIC -import net.corda.node.services.network.NetworkMapService.Companion.SUBSCRIPTION_PROTOCOL_TOPIC +import net.corda.flows.sendRequest +import net.corda.node.services.network.NetworkMapService.Companion.FETCH_FLOW_TOPIC +import net.corda.node.services.network.NetworkMapService.Companion.SUBSCRIPTION_FLOW_TOPIC import net.corda.node.services.network.NetworkMapService.FetchMapResponse import net.corda.node.services.network.NetworkMapService.SubscribeResponse import net.corda.node.utilities.AddOrRemove -import net.corda.protocols.sendRequest import rx.Observable import rx.subjects.PublishSubject import java.security.SignatureException @@ -106,10 +106,10 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach ifChangedSinceVer: Int?): ListenableFuture { if (subscribe && !registeredForPush) { // Add handler to the network, for updates received from the remote network map service. - net.addMessageHandler(NetworkMapService.PUSH_PROTOCOL_TOPIC, DEFAULT_SESSION_ID) { message, r -> + net.addMessageHandler(NetworkMapService.PUSH_FLOW_TOPIC, DEFAULT_SESSION_ID) { message, r -> try { val req = message.data.deserialize() - val ackMessage = net.createMessage(NetworkMapService.PUSH_ACK_PROTOCOL_TOPIC, DEFAULT_SESSION_ID, + val ackMessage = net.createMessage(NetworkMapService.PUSH_ACK_FLOW_TOPIC, DEFAULT_SESSION_ID, NetworkMapService.UpdateAcknowledge(req.mapVersion, net.myAddress).serialize().bytes) net.send(ackMessage, req.replyTo) processUpdatePush(req) @@ -124,7 +124,7 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach // Fetch the network map and register for updates at the same time val req = NetworkMapService.FetchMapRequest(subscribe, ifChangedSinceVer, net.myAddress) - val future = net.sendRequest(FETCH_PROTOCOL_TOPIC, req, networkMapAddress).map { resp -> + val future = net.sendRequest(FETCH_FLOW_TOPIC, req, networkMapAddress).map { resp -> // We may not receive any nodes back, if the map hasn't changed since the version specified resp.nodes?.forEach { processRegistration(it) } Unit @@ -161,7 +161,7 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach override fun deregisterForUpdates(net: MessagingService, service: NodeInfo): ListenableFuture { // Fetch the network map and register for updates at the same time val req = NetworkMapService.SubscribeRequest(false, net.myAddress) - val future = net.sendRequest(SUBSCRIPTION_PROTOCOL_TOPIC, req, service.address).map { + val future = net.sendRequest(SUBSCRIPTION_FLOW_TOPIC, req, service.address).map { if (it.confirmed) Unit else throw NetworkCacheError.DeregistrationFailed() } _registrationFuture.setFuture(future) diff --git a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt index ceacaa7c95..6bf695a978 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/NetworkMapService.kt @@ -20,10 +20,10 @@ import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize import net.corda.core.utilities.loggerFor +import net.corda.flows.ServiceRequestMessage import net.corda.node.services.api.AbstractNodeService import net.corda.node.services.api.ServiceHubInternal import net.corda.node.utilities.AddOrRemove -import net.corda.protocols.ServiceRequestMessage import java.security.PrivateKey import java.security.SignatureException import java.time.Instant @@ -51,15 +51,15 @@ interface NetworkMapService { companion object { val DEFAULT_EXPIRATION_PERIOD = Period.ofWeeks(4) - val FETCH_PROTOCOL_TOPIC = "platform.network_map.fetch" - val QUERY_PROTOCOL_TOPIC = "platform.network_map.query" - val REGISTER_PROTOCOL_TOPIC = "platform.network_map.register" - val SUBSCRIPTION_PROTOCOL_TOPIC = "platform.network_map.subscribe" + val FETCH_FLOW_TOPIC = "platform.network_map.fetch" + val QUERY_FLOW_TOPIC = "platform.network_map.query" + val REGISTER_FLOW_TOPIC = "platform.network_map.register" + val SUBSCRIPTION_FLOW_TOPIC = "platform.network_map.subscribe" // Base topic used when pushing out updates to the network map. Consumed, for example, by the map cache. // When subscribing to these updates, remember they must be acknowledged - val PUSH_PROTOCOL_TOPIC = "platform.network_map.push" + val PUSH_FLOW_TOPIC = "platform.network_map.push" // Base topic for messages acknowledging pushed updates - val PUSH_ACK_PROTOCOL_TOPIC = "platform.network_map.push_ack" + val PUSH_ACK_FLOW_TOPIC = "platform.network_map.push_ack" val logger = loggerFor() @@ -142,19 +142,19 @@ abstract class AbstractNetworkMapService protected fun setup() { // Register message handlers - handlers += addMessageHandler(NetworkMapService.FETCH_PROTOCOL_TOPIC, + handlers += addMessageHandler(NetworkMapService.FETCH_FLOW_TOPIC, { req: NetworkMapService.FetchMapRequest -> processFetchAllRequest(req) } ) - handlers += addMessageHandler(NetworkMapService.QUERY_PROTOCOL_TOPIC, + handlers += addMessageHandler(NetworkMapService.QUERY_FLOW_TOPIC, { req: NetworkMapService.QueryIdentityRequest -> processQueryRequest(req) } ) - handlers += addMessageHandler(NetworkMapService.REGISTER_PROTOCOL_TOPIC, + handlers += addMessageHandler(NetworkMapService.REGISTER_FLOW_TOPIC, { req: NetworkMapService.RegistrationRequest -> processRegistrationChangeRequest(req) } ) - handlers += addMessageHandler(NetworkMapService.SUBSCRIPTION_PROTOCOL_TOPIC, + handlers += addMessageHandler(NetworkMapService.SUBSCRIPTION_FLOW_TOPIC, { req: NetworkMapService.SubscribeRequest -> processSubscriptionRequest(req) } ) - handlers += net.addMessageHandler(NetworkMapService.PUSH_ACK_PROTOCOL_TOPIC, DEFAULT_SESSION_ID) { message, r -> + handlers += net.addMessageHandler(NetworkMapService.PUSH_ACK_FLOW_TOPIC, DEFAULT_SESSION_ID) { message, r -> val req = message.data.deserialize() processAcknowledge(req) } @@ -200,7 +200,7 @@ abstract class AbstractNetworkMapService // to a MessageRecipientGroup that nodes join/leave, rather than the network map // service itself managing the group val update = NetworkMapService.Update(wireReg, mapVersion, net.myAddress).serialize().bytes - val message = net.createMessage(NetworkMapService.PUSH_PROTOCOL_TOPIC, DEFAULT_SESSION_ID, update) + val message = net.createMessage(NetworkMapService.PUSH_FLOW_TOPIC, DEFAULT_SESSION_ID, update) subscribers.locked { val toRemove = mutableListOf() diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt index 887586f69a..ee4e962c94 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt @@ -3,9 +3,9 @@ package net.corda.node.services.persistence import net.corda.core.ThreadBox import net.corda.core.bufferUntilSubscribed import net.corda.core.crypto.SecureHash +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.services.StateMachineRecordedTransactionMappingStorage import net.corda.core.node.services.StateMachineTransactionMapping -import net.corda.core.protocols.StateMachineRunId import net.corda.node.utilities.* import org.jetbrains.exposed.sql.ResultRow import org.jetbrains.exposed.sql.statements.InsertStatement @@ -17,7 +17,7 @@ import javax.annotation.concurrent.ThreadSafe * Database storage of a txhash -> state machine id mapping. * * Mappings are added as transactions are persisted by [ServiceHub.recordTransaction], and never deleted. Used in the - * RPC API to correlate transaction creation with protocols. + * RPC API to correlate transaction creation with flows. * */ @ThreadSafe diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DataVendingService.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DataVendingService.kt index f048f22e70..7f6f559014 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DataVendingService.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DataVendingService.kt @@ -2,14 +2,13 @@ package net.corda.node.services.persistence import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.PluginServiceHub import net.corda.core.node.recordTransactions -import net.corda.core.protocols.ProtocolLogic import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.loggerFor -import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.* +import net.corda.flows.* import java.io.InputStream import javax.annotation.concurrent.ThreadSafe @@ -41,16 +40,16 @@ object DataVending { class TransactionRejectedError(msg: String) : Exception(msg) init { - services.registerProtocolInitiator(FetchTransactionsProtocol::class, ::FetchTransactionsHandler) - services.registerProtocolInitiator(FetchAttachmentsProtocol::class, ::FetchAttachmentsHandler) - services.registerProtocolInitiator(BroadcastTransactionProtocol::class, ::NotifyTransactionHandler) + services.registerFlowInitiator(FetchTransactionsFlow::class, ::FetchTransactionsHandler) + services.registerFlowInitiator(FetchAttachmentsFlow::class, ::FetchAttachmentsHandler) + services.registerFlowInitiator(BroadcastTransactionFlow::class, ::NotifyTransactionHandler) } - private class FetchTransactionsHandler(val otherParty: Party) : ProtocolLogic() { + private class FetchTransactionsHandler(val otherParty: Party) : FlowLogic() { @Suspendable override fun call() { - val request = receive(otherParty).unwrap { + val request = receive(otherParty).unwrap { require(it.hashes.isNotEmpty()) it } @@ -66,10 +65,10 @@ object DataVending { // TODO: Use Artemis message streaming support here, called "large messages". This avoids the need to buffer. - private class FetchAttachmentsHandler(val otherParty: Party) : ProtocolLogic() { + private class FetchAttachmentsHandler(val otherParty: Party) : FlowLogic() { @Suspendable override fun call() { - val request = receive(otherParty).unwrap { + val request = receive(otherParty).unwrap { require(it.hashes.isNotEmpty()) it } @@ -91,11 +90,11 @@ object DataVending { // includes us in any outside that list. Potentially just if it includes any outside that list at all. // TODO: Do we want to be able to reject specific transactions on more complex rules, for example reject incoming // cash without from unknown parties? - class NotifyTransactionHandler(val otherParty: Party) : ProtocolLogic() { + class NotifyTransactionHandler(val otherParty: Party) : FlowLogic() { @Suspendable override fun call() { - val request = receive(otherParty).unwrap { it } - subProtocol(ResolveTransactionsProtocol(request.tx, otherParty), shareParentSessions = true) + val request = receive(otherParty).unwrap { it } + subFlow(ResolveTransactionsFlow(request.tx, otherParty), shareParentSessions = true) serviceHub.recordTransactions(request.tx) } } diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt index 48173d3123..eccd071b1b 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt @@ -5,7 +5,7 @@ import net.corda.core.bufferUntilSubscribed import net.corda.core.crypto.SecureHash import net.corda.core.node.services.StateMachineRecordedTransactionMappingStorage import net.corda.core.node.services.StateMachineTransactionMapping -import net.corda.core.protocols.StateMachineRunId +import net.corda.core.flows.StateMachineRunId import rx.Observable import rx.subjects.PublishSubject import java.util.* diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolStateMachineImpl.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt similarity index 79% rename from node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolStateMachineImpl.kt rename to node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt index 9c015307a6..82c575efea 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolStateMachineImpl.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt @@ -7,10 +7,10 @@ import co.paralleluniverse.strands.Strand import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.SettableFuture import net.corda.core.crypto.Party -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolSessionException -import net.corda.core.protocols.ProtocolStateMachine -import net.corda.core.protocols.StateMachineRunId +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowSessionException +import net.corda.core.flows.FlowStateMachine +import net.corda.core.flows.StateMachineRunId import net.corda.core.random63BitValue import net.corda.core.utilities.UntrustworthyData import net.corda.core.utilities.trace @@ -28,9 +28,9 @@ import java.sql.SQLException import java.util.* import java.util.concurrent.ExecutionException -class ProtocolStateMachineImpl(override val id: StateMachineRunId, - val logic: ProtocolLogic, - scheduler: FiberScheduler) : Fiber("protocol", scheduler), ProtocolStateMachine { +class FlowStateMachineImpl(override val id: StateMachineRunId, + val logic: FlowLogic, + scheduler: FiberScheduler) : Fiber("flow", scheduler), FlowStateMachine { companion object { // Used to work around a small limitation in Quasar. @@ -41,14 +41,14 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, } /** - * Return the current [ProtocolStateMachineImpl] or null if executing outside of one. + * Return the current [FlowStateMachineImpl] or null if executing outside of one. */ - fun currentStateMachine(): ProtocolStateMachineImpl<*>? = Strand.currentStrand() as? ProtocolStateMachineImpl<*> + fun currentStateMachine(): FlowStateMachineImpl<*>? = Strand.currentStrand() as? FlowStateMachineImpl<*> } // These fields shouldn't be serialised, so they are marked @Transient. @Transient lateinit override var serviceHub: ServiceHubInternal - @Transient internal lateinit var actionOnSuspend: (ProtocolIORequest) -> Unit + @Transient internal lateinit var actionOnSuspend: (FlowIORequest) -> Unit @Transient internal lateinit var actionOnEnd: () -> Unit @Transient internal lateinit var database: Database @Transient internal var fromCheckpoint: Boolean = false @@ -73,10 +73,10 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, } } - internal val openSessions = HashMap, Party>, ProtocolSession>() + internal val openSessions = HashMap, Party>, FlowSession>() init { - logic.psm = this + logic.fsm = this name = id.toString() } @@ -122,8 +122,8 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, override fun sendAndReceive(otherParty: Party, payload: Any, receiveType: Class, - sessionProtocol: ProtocolLogic<*>): UntrustworthyData { - val (session, new) = getSession(otherParty, sessionProtocol, payload) + sessionFlow: FlowLogic<*>): UntrustworthyData { + val (session, new) = getSession(otherParty, sessionFlow, payload) val receivedSessionData = if (new) { // Only do a receive here as the session init has carried the payload receiveInternal(session) @@ -137,48 +137,48 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, @Suspendable override fun receive(otherParty: Party, receiveType: Class, - sessionProtocol: ProtocolLogic<*>): UntrustworthyData { - val session = getSession(otherParty, sessionProtocol, null).first + sessionFlow: FlowLogic<*>): UntrustworthyData { + val session = getSession(otherParty, sessionFlow, null).first val receivedSessionData = receiveInternal(session) return UntrustworthyData(receiveType.cast(receivedSessionData.payload)) } @Suspendable - override fun send(otherParty: Party, payload: Any, sessionProtocol: ProtocolLogic<*>) { - val (session, new) = getSession(otherParty, sessionProtocol, payload) + override fun send(otherParty: Party, payload: Any, sessionFlow: FlowLogic<*>) { + val (session, new) = getSession(otherParty, sessionFlow, payload) if (!new) { // Don't send the payload again if it was already piggy-backed on a session init sendInternal(session, createSessionData(session, payload)) } } - private fun createSessionData(session: ProtocolSession, payload: Any): SessionData { + private fun createSessionData(session: FlowSession, payload: Any): SessionData { val otherPartySessionId = session.otherPartySessionId ?: throw IllegalStateException("We've somehow held onto an unconfirmed session: $session") return SessionData(otherPartySessionId, payload) } @Suspendable - private fun sendInternal(session: ProtocolSession, message: SessionMessage) { + private fun sendInternal(session: FlowSession, message: SessionMessage) { suspend(SendOnly(session, message)) } @Suspendable - private inline fun receiveInternal(session: ProtocolSession): M { + private inline fun receiveInternal(session: FlowSession): M { return suspendAndExpectReceive(ReceiveOnly(session, M::class.java)) } - private inline fun sendAndReceiveInternal(session: ProtocolSession, message: SessionMessage): M { + private inline fun sendAndReceiveInternal(session: FlowSession, message: SessionMessage): M { return suspendAndExpectReceive(SendAndReceive(session, message, M::class.java)) } @Suspendable - private fun getSession(otherParty: Party, sessionProtocol: ProtocolLogic<*>, firstPayload: Any?): Pair { - val session = openSessions[Pair(sessionProtocol, otherParty)] + private fun getSession(otherParty: Party, sessionFlow: FlowLogic<*>, firstPayload: Any?): Pair { + val session = openSessions[Pair(sessionFlow, otherParty)] return if (session != null) { Pair(session, false) } else { - Pair(startNewSession(otherParty, sessionProtocol, firstPayload), true) + Pair(startNewSession(otherParty, sessionFlow, firstPayload), true) } } @@ -189,21 +189,21 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, * multiple public keys, but we **don't support multiple nodes advertising the same legal identity**. */ @Suspendable - private fun startNewSession(otherParty: Party, sessionProtocol: ProtocolLogic<*>, firstPayload: Any?) : ProtocolSession { + private fun startNewSession(otherParty: Party, sessionFlow: FlowLogic<*>, firstPayload: Any?): FlowSession { val node = serviceHub.networkMapCache.getRepresentativeNode(otherParty) ?: throw IllegalArgumentException("Don't know about party $otherParty") val nodeIdentity = node.legalIdentity logger.trace { "Initiating a new session with $nodeIdentity (representative of $otherParty)" } - val session = ProtocolSession(sessionProtocol, nodeIdentity, random63BitValue(), null) - openSessions[Pair(sessionProtocol, nodeIdentity)] = session - val counterpartyProtocol = sessionProtocol.getCounterpartyMarker(nodeIdentity).name - val sessionInit = SessionInit(session.ourSessionId, serviceHub.myInfo.legalIdentity, counterpartyProtocol, firstPayload) + val session = FlowSession(sessionFlow, nodeIdentity, random63BitValue(), null) + openSessions[Pair(sessionFlow, nodeIdentity)] = session + val counterpartyFlow = sessionFlow.getCounterpartyMarker(nodeIdentity).name + val sessionInit = SessionInit(session.ourSessionId, serviceHub.myInfo.legalIdentity, counterpartyFlow, firstPayload) val sessionInitResponse = sendAndReceiveInternal(session, sessionInit) if (sessionInitResponse is SessionConfirm) { session.otherPartySessionId = sessionInitResponse.initiatedSessionId return session } else { sessionInitResponse as SessionReject - throw ProtocolSessionException("Party $nodeIdentity rejected session attempt: ${sessionInitResponse.errorMessage}") + throw FlowSessionException("Party $nodeIdentity rejected session attempt: ${sessionInitResponse.errorMessage}") } } @@ -227,7 +227,7 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, if (receivedMessage is SessionEnd) { openSessions.values.remove(receiveRequest.session) - throw ProtocolSessionException("Counterparty on ${receiveRequest.session.otherParty} has prematurely ended on $receiveRequest") + throw FlowSessionException("Counterparty on ${receiveRequest.session.otherParty} has prematurely ended on $receiveRequest") } else if (receiveRequest.receiveType.isInstance(receivedMessage)) { return receiveRequest.receiveType.cast(receivedMessage) } else { @@ -236,7 +236,7 @@ class ProtocolStateMachineImpl(override val id: StateMachineRunId, } @Suspendable - private fun suspend(ioRequest: ProtocolIORequest) { + private fun suspend(ioRequest: FlowIORequest) { // we have to pass the Thread local Transaction across via a transient field as the Fiber Park swaps them out. txTrampoline = TransactionManager.currentOrNull() StrandLocalTransactionManager.setThreadLocalTx(null) diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolIORequest.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolIORequest.kt index 4e21817251..42bd7c579d 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolIORequest.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/ProtocolIORequest.kt @@ -1,38 +1,38 @@ package net.corda.node.services.statemachine -import net.corda.node.services.statemachine.StateMachineManager.ProtocolSession +import net.corda.node.services.statemachine.StateMachineManager.FlowSession import net.corda.node.services.statemachine.StateMachineManager.SessionMessage // TODO revisit when Kotlin 1.1 is released and data classes can extend other classes -interface ProtocolIORequest { +interface FlowIORequest { // This is used to identify where we suspended, in case of message mismatch errors and other things where we // don't have the original stack trace because it's in a suspended fiber. val stackTraceInCaseOfProblems: StackSnapshot - val session: ProtocolSession + val session: FlowSession } -interface SendRequest : ProtocolIORequest { +interface SendRequest : FlowIORequest { val message: SessionMessage } -interface ReceiveRequest : ProtocolIORequest { +interface ReceiveRequest : FlowIORequest { val receiveType: Class } -data class SendAndReceive(override val session: ProtocolSession, +data class SendAndReceive(override val session: FlowSession, override val message: SessionMessage, override val receiveType: Class) : SendRequest, ReceiveRequest { @Transient override val stackTraceInCaseOfProblems: StackSnapshot = StackSnapshot() } -data class ReceiveOnly(override val session: ProtocolSession, +data class ReceiveOnly(override val session: FlowSession, override val receiveType: Class) : ReceiveRequest { @Transient override val stackTraceInCaseOfProblems: StackSnapshot = StackSnapshot() } -data class SendOnly(override val session: ProtocolSession, override val message: SessionMessage) : SendRequest { +data class SendOnly(override val session: FlowSession, override val message: SessionMessage) : SendRequest { @Transient override val stackTraceInCaseOfProblems: StackSnapshot = StackSnapshot() } diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt index 1148b626fd..7260ef962a 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt @@ -11,11 +11,11 @@ import kotlinx.support.jdk8.collections.removeIf import net.corda.core.ThreadBox import net.corda.core.abbreviate import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowStateMachine +import net.corda.core.flows.StateMachineRunId import net.corda.core.messaging.TopicSession import net.corda.core.messaging.send -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolStateMachine -import net.corda.core.protocols.StateMachineRunId import net.corda.core.random63BitValue import net.corda.core.serialization.* import net.corda.core.then @@ -41,8 +41,8 @@ import java.util.concurrent.ExecutionException import javax.annotation.concurrent.ThreadSafe /** - * A StateMachineManager is responsible for coordination and persistence of multiple [ProtocolStateMachine] objects. - * Each such object represents an instantiation of a (two-party) protocol that has reached a particular point. + * A StateMachineManager is responsible for coordination and persistence of multiple [FlowStateMachine] objects. + * Each such object represents an instantiation of a (two-party) flow that has reached a particular point. * * An implementation of this class will persist state machines to long term storage so they can survive process restarts * and, if run with a single-threaded executor, will ensure no two state machines run concurrently with each other @@ -51,7 +51,7 @@ import javax.annotation.concurrent.ThreadSafe * A "state machine" is a class with a single call method. The call method and any others it invokes are rewritten by * a bytecode rewriting engine called Quasar, to ensure the code can be suspended and resumed at any point. * - * The SMM will always invoke the protocol fibers on the given [AffinityExecutor], regardless of which thread actually + * The SMM will always invoke the flow fibers on the given [AffinityExecutor], regardless of which thread actually * starts them via [add]. * * TODO: Consider the issue of continuation identity more deeply: is it a safe assumption that a serialised @@ -79,7 +79,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, val scheduler = FiberScheduler() data class Change( - val logic: ProtocolLogic<*>, + val logic: FlowLogic<*>, val addOrRemove: AddOrRemove, val id: StateMachineRunId ) @@ -88,10 +88,10 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, // property. private val mutex = ThreadBox(object { var started = false - val stateMachines = LinkedHashMap, Checkpoint>() + val stateMachines = LinkedHashMap, Checkpoint>() val changesPublisher = PublishSubject.create() - fun notifyChangeObservers(psm: ProtocolStateMachineImpl<*>, addOrRemove: AddOrRemove) { + fun notifyChangeObservers(psm: FlowStateMachineImpl<*>, addOrRemove: AddOrRemove) { changesPublisher.onNext(Change(psm.logic, addOrRemove, psm.id)) } }) @@ -105,35 +105,35 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, private val metrics = serviceHub.monitoringService.metrics init { - metrics.register("Protocols.InFlight", Gauge { mutex.content.stateMachines.size }) + metrics.register("Flows.InFlight", Gauge { mutex.content.stateMachines.size }) } - private val checkpointingMeter = metrics.meter("Protocols.Checkpointing Rate") - private val totalStartedProtocols = metrics.counter("Protocols.Started") - private val totalFinishedProtocols = metrics.counter("Protocols.Finished") + private val checkpointingMeter = metrics.meter("Flows.Checkpointing Rate") + private val totalStartedFlows = metrics.counter("Flows.Started") + private val totalFinishedFlows = metrics.counter("Flows.Finished") - private val openSessions = ConcurrentHashMap() + private val openSessions = ConcurrentHashMap() private val recentlyClosedSessions = ConcurrentHashMap() // Context for tokenized services in checkpoints private val serializationContext = SerializeAsTokenContext(tokenizableServices, quasarKryo()) - /** Returns a list of all state machines executing the given protocol logic at the top level (subprotocols do not count) */ - fun

, T> findStateMachines(protocolClass: Class

): List>> { + /** Returns a list of all state machines executing the given flow logic at the top level (subflows do not count) */ + fun

, T> findStateMachines(flowClass: Class

): List>> { @Suppress("UNCHECKED_CAST") return mutex.locked { stateMachines.keys .map { it.logic } - .filterIsInstance(protocolClass) - .map { it to (it.psm as ProtocolStateMachineImpl).resultFuture } + .filterIsInstance(flowClass) + .map { it to (it.fsm as FlowStateMachineImpl).resultFuture } } } - val allStateMachines: List> + val allStateMachines: List> get() = mutex.locked { stateMachines.keys.map { it.logic } } /** - * An observable that emits triples of the changing protocol, the type of change, and a process-specific ID number + * An observable that emits triples of the changing flow, the type of change, and a process-specific ID number * which may change across restarts. */ val changes: Observable @@ -141,7 +141,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, init { Fiber.setDefaultUncaughtExceptionHandler { fiber, throwable -> - (fiber as ProtocolStateMachineImpl<*>).logger.error("Caught exception from protocol", throwable) + (fiber as FlowStateMachineImpl<*>).logger.error("Caught exception from flow", throwable) } } @@ -179,7 +179,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, * Atomic get snapshot + subscribe. This is needed so we don't miss updates between subscriptions to [changes] and * calls to [allStateMachines] */ - fun track(): Pair>, Observable> { + fun track(): Pair>, Observable> { return mutex.locked { val bufferedChanges = UnicastSubject.create() changesPublisher.subscribe(bufferedChanges) @@ -190,7 +190,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, private fun restoreFibersFromCheckpoints() { mutex.locked { checkpointStorage.forEach { - // If a protocol is added before start() then don't attempt to restore it + // If a flow is added before start() then don't attempt to restore it if (!stateMachines.containsValue(it)) { val fiber = deserializeFiber(it.serializedFiber) initFiber(fiber) @@ -216,7 +216,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, } } - private fun resumeRestoredFiber(fiber: ProtocolStateMachineImpl<*>) { + private fun resumeRestoredFiber(fiber: FlowStateMachineImpl<*>) { fiber.openSessions.values.forEach { openSessions[it.ourSessionId] = it } if (fiber.openSessions.values.any { it.waitingForResponse }) { fiber.logger.info("Restored, pending on receive") @@ -260,23 +260,23 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, val otherParty = sessionInit.initiatorParty val otherPartySessionId = sessionInit.initiatorSessionId try { - val markerClass = Class.forName(sessionInit.protocolName) - val protocolFactory = serviceHub.getProtocolFactory(markerClass) - if (protocolFactory != null) { - val protocol = protocolFactory(otherParty) - val psm = createFiber(protocol) - val session = ProtocolSession(protocol, otherParty, random63BitValue(), otherPartySessionId) + val markerClass = Class.forName(sessionInit.flowName) + val flowFactory = serviceHub.getFlowFactory(markerClass) + if (flowFactory != null) { + val flow = flowFactory(otherParty) + val psm = createFiber(flow) + val session = FlowSession(flow, otherParty, random63BitValue(), otherPartySessionId) if (sessionInit.firstPayload != null) { session.receivedMessages += SessionData(session.ourSessionId, sessionInit.firstPayload) } openSessions[session.ourSessionId] = session - psm.openSessions[Pair(protocol, otherParty)] = session + psm.openSessions[Pair(flow, otherParty)] = session updateCheckpoint(psm) sendSessionMessage(otherParty, SessionConfirm(otherPartySessionId, session.ourSessionId), psm) psm.logger.debug { "Initiated from $sessionInit on $session" } startFiber(psm) } else { - logger.warn("Unknown protocol marker class in $sessionInit") + logger.warn("Unknown flow marker class in $sessionInit") sendSessionMessage(otherParty, SessionReject(otherPartySessionId, "Don't know ${markerClass.name}"), null) } } catch (e: Exception) { @@ -285,14 +285,14 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, } } - private fun serializeFiber(fiber: ProtocolStateMachineImpl<*>): SerializedBytes> { + private fun serializeFiber(fiber: FlowStateMachineImpl<*>): SerializedBytes> { val kryo = quasarKryo() // add the map of tokens -> tokenizedServices to the kyro context SerializeAsTokenSerializer.setContext(kryo, serializationContext) return fiber.serialize(kryo) } - private fun deserializeFiber(serialisedFiber: SerializedBytes>): ProtocolStateMachineImpl<*> { + private fun deserializeFiber(serialisedFiber: SerializedBytes>): FlowStateMachineImpl<*> { val kryo = quasarKryo() // put the map of token -> tokenized into the kryo context SerializeAsTokenSerializer.setContext(kryo, serializationContext) @@ -304,12 +304,12 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, return createKryo(serializer.kryo) } - private fun createFiber(logic: ProtocolLogic): ProtocolStateMachineImpl { + private fun createFiber(logic: FlowLogic): FlowStateMachineImpl { val id = StateMachineRunId.createRandom() - return ProtocolStateMachineImpl(id, logic, scheduler).apply { initFiber(this) } + return FlowStateMachineImpl(id, logic, scheduler).apply { initFiber(this) } } - private fun initFiber(psm: ProtocolStateMachineImpl<*>) { + private fun initFiber(psm: FlowStateMachineImpl<*>) { psm.database = database psm.serviceHub = serviceHub psm.actionOnSuspend = { ioRequest -> @@ -325,7 +325,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, psm.logic.progressTracker?.currentStep = ProgressTracker.DONE mutex.locked { stateMachines.remove(psm)?.let { checkpointStorage.removeCheckpoint(it) } - totalFinishedProtocols.inc() + totalFinishedFlows.inc() notifyChangeObservers(psm, AddOrRemove.REMOVE) } endAllFiberSessions(psm) @@ -334,12 +334,12 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, } } mutex.locked { - totalStartedProtocols.inc() + totalStartedFlows.inc() notifyChangeObservers(psm, AddOrRemove.ADD) } } - private fun endAllFiberSessions(psm: ProtocolStateMachineImpl<*>) { + private fun endAllFiberSessions(psm: FlowStateMachineImpl<*>) { openSessions.values.removeIf { session -> if (session.psm == psm) { val otherPartySessionId = session.otherPartySessionId @@ -354,17 +354,17 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, } } - private fun startFiber(fiber: ProtocolStateMachineImpl<*>) { + private fun startFiber(fiber: FlowStateMachineImpl<*>) { try { resumeFiber(fiber) } catch (e: ExecutionException) { // There are two ways we can take exceptions in this method: // - // 1) A bug in the SMM code itself whilst setting up the new protocol. In that case the exception will + // 1) A bug in the SMM code itself whilst setting up the new flow. In that case the exception will // propagate out of this method as it would for any method. // // 2) An exception in the first part of the fiber after it's been invoked for the first time via - // fiber.start(). In this case the exception will be caught and stashed in the protocol logic future, + // fiber.start(). In this case the exception will be caught and stashed in the flow logic future, // then sent to the unhandled exception handler above which logs it, and is then rethrown wrapped // in an ExecutionException or RuntimeException+EE so we can just catch it here and ignore it. } catch (e: RuntimeException) { @@ -378,10 +378,10 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, * The state machine will be persisted when it suspends, with automated restart if the StateMachineManager is * restarted with checkpointed state machines in the storage service. */ - fun add(logic: ProtocolLogic): ProtocolStateMachine { + fun add(logic: FlowLogic): FlowStateMachine { val fiber = createFiber(logic) // We swap out the parent transaction context as using this frequently leads to a deadlock as we wait - // on the protocol completion future inside that context. The problem is that any progress checkpoints are + // on the flow completion future inside that context. The problem is that any progress checkpoints are // unable to acquire the table lock and move forward till the calling transaction finishes. // Committing in line here on a fresh context ensure we can progress. isolatedTransaction(database) { @@ -396,7 +396,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, return fiber } - private fun updateCheckpoint(psm: ProtocolStateMachineImpl<*>) { + private fun updateCheckpoint(psm: FlowStateMachineImpl<*>) { check(psm.state != Strand.State.RUNNING) { "Fiber cannot be running when checkpointing" } val newCheckpoint = Checkpoint(serializeFiber(psm)) val previousCheckpoint = mutex.locked { stateMachines.put(psm, newCheckpoint) } @@ -407,7 +407,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, checkpointingMeter.mark() } - private fun resumeFiber(psm: ProtocolStateMachineImpl<*>) { + private fun resumeFiber(psm: FlowStateMachineImpl<*>) { // Avoid race condition when setting stopping to true and then checking liveFibers incrementLiveFibers() if (!stopping) executor.executeASAP { @@ -418,7 +418,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, } } - private fun processIORequest(ioRequest: ProtocolIORequest) { + private fun processIORequest(ioRequest: FlowIORequest) { if (ioRequest is SendRequest) { if (ioRequest.message is SessionInit) { openSessions[ioRequest.session.ourSessionId] = ioRequest.session @@ -431,7 +431,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, } } - private fun sendSessionMessage(party: Party, message: SessionMessage, psm: ProtocolStateMachineImpl<*>?) { + private fun sendSessionMessage(party: Party, message: SessionMessage, psm: FlowStateMachineImpl<*>?) { val node = serviceHub.networkMapCache.getNodeByCompositeKey(party.owningKey) ?: throw IllegalArgumentException("Don't know about party $party") val logger = psm?.logger ?: logger @@ -448,7 +448,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, data class SessionInit(val initiatorSessionId: Long, val initiatorParty: Party, - val protocolName: String, + val flowName: String, val firstPayload: Any?) : SessionMessage interface SessionInitResponse : ExistingSessionMessage @@ -470,14 +470,14 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, data class SessionEnd(override val recipientSessionId: Long) : ExistingSessionMessage - data class ProtocolSession(val protocol: ProtocolLogic<*>, - val otherParty: Party, - val ourSessionId: Long, - var otherPartySessionId: Long?, - @Volatile var waitingForResponse: Boolean = false) { + data class FlowSession(val flow: FlowLogic<*>, + val otherParty: Party, + val ourSessionId: Long, + var otherPartySessionId: Long?, + @Volatile var waitingForResponse: Boolean = false) { val receivedMessages = ConcurrentLinkedQueue() - val psm: ProtocolStateMachineImpl<*> get() = protocol.psm as ProtocolStateMachineImpl<*> + val psm: FlowStateMachineImpl<*> get() = flow.fsm as FlowStateMachineImpl<*> } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/NotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/NotaryService.kt index 5920f88579..66410033cb 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/NotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/NotaryService.kt @@ -1,11 +1,9 @@ package net.corda.node.services.transactions import net.corda.core.crypto.Party -import net.corda.core.node.services.ServiceType import net.corda.core.serialization.SingletonSerializeAsToken +import net.corda.flows.NotaryFlow import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.NotaryProtocol -import kotlin.reflect.KClass /** * A Notary service acts as the final signer of a transaction ensuring two things: @@ -14,15 +12,15 @@ import kotlin.reflect.KClass *O * A transaction has to be signed by a Notary to be considered valid (except for output-only transactions without a timestamp). * - * This is the base implementation that can be customised with specific Notary transaction commit protocol. + * This is the base implementation that can be customised with specific Notary transaction commit flow. */ abstract class NotaryService(services: ServiceHubInternal) : SingletonSerializeAsToken() { init { - services.registerProtocolInitiator(NotaryProtocol.Client::class) { createProtocol(it) } + services.registerFlowInitiator(NotaryFlow.Client::class) { createFlow(it) } } - /** Implement a factory that specifies the transaction commit protocol for the notary service to use */ - abstract fun createProtocol(otherParty: Party): NotaryProtocol.Service + /** Implement a factory that specifies the transaction commit flow for the notary service to use */ + abstract fun createFlow(otherParty: Party): NotaryFlow.Service } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt index 38056d9904..3ef3e1610f 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/RaftValidatingNotaryService.kt @@ -2,8 +2,8 @@ package net.corda.node.services.transactions import net.corda.core.crypto.Party import net.corda.core.node.services.TimestampChecker +import net.corda.flows.ValidatingNotaryFlow import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.ValidatingNotaryProtocol /** A validating notary service operated by a group of mutually trusting parties, uses the Raft algorithm to achieve consensus. */ class RaftValidatingNotaryService(services: ServiceHubInternal, @@ -13,7 +13,7 @@ class RaftValidatingNotaryService(services: ServiceHubInternal, val type = ValidatingNotaryService.type.getSubType("raft") } - override fun createProtocol(otherParty: Party): ValidatingNotaryProtocol { - return ValidatingNotaryProtocol(otherParty, timestampChecker, uniquenessProvider) + override fun createFlow(otherParty: Party): ValidatingNotaryFlow { + return ValidatingNotaryFlow(otherParty, timestampChecker, uniquenessProvider) } } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/SimpleNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/SimpleNotaryService.kt index 8ad61e4bf7..155e2b1594 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/SimpleNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/SimpleNotaryService.kt @@ -4,9 +4,8 @@ import net.corda.core.crypto.Party import net.corda.core.node.services.ServiceType import net.corda.core.node.services.TimestampChecker import net.corda.core.node.services.UniquenessProvider -import net.corda.core.utilities.loggerFor +import net.corda.flows.NotaryFlow import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.NotaryProtocol /** A simple Notary service that does not perform transaction validation */ class SimpleNotaryService(services: ServiceHubInternal, @@ -16,7 +15,7 @@ class SimpleNotaryService(services: ServiceHubInternal, val type = ServiceType.notary.getSubType("simple") } - override fun createProtocol(otherParty: Party): NotaryProtocol.Service { - return NotaryProtocol.Service(otherParty, timestampChecker, uniquenessProvider) + override fun createFlow(otherParty: Party): NotaryFlow.Service { + return NotaryFlow.Service(otherParty, timestampChecker, uniquenessProvider) } } diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt b/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt index 8ecbfb62c4..9bdf100e3f 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/ValidatingNotaryService.kt @@ -4,8 +4,8 @@ import net.corda.core.crypto.Party import net.corda.core.node.services.ServiceType import net.corda.core.node.services.TimestampChecker import net.corda.core.node.services.UniquenessProvider +import net.corda.flows.ValidatingNotaryFlow import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.ValidatingNotaryProtocol /** A Notary service that validates the transaction chain of he submitted transaction before committing it */ class ValidatingNotaryService(services: ServiceHubInternal, @@ -15,7 +15,7 @@ class ValidatingNotaryService(services: ServiceHubInternal, val type = ServiceType.notary.getSubType("validating") } - override fun createProtocol(otherParty: Party): ValidatingNotaryProtocol { - return ValidatingNotaryProtocol(otherParty, timestampChecker, uniquenessProvider) + override fun createFlow(otherParty: Party): ValidatingNotaryFlow { + return ValidatingNotaryFlow(otherParty, timestampChecker, uniquenessProvider) } } diff --git a/node/src/main/kotlin/net/corda/node/utilities/ANSIProgressObserver.kt b/node/src/main/kotlin/net/corda/node/utilities/ANSIProgressObserver.kt index 6cd934c4d3..6f449311ce 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/ANSIProgressObserver.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/ANSIProgressObserver.kt @@ -1,28 +1,28 @@ package net.corda.node.utilities import net.corda.core.ThreadBox -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import net.corda.core.utilities.ProgressTracker import net.corda.node.services.statemachine.StateMachineManager import java.util.* /** - * This observes the [StateMachineManager] and follows the progress of [ProtocolLogic]s until they complete in the order + * This observes the [StateMachineManager] and follows the progress of [FlowLogic]s until they complete in the order * they are added to the [StateMachineManager]. */ class ANSIProgressObserver(val smm: StateMachineManager) { init { smm.changes.subscribe { change -> when (change.addOrRemove) { - AddOrRemove.ADD -> addProtocolLogic(change.logic) - AddOrRemove.REMOVE -> removeProtocolLogic(change.logic) + AddOrRemove.ADD -> addFlowLogic(change.logic) + AddOrRemove.REMOVE -> removeFlowLogic(change.logic) } } } private class Content { - var currentlyRendering: ProtocolLogic<*>? = null - val pending = ArrayDeque>() + var currentlyRendering: FlowLogic<*>? = null + val pending = ArrayDeque>() } private val state = ThreadBox(Content()) @@ -39,18 +39,18 @@ class ANSIProgressObserver(val smm: StateMachineManager) { } } - private fun removeProtocolLogic(protocolLogic: ProtocolLogic<*>) { + private fun removeFlowLogic(flowLogic: FlowLogic<*>) { state.locked { - protocolLogic.progressTracker?.currentStep = ProgressTracker.DONE - if (currentlyRendering == protocolLogic) { + flowLogic.progressTracker?.currentStep = ProgressTracker.DONE + if (currentlyRendering == flowLogic) { wireUpProgressRendering() } } } - private fun addProtocolLogic(protocolLogic: ProtocolLogic<*>) { + private fun addFlowLogic(flowLogic: FlowLogic<*>) { state.locked { - pending.add(protocolLogic) + pending.add(flowLogic) if ((currentlyRendering?.progressTracker?.currentStep ?: ProgressTracker.DONE) == ProgressTracker.DONE) { wireUpProgressRendering() } diff --git a/node/src/main/kotlin/net/corda/node/utilities/FiberBox.kt b/node/src/main/kotlin/net/corda/node/utilities/FiberBox.kt index b912399b6a..0d9acdf61b 100644 --- a/node/src/main/kotlin/net/corda/node/utilities/FiberBox.kt +++ b/node/src/main/kotlin/net/corda/node/utilities/FiberBox.kt @@ -27,9 +27,9 @@ import kotlin.concurrent.withLock * or testing. * * Currently this is intended for use within a node as a simplified way for Oracles to implement subscriptions for changing - * data by running a protocol internally to implement the request handler (see [NodeInterestRates.Oracle]), which can then + * data by running a flow internally to implement the request handler (see [NodeInterestRates.Oracle]), which can then * effectively relinquish control until the data becomes available. This isn't the most scalable design and is intended - * to be temporary. In addition, it's enitrely possible to envisage a time when we want public [ProtocolLogic] + * to be temporary. In addition, it's enitrely possible to envisage a time when we want public [FlowLogic] * implementations to be able to wait for some condition to become true outside of message send/receive. At that point * we may revisit this implementation and indeed the whole model for this, when we understand that requirement more fully. * diff --git a/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt b/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt index 4fa1f662aa..7fbf19ef29 100644 --- a/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt +++ b/node/src/test/kotlin/net/corda/node/CordaRPCOpsImplTest.kt @@ -2,23 +2,23 @@ package net.corda.node import net.corda.contracts.asset.Cash import net.corda.core.contracts.* +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.Vault -import net.corda.core.protocols.StateMachineRunId import net.corda.core.serialization.OpaqueBytes import net.corda.core.transactions.SignedTransaction +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow import net.corda.node.internal.CordaRPCOpsImpl import net.corda.node.services.User import net.corda.node.services.messaging.CURRENT_RPC_USER import net.corda.node.services.messaging.PermissionException import net.corda.node.services.messaging.StateMachineUpdate -import net.corda.node.services.messaging.startProtocol +import net.corda.node.services.messaging.startFlow import net.corda.node.services.network.NetworkMapService -import net.corda.node.services.startProtocolPermission +import net.corda.node.services.startFlowPermission import net.corda.node.services.transactions.SimpleNotaryService import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol import net.corda.testing.expect import net.corda.testing.expectEvents import net.corda.testing.node.MockNetwork @@ -48,7 +48,7 @@ class CordaRPCOpsImplTest { aliceNode = network.createNode(networkMapAddress = networkMap.info.address) notaryNode = network.createNode(advertisedServices = ServiceInfo(SimpleNotaryService.type), networkMapAddress = networkMap.info.address) rpc = CordaRPCOpsImpl(aliceNode.services, aliceNode.smm, aliceNode.database) - CURRENT_RPC_USER.set(User("user", "pwd", permissions = setOf(startProtocolPermission()))) + CURRENT_RPC_USER.set(User("user", "pwd", permissions = setOf(startFlowPermission()))) stateMachineUpdates = rpc.stateMachinesAndUpdates().second transactions = rpc.verifiedTransactions().second @@ -68,7 +68,7 @@ class CordaRPCOpsImplTest { // Tell the monitoring service node to issue some cash val recipient = aliceNode.info.legalIdentity val outEvent = CashCommand.IssueCash(Amount(quantity, GBP), ref, recipient, notaryNode.info.notaryIdentity) - rpc.startProtocol(::CashProtocol, outEvent) + rpc.startFlow(::CashFlow, outEvent) network.runNetwork() val expectedState = Cash.State(Amount(quantity, @@ -105,7 +105,7 @@ class CordaRPCOpsImplTest { @Test fun `issue and move`() { - rpc.startProtocol(::CashProtocol, CashCommand.IssueCash( + rpc.startFlow(::CashFlow, CashCommand.IssueCash( amount = Amount(100, USD), issueRef = OpaqueBytes(ByteArray(1, { 1 })), recipient = aliceNode.info.legalIdentity, @@ -114,7 +114,7 @@ class CordaRPCOpsImplTest { network.runNetwork() - rpc.startProtocol(::CashProtocol, CashCommand.PayCash( + rpc.startFlow(::CashFlow, CashCommand.PayCash( amount = Amount(100, Issued(PartyAndReference(aliceNode.info.legalIdentity, OpaqueBytes(ByteArray(1, { 1 }))), USD)), recipient = aliceNode.info.legalIdentity )) @@ -186,7 +186,7 @@ class CordaRPCOpsImplTest { fun `cash command by user not permissioned for cash`() { CURRENT_RPC_USER.set(User("user", "pwd", permissions = emptySet())) assertThatExceptionOfType(PermissionException::class.java).isThrownBy { - rpc.startProtocol(::CashProtocol, CashCommand.IssueCash( + rpc.startFlow(::CashFlow, CashCommand.IssueCash( amount = Amount(100, USD), issueRef = OpaqueBytes(ByteArray(1, { 1 })), recipient = aliceNode.info.legalIdentity, diff --git a/node/src/test/kotlin/net/corda/node/messaging/AttachmentTests.kt b/node/src/test/kotlin/net/corda/node/messaging/AttachmentTests.kt index a789793ff9..e2d1ffb6e1 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/AttachmentTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/AttachmentTests.kt @@ -6,12 +6,12 @@ import net.corda.core.crypto.sha256 import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.services.ServiceInfo import net.corda.core.write +import net.corda.flows.FetchAttachmentsFlow +import net.corda.flows.FetchDataFlow import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.network.NetworkMapService import net.corda.node.services.persistence.NodeAttachmentService import net.corda.node.services.transactions.SimpleNotaryService -import net.corda.protocols.FetchAttachmentsProtocol -import net.corda.protocols.FetchDataProtocol import net.corda.testing.node.MockNetwork import net.corda.testing.rootCauseExceptions import org.junit.Before @@ -49,9 +49,9 @@ class AttachmentTests { // Insert an attachment into node zero's store directly. val id = n0.storage.attachments.importAttachment(ByteArrayInputStream(fakeAttachment())) - // Get node one to run a protocol to fetch it and insert it. + // Get node one to run a flow to fetch it and insert it. network.runNetwork() - val f1 = n1.services.startProtocol(FetchAttachmentsProtocol(setOf(id), n0.info.legalIdentity)) + val f1 = n1.services.startFlow(FetchAttachmentsFlow(setOf(id), n0.info.legalIdentity)) network.runNetwork() assertEquals(0, f1.resultFuture.get().fromDisk.size) @@ -62,7 +62,7 @@ class AttachmentTests { // Shut down node zero and ensure node one can still resolve the attachment. n0.stop() - val response: FetchDataProtocol.Result = n1.services.startProtocol(FetchAttachmentsProtocol(setOf(id), n0.info.legalIdentity)).resultFuture.get() + val response: FetchDataFlow.Result = n1.services.startFlow(FetchAttachmentsFlow(setOf(id), n0.info.legalIdentity)).resultFuture.get() assertEquals(attachment, response.fromDisk[0]) } @@ -73,9 +73,9 @@ class AttachmentTests { // Get node one to fetch a non-existent attachment. val hash = SecureHash.randomSHA256() network.runNetwork() - val f1 = n1.services.startProtocol(FetchAttachmentsProtocol(setOf(hash), n0.info.legalIdentity)) + val f1 = n1.services.startFlow(FetchAttachmentsFlow(setOf(hash), n0.info.legalIdentity)) network.runNetwork() - val e = assertFailsWith { rootCauseExceptions { f1.resultFuture.get() } } + val e = assertFailsWith { rootCauseExceptions { f1.resultFuture.get() } } assertEquals(hash, e.requested) } @@ -104,9 +104,9 @@ class AttachmentTests { // Get n1 to fetch the attachment. Should receive corrupted bytes. network.runNetwork() - val f1 = n1.services.startProtocol(FetchAttachmentsProtocol(setOf(id), n0.info.legalIdentity)) + val f1 = n1.services.startFlow(FetchAttachmentsFlow(setOf(id), n0.info.legalIdentity)) network.runNetwork() - assertFailsWith { + assertFailsWith { rootCauseExceptions { f1.resultFuture.get() } } } diff --git a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeProtocolTests.kt b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeProtocolTests.kt index 6b595db05f..fdc7a7678f 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeProtocolTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeProtocolTests.kt @@ -9,11 +9,11 @@ import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.crypto.composite import net.corda.core.days +import net.corda.core.flows.FlowStateMachine +import net.corda.core.flows.StateMachineRunId import net.corda.core.map import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.services.* -import net.corda.core.protocols.ProtocolStateMachine -import net.corda.core.protocols.StateMachineRunId import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.WireTransaction @@ -21,6 +21,8 @@ import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY import net.corda.core.utilities.LogHelper import net.corda.core.utilities.TEST_TX_TIME +import net.corda.flows.TwoPartyTradeFlow.Buyer +import net.corda.flows.TwoPartyTradeFlow.Seller import net.corda.node.internal.AbstractNode import net.corda.node.services.config.NodeConfiguration import net.corda.node.services.persistence.DBTransactionStorage @@ -28,8 +30,6 @@ import net.corda.node.services.persistence.NodeAttachmentService import net.corda.node.services.persistence.StorageServiceImpl import net.corda.node.services.persistence.checkpoints import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.TwoPartyTradeProtocol.Buyer -import net.corda.protocols.TwoPartyTradeProtocol.Seller import net.corda.testing.* import net.corda.testing.node.InMemoryMessagingNetwork import net.corda.testing.node.MockNetwork @@ -58,7 +58,7 @@ import kotlin.test.assertTrue * * We assume that Alice and Bob already found each other via some market, and have agreed the details already. */ -class TwoPartyTradeProtocolTests { +class TwoPartyTradeFlowTests { lateinit var net: MockNetwork lateinit var notaryNode: MockNetwork.MockNode @@ -146,7 +146,7 @@ class TwoPartyTradeProtocolTests { insertFakeTransactions(alicesFakePaper, aliceNode, aliceKey, notaryKey) val aliceFuture = runBuyerAndSeller("alice's paper".outputStateAndRef()).sellerResult - // Everything is on this thread so we can now step through the protocol one step at a time. + // Everything is on this thread so we can now step through the flow one step at a time. // Seller Alice already sent a message to Buyer Bob. Pump once: bobNode.pumpReceive() @@ -408,18 +408,18 @@ class TwoPartyTradeProtocolTests { private data class RunResult( // The buyer is not created immediately, only when the seller starts running - val buyer: Future>, + val buyer: Future>, val sellerResult: Future, val sellerId: StateMachineRunId ) private fun runBuyerAndSeller(assetToSell: StateAndRef) : RunResult { - val buyerFuture = bobNode.initiateSingleShotProtocol(Seller::class) { otherParty -> + val buyerFuture = bobNode.initiateSingleShotFlow(Seller::class) { otherParty -> Buyer(otherParty, notaryNode.info.notaryIdentity, 1000.DOLLARS, CommercialPaper.State::class.java) - }.map { it.psm } + }.map { it.fsm } val seller = Seller(bobNode.info.legalIdentity, notaryNode.info, assetToSell, 1000.DOLLARS, ALICE_KEY) val sellerResultFuture = aliceNode.smm.add(seller).resultFuture - return RunResult(buyerFuture, sellerResultFuture, seller.psm.id) + return RunResult(buyerFuture, sellerResultFuture, seller.fsm.id) } private fun LedgerDSL.runWithError( diff --git a/node/src/test/kotlin/net/corda/node/services/ArtemisMessagingTests.kt b/node/src/test/kotlin/net/corda/node/services/ArtemisMessagingTests.kt index 3876d0e220..db3e643c18 100644 --- a/node/src/test/kotlin/net/corda/node/services/ArtemisMessagingTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/ArtemisMessagingTests.kt @@ -152,7 +152,7 @@ class ArtemisMessagingTests { val message = messagingClient.createMessage(topic, DEFAULT_SESSION_ID, "first msg".toByteArray()) messagingClient.send(message, messagingClient.myAddress) - val networkMapMessage = messagingClient.createMessage(NetworkMapService.FETCH_PROTOCOL_TOPIC, DEFAULT_SESSION_ID, "second msg".toByteArray()) + val networkMapMessage = messagingClient.createMessage(NetworkMapService.FETCH_FLOW_TOPIC, DEFAULT_SESSION_ID, "second msg".toByteArray()) messagingClient.send(networkMapMessage, messagingClient.myAddress) val actual: Message = receivedMessages.take() @@ -179,7 +179,7 @@ class ArtemisMessagingTests { messagingClient.send(message, messagingClient.myAddress) } - val networkMapMessage = messagingClient.createMessage(NetworkMapService.FETCH_PROTOCOL_TOPIC, DEFAULT_SESSION_ID, "second msg".toByteArray()) + val networkMapMessage = messagingClient.createMessage(NetworkMapService.FETCH_FLOW_TOPIC, DEFAULT_SESSION_ID, "second msg".toByteArray()) messagingClient.send(networkMapMessage, messagingClient.myAddress) val actual: Message = receivedMessages.take() @@ -212,7 +212,7 @@ class ArtemisMessagingTests { messagingClient.addMessageHandler(topic) { message, r -> receivedMessages.add(message) } - messagingClient.addMessageHandler(NetworkMapService.FETCH_PROTOCOL_TOPIC) { message, r -> + messagingClient.addMessageHandler(NetworkMapService.FETCH_FLOW_TOPIC) { message, r -> receivedMessages.add(message) } // Run after the handlers are added, otherwise (some of) the messages get delivered and discarded / dead-lettered. diff --git a/node/src/test/kotlin/net/corda/node/services/InMemoryNetworkMapServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/InMemoryNetworkMapServiceTest.kt index 28ebede787..8713c66eaa 100644 --- a/node/src/test/kotlin/net/corda/node/services/InMemoryNetworkMapServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/InMemoryNetworkMapServiceTest.kt @@ -4,17 +4,17 @@ import com.google.common.util.concurrent.ListenableFuture import net.corda.core.map import net.corda.core.messaging.send import net.corda.core.node.services.DEFAULT_SESSION_ID +import net.corda.flows.sendRequest import net.corda.node.services.network.AbstractNetworkMapService import net.corda.node.services.network.InMemoryNetworkMapService import net.corda.node.services.network.NetworkMapService import net.corda.node.services.network.NetworkMapService.* -import net.corda.node.services.network.NetworkMapService.Companion.FETCH_PROTOCOL_TOPIC -import net.corda.node.services.network.NetworkMapService.Companion.PUSH_ACK_PROTOCOL_TOPIC -import net.corda.node.services.network.NetworkMapService.Companion.REGISTER_PROTOCOL_TOPIC -import net.corda.node.services.network.NetworkMapService.Companion.SUBSCRIPTION_PROTOCOL_TOPIC +import net.corda.node.services.network.NetworkMapService.Companion.FETCH_FLOW_TOPIC +import net.corda.node.services.network.NetworkMapService.Companion.PUSH_ACK_FLOW_TOPIC +import net.corda.node.services.network.NetworkMapService.Companion.REGISTER_FLOW_TOPIC +import net.corda.node.services.network.NetworkMapService.Companion.SUBSCRIPTION_FLOW_TOPIC import net.corda.node.services.network.NodeRegistration import net.corda.node.utilities.AddOrRemove -import net.corda.protocols.sendRequest import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork.MockNode import org.junit.Before @@ -165,23 +165,23 @@ abstract class AbstractNetworkMapServiceTest { private fun MockNode.registration(mapServiceNode: MockNode, reg: NodeRegistration, privateKey: PrivateKey): ListenableFuture { val req = RegistrationRequest(reg.toWire(privateKey), services.networkService.myAddress) - return services.networkService.sendRequest(REGISTER_PROTOCOL_TOPIC, req, mapServiceNode.info.address) + return services.networkService.sendRequest(REGISTER_FLOW_TOPIC, req, mapServiceNode.info.address) } private fun MockNode.subscribe(mapServiceNode: MockNode, subscribe: Boolean): ListenableFuture { val req = SubscribeRequest(subscribe, services.networkService.myAddress) - return services.networkService.sendRequest(SUBSCRIPTION_PROTOCOL_TOPIC, req, mapServiceNode.info.address) + return services.networkService.sendRequest(SUBSCRIPTION_FLOW_TOPIC, req, mapServiceNode.info.address) } private fun MockNode.updateAcknowlege(mapServiceNode: MockNode, mapVersion: Int) { val req = UpdateAcknowledge(mapVersion, services.networkService.myAddress) - services.networkService.send(PUSH_ACK_PROTOCOL_TOPIC, DEFAULT_SESSION_ID, req, mapServiceNode.info.address) + services.networkService.send(PUSH_ACK_FLOW_TOPIC, DEFAULT_SESSION_ID, req, mapServiceNode.info.address) } private fun MockNode.fetchMap(mapServiceNode: MockNode, subscribe: Boolean, ifChangedSinceVersion: Int? = null): Future?> { val net = services.networkService val req = FetchMapRequest(subscribe, ifChangedSinceVersion, net.myAddress) - return net.sendRequest(FETCH_PROTOCOL_TOPIC, req, mapServiceNode.info.address).map { it.nodes } + return net.sendRequest(FETCH_FLOW_TOPIC, req, mapServiceNode.info.address).map { it.nodes } } } diff --git a/node/src/test/kotlin/net/corda/node/services/MockServiceHubInternal.kt b/node/src/test/kotlin/net/corda/node/services/MockServiceHubInternal.kt index ee0eda720a..85550fd72a 100644 --- a/node/src/test/kotlin/net/corda/node/services/MockServiceHubInternal.kt +++ b/node/src/test/kotlin/net/corda/node/services/MockServiceHubInternal.kt @@ -2,11 +2,11 @@ package net.corda.node.services import com.codahale.metrics.MetricRegistry import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.flows.FlowStateMachine import net.corda.core.node.NodeInfo import net.corda.core.node.services.* -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolLogicRefFactory -import net.corda.core.protocols.ProtocolStateMachine import net.corda.core.transactions.SignedTransaction import net.corda.node.serialization.NodeClock import net.corda.node.services.api.MessagingServiceInternal @@ -34,7 +34,7 @@ open class MockServiceHubInternal( val mapCache: NetworkMapCache? = MockNetworkMapCache(), val scheduler: SchedulerService? = null, val overrideClock: Clock? = NodeClock(), - val protocolFactory: ProtocolLogicRefFactory? = ProtocolLogicRefFactory(), + val flowFactory: FlowLogicRefFactory? = FlowLogicRefFactory(), val schemas: SchemaService? = NodeSchemaService() ) : ServiceHubInternal() { override val vaultService: VaultService = customVault ?: NodeVaultService(this) @@ -56,8 +56,8 @@ open class MockServiceHubInternal( get() = throw UnsupportedOperationException() override val monitoringService: MonitoringService = MonitoringService(MetricRegistry()) - override val protocolLogicRefFactory: ProtocolLogicRefFactory - get() = protocolFactory ?: throw UnsupportedOperationException() + override val flowLogicRefFactory: FlowLogicRefFactory + get() = flowFactory ?: throw UnsupportedOperationException() override val schemaService: SchemaService get() = schemas ?: throw UnsupportedOperationException() @@ -65,7 +65,7 @@ open class MockServiceHubInternal( private val txStorageService: TxWritableStorageService get() = storage ?: throw UnsupportedOperationException() - private val protocolFactories = ConcurrentHashMap, (Party) -> ProtocolLogic<*>>() + private val flowFactories = ConcurrentHashMap, (Party) -> FlowLogic<*>>() lateinit var smm: StateMachineManager @@ -79,13 +79,13 @@ open class MockServiceHubInternal( override fun recordTransactions(txs: Iterable) = recordTransactionsInternal(txStorageService, txs) - override fun startProtocol(logic: ProtocolLogic): ProtocolStateMachine = smm.add(logic) + override fun startFlow(logic: FlowLogic): FlowStateMachine = smm.add(logic) - override fun registerProtocolInitiator(markerClass: KClass<*>, protocolFactory: (Party) -> ProtocolLogic<*>) { - protocolFactories[markerClass.java] = protocolFactory + override fun registerFlowInitiator(markerClass: KClass<*>, flowFactory: (Party) -> FlowLogic<*>) { + flowFactories[markerClass.java] = flowFactory } - override fun getProtocolFactory(markerClass: Class<*>): ((Party) -> ProtocolLogic<*>)? { - return protocolFactories[markerClass] + override fun getFlowFactory(markerClass: Class<*>): ((Party) -> FlowLogic<*>)? { + return flowFactories[markerClass] } } diff --git a/node/src/test/kotlin/net/corda/node/services/NodeSchedulerServiceTest.kt b/node/src/test/kotlin/net/corda/node/services/NodeSchedulerServiceTest.kt index 2537968ee1..bf502a8f83 100644 --- a/node/src/test/kotlin/net/corda/node/services/NodeSchedulerServiceTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/NodeSchedulerServiceTest.kt @@ -4,11 +4,11 @@ import net.corda.core.contracts.* import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.composite import net.corda.core.days +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowLogicRef +import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.node.ServiceHub import net.corda.core.node.recordTransactions -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolLogicRef -import net.corda.core.protocols.ProtocolLogicRefFactory import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.utilities.DUMMY_NOTARY import net.corda.node.services.events.NodeSchedulerService @@ -47,7 +47,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { // We have to allow Java boxed primitives but Kotlin warns we shouldn't be using them @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") - val factory = ProtocolLogicRefFactory(mapOf(Pair(TestProtocolLogic::class.java.name, setOf(NodeSchedulerServiceTest::class.java.name, Integer::class.java.name)))) + val factory = FlowLogicRefFactory(mapOf(Pair(TestFlowLogic::class.java.name, setOf(NodeSchedulerServiceTest::class.java.name, Integer::class.java.name)))) lateinit var services: MockServiceHubInternal @@ -56,12 +56,12 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { lateinit var dataSource: Closeable lateinit var database: Database lateinit var countDown: CountDownLatch - lateinit var smmHasRemovedAllProtocols: CountDownLatch + lateinit var smmHasRemovedAllFlows: CountDownLatch var calls: Int = 0 /** - * Have a reference to this test added to [ServiceHub] so that when the [ProtocolLogic] runs it can access the test instance. + * Have a reference to this test added to [ServiceHub] so that when the [FlowLogic] runs it can access the test instance. * The [TestState] is serialized and deserialized so attempting to use a transient field won't work, as it just * results in NPE. */ @@ -73,7 +73,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { @Before fun setup() { countDown = CountDownLatch(1) - smmHasRemovedAllProtocols = CountDownLatch(1) + smmHasRemovedAllFlows = CountDownLatch(1) calls = 0 val dataSourceAndDatabase = configureDatabase(makeTestDataSourceProperties()) dataSource = dataSourceAndDatabase.first @@ -90,7 +90,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { val mockSMM = StateMachineManager(services, listOf(services, scheduler), DBCheckpointStorage(), smmExecutor, database) mockSMM.changes.subscribe { change -> if (change.addOrRemove == AddOrRemove.REMOVE && mockSMM.allStateMachines.isEmpty()) { - smmHasRemovedAllProtocols.countDown() + smmHasRemovedAllFlows.countDown() } } mockSMM.start() @@ -103,14 +103,14 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { fun tearDown() { // We need to make sure the StateMachineManager is done before shutting down executors. if (services.smm.allStateMachines.isNotEmpty()) { - smmHasRemovedAllProtocols.await() + smmHasRemovedAllFlows.await() } smmExecutor.shutdown() smmExecutor.awaitTermination(60, TimeUnit.SECONDS) dataSource.close() } - class TestState(val protocolLogicRef: ProtocolLogicRef, val instant: Instant) : LinearState, SchedulableState { + class TestState(val flowLogicRef: FlowLogicRef, val instant: Instant) : LinearState, SchedulableState { override val participants: List get() = throw UnsupportedOperationException() @@ -118,13 +118,13 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { override fun isRelevant(ourKeys: Set): Boolean = true - override fun nextScheduledActivity(thisStateRef: StateRef, protocolLogicRefFactory: ProtocolLogicRefFactory): ScheduledActivity? = ScheduledActivity(protocolLogicRef, instant) + override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? = ScheduledActivity(flowLogicRef, instant) override val contract: Contract get() = throw UnsupportedOperationException() } - class TestProtocolLogic(val increment: Int = 1) : ProtocolLogic() { + class TestFlowLogic(val increment: Int = 1) : FlowLogic() { override fun call() { (serviceHub as TestReference).testReference.calls += increment (serviceHub as TestReference).testReference.countDown.countDown() @@ -267,7 +267,7 @@ class NodeSchedulerServiceTest : SingletonSerializeAsToken() { databaseTransaction(database) { apply { val freshKey = services.keyManagementService.freshKey() - val state = TestState(factory.create(TestProtocolLogic::class.java, increment), instant) + val state = TestState(factory.create(TestFlowLogic::class.java, increment), instant) val usefulTX = TransactionType.General.Builder(null).apply { addOutputState(state, DUMMY_NOTARY) addCommand(Command(), freshKey.public.composite) diff --git a/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt b/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt index 84d7b1de9b..2835a8fcc7 100644 --- a/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/NotaryChangeTests.kt @@ -7,12 +7,12 @@ import net.corda.core.node.services.ServiceInfo import net.corda.core.seconds import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY +import net.corda.flows.NotaryChangeFlow.Instigator +import net.corda.flows.StateReplacementException +import net.corda.flows.StateReplacementRefused import net.corda.node.internal.AbstractNode import net.corda.node.services.network.NetworkMapService import net.corda.node.services.transactions.SimpleNotaryService -import net.corda.protocols.NotaryChangeProtocol.Instigator -import net.corda.protocols.StateReplacementException -import net.corda.protocols.StateReplacementRefused import net.corda.testing.node.MockNetwork import org.junit.Before import org.junit.Test @@ -48,8 +48,8 @@ class NotaryChangeTests { fun `should change notary for a state with single participant`() { val state = issueState(clientNodeA, oldNotaryNode) val newNotary = newNotaryNode.info.notaryIdentity - val protocol = Instigator(state, newNotary) - val future = clientNodeA.services.startProtocol(protocol) + val flow = Instigator(state, newNotary) + val future = clientNodeA.services.startFlow(flow) net.runNetwork() @@ -61,8 +61,8 @@ class NotaryChangeTests { fun `should change notary for a state with multiple participants`() { val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode) val newNotary = newNotaryNode.info.notaryIdentity - val protocol = Instigator(state, newNotary) - val future = clientNodeA.services.startProtocol(protocol) + val flow = Instigator(state, newNotary) + val future = clientNodeA.services.startFlow(flow) net.runNetwork() @@ -77,8 +77,8 @@ class NotaryChangeTests { fun `should throw when a participant refuses to change Notary`() { val state = issueMultiPartyState(clientNodeA, clientNodeB, oldNotaryNode) val newEvilNotary = Party("Evil Notary", generateKeyPair().public) - val protocol = Instigator(state, newEvilNotary) - val future = clientNodeA.services.startProtocol(protocol) + val flow = Instigator(state, newEvilNotary) + val future = clientNodeA.services.startFlow(flow) net.runNetwork() @@ -87,7 +87,7 @@ class NotaryChangeTests { assertTrue(error is StateReplacementRefused) } - // TODO: Add more test cases once we have a general protocol/service exception handling mechanism: + // TODO: Add more test cases once we have a general flow/service exception handling mechanism: // - A participant is offline/can't be found on the network // - The requesting party is not a participant // - The requesting party wants to change additional state fields diff --git a/node/src/test/kotlin/net/corda/node/services/NotaryServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/NotaryServiceTests.kt index 0b89899652..8b7b6d63d7 100644 --- a/node/src/test/kotlin/net/corda/node/services/NotaryServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/NotaryServiceTests.kt @@ -11,12 +11,12 @@ import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY +import net.corda.flows.NotaryError +import net.corda.flows.NotaryException +import net.corda.flows.NotaryFlow import net.corda.node.internal.AbstractNode import net.corda.node.services.network.NetworkMapService import net.corda.node.services.transactions.SimpleNotaryService -import net.corda.protocols.NotaryError -import net.corda.protocols.NotaryException -import net.corda.protocols.NotaryProtocol import net.corda.testing.MINI_CORP_KEY import net.corda.testing.node.MockNetwork import org.junit.Before @@ -94,10 +94,10 @@ class NotaryServiceTests { tx.toSignedTransaction(false) } - val firstSpend = NotaryProtocol.Client(stx) - val secondSpend = NotaryProtocol.Client(stx) - clientNode.services.startProtocol(firstSpend) - val future = clientNode.services.startProtocol(secondSpend) + val firstSpend = NotaryFlow.Client(stx) + val secondSpend = NotaryFlow.Client(stx) + clientNode.services.startFlow(firstSpend) + val future = clientNode.services.startFlow(secondSpend) net.runNetwork() @@ -109,8 +109,8 @@ class NotaryServiceTests { private fun runNotaryClient(stx: SignedTransaction): ListenableFuture { - val protocol = NotaryProtocol.Client(stx) - val future = clientNode.services.startProtocol(protocol).resultFuture + val flow = NotaryFlow.Client(stx) + val future = clientNode.services.startFlow(flow).resultFuture net.runNetwork() return future } diff --git a/node/src/test/kotlin/net/corda/node/services/ValidatingNotaryServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/ValidatingNotaryServiceTests.kt index ebf87a3728..e364ea9f5a 100644 --- a/node/src/test/kotlin/net/corda/node/services/ValidatingNotaryServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/ValidatingNotaryServiceTests.kt @@ -8,12 +8,12 @@ import net.corda.core.node.services.ServiceInfo import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY +import net.corda.flows.NotaryError +import net.corda.flows.NotaryException +import net.corda.flows.NotaryFlow import net.corda.node.internal.AbstractNode import net.corda.node.services.network.NetworkMapService import net.corda.node.services.transactions.ValidatingNotaryService -import net.corda.protocols.NotaryError -import net.corda.protocols.NotaryException -import net.corda.protocols.NotaryProtocol import net.corda.testing.MEGA_CORP_KEY import net.corda.testing.MINI_CORP_KEY import net.corda.testing.node.MockNetwork @@ -79,8 +79,8 @@ class ValidatingNotaryServiceTests { } private fun runClient(stx: SignedTransaction): ListenableFuture { - val protocol = NotaryProtocol.Client(stx) - val future = clientNode.services.startProtocol(protocol).resultFuture + val flow = NotaryFlow.Client(stx) + val future = clientNode.services.startFlow(flow).resultFuture net.runNetwork() return future } diff --git a/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt b/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt index 77e4e09af1..c5aeba062f 100644 --- a/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/persistence/DataVendingServiceTests.kt @@ -7,12 +7,12 @@ import net.corda.core.contracts.Issued import net.corda.core.contracts.TransactionType import net.corda.core.contracts.USD import net.corda.core.crypto.Party -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.DUMMY_NOTARY +import net.corda.flows.BroadcastTransactionFlow.NotifyTxRequest import net.corda.node.services.persistence.DataVending.Service.NotifyTransactionHandler import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.BroadcastTransactionProtocol.NotifyTxRequest import net.corda.testing.MEGA_CORP import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork.MockNode @@ -88,13 +88,13 @@ class DataVendingServiceTests { } private fun MockNode.sendNotifyTx(tx: SignedTransaction, walletServiceNode: MockNode) { - walletServiceNode.services.registerProtocolInitiator(NotifyTxProtocol::class, ::NotifyTransactionHandler) - services.startProtocol(NotifyTxProtocol(walletServiceNode.info.legalIdentity, tx)) + walletServiceNode.services.registerFlowInitiator(NotifyTxFlow::class, ::NotifyTransactionHandler) + services.startFlow(NotifyTxFlow(walletServiceNode.info.legalIdentity, tx)) network.runNetwork() } - private class NotifyTxProtocol(val otherParty: Party, val stx: SignedTransaction) : ProtocolLogic() { + private class NotifyTxFlow(val otherParty: Party, val stx: SignedTransaction) : FlowLogic() { @Suspendable override fun call() = send(otherParty, NotifyTxRequest(stx)) } diff --git a/node/src/test/kotlin/net/corda/node/services/statemachine/StateMachineManagerTests.kt b/node/src/test/kotlin/net/corda/node/services/statemachine/StateMachineManagerTests.kt index 0a664c0ae6..1af9d24a32 100644 --- a/node/src/test/kotlin/net/corda/node/services/statemachine/StateMachineManagerTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/statemachine/StateMachineManagerTests.kt @@ -4,14 +4,14 @@ import co.paralleluniverse.fibers.Fiber import co.paralleluniverse.fibers.Suspendable import com.google.common.util.concurrent.ListenableFuture import net.corda.core.crypto.Party -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolSessionException +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowSessionException import net.corda.core.random63BitValue import net.corda.core.serialization.deserialize import net.corda.node.services.persistence.checkpoints import net.corda.node.services.statemachine.StateMachineManager.* import net.corda.node.utilities.databaseTransaction -import net.corda.testing.initiateSingleShotProtocol +import net.corda.testing.initiateSingleShotFlow import net.corda.testing.node.InMemoryMessagingNetwork import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer import net.corda.testing.node.MockNetwork @@ -49,29 +49,29 @@ class StateMachineManagerTests { } @Test - fun `newly added protocol is preserved on restart`() { - node1.smm.add(NoOpProtocol(nonTerminating = true)) + fun `newly added flow is preserved on restart`() { + node1.smm.add(NoOpFlow(nonTerminating = true)) node1.acceptableLiveFiberCountOnStop = 1 - val restoredProtocol = node1.restartAndGetRestoredProtocol() - assertThat(restoredProtocol.protocolStarted).isTrue() + val restoredFlow = node1.restartAndGetRestoredFlow() + assertThat(restoredFlow.flowStarted).isTrue() } @Test - fun `protocol can lazily use the serviceHub in its constructor`() { - val protocol = object : ProtocolLogic() { + fun `flow can lazily use the serviceHub in its constructor`() { + val flow = object : FlowLogic() { val lazyTime by lazy { serviceHub.clock.instant() } @Suspendable override fun call() = Unit } - node1.smm.add(protocol) - assertThat(protocol.lazyTime).isNotNull() + node1.smm.add(flow) + assertThat(flow.lazyTime).isNotNull() } @Test - fun `protocol restarted just after receiving payload`() { - node2.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) } + fun `flow restarted just after receiving payload`() { + node2.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) } val payload = random63BitValue() - node1.smm.add(SendProtocol(payload, node2.info.legalIdentity)) + node1.smm.add(SendFlow(payload, node2.info.legalIdentity)) // We push through just enough messages to get only the payload sent node2.pumpReceive() @@ -79,60 +79,60 @@ class StateMachineManagerTests { node2.acceptableLiveFiberCountOnStop = 1 node2.stop() net.runNetwork() - val restoredProtocol = node2.restartAndGetRestoredProtocol(node1) - assertThat(restoredProtocol.receivedPayloads[0]).isEqualTo(payload) + val restoredFlow = node2.restartAndGetRestoredFlow(node1) + assertThat(restoredFlow.receivedPayloads[0]).isEqualTo(payload) } @Test - fun `protocol added before network map does run after init`() { + fun `flow added before network map does run after init`() { val node3 = net.createNode(node1.info.address) //create vanilla node - val protocol = NoOpProtocol() - node3.smm.add(protocol) - assertEquals(false, protocol.protocolStarted) // Not started yet as no network activity has been allowed yet + val flow = NoOpFlow() + node3.smm.add(flow) + assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet net.runNetwork() // Allow network map messages to flow - assertEquals(true, protocol.protocolStarted) // Now we should have run the protocol + assertEquals(true, flow.flowStarted) // Now we should have run the flow } @Test - fun `protocol added before network map will be init checkpointed`() { + fun `flow added before network map will be init checkpointed`() { var node3 = net.createNode(node1.info.address) //create vanilla node - val protocol = NoOpProtocol() - node3.smm.add(protocol) - assertEquals(false, protocol.protocolStarted) // Not started yet as no network activity has been allowed yet + val flow = NoOpFlow() + node3.smm.add(flow) + assertEquals(false, flow.flowStarted) // Not started yet as no network activity has been allowed yet node3.disableDBCloseOnStop() node3.stop() node3 = net.createNode(node1.info.address, forcedID = node3.id) - val restoredProtocol = node3.getSingleProtocol().first - assertEquals(false, restoredProtocol.protocolStarted) // Not started yet as no network activity has been allowed yet + val restoredFlow = node3.getSingleFlow().first + assertEquals(false, restoredFlow.flowStarted) // Not started yet as no network activity has been allowed yet net.runNetwork() // Allow network map messages to flow node3.smm.executor.flush() - assertEquals(true, restoredProtocol.protocolStarted) // Now we should have run the protocol and hopefully cleared the init checkpoint + assertEquals(true, restoredFlow.flowStarted) // Now we should have run the flow and hopefully cleared the init checkpoint node3.disableDBCloseOnStop() node3.stop() - // Now it is completed the protocol should leave no Checkpoint. + // Now it is completed the flow should leave no Checkpoint. node3 = net.createNode(node1.info.address, forcedID = node3.id) net.runNetwork() // Allow network map messages to flow node3.smm.executor.flush() - assertTrue(node3.smm.findStateMachines(NoOpProtocol::class.java).isEmpty()) + assertTrue(node3.smm.findStateMachines(NoOpFlow::class.java).isEmpty()) } @Test - fun `protocol loaded from checkpoint will respond to messages from before start`() { + fun `flow loaded from checkpoint will respond to messages from before start`() { val payload = random63BitValue() - node1.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(payload, it) } - node2.smm.add(ReceiveThenSuspendProtocol(node1.info.legalIdentity)) // Prepare checkpointed receive protocol + node1.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(payload, it) } + node2.smm.add(ReceiveThenSuspendFlow(node1.info.legalIdentity)) // Prepare checkpointed receive flow // Make sure the add() has finished initial processing. node2.smm.executor.flush() node2.disableDBCloseOnStop() node2.stop() // kill receiver - val restoredProtocol = node2.restartAndGetRestoredProtocol(node1) - assertThat(restoredProtocol.receivedPayloads[0]).isEqualTo(payload) + val restoredFlow = node2.restartAndGetRestoredFlow(node1) + assertThat(restoredFlow.receivedPayloads[0]).isEqualTo(payload) } @Test - fun `protocol with send will resend on interrupted restart`() { + fun `flow with send will resend on interrupted restart`() { val payload = random63BitValue() val payload2 = random63BitValue() @@ -140,11 +140,11 @@ class StateMachineManagerTests { net.messagingNetwork.sentMessages.toSessionTransfers().filter { it.isPayloadTransfer }.forEach { sentCount++ } val node3 = net.createNode(node1.info.address) - val secondProtocol = node3.initiateSingleShotProtocol(PingPongProtocol::class) { PingPongProtocol(it, payload2) } + val secondFlow = node3.initiateSingleShotFlow(PingPongFlow::class) { PingPongFlow(it, payload2) } net.runNetwork() // Kick off first send and receive - node2.smm.add(PingPongProtocol(node3.info.legalIdentity, payload)) + node2.smm.add(PingPongFlow(node3.info.legalIdentity, payload)) databaseTransaction(node2.database) { assertEquals(1, node2.checkpointStorage.checkpoints().size) } @@ -158,55 +158,55 @@ class StateMachineManagerTests { } val node2b = net.createNode(node1.info.address, node2.id, advertisedServices = *node2.advertisedServices.toTypedArray()) node2.manuallyCloseDB() - val (firstAgain, fut1) = node2b.getSingleProtocol() - // Run the network which will also fire up the second protocol. First message should get deduped. So message data stays in sync. + val (firstAgain, fut1) = node2b.getSingleFlow() + // Run the network which will also fire up the second flow. First message should get deduped. So message data stays in sync. net.runNetwork() node2b.smm.executor.flush() fut1.get() val receivedCount = sessionTransfers.count { it.isPayloadTransfer } - // Check protocols completed cleanly and didn't get out of phase - assertEquals(4, receivedCount, "Protocol should have exchanged 4 unique messages")// Two messages each way + // Check flows completed cleanly and didn't get out of phase + assertEquals(4, receivedCount, "Flow should have exchanged 4 unique messages")// Two messages each way // can't give a precise value as every addMessageHandler re-runs the undelivered messages assertTrue(sentCount > receivedCount, "Node restart should have retransmitted messages") databaseTransaction(node2b.database) { - assertEquals(0, node2b.checkpointStorage.checkpoints().size, "Checkpoints left after restored protocol should have ended") + assertEquals(0, node2b.checkpointStorage.checkpoints().size, "Checkpoints left after restored flow should have ended") } databaseTransaction(node3.database) { - assertEquals(0, node3.checkpointStorage.checkpoints().size, "Checkpoints left after restored protocol should have ended") + assertEquals(0, node3.checkpointStorage.checkpoints().size, "Checkpoints left after restored flow should have ended") } assertEquals(payload2, firstAgain.receivedPayload, "Received payload does not match the first value on Node 3") assertEquals(payload2 + 1, firstAgain.receivedPayload2, "Received payload does not match the expected second value on Node 3") - assertEquals(payload, secondProtocol.get().receivedPayload, "Received payload does not match the (restarted) first value on Node 2") - assertEquals(payload + 1, secondProtocol.get().receivedPayload2, "Received payload does not match the expected second value on Node 2") + assertEquals(payload, secondFlow.get().receivedPayload, "Received payload does not match the (restarted) first value on Node 2") + assertEquals(payload + 1, secondFlow.get().receivedPayload2, "Received payload does not match the expected second value on Node 2") } @Test fun `sending to multiple parties`() { val node3 = net.createNode(node1.info.address) net.runNetwork() - node2.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) } - node3.services.registerProtocolInitiator(SendProtocol::class) { ReceiveThenSuspendProtocol(it) } + node2.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) } + node3.services.registerFlowInitiator(SendFlow::class) { ReceiveThenSuspendFlow(it) } val payload = random63BitValue() - node1.smm.add(SendProtocol(payload, node2.info.legalIdentity, node3.info.legalIdentity)) + node1.smm.add(SendFlow(payload, node2.info.legalIdentity, node3.info.legalIdentity)) net.runNetwork() - val node2Protocol = node2.getSingleProtocol().first - val node3Protocol = node3.getSingleProtocol().first - assertThat(node2Protocol.receivedPayloads[0]).isEqualTo(payload) - assertThat(node3Protocol.receivedPayloads[0]).isEqualTo(payload) + val node2Flow = node2.getSingleFlow().first + val node3Flow = node3.getSingleFlow().first + assertThat(node2Flow.receivedPayloads[0]).isEqualTo(payload) + assertThat(node3Flow.receivedPayloads[0]).isEqualTo(payload) assertSessionTransfers(node2, - node1 sent sessionInit(node1, SendProtocol::class, payload) to node2, + node1 sent sessionInit(node1, SendFlow::class, payload) to node2, node2 sent sessionConfirm() to node1, node1 sent sessionEnd() to node2 - //There's no session end from the other protocols as they're manually suspended + //There's no session end from the other flows as they're manually suspended ) assertSessionTransfers(node3, - node1 sent sessionInit(node1, SendProtocol::class, payload) to node3, + node1 sent sessionInit(node1, SendFlow::class, payload) to node3, node3 sent sessionConfirm() to node1, node1 sent sessionEnd() to node3 - //There's no session end from the other protocols as they're manually suspended + //There's no session end from the other flows as they're manually suspended ) node2.acceptableLiveFiberCountOnStop = 1 @@ -219,24 +219,24 @@ class StateMachineManagerTests { net.runNetwork() val node2Payload = random63BitValue() val node3Payload = random63BitValue() - node2.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(node2Payload, it) } - node3.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { SendProtocol(node3Payload, it) } - val multiReceiveProtocol = ReceiveThenSuspendProtocol(node2.info.legalIdentity, node3.info.legalIdentity) - node1.smm.add(multiReceiveProtocol) + node2.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(node2Payload, it) } + node3.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { SendFlow(node3Payload, it) } + val multiReceiveFlow = ReceiveThenSuspendFlow(node2.info.legalIdentity, node3.info.legalIdentity) + node1.smm.add(multiReceiveFlow) node1.acceptableLiveFiberCountOnStop = 1 net.runNetwork() - assertThat(multiReceiveProtocol.receivedPayloads[0]).isEqualTo(node2Payload) - assertThat(multiReceiveProtocol.receivedPayloads[1]).isEqualTo(node3Payload) + assertThat(multiReceiveFlow.receivedPayloads[0]).isEqualTo(node2Payload) + assertThat(multiReceiveFlow.receivedPayloads[1]).isEqualTo(node3Payload) assertSessionTransfers(node2, - node1 sent sessionInit(node1, ReceiveThenSuspendProtocol::class) to node2, + node1 sent sessionInit(node1, ReceiveThenSuspendFlow::class) to node2, node2 sent sessionConfirm() to node1, node2 sent sessionData(node2Payload) to node1, node2 sent sessionEnd() to node1 ) assertSessionTransfers(node3, - node1 sent sessionInit(node1, ReceiveThenSuspendProtocol::class) to node3, + node1 sent sessionInit(node1, ReceiveThenSuspendFlow::class) to node3, node3 sent sessionConfirm() to node1, node3 sent sessionData(node3Payload) to node1, node3 sent sessionEnd() to node1 @@ -245,12 +245,12 @@ class StateMachineManagerTests { @Test fun `both sides do a send as their first IO request`() { - node2.services.registerProtocolInitiator(PingPongProtocol::class) { PingPongProtocol(it, 20L) } - node1.smm.add(PingPongProtocol(node2.info.legalIdentity, 10L)) + node2.services.registerFlowInitiator(PingPongFlow::class) { PingPongFlow(it, 20L) } + node1.smm.add(PingPongFlow(node2.info.legalIdentity, 10L)) net.runNetwork() assertSessionTransfers( - node1 sent sessionInit(node1, PingPongProtocol::class, 10L) to node2, + node1 sent sessionInit(node1, PingPongFlow::class, 10L) to node2, node2 sent sessionConfirm() to node1, node2 sent sessionData(20L) to node1, node1 sent sessionData(11L) to node2, @@ -261,18 +261,18 @@ class StateMachineManagerTests { @Test fun `exception thrown on other side`() { - node2.services.registerProtocolInitiator(ReceiveThenSuspendProtocol::class) { ExceptionProtocol } - val future = node1.smm.add(ReceiveThenSuspendProtocol(node2.info.legalIdentity)).resultFuture + node2.services.registerFlowInitiator(ReceiveThenSuspendFlow::class) { ExceptionFlow } + val future = node1.smm.add(ReceiveThenSuspendFlow(node2.info.legalIdentity)).resultFuture net.runNetwork() - assertThatThrownBy { future.get() }.hasCauseInstanceOf(ProtocolSessionException::class.java) + assertThatThrownBy { future.get() }.hasCauseInstanceOf(FlowSessionException::class.java) assertSessionTransfers( - node1 sent sessionInit(node1, ReceiveThenSuspendProtocol::class) to node2, + node1 sent sessionInit(node1, ReceiveThenSuspendFlow::class) to node2, node2 sent sessionConfirm() to node1, node2 sent sessionEnd() to node1 ) } - private inline fun > MockNode.restartAndGetRestoredProtocol( + private inline fun > MockNode.restartAndGetRestoredFlow( networkMapNode: MockNode? = null): P { disableDBCloseOnStop() //Handover DB to new node copy stop() @@ -280,15 +280,15 @@ class StateMachineManagerTests { newNode.acceptableLiveFiberCountOnStop = 1 manuallyCloseDB() mockNet.runNetwork() // allow NetworkMapService messages to stabilise and thus start the state machine - return newNode.getSingleProtocol

().first + return newNode.getSingleFlow

().first } - private inline fun > MockNode.getSingleProtocol(): Pair> { + private inline fun > MockNode.getSingleFlow(): Pair> { return smm.findStateMachines(P::class.java).single() } - private fun sessionInit(initiatorNode: MockNode, protocolMarker: KClass<*>, payload: Any? = null): SessionInit { - return SessionInit(0, initiatorNode.info.legalIdentity, protocolMarker.java.name, payload) + private fun sessionInit(initiatorNode: MockNode, flowMarker: KClass<*>, payload: Any? = null): SessionInit { + return SessionInit(0, initiatorNode.info.legalIdentity, flowMarker.java.name, payload) } private fun sessionConfirm() = SessionConfirm(0, 0) @@ -334,13 +334,13 @@ class StateMachineManagerTests { private infix fun Pair.to(node: MockNode): SessionTransfer = SessionTransfer(first, second, node.id) - private class NoOpProtocol(val nonTerminating: Boolean = false) : ProtocolLogic() { + private class NoOpFlow(val nonTerminating: Boolean = false) : FlowLogic() { - @Transient var protocolStarted = false + @Transient var flowStarted = false @Suspendable override fun call() { - protocolStarted = true + flowStarted = true if (nonTerminating) { Fiber.park() } @@ -348,7 +348,7 @@ class StateMachineManagerTests { } - private class SendProtocol(val payload: Any, vararg val otherParties: Party) : ProtocolLogic() { + private class SendFlow(val payload: Any, vararg val otherParties: Party) : FlowLogic() { init { require(otherParties.isNotEmpty()) @@ -359,7 +359,7 @@ class StateMachineManagerTests { } - private class ReceiveThenSuspendProtocol(vararg val otherParties: Party) : ProtocolLogic() { + private class ReceiveThenSuspendFlow(vararg val otherParties: Party) : FlowLogic() { init { require(otherParties.isNotEmpty()) @@ -375,7 +375,7 @@ class StateMachineManagerTests { } } - private class PingPongProtocol(val otherParty: Party, val payload: Long) : ProtocolLogic() { + private class PingPongFlow(val otherParty: Party, val payload: Long) : FlowLogic() { @Transient var receivedPayload: Long? = null @Transient var receivedPayload2: Long? = null @@ -383,13 +383,13 @@ class StateMachineManagerTests { @Suspendable override fun call() { receivedPayload = sendAndReceive(otherParty, payload).unwrap { it } - println("${psm.id} Received $receivedPayload") + println("${fsm.id} Received $receivedPayload") receivedPayload2 = sendAndReceive(otherParty, payload + 1).unwrap { it } - println("${psm.id} Received $receivedPayload2") + println("${fsm.id} Received $receivedPayload2") } } - private object ExceptionProtocol : ProtocolLogic() { + private object ExceptionFlow : FlowLogic() { override fun call(): Nothing = throw Exception() } diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/api/AttachmentDemoApi.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/api/AttachmentDemoApi.kt index 8814939ee1..6d85e8cabd 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/api/AttachmentDemoApi.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/api/AttachmentDemoApi.kt @@ -8,7 +8,7 @@ import net.corda.core.success import net.corda.core.utilities.ApiUtils import net.corda.core.utilities.Emoji import net.corda.core.utilities.loggerFor -import net.corda.protocols.FinalityProtocol +import net.corda.flows.FinalityFlow import net.corda.testing.ALICE_KEY import java.util.concurrent.CompletableFuture import javax.ws.rs.* @@ -49,10 +49,10 @@ class AttachmentDemoApi(val services: ServiceHub) { // Send the transaction to the other recipient val tx = ptx.toSignedTransaction() - services.invokeProtocolAsync(FinalityProtocol::class.java, tx, setOf(it)).resultFuture.success { - println("Successfully sent attachment with the FinalityProtocol") + services.invokeFlowAsync(FinalityFlow::class.java, tx, setOf(it)).resultFuture.success { + println("Successfully sent attachment with the FinalityFlow") }.failure { - logger.error("Failed to send attachment with the FinalityProtocol", it) + logger.error("Failed to send attachment with the FinalityFlow") } Response.accepted().build() @@ -64,10 +64,10 @@ class AttachmentDemoApi(val services: ServiceHub) { @Consumes(MediaType.APPLICATION_JSON) fun runRecipient(): Response { val future = CompletableFuture() - // Normally we would receive the transaction from a more specific protocol, but in this case we let [FinalityProtocol] + // Normally we would receive the transaction from a more specific flow, but in this case we let [FinalityFlow] // handle receiving it for us. services.storageService.validatedTransactions.updates.subscribe { event -> - // When the transaction is received, it's passed through [ResolveTransactionsProtocol], which first fetches any + // When the transaction is received, it's passed through [ResolveTransactionsFlow], which first fetches any // attachments for us, then verifies the transaction. As such, by the time it hits the validated transaction store, // we have a copy of the attachment. val tx = event.tx diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/plugin/AttachmentDemoPlugin.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/plugin/AttachmentDemoPlugin.kt index b8c82ca714..4605eb3f1c 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/plugin/AttachmentDemoPlugin.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/plugin/AttachmentDemoPlugin.kt @@ -3,14 +3,14 @@ package net.corda.attachmentdemo.plugin import net.corda.attachmentdemo.api.AttachmentDemoApi import net.corda.core.node.CordaPluginRegistry import net.corda.core.transactions.SignedTransaction -import net.corda.protocols.FinalityProtocol +import net.corda.flows.FinalityFlow class AttachmentDemoPlugin : CordaPluginRegistry() { // A list of classes that expose web APIs. override val webApis: List> = listOf(AttachmentDemoApi::class.java) - // A list of protocols that are required for this cordapp - override val requiredProtocols: Map> = mapOf( - FinalityProtocol::class.java.name to setOf(SignedTransaction::class.java.name, setOf(Unit).javaClass.name, setOf(Unit).javaClass.name) + // A list of flows that are required for this cordapp + override val requiredFlows: Map> = mapOf( + FinalityFlow::class.java.name to setOf(SignedTransaction::class.java.name, setOf(Unit).javaClass.name, setOf(Unit).javaClass.name) ) override val servicePlugins: List> = listOf() } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt index d7375b245f..4bd9655d64 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/InterestRateSwapAPI.kt @@ -4,9 +4,9 @@ import net.corda.core.node.ServiceHub import net.corda.core.node.services.linearHeadsOfType import net.corda.core.utilities.loggerFor import net.corda.irs.contract.InterestRateSwap -import net.corda.irs.protocols.AutoOfferProtocol -import net.corda.irs.protocols.ExitServerProtocol -import net.corda.irs.protocols.UpdateBusinessDayProtocol +import net.corda.irs.flows.AutoOfferFlow +import net.corda.irs.flows.ExitServerFlow +import net.corda.irs.flows.UpdateBusinessDayFlow import java.net.URI import java.time.LocalDate import java.time.LocalDateTime @@ -65,7 +65,7 @@ class InterestRateSwapAPI(val services: ServiceHub) { @Consumes(MediaType.APPLICATION_JSON) fun storeDeal(newDeal: InterestRateSwap.State): Response { try { - services.invokeProtocolAsync(AutoOfferProtocol.Requester::class.java, newDeal).resultFuture.get() + services.invokeFlowAsync(AutoOfferFlow.Requester::class.java, newDeal).resultFuture.get() return Response.created(URI.create(generateDealLink(newDeal))).build() } catch (ex: Throwable) { logger.info("Exception when creating deal: $ex") @@ -92,7 +92,7 @@ class InterestRateSwapAPI(val services: ServiceHub) { val priorDemoDate = fetchDemoDate() // Can only move date forwards if (newDemoDate.isAfter(priorDemoDate)) { - services.invokeProtocolAsync(UpdateBusinessDayProtocol.Broadcast::class.java, newDemoDate).resultFuture.get() + services.invokeFlowAsync(UpdateBusinessDayFlow.Broadcast::class.java, newDemoDate).resultFuture.get() return Response.ok().build() } val msg = "demodate is already $priorDemoDate and can only be updated with a later date" @@ -111,7 +111,7 @@ class InterestRateSwapAPI(val services: ServiceHub) { @Path("restart") @Consumes(MediaType.APPLICATION_JSON) fun exitServer(): Response { - services.invokeProtocolAsync(ExitServerProtocol.Broadcast::class.java, 83).resultFuture.get() + services.invokeFlowAsync(ExitServerFlow.Broadcast::class.java, 83).resultFuture.get() return Response.ok().build() } } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt index ef8903e806..999e6989d6 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/api/NodeInterestRates.kt @@ -4,18 +4,18 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.RetryableException import net.corda.core.contracts.* import net.corda.core.crypto.* +import net.corda.core.flows.FlowLogic import net.corda.core.math.CubicSplineInterpolator import net.corda.core.math.Interpolator import net.corda.core.math.InterpolatorFactory import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.PluginServiceHub import net.corda.core.node.services.ServiceType -import net.corda.core.protocols.ProtocolLogic import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.transactions.FilteredTransaction import net.corda.core.utilities.ProgressTracker -import net.corda.irs.protocols.FixingProtocol -import net.corda.irs.protocols.RatesFixProtocol +import net.corda.irs.flows.FixingFlow +import net.corda.irs.flows.RatesFixFlow import net.corda.node.services.api.AcceptsFileUpload import net.corda.node.utilities.AbstractJDBCHashSet import net.corda.node.utilities.FiberBox @@ -46,10 +46,10 @@ object NodeInterestRates { val type = ServiceType.corda.getSubType("interest_rates") /** - * Register the protocol that is used with the Fixing integration tests. + * Register the flow that is used with the Fixing integration tests. */ class Plugin : CordaPluginRegistry() { - override val requiredProtocols: Map> = mapOf(Pair(FixingProtocol.FixingRoleDecider::class.java.name, setOf(Duration::class.java.name, StateRef::class.java.name))) + override val requiredFlows: Map> = mapOf(Pair(FixingFlow.FixingRoleDecider::class.java.name, setOf(Duration::class.java.name, StateRef::class.java.name))) override val servicePlugins: List> = listOf(Service::class.java) } @@ -67,20 +67,20 @@ object NodeInterestRates { init { // Note access to the singleton oracle property is via the registered SingletonSerializeAsToken Service. // Otherwise the Kryo serialisation of the call stack in the Quasar Fiber extends to include - // the framework Oracle and the protocol will crash. - services.registerProtocolInitiator(RatesFixProtocol.FixSignProtocol::class) { FixSignHandler(it, this) } - services.registerProtocolInitiator(RatesFixProtocol.FixQueryProtocol::class) { FixQueryHandler(it, this) } + // the framework Oracle and the flow will crash. + services.registerFlowInitiator(RatesFixFlow.FixSignFlow::class) { FixSignHandler(it, this) } + services.registerFlowInitiator(RatesFixFlow.FixQueryFlow::class) { FixQueryHandler(it, this) } } - private class FixSignHandler(val otherParty: Party, val service: Service) : ProtocolLogic() { + private class FixSignHandler(val otherParty: Party, val service: Service) : FlowLogic() { @Suspendable override fun call() { - val request = receive(otherParty).unwrap { it } + val request = receive(otherParty).unwrap { it } send(otherParty, service.oracle.sign(request.ftx, request.rootHash)) } } - private class FixQueryHandler(val otherParty: Party, val service: Service) : ProtocolLogic() { + private class FixQueryHandler(val otherParty: Party, val service: Service) : FlowLogic() { companion object { object RECEIVED : ProgressTracker.Step("Received fix request") @@ -95,7 +95,7 @@ object NodeInterestRates { @Suspendable override fun call(): Unit { - val request = receive(otherParty).unwrap { it } + val request = receive(otherParty).unwrap { it } val answers = service.oracle.query(request.queries, request.deadline) progressTracker.currentStep = SENDING send(otherParty, answers) diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt index bc80b434bb..3e51db166a 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/contract/IRS.kt @@ -5,10 +5,10 @@ import net.corda.core.contracts.clauses.* import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.node.services.ServiceType -import net.corda.core.protocols.ProtocolLogicRefFactory import net.corda.core.transactions.TransactionBuilder -import net.corda.irs.protocols.FixingProtocol +import net.corda.irs.flows.FixingFlow import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow import org.apache.commons.jexl3.JexlBuilder import org.apache.commons.jexl3.MapContext @@ -674,12 +674,12 @@ class InterestRateSwap() : Contract { override val parties: List get() = listOf(fixedLeg.fixedRatePayer, floatingLeg.floatingRatePayer) - override fun nextScheduledActivity(thisStateRef: StateRef, protocolLogicRefFactory: ProtocolLogicRefFactory): ScheduledActivity? { + override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? { val nextFixingOf = nextFixingOf() ?: return null // This is perhaps not how we should determine the time point in the business day, but instead expect the schedule to detail some of these aspects val instant = suggestInterestRateAnnouncementTimeWindow(index = nextFixingOf.name, source = floatingLeg.indexSource, date = nextFixingOf.forDay).start - return ScheduledActivity(protocolLogicRefFactory.create(FixingProtocol.FixingRoleDecider::class.java, thisStateRef), instant) + return ScheduledActivity(flowLogicRefFactory.create(FixingFlow.FixingRoleDecider::class.java, thisStateRef), instant) } override fun generateAgreement(notary: Party): TransactionBuilder = InterestRateSwap().generateAgreement(floatingLeg, fixedLeg, calculation, common, notary) diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/AutoOfferProtocol.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/AutoOfferFlow.kt similarity index 76% rename from samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/AutoOfferProtocol.kt rename to samples/irs-demo/src/main/kotlin/net/corda/irs/flows/AutoOfferFlow.kt index 67ab892e8d..4f800808aa 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/AutoOfferProtocol.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/AutoOfferFlow.kt @@ -1,28 +1,27 @@ -package net.corda.irs.protocols +package net.corda.irs.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.DealState import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.PluginServiceHub -import net.corda.core.protocols.ProtocolLogic import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker -import net.corda.node.services.api.ServiceHubInternal -import net.corda.protocols.TwoPartyDealProtocol -import net.corda.protocols.TwoPartyDealProtocol.Acceptor -import net.corda.protocols.TwoPartyDealProtocol.AutoOffer -import net.corda.protocols.TwoPartyDealProtocol.Instigator +import net.corda.flows.TwoPartyDealFlow +import net.corda.flows.TwoPartyDealFlow.Acceptor +import net.corda.flows.TwoPartyDealFlow.AutoOffer +import net.corda.flows.TwoPartyDealFlow.Instigator /** * This whole class is really part of a demo just to initiate the agreement of a deal with a simple * API call from a single party without bi-directional access to the database of offers etc. * * In the "real world", we'd probably have the offers sitting in the platform prior to the agreement step - * or the protocol would have to reach out to external systems (or users) to verify the deals. + * or the flow would have to reach out to external systems (or users) to verify the deals. */ -object AutoOfferProtocol { +object AutoOfferFlow { class Plugin : CordaPluginRegistry() { override val servicePlugins: List> = listOf(Service::class.java) @@ -31,24 +30,24 @@ object AutoOfferProtocol { class Service(services: PluginServiceHub) : SingletonSerializeAsToken() { - object DEALING : ProgressTracker.Step("Starting the deal protocol") { - override fun childProgressTracker(): ProgressTracker = TwoPartyDealProtocol.Secondary.tracker() + object DEALING : ProgressTracker.Step("Starting the deal flow") { + override fun childProgressTracker(): ProgressTracker = TwoPartyDealFlow.Secondary.tracker() } init { - services.registerProtocolInitiator(Instigator::class) { Acceptor(it) } + services.registerFlowInitiator(Instigator::class) { Acceptor(it) } } } - class Requester(val dealToBeOffered: DealState) : ProtocolLogic() { + class Requester(val dealToBeOffered: DealState) : FlowLogic() { companion object { object RECEIVED : ProgressTracker.Step("Received API call") - object DEALING : ProgressTracker.Step("Starting the deal protocol") { - override fun childProgressTracker(): ProgressTracker = TwoPartyDealProtocol.Primary.tracker() + object DEALING : ProgressTracker.Step("Starting the deal flow") { + override fun childProgressTracker(): ProgressTracker = TwoPartyDealFlow.Primary.tracker() } - // We vend a progress tracker that already knows there's going to be a TwoPartyTradingProtocol involved at some + // We vend a progress tracker that already knows there's going to be a TwoPartyTradingFlow involved at some // point: by setting up the tracker in advance, the user can see what's coming in more detail, instead of being // surprised when it appears as a new set of tasks below the current one. fun tracker() = ProgressTracker(RECEIVED, DEALING) @@ -74,7 +73,7 @@ object AutoOfferProtocol { myKey, progressTracker.getChildProgressTracker(DEALING)!! ) - val stx = subProtocol(instigator) + val stx = subFlow(instigator) return stx } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/ExitServerProtocol.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/ExitServerFlow.kt similarity index 82% rename from samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/ExitServerProtocol.kt rename to samples/irs-demo/src/main/kotlin/net/corda/irs/flows/ExitServerFlow.kt index 47fbe8f68c..ff3770f03d 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/ExitServerProtocol.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/ExitServerFlow.kt @@ -1,23 +1,22 @@ -package net.corda.irs.protocols +package net.corda.irs.flows import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.strands.Strand import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.NodeInfo import net.corda.core.node.PluginServiceHub -import net.corda.core.protocols.ProtocolLogic -import net.corda.node.services.api.ServiceHubInternal import net.corda.testing.node.MockNetworkMapCache import java.util.concurrent.TimeUnit -object ExitServerProtocol { +object ExitServerFlow { // Will only be enabled if you install the Handler @Volatile private var enabled = false // This is not really a HandshakeMessage but needs to be so that the send uses the default session ID. This will - // resolve itself when the protocol session stuff is done. + // resolve itself when the flow session stuff is done. data class ExitMessage(val exitCode: Int) class Plugin: CordaPluginRegistry() { @@ -26,13 +25,13 @@ object ExitServerProtocol { class Service(services: PluginServiceHub) { init { - services.registerProtocolInitiator(Broadcast::class, ::ExitServerHandler) + services.registerFlowInitiator(Broadcast::class, ::ExitServerHandler) enabled = true } } - private class ExitServerHandler(val otherParty: Party) : ProtocolLogic() { + private class ExitServerHandler(val otherParty: Party) : FlowLogic() { override fun call() { // Just to validate we got the message if (enabled) { @@ -47,7 +46,7 @@ object ExitServerProtocol { * This takes a Java Integer rather than Kotlin Int as that is what we end up with in the calling map and currently * we do not support coercing numeric types in the reflective search for matching constructors. */ - class Broadcast(val exitCode: Int) : ProtocolLogic() { + class Broadcast(val exitCode: Int) : FlowLogic() { @Suspendable override fun call(): Boolean { diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/FixingProtocol.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/FixingFlow.kt similarity index 77% rename from samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/FixingProtocol.kt rename to samples/irs-demo/src/main/kotlin/net/corda/irs/flows/FixingFlow.kt index f391798960..d1f0c6a5d2 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/FixingProtocol.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/FixingFlow.kt @@ -1,45 +1,45 @@ -package net.corda.irs.protocols +package net.corda.irs.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.TransientProperty import net.corda.core.contracts.* import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.NodeInfo import net.corda.core.node.PluginServiceHub import net.corda.core.node.services.ServiceType -import net.corda.core.protocols.ProtocolLogic import net.corda.core.seconds import net.corda.core.transactions.FilterFuns import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.ProgressTracker import net.corda.core.utilities.trace -import net.corda.protocols.TwoPartyDealProtocol +import net.corda.flows.TwoPartyDealFlow import java.math.BigDecimal import java.security.KeyPair -object FixingProtocol { +object FixingFlow { class Service(services: PluginServiceHub) { init { - services.registerProtocolInitiator(Floater::class) { Fixer(it) } + services.registerFlowInitiator(Floater::class) { Fixer(it) } } } /** - * One side of the fixing protocol for an interest rate swap, but could easily be generalised further. + * One side of the fixing flow for an interest rate swap, but could easily be generalised further. * * Do not infer too much from the name of the class. This is just to indicate that it is the "side" - * of the protocol that is run by the party with the fixed leg of swap deal, which is the basis for deciding - * who does what in the protocol. + * of the flow that is run by the party with the fixed leg of swap deal, which is the basis for deciding + * who does what in the flow. */ class Fixer(override val otherParty: Party, - override val progressTracker: ProgressTracker = TwoPartyDealProtocol.Secondary.tracker()) : TwoPartyDealProtocol.Secondary() { + override val progressTracker: ProgressTracker = TwoPartyDealFlow.Secondary.tracker()) : TwoPartyDealFlow.Secondary() { private lateinit var txState: TransactionState<*> private lateinit var deal: FixableDealState - override fun validateHandshake(handshake: TwoPartyDealProtocol.Handshake): TwoPartyDealProtocol.Handshake { + override fun validateHandshake(handshake: TwoPartyDealFlow.Handshake): TwoPartyDealFlow.Handshake { logger.trace { "Got fixing request for: ${handshake.payload}" } txState = serviceHub.loadState(handshake.payload.ref) @@ -55,7 +55,7 @@ object FixingProtocol { } @Suspendable - override fun assembleSharedTX(handshake: TwoPartyDealProtocol.Handshake): Pair> { + override fun assembleSharedTX(handshake: TwoPartyDealFlow.Handshake): Pair> { @Suppress("UNCHECKED_CAST") val fixOf = deal.nextFixingOf()!! @@ -70,10 +70,10 @@ object FixingProtocol { val oracle = serviceHub.networkMapCache.get(handshake.payload.oracleType).first() val oracleParty = oracle.serviceIdentities(handshake.payload.oracleType).first() - // TODO Could it be solved in better way, move filtering here not in RatesFixProtocol? + // TODO Could it be solved in better way, move filtering here not in RatesFixFlow? fun filterCommands(c: Command) = oracleParty.owningKey in c.signers && c.value is Fix val filterFuns = FilterFuns(filterCommands = ::filterCommands) - val addFixing = object : RatesFixProtocol(ptx, filterFuns, oracleParty, fixOf, BigDecimal.ZERO, BigDecimal.ONE) { + val addFixing = object : RatesFixFlow(ptx, filterFuns, oracleParty, fixOf, BigDecimal.ZERO, BigDecimal.ONE) { @Suspendable override fun beforeSigning(fix: Fix) { newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload.ref), fix) @@ -83,21 +83,21 @@ object FixingProtocol { ptx.setTime(serviceHub.clock.instant(), 30.seconds) } } - subProtocol(addFixing) + subFlow(addFixing) return Pair(ptx, arrayListOf(myOldParty.owningKey)) } } /** - * One side of the fixing protocol for an interest rate swap, but could easily be generalised furher. + * One side of the fixing flow for an interest rate swap, but could easily be generalised furher. * * As per the [Fixer], do not infer too much from this class name in terms of business roles. This - * is just the "side" of the protocol run by the party with the floating leg as a way of deciding who - * does what in the protocol. + * is just the "side" of the flow run by the party with the floating leg as a way of deciding who + * does what in the flow. */ class Floater(override val otherParty: Party, override val payload: FixingSession, - override val progressTracker: ProgressTracker = TwoPartyDealProtocol.Primary.tracker()) : TwoPartyDealProtocol.Primary() { + override val progressTracker: ProgressTracker = TwoPartyDealFlow.Primary.tracker()) : TwoPartyDealFlow.Primary() { @Suppress("UNCHECKED_CAST") internal val dealToFix: StateAndRef by TransientProperty { @@ -120,7 +120,7 @@ object FixingProtocol { data class FixingSession(val ref: StateRef, val oracleType: ServiceType) /** - * This protocol looks at the deal and decides whether to be the Fixer or Floater role in agreeing a fixing. + * This flow looks at the deal and decides whether to be the Fixer or Floater role in agreeing a fixing. * * It is kicked off as an activity on both participant nodes by the scheduler when it's time for a fixing. If the * Fixer role is chosen, then that will be initiated by the [FixingSession] message sent from the other party and @@ -129,7 +129,7 @@ object FixingProtocol { * TODO: Replace [FixingSession] and [FixingSessionInitiationHandler] with generic session initiation logic once it exists. */ class FixingRoleDecider(val ref: StateRef, - override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic() { + override val progressTracker: ProgressTracker = tracker()) : FlowLogic() { companion object { class LOADING() : ProgressTracker.Step("Loading state to decide fixing role") @@ -147,7 +147,7 @@ object FixingProtocol { if (sortedParties[0].name == serviceHub.myInfo.legalIdentity.name) { val fixing = FixingSession(ref, fixableDeal.oracleType) // Start the Floater which will then kick-off the Fixer - subProtocol(Floater(sortedParties[1], fixing)) + subFlow(Floater(sortedParties[1], fixing)) } } } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/RatesFixProtocol.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt similarity index 77% rename from samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/RatesFixProtocol.kt rename to samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt index 8005abaa83..5bedcde57b 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/RatesFixProtocol.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/RatesFixFlow.kt @@ -1,17 +1,17 @@ -package net.corda.irs.protocols +package net.corda.irs.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.Fix import net.corda.core.contracts.FixOf -import net.corda.core.contracts.Timestamp import net.corda.core.crypto.DigitalSignature import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash -import net.corda.core.protocols.ProtocolLogic +import net.corda.core.flows.FlowLogic import net.corda.core.transactions.FilterFuns import net.corda.core.transactions.FilteredTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.ProgressTracker +import net.corda.irs.flows.RatesFixFlow.FixOutOfRange import net.corda.irs.utilities.suggestInterestRateAnnouncementTimeWindow import java.math.BigDecimal import java.time.Instant @@ -20,21 +20,21 @@ import java.util.* // This code is unit tested in NodeInterestRates.kt /** - * This protocol queries the given oracle for an interest rate fix, and if it is within the given tolerance embeds the + * This flow queries the given oracle for an interest rate fix, and if it is within the given tolerance embeds the * fix in the transaction and then proceeds to get the oracle to sign it. Although the [call] method combines the query * and signing step, you can run the steps individually by constructing this object and then using the public methods * for each step. * * @throws FixOutOfRange if the returned fix was further away from the expected rate by the given amount. */ -open class RatesFixProtocol(protected val tx: TransactionBuilder, +open class RatesFixFlow(protected val tx: TransactionBuilder, // Filtering functions over transaction, used to build partial transaction presented to oracle. - private val filterFuns: FilterFuns, - private val oracle: Party, - private val fixOf: FixOf, - private val expectedRate: BigDecimal, - private val rateTolerance: BigDecimal, - override val progressTracker: ProgressTracker = RatesFixProtocol.tracker(fixOf.name)) : ProtocolLogic() { + private val filterFuns: FilterFuns, + private val oracle: Party, + private val fixOf: FixOf, + private val expectedRate: BigDecimal, + private val rateTolerance: BigDecimal, + override val progressTracker: ProgressTracker = RatesFixFlow.tracker(fixOf.name)) : FlowLogic() { companion object { class QUERYING(val name: String) : ProgressTracker.Step("Querying oracle for $name interest rate") @@ -52,13 +52,13 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder, @Suspendable override fun call() { progressTracker.currentStep = progressTracker.steps[1] - val fix = subProtocol(FixQueryProtocol(fixOf, oracle)) + val fix = subFlow(FixQueryFlow(fixOf, oracle)) progressTracker.currentStep = WORKING checkFixIsNearExpected(fix) tx.addCommand(fix, oracle.owningKey) beforeSigning(fix) progressTracker.currentStep = SIGNING - val signature = subProtocol(FixSignProtocol(tx, oracle, filterFuns)) + val signature = subFlow(FixSignFlow(tx, oracle, filterFuns)) tx.addSignatureUnchecked(signature) } @@ -79,7 +79,7 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder, } - class FixQueryProtocol(val fixOf: FixOf, val oracle: Party) : ProtocolLogic() { + class FixQueryFlow(val fixOf: FixOf, val oracle: Party) : FlowLogic() { @Suspendable override fun call(): Fix { val deadline = suggestInterestRateAnnouncementTimeWindow(fixOf.name, oracle.name, fixOf.forDay).end @@ -95,7 +95,7 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder, } } - class FixSignProtocol(val tx: TransactionBuilder, val oracle: Party, val filterFuns: FilterFuns) : ProtocolLogic() { + class FixSignFlow(val tx: TransactionBuilder, val oracle: Party, val filterFuns: FilterFuns) : FlowLogic() { @Suspendable override fun call(): DigitalSignature.LegallyIdentifiable { val wtx = tx.toWireTransaction() diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/UpdateBusinessDayProtocol.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/UpdateBusinessDayFlow.kt similarity index 83% rename from samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/UpdateBusinessDayProtocol.kt rename to samples/irs-demo/src/main/kotlin/net/corda/irs/flows/UpdateBusinessDayFlow.kt index 29657bd1e5..3f8c40f9a7 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/protocols/UpdateBusinessDayProtocol.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/flows/UpdateBusinessDayFlow.kt @@ -1,24 +1,23 @@ -package net.corda.irs.protocols +package net.corda.irs.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.CordaPluginRegistry import net.corda.core.node.NodeInfo import net.corda.core.node.PluginServiceHub -import net.corda.core.protocols.ProtocolLogic import net.corda.core.utilities.ProgressTracker import net.corda.node.utilities.TestClock -import net.corda.node.services.api.ServiceHubInternal import net.corda.testing.node.MockNetworkMapCache import java.time.LocalDate /** * This is a less temporary, demo-oriented way of initiating processing of temporal events. */ -object UpdateBusinessDayProtocol { +object UpdateBusinessDayFlow { // This is not really a HandshakeMessage but needs to be so that the send uses the default session ID. This will - // resolve itself when the protocol session stuff is done. + // resolve itself when the flow session stuff is done. data class UpdateBusinessDayMessage(val date: LocalDate) class Plugin: CordaPluginRegistry() { @@ -27,11 +26,11 @@ object UpdateBusinessDayProtocol { class Service(services: PluginServiceHub) { init { - services.registerProtocolInitiator(Broadcast::class, ::UpdateBusinessDayHandler) + services.registerFlowInitiator(Broadcast::class, ::UpdateBusinessDayHandler) } } - private class UpdateBusinessDayHandler(val otherParty: Party) : ProtocolLogic() { + private class UpdateBusinessDayHandler(val otherParty: Party) : FlowLogic() { override fun call() { val message = receive(otherParty).unwrap { it } (serviceHub.clock as TestClock).updateDate(message.date) @@ -40,7 +39,7 @@ object UpdateBusinessDayProtocol { class Broadcast(val date: LocalDate, - override val progressTracker: ProgressTracker = Broadcast.tracker()) : ProtocolLogic() { + override val progressTracker: ProgressTracker = Broadcast.tracker()) : FlowLogic() { companion object { object NOTIFYING : ProgressTracker.Step("Notifying peers") diff --git a/samples/irs-demo/src/main/kotlin/net/corda/irs/plugin/IRSPlugin.kt b/samples/irs-demo/src/main/kotlin/net/corda/irs/plugin/IRSPlugin.kt index 0aae2acb1d..a4cf88a8b7 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/irs/plugin/IRSPlugin.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/irs/plugin/IRSPlugin.kt @@ -5,11 +5,10 @@ import net.corda.core.crypto.Party import net.corda.core.node.CordaPluginRegistry import net.corda.irs.api.InterestRateSwapAPI import net.corda.irs.contract.InterestRateSwap -import net.corda.irs.protocols.AutoOfferProtocol -import net.corda.irs.protocols.ExitServerProtocol -import net.corda.irs.protocols.FixingProtocol -import net.corda.irs.protocols.UpdateBusinessDayProtocol -import net.corda.protocols.TwoPartyDealProtocol +import net.corda.irs.flows.AutoOfferFlow +import net.corda.irs.flows.ExitServerFlow +import net.corda.irs.flows.FixingFlow +import net.corda.irs.flows.UpdateBusinessDayFlow import java.time.Duration class IRSPlugin : CordaPluginRegistry() { @@ -17,11 +16,11 @@ class IRSPlugin : CordaPluginRegistry() { override val staticServeDirs: Map = mapOf( "irsdemo" to javaClass.classLoader.getResource("irsweb").toExternalForm() ) - override val servicePlugins: List> = listOf(FixingProtocol.Service::class.java) - override val requiredProtocols: Map> = mapOf( - Pair(AutoOfferProtocol.Requester::class.java.name, setOf(InterestRateSwap.State::class.java.name)), - Pair(UpdateBusinessDayProtocol.Broadcast::class.java.name, setOf(java.time.LocalDate::class.java.name)), - Pair(ExitServerProtocol.Broadcast::class.java.name, setOf(kotlin.Int::class.java.name)), - Pair(FixingProtocol.FixingRoleDecider::class.java.name, setOf(StateRef::class.java.name, Duration::class.java.name)), - Pair(FixingProtocol.Floater::class.java.name, setOf(Party::class.java.name, FixingProtocol.FixingSession::class.java.name))) + override val servicePlugins: List> = listOf(FixingFlow.Service::class.java) + override val requiredFlows: Map> = mapOf( + Pair(AutoOfferFlow.Requester::class.java.name, setOf(InterestRateSwap.State::class.java.name)), + Pair(UpdateBusinessDayFlow.Broadcast::class.java.name, setOf(java.time.LocalDate::class.java.name)), + Pair(ExitServerFlow.Broadcast::class.java.name, setOf(kotlin.Int::class.java.name)), + Pair(FixingFlow.FixingRoleDecider::class.java.name, setOf(StateRef::class.java.name, Duration::class.java.name)), + Pair(FixingFlow.Floater::class.java.name, setOf(Party::class.java.name, FixingFlow.FixingSession::class.java.name))) } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt b/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt index 893f6112e5..6d18246569 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/simulation/IRSSimulation.kt @@ -9,17 +9,17 @@ import net.corda.core.RunOnCallerThread import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.UniqueIdentifier import net.corda.core.flatMap +import net.corda.core.flows.FlowStateMachine import net.corda.core.map import net.corda.core.node.services.linearHeadsOfType -import net.corda.core.protocols.ProtocolStateMachine import net.corda.core.success import net.corda.core.transactions.SignedTransaction +import net.corda.flows.TwoPartyDealFlow.Acceptor +import net.corda.flows.TwoPartyDealFlow.AutoOffer +import net.corda.flows.TwoPartyDealFlow.Instigator import net.corda.irs.contract.InterestRateSwap import net.corda.node.utilities.databaseTransaction -import net.corda.protocols.TwoPartyDealProtocol.Acceptor -import net.corda.protocols.TwoPartyDealProtocol.AutoOffer -import net.corda.protocols.TwoPartyDealProtocol.Instigator -import net.corda.testing.initiateSingleShotProtocol +import net.corda.testing.initiateSingleShotFlow import net.corda.testing.node.InMemoryMessagingNetwork import net.corda.testing.node.MockIdentityService import java.time.LocalDate @@ -118,15 +118,15 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten irs.fixedLeg.fixedRatePayer = node1.info.legalIdentity irs.floatingLeg.floatingRatePayer = node2.info.legalIdentity - val acceptorTx = node2.initiateSingleShotProtocol(Instigator::class) { Acceptor(it) }.flatMap { - (it.psm as ProtocolStateMachine).resultFuture + val acceptorTx = node2.initiateSingleShotFlow(Instigator::class) { Acceptor(it) }.flatMap { + (it.fsm as FlowStateMachine).resultFuture } showProgressFor(listOf(node1, node2)) showConsensusFor(listOf(node1, node2, regulators[0])) val instigator = Instigator(node2.info.legalIdentity, AutoOffer(notary.info.notaryIdentity, irs), node1.keyPair!!) - val instigatorTx: ListenableFuture = node1.services.startProtocol(instigator).resultFuture + val instigatorTx: ListenableFuture = node1.services.startFlow(instigator).resultFuture return Futures.allAsList(instigatorTx, acceptorTx).flatMap { instigatorTx } } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/simulation/Simulation.kt b/samples/irs-demo/src/main/kotlin/net/corda/simulation/Simulation.kt index 1b83c4647e..3863631146 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/simulation/Simulation.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/simulation/Simulation.kt @@ -4,12 +4,12 @@ import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.ListenableFuture import net.corda.core.crypto.generateKeyPair import net.corda.core.flatMap +import net.corda.core.flows.FlowLogic import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.CityDatabase import net.corda.core.node.PhysicalLocation import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.containsType -import net.corda.core.protocols.ProtocolLogic import net.corda.core.then import net.corda.core.utilities.ProgressTracker import net.corda.irs.api.NodeInterestRates @@ -31,7 +31,7 @@ import java.util.* /** * Base class for network simulations that are based on the unit test / mock environment. * - * Sets up some nodes that can run protocols between each other, and exposes their progress trackers. Provides banks + * Sets up some nodes that can run flows between each other, and exposes their progress trackers. Provides banks * in a few cities around the world. */ abstract class Simulation(val networkSendManuallyPumped: Boolean, @@ -202,9 +202,9 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, val clocks = (serviceProviders + regulators + banks).map { it.services.clock as TestClock } // These are used from the network visualiser tool. - private val _allProtocolSteps = PublishSubject.create>() + private val _allFlowSteps = PublishSubject.create>() private val _doneSteps = PublishSubject.create>() - @Suppress("unused") val allProtocolSteps: Observable> = _allProtocolSteps + @Suppress("unused") val allFlowSteps: Observable> = _allFlowSteps @Suppress("unused") val doneSteps: Observable> = _doneSteps private var pumpCursor = 0 @@ -268,16 +268,16 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, protected fun showProgressFor(nodes: List) { nodes.forEach { node -> node.smm.changes.filter { it.addOrRemove == AddOrRemove.ADD }.subscribe { - linkProtocolProgress(node, it.logic) + linkFlowProgress(node, it.logic) } } } - private fun linkProtocolProgress(node: SimulatedNode, protocol: ProtocolLogic<*>) { - val pt = protocol.progressTracker ?: return + private fun linkFlowProgress(node: SimulatedNode, flow: FlowLogic<*>) { + val pt = flow.progressTracker ?: return pt.changes.subscribe { change: ProgressTracker.Change -> // Runs on node thread. - _allProtocolSteps.onNext(Pair(node, change)) + _allFlowSteps.onNext(Pair(node, change)) } } @@ -289,10 +289,10 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, } } - private fun linkConsensus(nodes: Collection, protocol: ProtocolLogic<*>) { - protocol.progressTracker?.changes?.subscribe { change: ProgressTracker.Change -> + private fun linkConsensus(nodes: Collection, flow: FlowLogic<*>) { + flow.progressTracker?.changes?.subscribe { change: ProgressTracker.Change -> // Runs on node thread. - if (protocol.progressTracker!!.currentStep == ProgressTracker.DONE) { + if (flow.progressTracker!!.currentStep == ProgressTracker.DONE) { _doneSteps.onNext(nodes) } } diff --git a/samples/irs-demo/src/main/kotlin/net/corda/simulation/TradeSimulation.kt b/samples/irs-demo/src/main/kotlin/net/corda/simulation/TradeSimulation.kt index 896b16e169..e483083c1f 100644 --- a/samples/irs-demo/src/main/kotlin/net/corda/simulation/TradeSimulation.kt +++ b/samples/irs-demo/src/main/kotlin/net/corda/simulation/TradeSimulation.kt @@ -10,13 +10,13 @@ import net.corda.core.contracts.OwnableState import net.corda.core.contracts.`issued by` import net.corda.core.days import net.corda.core.flatMap +import net.corda.core.flows.FlowStateMachine import net.corda.core.node.recordTransactions -import net.corda.core.protocols.ProtocolStateMachine import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction -import net.corda.protocols.TwoPartyTradeProtocol.Buyer -import net.corda.protocols.TwoPartyTradeProtocol.Seller -import net.corda.testing.initiateSingleShotProtocol +import net.corda.flows.TwoPartyTradeFlow.Buyer +import net.corda.flows.TwoPartyTradeFlow.Seller +import net.corda.testing.initiateSingleShotFlow import net.corda.testing.node.InMemoryMessagingNetwork import java.time.Instant @@ -50,12 +50,12 @@ class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwo val amount = 1000.DOLLARS - val buyerFuture = buyer.initiateSingleShotProtocol(Seller::class) { + val buyerFuture = buyer.initiateSingleShotFlow(Seller::class) { Buyer(it, notary.info.notaryIdentity, amount, CommercialPaper.State::class.java) - }.flatMap { (it.psm as ProtocolStateMachine).resultFuture } + }.flatMap { (it.fsm as FlowStateMachine).resultFuture } val sellerKey = seller.services.legalIdentityKey - val sellerProtocol = Seller( + val sellerFlow = Seller( buyer.info.legalIdentity, notary.info, issuance.tx.outRef(0), @@ -65,7 +65,7 @@ class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwo showConsensusFor(listOf(buyer, seller, notary)) showProgressFor(listOf(buyer, seller)) - val sellerFuture = seller.services.startProtocol(sellerProtocol).resultFuture + val sellerFuture = seller.services.startFlow(sellerFlow).resultFuture return Futures.successfulAsList(buyerFuture, sellerFuture) } diff --git a/samples/irs-demo/src/main/resources/META-INF/services/net.corda.core.node.CordaPluginRegistry b/samples/irs-demo/src/main/resources/META-INF/services/net.corda.core.node.CordaPluginRegistry index de01bf3f01..c3eae17451 100644 --- a/samples/irs-demo/src/main/resources/META-INF/services/net.corda.core.node.CordaPluginRegistry +++ b/samples/irs-demo/src/main/resources/META-INF/services/net.corda.core.node.CordaPluginRegistry @@ -1,6 +1,6 @@ # Register a ServiceLoader service extending from net.corda.node.CordaPluginRegistry net.corda.irs.plugin.IRSPlugin net.corda.irs.api.NodeInterestRates$Plugin -net.corda.irs.protocols.AutoOfferProtocol$Plugin -net.corda.irs.protocols.ExitServerProtocol$Plugin -net.corda.irs.protocols.UpdateBusinessDayProtocol$Plugin +net.corda.irs.flows.AutoOfferFlow$Plugin +net.corda.irs.flows.ExitServerFlow$Plugin +net.corda.irs.flows.UpdateBusinessDayFlow$Plugin diff --git a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt index f2a1273af0..14742aeb4d 100644 --- a/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt +++ b/samples/irs-demo/src/test/kotlin/net/corda/irs/testing/NodeInterestRatesTest.kt @@ -15,16 +15,19 @@ import net.corda.core.transactions.FilteredTransaction import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.LogHelper import net.corda.irs.api.NodeInterestRates -import net.corda.irs.protocols.RatesFixProtocol -import net.corda.testing.node.MockNetwork +import net.corda.irs.flows.RatesFixFlow import net.corda.node.utilities.configureDatabase import net.corda.node.utilities.databaseTransaction import net.corda.testing.ALICE_PUBKEY import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP_KEY +import net.corda.testing.node.MockNetwork import net.corda.testing.node.makeTestDataSourceProperties import org.jetbrains.exposed.sql.Database -import org.junit.* +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Test import java.io.Closeable import java.time.Clock import kotlin.test.assertEquals @@ -198,10 +201,10 @@ class NodeInterestRatesTest { val oracle = n2.info.serviceIdentities(NodeInterestRates.type).first() fun filterCommands(c: Command) = oracle.owningKey in c.signers && c.value is Fix val filterFuns = FilterFuns(filterCommands = ::filterCommands) - val protocol = RatesFixProtocol(tx, filterFuns, oracle, fixOf, "0.675".bd, "0.1".bd) + val flow = RatesFixFlow(tx, filterFuns, oracle, fixOf, "0.675".bd, "0.1".bd) LogHelper.setLevel("rates") net.runNetwork() - val future = n1.services.startProtocol(protocol).resultFuture + val future = n1.services.startFlow(flow).resultFuture net.runNetwork() future.get() // We should now have a valid signature over our tx from the oracle. diff --git a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt index 33d1b68327..3466fe3a6a 100644 --- a/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt +++ b/samples/network-visualiser/src/main/kotlin/net/corda/netmap/NetworkMapVisualiser.kt @@ -1,16 +1,5 @@ package net.corda.netmap -import net.corda.netmap.VisualiserViewModel.Style -import net.corda.core.messaging.SingleMessageRecipient -import net.corda.core.serialization.deserialize -import net.corda.core.then -import net.corda.core.utilities.ProgressTracker -import net.corda.node.services.network.NetworkMapService -import net.corda.node.services.statemachine.StateMachineManager -import net.corda.simulation.IRSSimulation -import net.corda.simulation.Simulation -import net.corda.testing.node.InMemoryMessagingNetwork -import net.corda.testing.node.MockNetwork import javafx.animation.* import javafx.application.Application import javafx.application.Platform @@ -22,6 +11,17 @@ import javafx.scene.input.KeyCodeCombination import javafx.scene.layout.VBox import javafx.stage.Stage import javafx.util.Duration +import net.corda.core.messaging.SingleMessageRecipient +import net.corda.core.serialization.deserialize +import net.corda.core.then +import net.corda.core.utilities.ProgressTracker +import net.corda.netmap.VisualiserViewModel.Style +import net.corda.node.services.network.NetworkMapService +import net.corda.node.services.statemachine.StateMachineManager +import net.corda.simulation.IRSSimulation +import net.corda.simulation.Simulation +import net.corda.testing.node.InMemoryMessagingNetwork +import net.corda.testing.node.MockNetwork import rx.Scheduler import rx.schedulers.Schedulers import java.time.format.DateTimeFormatter @@ -74,8 +74,8 @@ class NetworkMapVisualiser : Application() { viewModel.displayStyle = if ("--circle" in parameters.raw) { Style.CIRCLE } else { viewModel.displayStyle } val simulation = viewModel.simulation - // Update the white-backgrounded label indicating what protocol step it's up to. - simulation.allProtocolSteps.observeOn(uiThread).subscribe { step: Pair -> + // Update the white-backgrounded label indicating what flow step it's up to. + simulation.allFlowSteps.observeOn(uiThread).subscribe { step: Pair -> val (node, change) = step val label = viewModel.nodesToWidgets[node]!!.statusLabel if (change is ProgressTracker.Change.Position) { @@ -213,23 +213,23 @@ class NetworkMapVisualiser : Application() { } private fun bindSidebar() { - viewModel.simulation.allProtocolSteps.observeOn(uiThread).subscribe { step: Pair -> + viewModel.simulation.allFlowSteps.observeOn(uiThread).subscribe { step: Pair -> val (node, change) = step if (change is ProgressTracker.Change.Position) { val tracker = change.tracker.topLevelTracker if (change.newStep == ProgressTracker.DONE) { if (change.tracker == tracker) { - // Protocol done; schedule it for removal in a few seconds. We batch them up to make nicer + // Flow done; schedule it for removal in a few seconds. We batch them up to make nicer // animations. updateProgressTrackerWidget(change) - println("Protocol done for ${node.info.legalIdentity.name}") + println("Flow done for ${node.info.legalIdentity.name}") viewModel.doneTrackers += tracker } else { - // Subprotocol is done; ignore it. + // Subflow is done; ignore it. } } else if (!viewModel.trackerBoxes.containsKey(tracker)) { - // New protocol started up; add. + // New flow started up; add. val extraLabel = viewModel.simulation.extraNodeLabels[node] val label = if (extraLabel != null) "${node.info.legalIdentity.name}: $extraLabel" else node.info.legalIdentity.name val widget = view.buildProgressTrackerWidget(label, tracker.topLevelTracker) @@ -343,7 +343,7 @@ class NetworkMapVisualiser : Application() { // Loopback messages are boring. if (transfer.sender.myAddress == transfer.recipients) return false // Network map push acknowledgements are boring. - if (NetworkMapService.PUSH_ACK_PROTOCOL_TOPIC in transfer.message.topicSession.topic) return false + if (NetworkMapService.PUSH_ACK_FLOW_TOPIC in transfer.message.topicSession.topic) return false val message = transfer.message.data.deserialize() val messageClassType = message.javaClass.name when (messageClassType) { diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/analytics/AnalyticsEngine.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/analytics/AnalyticsEngine.kt index ad8026c593..81622f022e 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/analytics/AnalyticsEngine.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/analytics/AnalyticsEngine.kt @@ -17,9 +17,7 @@ import com.opengamma.strata.pricer.rate.ImmutableRatesProvider import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer import com.opengamma.strata.product.swap.ResolvedSwapTrade import net.corda.core.utilities.loggerFor -import net.corda.vega.protocols.toCordaCompatible -import org.slf4j.Logger -import org.slf4j.LoggerFactory +import net.corda.vega.flows.toCordaCompatible import java.time.LocalDate /** diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/api/PortfolioApi.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/api/PortfolioApi.kt index d9d027c12f..205923ad82 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/api/PortfolioApi.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/api/PortfolioApi.kt @@ -9,12 +9,12 @@ import net.corda.core.node.services.dealsWith import net.corda.vega.analytics.InitialMarginTriple import net.corda.vega.contracts.IRSState import net.corda.vega.contracts.PortfolioState +import net.corda.vega.flows.IRSTradeFlow +import net.corda.vega.flows.SimmFlow +import net.corda.vega.flows.SimmRevaluation import net.corda.vega.portfolio.Portfolio import net.corda.vega.portfolio.toPortfolio import net.corda.vega.portfolio.toStateAndRef -import net.corda.vega.protocols.IRSTradeProtocol -import net.corda.vega.protocols.SimmProtocol -import net.corda.vega.protocols.SimmRevaluation import java.time.LocalDate import java.time.LocalDateTime import javax.ws.rs.* @@ -153,7 +153,7 @@ class PortfolioApi(val services: ServiceHub) { return withParty(partyName) { val buyer = if (swap.buySell.isBuy) ownParty else it val seller = if (swap.buySell.isSell) ownParty else it - services.invokeProtocolAsync(IRSTradeProtocol.Requester::class.java, swap.toData(buyer, seller), it).resultFuture.get() + services.invokeFlowAsync(IRSTradeFlow.Requester::class.java, swap.toData(buyer, seller), it).resultFuture.get() Response.accepted().entity("{}").build() } } @@ -268,9 +268,9 @@ class PortfolioApi(val services: ServiceHub) { return withParty(partyName) { otherParty -> val existingSwap = getPortfolioWith(otherParty) if (existingSwap == null) { - services.invokeProtocolAsync(SimmProtocol.Requester::class.java, otherParty, params.valuationDate).resultFuture.get() + services.invokeFlowAsync(SimmFlow.Requester::class.java, otherParty, params.valuationDate).resultFuture.get() } else { - services.invokeProtocolAsync(SimmRevaluation.Initiator::class.java, getPortfolioStateAndRefWith(otherParty).ref, params.valuationDate).resultFuture.get() + services.invokeFlowAsync(SimmRevaluation.Initiator::class.java, getPortfolioStateAndRefWith(otherParty).ref, params.valuationDate).resultFuture.get() } withPortfolio(otherParty) { portfolioState -> diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt index d7becdb689..08c94e49e0 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/PortfolioState.kt @@ -3,9 +3,9 @@ package net.corda.vega.contracts import net.corda.core.contracts.* import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.Party -import net.corda.core.protocols.ProtocolLogicRefFactory +import net.corda.core.flows.FlowLogicRefFactory import net.corda.core.transactions.TransactionBuilder -import net.corda.vega.protocols.SimmRevaluation +import net.corda.vega.flows.SimmRevaluation import java.security.PublicKey import java.time.LocalDate import java.time.ZoneOffset @@ -31,9 +31,9 @@ data class PortfolioState(val portfolio: List, override val participants: List get() = parties.map { it.owningKey } - override fun nextScheduledActivity(thisStateRef: StateRef, protocolLogicRefFactory: ProtocolLogicRefFactory): ScheduledActivity { - val protocol = protocolLogicRefFactory.create(SimmRevaluation.Initiator::class.java, thisStateRef, LocalDate.now()) - return ScheduledActivity(protocol, LocalDate.now().plus(1, ChronoUnit.DAYS).atStartOfDay().toInstant(ZoneOffset.UTC)) + override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity { + val flow = flowLogicRefFactory.create(SimmRevaluation.Initiator::class.java, thisStateRef, LocalDate.now()) + return ScheduledActivity(flow, LocalDate.now().plus(1, ChronoUnit.DAYS).atStartOfDay().toInstant(ZoneOffset.UTC)) } override fun isRelevant(ourKeys: Set): Boolean { diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/RevisionedState.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/RevisionedState.kt index c2db5f5bd4..ee606147c7 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/RevisionedState.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/contracts/RevisionedState.kt @@ -6,7 +6,7 @@ import net.corda.core.crypto.Party import net.corda.core.transactions.TransactionBuilder /** - * Deals implementing this interface will be usable with the StateRevisionProtocol that allows arbitrary updates + * Deals implementing this interface will be usable with the StateRevisionFlow that allows arbitrary updates * to a state. This is not really an "amendable" state (recall the Corda model - all states are immutable in the * functional sense) however it can be amended and then re-written as another state into the ledger. */ diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/IRSTradeProtocol.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt similarity index 74% rename from samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/IRSTradeProtocol.kt rename to samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt index e1706fd033..c9e60d7296 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/IRSTradeProtocol.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/IRSTradeFlow.kt @@ -1,20 +1,19 @@ -package net.corda.vega.protocols +package net.corda.vega.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.PluginServiceHub -import net.corda.core.protocols.ProtocolLogic import net.corda.core.transactions.SignedTransaction -import net.corda.protocols.TwoPartyDealProtocol +import net.corda.flows.TwoPartyDealFlow import net.corda.vega.contracts.IRSState import net.corda.vega.contracts.OGTrade import net.corda.vega.contracts.SwapData -import org.slf4j.Logger -object IRSTradeProtocol { +object IRSTradeFlow { data class OfferMessage(val notary: Party, val dealBeingOffered: IRSState) - class Requester(val swap: SwapData, val otherParty: Party) : ProtocolLogic() { + class Requester(val swap: SwapData, val otherParty: Party) : FlowLogic() { @Suspendable override fun call(): SignedTransaction { @@ -33,31 +32,31 @@ object IRSTradeProtocol { val otherPartyAgreeFlag = sendAndReceive(otherParty, OfferMessage(notary, offer)).unwrap { it } require(otherPartyAgreeFlag) - return subProtocol(TwoPartyDealProtocol.Instigator( + return subFlow(TwoPartyDealFlow.Instigator( otherParty, - TwoPartyDealProtocol.AutoOffer(notary, offer), + TwoPartyDealFlow.AutoOffer(notary, offer), serviceHub.legalIdentityKey), shareParentSessions = true) } } class Service(services: PluginServiceHub) { init { - services.registerProtocolInitiator(Requester::class, ::Receiver) + services.registerFlowInitiator(Requester::class, ::Receiver) } } - class Receiver(private val replyToParty: Party) : ProtocolLogic() { + class Receiver(private val replyToParty: Party) : FlowLogic() { @Suspendable override fun call() { - logger.info("IRSTradeProtocol receiver started") + logger.info("IRSTradeFlow receiver started") logger.info("Handshake finished, awaiting IRS trade offer") val offer = receive(replyToParty).unwrap { it } // Automatically agree - in reality we'd vet the offer message require(serviceHub.networkMapCache.notaryNodes.map { it.notaryIdentity }.contains(offer.notary)) send(replyToParty, true) - subProtocol(TwoPartyDealProtocol.Acceptor(replyToParty), shareParentSessions = true) + subFlow(TwoPartyDealFlow.Acceptor(replyToParty), shareParentSessions = true) } } } diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/OpenGammaCordaUtils.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/OpenGammaCordaUtils.kt similarity index 98% rename from samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/OpenGammaCordaUtils.kt rename to samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/OpenGammaCordaUtils.kt index 2a502dd7d3..a30bc3f7fe 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/OpenGammaCordaUtils.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/OpenGammaCordaUtils.kt @@ -1,4 +1,4 @@ -package net.corda.vega.protocols +package net.corda.vega.flows import com.opengamma.strata.basics.currency.Currency import com.opengamma.strata.basics.currency.CurrencyAmount diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/SimmProtocol.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt similarity index 90% rename from samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/SimmProtocol.kt rename to samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt index 73f5ac9161..ac80e3ae36 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/SimmProtocol.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmFlow.kt @@ -1,4 +1,4 @@ -package net.corda.vega.protocols +package net.corda.vega.flows import co.paralleluniverse.fibers.Suspendable import com.opengamma.strata.basics.ReferenceData @@ -13,12 +13,12 @@ import com.opengamma.strata.pricer.swap.DiscountingSwapProductPricer import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateRef import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.messaging.Ack import net.corda.core.node.PluginServiceHub import net.corda.core.node.services.dealsWith -import net.corda.core.protocols.ProtocolLogic import net.corda.core.transactions.SignedTransaction -import net.corda.protocols.TwoPartyDealProtocol +import net.corda.flows.TwoPartyDealFlow import net.corda.vega.analytics.* import net.corda.vega.contracts.* import net.corda.vega.portfolio.Portfolio @@ -27,11 +27,11 @@ import net.corda.vega.portfolio.toStateAndRef import java.time.LocalDate /** - * The Simm Protocol is between two parties that both agree on a portfolio of trades to run valuations on. Both sides + * The Simm Flow is between two parties that both agree on a portfolio of trades to run valuations on. Both sides * will independently value the portfolio using a SIMM implementation and then come to consensus over those valuations. * It can also update an existing portfolio and revalue it. */ -object SimmProtocol { +object SimmFlow { /** * Represents a new portfolio offer unless the stateRef field is non-null, at which point it represents a * portfolio update offer. @@ -48,7 +48,7 @@ object SimmProtocol { class Requester(val otherParty: Party, val valuationDate: LocalDate, val existing: StateAndRef? = null) - : ProtocolLogic>() { + : FlowLogic>() { lateinit var myIdentity: Party lateinit var notary: Party @@ -68,7 +68,7 @@ object SimmProtocol { } val portfolioStateRef = serviceHub.vaultService.dealsWith(otherParty).first() val state = updateValuation(portfolioStateRef) - logger.info("SimmProtocol done") + logger.info("SimmFlow done") return state; } @@ -80,7 +80,7 @@ object SimmProtocol { send(otherParty, OfferMessage(notary, portfolioState, existing?.ref, valuationDate)) logger.info("Awaiting two party deal acceptor") - subProtocol(TwoPartyDealProtocol.Acceptor(otherParty), shareParentSessions = true) + subFlow(TwoPartyDealFlow.Acceptor(otherParty), shareParentSessions = true) } @Suspendable @@ -89,7 +89,7 @@ object SimmProtocol { sendAndReceive(otherParty, OfferMessage(notary, stateAndRef.state.data, existing?.ref, valuationDate)) logger.info("Updating portfolio") val update = PortfolioState.Update(portfolio = portfolio.refs) - subProtocol(StateRevisionProtocol.Requester(stateAndRef, update), shareParentSessions = true) + subFlow(StateRevisionFlow.Requester(stateAndRef, update), shareParentSessions = true) } @Suspendable @@ -100,7 +100,7 @@ object SimmProtocol { val valuer = state.valuer val valuation = agreeValuation(portfolio, valuationDate, valuer) val update = PortfolioState.Update(valuation = valuation) - return subProtocol(StateRevisionProtocol.Requester(stateRef, update), shareParentSessions = true).state.data + return subFlow(StateRevisionFlow.Requester(stateRef, update), shareParentSessions = true).state.data } @Suspendable @@ -171,18 +171,18 @@ object SimmProtocol { } /** - * Service plugin for listening for incoming Simm protocol communication + * Service plugin for listening for incoming Simm flow communication */ class Service(services: PluginServiceHub) { init { - services.registerProtocolInitiator(Requester::class, ::Receiver) + services.registerFlowInitiator(Requester::class, ::Receiver) } } /** * Receives and validates a portfolio and comes to consensus over the portfolio initial margin using SIMM. */ - class Receiver(val replyToParty: Party) : ProtocolLogic() { + class Receiver(val replyToParty: Party) : FlowLogic() { lateinit var ownParty: Party lateinit var offer: OfferMessage @@ -191,7 +191,7 @@ object SimmProtocol { ownParty = serviceHub.myInfo.legalIdentity val trades = serviceHub.vaultService.dealsWith(replyToParty) val portfolio = Portfolio(trades) - logger.info("SimmProtocol receiver started") + logger.info("SimmFlow receiver started") offer = receive(replyToParty).unwrap { it } if (offer.stateRef == null) { agreePortfolio(portfolio) @@ -209,7 +209,7 @@ object SimmProtocol { } /** - * So this is the crux of the Simm Agreement protocol + * So this is the crux of the Simm Agreement flow * It needs to do several things - which are mainly defined by the analytics engine we are using - which in this * case is the Open Gamma version. * @@ -221,7 +221,7 @@ object SimmProtocol { * 5) There is now some curve calibration and portfolio normalization that happens for OG * 6) Once we have the above, we can then calculate sensitivities to risk factors * ( In essence, this is a value that "if risk factor X changes, how much will that affect the PV of the trade" ) - * 7) Now the sensitivities can be agreed over the protocol + * 7) Now the sensitivities can be agreed over the flow * 8) Finally.. the last phase is the IM calculation. This occurs in several steps * 8a) "margin" is the colloquial initial margin for the entire portfolio * 8b) "cordaMargin" in an adjusted margin that we have (basically) rounded to 2dp such that it can be compared without issues in floating point accuracy @@ -285,19 +285,19 @@ object SimmProtocol { logger.info("Handshake finished, awaiting Simm offer") require(offer.dealBeingOffered.portfolio == portfolio.refs) - val seller = TwoPartyDealProtocol.Instigator( + val seller = TwoPartyDealFlow.Instigator( replyToParty, - TwoPartyDealProtocol.AutoOffer(offer.notary, offer.dealBeingOffered), + TwoPartyDealFlow.AutoOffer(offer.notary, offer.dealBeingOffered), serviceHub.legalIdentityKey) logger.info("Starting two party deal initiator with: ${replyToParty.name}") - return subProtocol(seller, shareParentSessions = true) + return subFlow(seller, shareParentSessions = true) } @Suspendable private fun updatePortfolio(portfolio: Portfolio) { logger.info("Handshake finished, awaiting Simm update") send(replyToParty, Ack) // Hack to state that this party is ready - subProtocol(StateRevisionProtocol.Receiver(replyToParty, { + subFlow(StateRevisionFlow.Receiver(replyToParty, { it.portfolio == portfolio.refs }), shareParentSessions = true) } @@ -308,7 +308,7 @@ object SimmProtocol { val valuer = stateRef.state.data.valuer val valuation = agreeValuation(portfolio, offer.valuationDate, valuer) - subProtocol(StateRevisionProtocol.Receiver(replyToParty) { + subFlow(StateRevisionFlow.Receiver(replyToParty) { it.valuation == valuation }, shareParentSessions = true) } diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/SimmRevaluation.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt similarity index 70% rename from samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/SimmRevaluation.kt rename to samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt index 73507f37a0..d4a339bc67 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/SimmRevaluation.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/SimmRevaluation.kt @@ -1,18 +1,18 @@ -package net.corda.vega.protocols +package net.corda.vega.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.StateRef +import net.corda.core.flows.FlowLogic import net.corda.core.node.services.linearHeadsOfType -import net.corda.core.protocols.ProtocolLogic import net.corda.vega.contracts.PortfolioState import java.time.LocalDate /** - * This is the daily protocol for generating a revalue of the portfolio initiated by the scheduler as per SIMM + * This is the daily flow for generating a revalue of the portfolio initiated by the scheduler as per SIMM * requirements */ object SimmRevaluation { - class Initiator(val curStateRef: StateRef, val valuationDate: LocalDate) : ProtocolLogic() { + class Initiator(val curStateRef: StateRef, val valuationDate: LocalDate) : FlowLogic() { @Suspendable override fun call(): Unit { val stateAndRef = serviceHub.vaultService.linearHeadsOfType().values.first { it.ref == curStateRef } @@ -20,7 +20,7 @@ object SimmRevaluation { val myIdentity = serviceHub.myInfo.legalIdentity if (myIdentity.name == curState.parties[0].name) { val otherParty = curState.parties[1] - subProtocol(SimmProtocol.Requester(otherParty, valuationDate, stateAndRef)) + subFlow(SimmFlow.Requester(otherParty, valuationDate, stateAndRef)) } } } diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/StateRevisionProtocol.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt similarity index 74% rename from samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/StateRevisionProtocol.kt rename to samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt index 977832801e..ddf24d7967 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/protocols/StateRevisionProtocol.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/flows/StateRevisionFlow.kt @@ -1,4 +1,4 @@ -package net.corda.vega.protocols +package net.corda.vega.flows import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateRef @@ -7,21 +7,21 @@ import net.corda.core.crypto.Party import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.UntrustworthyData -import net.corda.protocols.AbstractStateReplacementProtocol +import net.corda.flows.AbstractStateReplacementFlow import net.corda.vega.contracts.RevisionedState /** - * Protocol that generates an update on a mutable deal state and commits the resulting transaction reaching consensus + * Flow that generates an update on a mutable deal state and commits the resulting transaction reaching consensus * on the update between two parties */ -object StateRevisionProtocol { +object StateRevisionFlow { data class Proposal(override val stateRef: StateRef, override val modification: T, - override val stx: SignedTransaction) : AbstractStateReplacementProtocol.Proposal + override val stx: SignedTransaction) : AbstractStateReplacementFlow.Proposal class Requester(curStateRef: StateAndRef>, val updatedData: T) - : AbstractStateReplacementProtocol.Instigator, T>(curStateRef, updatedData) { - override fun assembleProposal(stateRef: StateRef, modification: T, stx: SignedTransaction): AbstractStateReplacementProtocol.Proposal + : AbstractStateReplacementFlow.Instigator, T>(curStateRef, updatedData) { + override fun assembleProposal(stateRef: StateRef, modification: T, stx: SignedTransaction): AbstractStateReplacementFlow.Proposal = Proposal(stateRef, modification, stx) override fun assembleTx(): Pair> { @@ -36,9 +36,9 @@ object StateRevisionProtocol { } class Receiver(otherParty: Party, private val validate: (T) -> Boolean) - : AbstractStateReplacementProtocol.Acceptor(otherParty) { - override fun verifyProposal(maybeProposal: UntrustworthyData>) - : AbstractStateReplacementProtocol.Proposal { + : AbstractStateReplacementFlow.Acceptor(otherParty) { + override fun verifyProposal(maybeProposal: UntrustworthyData>) + : AbstractStateReplacementFlow.Proposal { return maybeProposal.unwrap { val proposedTx = it.stx.tx val state = it.stateRef diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/services/SimmService.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/services/SimmService.kt index 588273a011..47e0d59562 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/services/SimmService.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/services/SimmService.kt @@ -3,29 +3,28 @@ package net.corda.vega.services import net.corda.core.contracts.StateRef import net.corda.core.crypto.Party import net.corda.core.node.CordaPluginRegistry -import net.corda.core.utilities.loggerFor import net.corda.vega.api.PortfolioApi import net.corda.vega.contracts.SwapData -import net.corda.vega.protocols.IRSTradeProtocol -import net.corda.vega.protocols.SimmProtocol -import net.corda.vega.protocols.SimmRevaluation +import net.corda.vega.flows.IRSTradeFlow +import net.corda.vega.flows.SimmFlow +import net.corda.vega.flows.SimmRevaluation import java.time.LocalDate /** - * [SimmService] is the object that makes available the protocols and services for the Simm agreement / evaluation protocol + * [SimmService] is the object that makes available the flows and services for the Simm agreement / evaluation flow * It also enables a human usable web service for demo purposes - if available. * It is loaded via discovery - see [CordaPluginRegistry] */ object SimmService { class Plugin : CordaPluginRegistry() { override val webApis: List> = listOf(PortfolioApi::class.java) - override val requiredProtocols: Map> = mapOf( - SimmProtocol.Requester::class.java.name to setOf(Party::class.java.name, LocalDate::class.java.name), + override val requiredFlows: Map> = mapOf( + SimmFlow.Requester::class.java.name to setOf(Party::class.java.name, LocalDate::class.java.name), SimmRevaluation.Initiator::class.java.name to setOf(StateRef::class.java.name, LocalDate::class.java.name), - IRSTradeProtocol.Requester::class.java.name to setOf(SwapData::class.java.name, Party::class.java.name)) + IRSTradeFlow.Requester::class.java.name to setOf(SwapData::class.java.name, Party::class.java.name)) override val servicePlugins: List> = listOf( - SimmProtocol.Service::class.java, - IRSTradeProtocol.Service::class.java) + SimmFlow.Service::class.java, + IRSTradeFlow.Service::class.java) override val staticServeDirs: Map = mapOf("simmvaluationdemo" to javaClass.classLoader.getResource("simmvaluationweb").toExternalForm()) } } diff --git a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/api/TraderDemoApi.kt b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/api/TraderDemoApi.kt index 5b7c115e47..a812e561bb 100644 --- a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/api/TraderDemoApi.kt +++ b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/api/TraderDemoApi.kt @@ -6,7 +6,7 @@ import net.corda.core.node.ServiceHub import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.Emoji import net.corda.core.utilities.loggerFor -import net.corda.traderdemo.protocol.SellerProtocol +import net.corda.traderdemo.flow.SellerFlow import javax.ws.rs.* import javax.ws.rs.core.MediaType import javax.ws.rs.core.Response @@ -48,15 +48,15 @@ class TraderDemoApi(val services: ServiceHub) { // attachment. Make sure we have the transaction prospectus attachment loaded into our store. // // This can also be done via an HTTP upload, but here we short-circuit and do it from code. - if (services.storageService.attachments.openAttachment(SellerProtocol.PROSPECTUS_HASH) == null) { + if (services.storageService.attachments.openAttachment(SellerFlow.PROSPECTUS_HASH) == null) { javaClass.classLoader.getResourceAsStream("bank-of-london-cp.jar").use { val id = services.storageService.attachments.importAttachment(it) - assertEquals(SellerProtocol.PROSPECTUS_HASH, id) + assertEquals(SellerFlow.PROSPECTUS_HASH, id) } } // The line below blocks and waits for the future to resolve. - val stx = services.invokeProtocolAsync(SellerProtocol::class.java, otherParty, params.amount.DOLLARS).resultFuture.get() + val stx = services.invokeFlowAsync(SellerFlow::class.java, otherParty, params.amount.DOLLARS).resultFuture.get() logger.info("Sale completed - we have a happy customer!\n\nFinal transaction is:\n\n${Emoji.renderIfSupported(stx.tx)}") return Response.status(Response.Status.OK).build() } else { diff --git a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/protocol/BuyerProtocol.kt b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/BuyerFlow.kt similarity index 80% rename from samples/trader-demo/src/main/kotlin/net/corda/traderdemo/protocol/BuyerProtocol.kt rename to samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/BuyerFlow.kt index a750c1ae4d..1226e178b9 100644 --- a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/protocol/BuyerProtocol.kt +++ b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/BuyerFlow.kt @@ -1,25 +1,25 @@ -package net.corda.traderdemo.protocol +package net.corda.traderdemo.flow import co.paralleluniverse.fibers.Suspendable import net.corda.contracts.CommercialPaper import net.corda.core.contracts.Amount import net.corda.core.contracts.TransactionGraphSearch import net.corda.core.crypto.Party +import net.corda.core.flows.FlowLogic import net.corda.core.node.NodeInfo import net.corda.core.node.PluginServiceHub -import net.corda.core.protocols.ProtocolLogic import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.Emoji import net.corda.core.utilities.ProgressTracker +import net.corda.flows.TwoPartyTradeFlow import net.corda.node.services.persistence.NodeAttachmentService -import net.corda.protocols.TwoPartyTradeProtocol import java.nio.file.Path import java.util.* -class BuyerProtocol(val otherParty: Party, - private val attachmentsPath: Path, - override val progressTracker: ProgressTracker = ProgressTracker(STARTING_BUY)) : ProtocolLogic() { +class BuyerFlow(val otherParty: Party, + private val attachmentsPath: Path, + override val progressTracker: ProgressTracker = ProgressTracker(STARTING_BUY)) : FlowLogic() { object STARTING_BUY : ProgressTracker.Step("Seller connected, purchasing commercial paper asset") @@ -31,7 +31,7 @@ class BuyerProtocol(val otherParty: Party, it.automaticallyExtractAttachments = true it.storePath } - services.registerProtocolInitiator(SellerProtocol::class) { BuyerProtocol(it, attachmentsPath) } + services.registerFlowInitiator(SellerFlow::class) { BuyerFlow(it, attachmentsPath) } } } @@ -42,15 +42,15 @@ class BuyerProtocol(val otherParty: Party, // Receive the offered amount and automatically agree to it (in reality this would be a longer negotiation) val amount = receive>(otherParty).unwrap { it } val notary: NodeInfo = serviceHub.networkMapCache.notaryNodes[0] - val buyer = TwoPartyTradeProtocol.Buyer( + val buyer = TwoPartyTradeFlow.Buyer( otherParty, notary.notaryIdentity, amount, CommercialPaper.State::class.java) - // This invokes the trading protocol and out pops our finished transaction. - val tradeTX: SignedTransaction = subProtocol(buyer, shareParentSessions = true) - // TODO: This should be moved into the protocol itself. + // This invokes the trading flow and out pops our finished transaction. + val tradeTX: SignedTransaction = subFlow(buyer, shareParentSessions = true) + // TODO: This should be moved into the flow itself. serviceHub.recordTransactions(listOf(tradeTX)) println("Purchase complete - we are a happy customer! Final transaction is: " + diff --git a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/protocol/SellerProtocol.kt b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt similarity index 81% rename from samples/trader-demo/src/main/kotlin/net/corda/traderdemo/protocol/SellerProtocol.kt rename to samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt index 44fe9db3f1..9966f23a12 100644 --- a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/protocol/SellerProtocol.kt +++ b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/SellerFlow.kt @@ -1,4 +1,4 @@ -package net.corda.traderdemo.protocol +package net.corda.traderdemo.flow import co.paralleluniverse.fibers.Suspendable import net.corda.contracts.CommercialPaper @@ -6,29 +6,29 @@ import net.corda.contracts.asset.DUMMY_CASH_ISSUER import net.corda.core.contracts.* import net.corda.core.crypto.* import net.corda.core.days +import net.corda.core.flows.FlowLogic import net.corda.core.node.NodeInfo -import net.corda.core.protocols.ProtocolLogic import net.corda.core.seconds import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker -import net.corda.protocols.NotaryProtocol -import net.corda.protocols.TwoPartyTradeProtocol +import net.corda.flows.NotaryFlow +import net.corda.flows.TwoPartyTradeFlow import java.time.Instant import java.util.* -class SellerProtocol(val otherParty: Party, - val amount: Amount, - override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic() { +class SellerFlow(val otherParty: Party, + val amount: Amount, + override val progressTracker: ProgressTracker = tracker()) : FlowLogic() { companion object { val PROSPECTUS_HASH = SecureHash.parse("decd098666b9657314870e192ced0c3519c2c9d395507a238338f8d003929de9") object SELF_ISSUING : ProgressTracker.Step("Got session ID back, issuing and timestamping some commercial paper") - object TRADING : ProgressTracker.Step("Starting the trade protocol") { - override fun childProgressTracker(): ProgressTracker = TwoPartyTradeProtocol.Seller.tracker() + object TRADING : ProgressTracker.Step("Starting the trade flow") { + override fun childProgressTracker(): ProgressTracker = TwoPartyTradeFlow.Seller.tracker() } - // We vend a progress tracker that already knows there's going to be a TwoPartyTradingProtocol involved at some + // We vend a progress tracker that already knows there's going to be a TwoPartyTradingFlow involved at some // point: by setting up the tracker in advance, the user can see what's coming in more detail, instead of being // surprised when it appears as a new set of tasks below the current one. fun tracker() = ProgressTracker(SELF_ISSUING, TRADING) @@ -46,14 +46,14 @@ class SellerProtocol(val otherParty: Party, // Send the offered amount. send(otherParty, amount) - val seller = TwoPartyTradeProtocol.Seller( + val seller = TwoPartyTradeFlow.Seller( otherParty, notary, commercialPaper, amount, cpOwnerKey, progressTracker.getChildProgressTracker(TRADING)!!) - val tradeTX: SignedTransaction = subProtocol(seller, shareParentSessions = true) + val tradeTX: SignedTransaction = subFlow(seller, shareParentSessions = true) serviceHub.recordTransactions(listOf(tradeTX)) return tradeTX @@ -81,7 +81,7 @@ class SellerProtocol(val otherParty: Party, tx.signWith(keyPair) // Get the notary to sign the timestamp - val notarySig = subProtocol(NotaryProtocol.Client(tx.toSignedTransaction(false))) + val notarySig = subFlow(NotaryFlow.Client(tx.toSignedTransaction(false))) tx.addSignatureUnchecked(notarySig) // Commit it to local storage. @@ -96,7 +96,7 @@ class SellerProtocol(val otherParty: Party, val builder = TransactionType.General.Builder(notaryNode.notaryIdentity) CommercialPaper().generateMove(builder, issuance.tx.outRef(0), ownedBy) builder.signWith(keyPair) - val notarySignature = subProtocol(NotaryProtocol.Client(builder.toSignedTransaction(false))) + val notarySignature = subFlow(NotaryFlow.Client(builder.toSignedTransaction(false))) builder.addSignatureUnchecked(notarySignature) val tx = builder.toSignedTransaction(true) serviceHub.recordTransactions(listOf(tx)) diff --git a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/plugin/TraderDemoPlugin.kt b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/plugin/TraderDemoPlugin.kt index f69f470611..d0f0e31761 100644 --- a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/plugin/TraderDemoPlugin.kt +++ b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/plugin/TraderDemoPlugin.kt @@ -4,15 +4,15 @@ import net.corda.core.contracts.Amount import net.corda.core.crypto.Party import net.corda.core.node.CordaPluginRegistry import net.corda.traderdemo.api.TraderDemoApi -import net.corda.traderdemo.protocol.BuyerProtocol -import net.corda.traderdemo.protocol.SellerProtocol +import net.corda.traderdemo.flow.BuyerFlow +import net.corda.traderdemo.flow.SellerFlow class TraderDemoPlugin : CordaPluginRegistry() { // A list of classes that expose web APIs. override val webApis: List> = listOf(TraderDemoApi::class.java) - // A list of protocols that are required for this cordapp - override val requiredProtocols: Map> = mapOf( - SellerProtocol::class.java.name to setOf(Party::class.java.name, Amount::class.java.name) + // A list of flows that are required for this cordapp + override val requiredFlows: Map> = mapOf( + SellerFlow::class.java.name to setOf(Party::class.java.name, Amount::class.java.name) ) - override val servicePlugins: List> = listOf(BuyerProtocol.Service::class.java) + override val servicePlugins: List> = listOf(BuyerFlow.Service::class.java) } diff --git a/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt b/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt index 0632e0b3ba..63a60cf107 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/CoreTestUtils.kt @@ -9,13 +9,13 @@ import com.google.common.util.concurrent.SettableFuture import com.typesafe.config.Config import net.corda.core.contracts.StateRef import net.corda.core.crypto.* +import net.corda.core.flows.FlowLogic import net.corda.core.node.ServiceHub -import net.corda.core.protocols.ProtocolLogic import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.DUMMY_NOTARY import net.corda.core.utilities.DUMMY_NOTARY_KEY import net.corda.node.internal.AbstractNode -import net.corda.node.services.statemachine.ProtocolStateMachineImpl +import net.corda.node.services.statemachine.FlowStateMachineImpl import net.corda.node.services.statemachine.StateMachineManager.Change import net.corda.node.utilities.AddOrRemove.ADD import net.corda.testing.node.MockIdentityService @@ -134,14 +134,14 @@ fun getFreeLocalPorts(hostName: String, numberToAlloc: Int): List { ) = ledger { this.transaction(transactionLabel, transactionBuilder, dsl) } /** - * The given protocol factory will be used to initiate just one instance of a protocol of type [P] when a counterparty - * protocol requests for it using [markerClass]. - * @return Returns a [ListenableFuture] holding the single [ProtocolStateMachineImpl] created by the request. + * The given flow factory will be used to initiate just one instance of a flow of type [P] when a counterparty + * flow requests for it using [markerClass]. + * @return Returns a [ListenableFuture] holding the single [FlowStateMachineImpl] created by the request. */ -inline fun > AbstractNode.initiateSingleShotProtocol( - markerClass: KClass>, - noinline protocolFactory: (Party) -> P): ListenableFuture

{ - services.registerProtocolInitiator(markerClass, protocolFactory) +inline fun > AbstractNode.initiateSingleShotFlow( + markerClass: KClass>, + noinline flowFactory: (Party) -> P): ListenableFuture

{ + services.registerFlowInitiator(markerClass, flowFactory) val future = SettableFuture.create

() diff --git a/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt b/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt index 219d67f3c3..3ea85a82b3 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/node/MockNode.kt @@ -170,7 +170,7 @@ class MockNetwork(private val networkSendManuallyPumped: Boolean = false, dbCloser = null } - // You can change this from zero if you have custom [ProtocolLogic] that park themselves. e.g. [StateMachineManagerTests] + // You can change this from zero if you have custom [FlowLogic] that park themselves. e.g. [StateMachineManagerTests] var acceptableLiveFiberCountOnStop: Int = 0 override fun acceptableLiveFiberCountOnStop(): Int = acceptableLiveFiberCountOnStop diff --git a/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt b/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt index b7fae9ead3..da29153ac3 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/node/MockServices.kt @@ -2,14 +2,14 @@ package net.corda.testing.node import net.corda.core.contracts.Attachment import net.corda.core.crypto.* +import net.corda.core.flows.FlowLogic +import net.corda.core.flows.FlowStateMachine +import net.corda.core.flows.StateMachineRunId import net.corda.core.messaging.MessagingService import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.NodeInfo import net.corda.core.node.ServiceHub import net.corda.core.node.services.* -import net.corda.core.protocols.ProtocolLogic -import net.corda.core.protocols.ProtocolStateMachine -import net.corda.core.protocols.StateMachineRunId import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.DUMMY_NOTARY @@ -35,10 +35,10 @@ import javax.annotation.concurrent.ThreadSafe /** * A singleton utility that only provides a mock identity, key and storage service. However, this is sufficient for - * building chains of transactions and verifying them. It isn't sufficient for testing protocols however. + * building chains of transactions and verifying them. It isn't sufficient for testing flows however. */ open class MockServices(val key: KeyPair = generateKeyPair()) : ServiceHub { - override fun invokeProtocolAsync(logicType: Class>, vararg args: Any?): ProtocolStateMachine { + override fun invokeFlowAsync(logicType: Class>, vararg args: Any?): FlowStateMachine { throw UnsupportedOperationException("not implemented") } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt index 9dd8dbbf5a..f79f0e3770 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/Main.kt @@ -15,16 +15,16 @@ import net.corda.core.node.services.ServiceInfo import net.corda.explorer.model.CordaViewModel import net.corda.explorer.views.* import net.corda.explorer.views.cordapps.CashViewer +import net.corda.flows.CashFlow import net.corda.node.driver.PortAllocation import net.corda.node.driver.driver import net.corda.node.services.User import net.corda.node.services.config.FullNodeConfiguration import net.corda.node.services.config.configureTestSSL import net.corda.node.services.messaging.ArtemisMessagingComponent -import net.corda.node.services.messaging.startProtocol -import net.corda.node.services.startProtocolPermission +import net.corda.node.services.messaging.startFlow +import net.corda.node.services.startFlowPermission import net.corda.node.services.transactions.SimpleNotaryService -import net.corda.protocols.CashProtocol import org.apache.commons.lang.SystemUtils import org.controlsfx.dialog.ExceptionDialog import tornadofx.App @@ -102,7 +102,7 @@ class Main : App() { fun main(args: Array) { val portAllocation = PortAllocation.Incremental(20000) driver(portAllocation = portAllocation) { - val user = User("user1", "test", permissions = setOf(startProtocolPermission())) + val user = User("user1", "test", permissions = setOf(startFlowPermission())) val notary = startNode("Notary", advertisedServices = setOf(ServiceInfo(SimpleNotaryService.type))) val alice = startNode("Alice", rpcUsers = arrayListOf(user)) val bob = startNode("Bob", rpcUsers = arrayListOf(user)) @@ -125,7 +125,7 @@ fun main(args: Array) { notary = notaryNode.nodeInfo.notaryIdentity ) eventGenerator.clientToServiceCommandGenerator.map { command -> - rpcProxy?.startProtocol(::CashProtocol, command) + rpcProxy?.startFlow(::CashFlow, command) Unit }.generate(SplittableRandom()) } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/NewTransaction.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/NewTransaction.kt index df59c322b9..9123712d36 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/NewTransaction.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/NewTransaction.kt @@ -15,10 +15,10 @@ import net.corda.core.crypto.Party import net.corda.core.node.NodeInfo import net.corda.core.serialization.OpaqueBytes import net.corda.explorer.model.CashTransaction -import net.corda.node.services.messaging.startProtocol -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol -import net.corda.protocols.CashProtocolResult +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow +import net.corda.flows.CashFlowResult +import net.corda.node.services.messaging.startFlow import org.controlsfx.dialog.ExceptionDialog import tornadofx.View import tornadofx.observable @@ -71,14 +71,14 @@ class NewTransaction : View() { } dialog.show() runAsync { - rpcProxy.value!!.startProtocol(::CashProtocol, it).returnValue.toBlocking().first() + rpcProxy.value!!.startFlow(::CashFlow, it).returnValue.toBlocking().first() }.ui { dialog.contentText = when (it) { - is CashProtocolResult.Success -> { + is CashFlowResult.Success -> { dialog.alertType = Alert.AlertType.INFORMATION "Transaction Started \nTransaction ID : ${it.transaction?.id} \nMessage : ${it.message}" } - is CashProtocolResult.Failed -> { + is CashFlowResult.Failed -> { dialog.alertType = Alert.AlertType.ERROR it.toString() } diff --git a/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt b/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt index dad61aa545..44a46499fa 100644 --- a/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt +++ b/tools/explorer/src/main/kotlin/net/corda/explorer/views/TransactionViewer.kt @@ -23,8 +23,8 @@ import net.corda.contracts.asset.Cash import net.corda.core.contracts.* import net.corda.core.crypto.CompositeKey import net.corda.core.crypto.composite +import net.corda.core.flows.StateMachineRunId import net.corda.core.node.NodeInfo -import net.corda.core.protocols.StateMachineRunId import net.corda.explorer.AmountDiff import net.corda.explorer.formatters.AmountFormatter import net.corda.explorer.identicon.identicon @@ -59,7 +59,7 @@ class TransactionViewer : CordaView("Transactions") { val outputContracts: List, val stateMachineRunId: ObservableValue, val stateMachineStatus: ObservableValue, - val protocolStatus: ObservableValue, + val flowStatus: ObservableValue, val commandTypes: Collection>, val totalValueEquiv: ObservableValue> ) @@ -87,7 +87,7 @@ class TransactionViewer : CordaView("Transactions") { inputContracts = it.transaction.inputs.map { it.value as? PartiallyResolvedTransaction.InputResolution.Resolved }.filterNotNull().map { it.stateAndRef.state.data.contract }, outputContracts = it.transaction.transaction.tx.outputs.map { it.data.contract }, stateMachineRunId = stateMachine.map { it?.id }, - protocolStatus = stateMachineProperty { it.protocolStatus }, + flowStatus = stateMachineProperty { it.flowStatus }, stateMachineStatus = stateMachineProperty { it.stateMachineStatus }, commandTypes = it.transaction.transaction.tx.commands.map { it.value.javaClass }, totalValueEquiv = { @@ -122,7 +122,7 @@ class TransactionViewer : CordaView("Transactions") { column("Input Contract Type(s)", ViewerNode::inputContracts).cellFormat { text = (it.map { it.javaClass.simpleName }.toSet().joinToString(", ")) } column("Output Contract Type(s)", ViewerNode::outputContracts).cellFormat { text = it.map { it.javaClass.simpleName }.toSet().joinToString(", ") } column("State Machine ID", ViewerNode::stateMachineRunId).cellFormat { text = "${it?.uuid ?: ""}" } - column("Protocol status", ViewerNode::protocolStatus).cellFormat { text = "${it.value ?: ""}" } + column("Flow status", ViewerNode::flowStatus).cellFormat { text = "${it.value ?: ""}" } column("SM Status", ViewerNode::stateMachineStatus).cellFormat { text = "${it.value ?: ""}" } column("Command type(s)", ViewerNode::commandTypes).cellFormat { text = it.map { it.simpleName }.joinToString(",") } column("Total value (USD equiv)", ViewerNode::totalValueEquiv) diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/Disruption.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/Disruption.kt index a192ea82a6..fdecd598c5 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/Disruption.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/Disruption.kt @@ -34,7 +34,7 @@ data class DisruptionSpec( * * Exhaust disk space * * Delete non-DB stored files like attachments. * * Strain on DB. - * * In theory starting protocols that hang in a tight loop should do the job. + * * In theory starting flows that hang in a tight loop should do the job. * * We could also mess with the database directly. * * Strain on ActiveMQ. * * Requires exposing of the Artemis client in [NodeConnection]. diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt index a019348e39..1c7724e213 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/CrossCashTest.kt @@ -8,12 +8,12 @@ import net.corda.core.contracts.PartyAndReference import net.corda.core.contracts.USD import net.corda.core.crypto.Party import net.corda.core.serialization.OpaqueBytes +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow +import net.corda.flows.CashFlowResult import net.corda.loadtest.LoadTest import net.corda.loadtest.NodeHandle -import net.corda.node.services.messaging.startProtocol -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol -import net.corda.protocols.CashProtocolResult +import net.corda.node.services.messaging.startFlow import org.slf4j.LoggerFactory import java.util.* @@ -205,12 +205,12 @@ val crossCashTest = LoadTest( }, execute = { command -> - val result = command.node.connection.proxy.startProtocol(::CashProtocol, command.command).returnValue.toBlocking().first() + val result = command.node.connection.proxy.startFlow(::CashFlow, command.command).returnValue.toBlocking().first() when (result) { - is CashProtocolResult.Success -> { + is CashFlowResult.Success -> { log.info(result.message) } - is CashProtocolResult.Failed -> { + is CashFlowResult.Failed -> { log.error(result.message) } } diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/GenerateHelpers.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/GenerateHelpers.kt index 8ade06232f..d8e51aee2a 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/GenerateHelpers.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/GenerateHelpers.kt @@ -7,7 +7,7 @@ import net.corda.core.contracts.Issued import net.corda.core.contracts.PartyAndReference import net.corda.core.crypto.Party import net.corda.core.serialization.OpaqueBytes -import net.corda.protocols.CashCommand +import net.corda.flows.CashCommand import java.util.* fun generateIssue( diff --git a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/SelfIssueTest.kt b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/SelfIssueTest.kt index d843361f6f..b7781de62b 100644 --- a/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/SelfIssueTest.kt +++ b/tools/loadtest/src/main/kotlin/net/corda/loadtest/tests/SelfIssueTest.kt @@ -7,12 +7,12 @@ import net.corda.client.mock.replicatePoisson import net.corda.contracts.asset.Cash import net.corda.core.contracts.USD import net.corda.core.crypto.Party +import net.corda.flows.CashCommand +import net.corda.flows.CashFlow +import net.corda.flows.CashFlowResult import net.corda.loadtest.LoadTest import net.corda.loadtest.NodeHandle -import net.corda.node.services.messaging.startProtocol -import net.corda.protocols.CashCommand -import net.corda.protocols.CashProtocol -import net.corda.protocols.CashProtocolResult +import net.corda.node.services.messaging.startFlow import org.slf4j.LoggerFactory import java.util.* @@ -60,12 +60,12 @@ val selfIssueTest = LoadTest( }, execute = { command -> - val result = command.node.connection.proxy.startProtocol(::CashProtocol, command.command).returnValue.toBlocking().first() + val result = command.node.connection.proxy.startFlow(::CashFlow, command.command).returnValue.toBlocking().first() when (result) { - is CashProtocolResult.Success -> { + is CashFlowResult.Success -> { log.info(result.message) } - is CashProtocolResult.Failed -> { + is CashFlowResult.Failed -> { log.error(result.message) } }