Introducing StartableByRPC and SchedulableFlow annotations, needed by flows started via RPC and schedulable flows respectively.

CordaPluginRegistry.requiredFlows is no longer needed as a result.
This commit is contained in:
Shams Asari
2017-05-10 11:28:25 +01:00
parent b155764023
commit 48f58b6dbc
52 changed files with 401 additions and 434 deletions

View File

@ -7,6 +7,7 @@ import net.corda.core.utilities.DUMMY_BANK_A
import net.corda.core.utilities.DUMMY_BANK_B
import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.node.driver.driver
import net.corda.node.services.startFlowPermission
import net.corda.node.services.transactions.SimpleNotaryService
import net.corda.nodeapi.User
import org.junit.Test
@ -17,11 +18,11 @@ class AttachmentDemoTest {
@Test fun `attachment demo using a 10MB zip file`() {
val numOfExpectedBytes = 10_000_000
driver(dsl = {
val demoUser = listOf(User("demo", "demo", setOf("StartFlow.net.corda.flows.FinalityFlow")))
val demoUser = listOf(User("demo", "demo", setOf(startFlowPermission<AttachmentDemoFlow>())))
val (nodeA, nodeB) = Futures.allAsList(
startNode(DUMMY_BANK_A.name, rpcUsers = demoUser),
startNode(DUMMY_BANK_B.name, rpcUsers = demoUser),
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.Companion.type)))
startNode(DUMMY_NOTARY.name, setOf(ServiceInfo(SimpleNotaryService.type)))
).getOrThrow()
val senderThread = CompletableFuture.supplyAsync {

View File

@ -1,5 +1,6 @@
package net.corda.attachmentdemo
import co.paralleluniverse.fibers.Suspendable
import com.google.common.net.HostAndPort
import joptsimple.OptionParser
import net.corda.client.rpc.CordaRPCClient
@ -9,14 +10,14 @@ import net.corda.core.contracts.TransactionForContract
import net.corda.core.contracts.TransactionType
import net.corda.core.identity.Party
import net.corda.core.crypto.SecureHash
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.StartableByRPC
import net.corda.core.getOrThrow
import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startTrackedFlow
import net.corda.core.sizedInputStreamAndHash
import net.corda.core.utilities.DUMMY_BANK_B
import net.corda.core.utilities.DUMMY_NOTARY
import net.corda.core.utilities.DUMMY_NOTARY_KEY
import net.corda.core.utilities.Emoji
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.*
import net.corda.flows.FinalityFlow
import net.corda.node.driver.poll
import java.io.InputStream
@ -83,26 +84,40 @@ fun sender(rpc: CordaRPCOps, inputStream: InputStream, hash: SecureHash.SHA256)
val id = rpc.uploadAttachment(it)
require(hash == id) { "Id was '$id' instead of '$hash'" }
}
require(rpc.attachmentExists(hash))
}
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
val ptx = TransactionType.General.Builder(notary = DUMMY_NOTARY)
require(rpc.attachmentExists(hash))
ptx.addOutputState(AttachmentContract.State(hash))
ptx.addAttachment(hash)
// Sign with the notary key
ptx.signWith(DUMMY_NOTARY_KEY)
// Send the transaction to the other recipient
val stx = ptx.toSignedTransaction()
println("Sending ${stx.id}")
val flowHandle = rpc.startTrackedFlow(::FinalityFlow, stx, setOf(otherSide))
val flowHandle = rpc.startTrackedFlow(::AttachmentDemoFlow, otherSide, hash)
flowHandle.progress.subscribe(::println)
flowHandle.returnValue.getOrThrow()
val stx = flowHandle.returnValue.getOrThrow()
println("Sent ${stx.id}")
}
@StartableByRPC
class AttachmentDemoFlow(val otherSide: Party, val hash: SecureHash.SHA256) : FlowLogic<SignedTransaction>() {
object SIGNING : ProgressTracker.Step("Signing transaction")
override val progressTracker: ProgressTracker = ProgressTracker(SIGNING)
@Suspendable
override fun call(): SignedTransaction {
// Create a trivial transaction with an output that describes the attachment, and the attachment itself
val ptx = TransactionType.General.Builder(notary = DUMMY_NOTARY)
ptx.addOutputState(AttachmentContract.State(hash))
ptx.addAttachment(hash)
progressTracker.currentStep = SIGNING
// Sign with the notary key
ptx.signWith(DUMMY_NOTARY_KEY)
// Send the transaction to the other recipient
val stx = ptx.toSignedTransaction()
return subFlow(FinalityFlow(stx, setOf(otherSide))).single()
}
}
fun recipient(rpc: CordaRPCOps) {
println("Waiting to receive transaction ...")
val stx = rpc.verifiedTransactions().second.toBlocking().first()

View File

@ -1,12 +0,0 @@
package net.corda.attachmentdemo.plugin
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.transactions.SignedTransaction
import net.corda.flows.FinalityFlow
class AttachmentDemoPlugin : CordaPluginRegistry() {
// A list of Flows that are required for this cordapp
override val requiredFlows: Map<String, Set<String>> = mapOf(
FinalityFlow::class.java.name to setOf(SignedTransaction::class.java.name, setOf(Unit).javaClass.name, setOf(Unit).javaClass.name)
)
}

View File

@ -1,2 +0,0 @@
# Register a ServiceLoader service extending from net.corda.core.node.CordaPluginRegistry
net.corda.attachmentdemo.plugin.AttachmentDemoPlugin

View File

@ -1,17 +1,13 @@
package net.corda.bank.plugin
import net.corda.bank.api.BankOfCordaWebApi
import net.corda.core.contracts.Amount
import net.corda.core.identity.Party
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.serialization.OpaqueBytes
import net.corda.flows.IssuerFlow
import java.util.function.Function
class BankOfCordaPlugin : CordaPluginRegistry() {
// A list of classes that expose web APIs.
override val webApis = listOf(Function(::BankOfCordaWebApi))
// A list of flow that are required for this cordapp
override val requiredFlows: Map<String, Set<String>> = mapOf(IssuerFlow.IssuanceRequester::class.java.name to setOf(Amount::class.java.name, Party::class.java.name, OpaqueBytes::class.java.name, Party::class.java.name))
override val servicePlugins = listOf(Function(IssuerFlow.Issuer::Service))
}

View File

@ -19,7 +19,6 @@ import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.transactions.FilteredTransaction
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.unwrap
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
@ -32,12 +31,14 @@ import java.io.InputStream
import java.math.BigDecimal
import java.security.KeyPair
import java.time.Clock
import java.time.Duration
import java.time.Instant
import java.time.LocalDate
import java.util.*
import java.util.function.Function
import javax.annotation.concurrent.ThreadSafe
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
/**
* An interest rates service is an oracle that signs transactions which contain embedded assertions about an interest
@ -55,7 +56,6 @@ object NodeInterestRates {
* Register the flow that is used with the Fixing integration tests.
*/
class Plugin : CordaPluginRegistry() {
override val requiredFlows = mapOf(Pair(FixingFlow.FixingRoleDecider::class.java.name, setOf(Duration::class.java.name, StateRef::class.java.name)))
override val servicePlugins = listOf(Function(::Service))
}

View File

@ -5,6 +5,7 @@ import net.corda.core.contracts.DealState
import net.corda.core.identity.AbstractParty
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.node.PluginServiceHub
import net.corda.core.serialization.SingletonSerializeAsToken
@ -37,6 +38,7 @@ object AutoOfferFlow {
}
@InitiatingFlow
@StartableByRPC
class Requester(val dealToBeOffered: DealState) : FlowLogic<SignedTransaction>() {
companion object {

View File

@ -8,6 +8,7 @@ import net.corda.core.crypto.keys
import net.corda.core.crypto.toBase58String
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.SchedulableFlow
import net.corda.core.node.NodeInfo
import net.corda.core.node.PluginServiceHub
import net.corda.core.node.services.ServiceType
@ -136,6 +137,7 @@ object FixingFlow {
* Fixer role is chosen, then that will be initiated by the [FixingSession] message sent from the other party.
*/
@InitiatingFlow
@SchedulableFlow
class FixingRoleDecider(val ref: StateRef, override val progressTracker: ProgressTracker) : FlowLogic<Unit>() {
@Suppress("unused") // Used via reflection.
constructor(ref: StateRef) : this(ref, tracker())

View File

@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.core.identity.Party
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.node.NodeInfo
import net.corda.core.node.PluginServiceHub
@ -44,6 +45,7 @@ object UpdateBusinessDayFlow {
@InitiatingFlow
@StartableByRPC
class Broadcast(val date: LocalDate, override val progressTracker: ProgressTracker) : FlowLogic<Unit>() {
constructor(date: LocalDate) : this(date, tracker())

View File

@ -1,15 +1,9 @@
package net.corda.irs.plugin
import net.corda.core.contracts.StateRef
import net.corda.core.identity.Party
import net.corda.core.node.CordaPluginRegistry
import net.corda.irs.api.InterestRateSwapAPI
import net.corda.irs.contract.InterestRateSwap
import net.corda.irs.flows.AutoOfferFlow
import net.corda.irs.flows.FixingFlow
import net.corda.irs.flows.UpdateBusinessDayFlow
import java.time.Duration
import java.time.LocalDate
import java.util.function.Function
class IRSPlugin : CordaPluginRegistry() {
@ -18,9 +12,4 @@ class IRSPlugin : CordaPluginRegistry() {
"irsdemo" to javaClass.classLoader.getResource("irsweb").toExternalForm()
)
override val servicePlugins = listOf(Function(FixingFlow::Service))
override val requiredFlows: Map<String, Set<String>> = mapOf(
AutoOfferFlow.Requester::class.java.name to setOf(InterestRateSwap.State::class.java.name),
UpdateBusinessDayFlow.Broadcast::class.java.name to setOf(LocalDate::class.java.name),
FixingFlow.FixingRoleDecider::class.java.name to setOf(StateRef::class.java.name, Duration::class.java.name),
FixingFlow.Floater::class.java.name to setOf(Party::class.java.name, FixingFlow.FixingSession::class.java.name))
}

View File

@ -1,15 +0,0 @@
package net.corda.notarydemo.plugin
import net.corda.core.identity.Party
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.transactions.SignedTransaction
import net.corda.flows.NotaryFlow
import net.corda.notarydemo.flows.DummyIssueAndMove
class NotaryDemoPlugin : CordaPluginRegistry() {
// A list of protocols that are required for this cordapp
override val requiredFlows = mapOf(
NotaryFlow.Client::class.java.name to setOf(SignedTransaction::class.java.name, setOf(Unit).javaClass.name),
DummyIssueAndMove::class.java.name to setOf(Party::class.java.name)
)
}

View File

@ -1,2 +0,0 @@
# Register a ServiceLoader service extending from net.corda.node.CordaPluginRegistry
net.corda.notarydemo.plugin.NotaryDemoPlugin

View File

@ -4,6 +4,7 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.core.identity.Party
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.PluginServiceHub
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.SignedTransaction
@ -24,6 +25,7 @@ object IRSTradeFlow {
data class OfferMessage(val notary: Party, val dealBeingOffered: IRSState)
@InitiatingFlow
@StartableByRPC
class Requester(val swap: SwapData, val otherParty: Party) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {

View File

@ -14,6 +14,7 @@ import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.Party
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.PluginServiceHub
import net.corda.core.node.services.dealsWith
import net.corda.core.serialization.CordaSerializable
@ -51,6 +52,7 @@ object SimmFlow {
* margin using SIMM. If there is an existing state it will update and revalue the portfolio agreement.
*/
@InitiatingFlow
@StartableByRPC
class Requester(val otherParty: Party,
val valuationDate: LocalDate,
val existing: StateAndRef<PortfolioState>?)

View File

@ -3,6 +3,8 @@ 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.flows.SchedulableFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.services.linearHeadsOfType
import net.corda.vega.contracts.PortfolioState
import java.time.LocalDate
@ -12,6 +14,8 @@ import java.time.LocalDate
* requirements
*/
object SimmRevaluation {
@StartableByRPC
@SchedulableFlow
class Initiator(val curStateRef: StateRef, val valuationDate: LocalDate) : FlowLogic<Unit>() {
@Suspendable
override fun call(): Unit {

View File

@ -10,18 +10,14 @@ import com.opengamma.strata.market.curve.CurveName
import com.opengamma.strata.market.param.CurrencyParameterSensitivities
import com.opengamma.strata.market.param.CurrencyParameterSensitivity
import com.opengamma.strata.market.param.TenorDateParameterMetadata
import net.corda.core.contracts.StateRef
import net.corda.core.identity.Party
import net.corda.core.node.CordaPluginRegistry
import net.corda.core.serialization.SerializationCustomization
import net.corda.vega.analytics.CordaMarketData
import net.corda.vega.analytics.InitialMarginTriple
import net.corda.vega.api.PortfolioApi
import net.corda.vega.contracts.SwapData
import net.corda.vega.flows.IRSTradeFlow
import net.corda.vega.flows.SimmFlow
import net.corda.vega.flows.SimmRevaluation
import java.time.LocalDate
import java.util.function.Function
/**
@ -32,10 +28,6 @@ import java.util.function.Function
object SimmService {
class Plugin : CordaPluginRegistry() {
override val webApis = listOf(Function(::PortfolioApi))
override val requiredFlows: Map<String, Set<String>> = 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),
IRSTradeFlow.Requester::class.java.name to setOf(SwapData::class.java.name, Party::class.java.name))
override val staticServeDirs: Map<String, String> = mapOf("simmvaluationdemo" to javaClass.classLoader.getResource("simmvaluationweb").toExternalForm())
override val servicePlugins = listOf(Function(SimmFlow::Service), Function(IRSTradeFlow::Service))
override fun customizeSerialization(custom: SerializationCustomization): Boolean {

View File

@ -10,6 +10,7 @@ import net.corda.core.crypto.generateKeyPair
import net.corda.core.days
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.StartableByRPC
import net.corda.core.node.NodeInfo
import net.corda.core.seconds
import net.corda.core.transactions.SignedTransaction
@ -22,6 +23,7 @@ import java.time.Instant
import java.util.*
@InitiatingFlow
@StartableByRPC
class SellerFlow(val otherParty: Party,
val amount: Amount<Currency>,
override val progressTracker: ProgressTracker) : FlowLogic<SignedTransaction>() {

View File

@ -1,16 +1,10 @@
package net.corda.traderdemo.plugin
import net.corda.core.contracts.Amount
import net.corda.core.identity.Party
import net.corda.core.node.CordaPluginRegistry
import net.corda.traderdemo.flow.BuyerFlow
import net.corda.traderdemo.flow.SellerFlow
import java.util.function.Function
class TraderDemoPlugin : CordaPluginRegistry() {
// A list of Flows that are required for this cordapp
override val requiredFlows: Map<String, Set<String>> = mapOf(
SellerFlow::class.java.name to setOf(Party::class.java.name, Amount::class.java.name)
)
override val servicePlugins = listOf(Function(BuyerFlow::Service))
}