diff --git a/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt b/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt index b88cda50f0..000910c60c 100644 --- a/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt +++ b/contracts/src/main/kotlin/com/r3corda/contracts/IRS.kt @@ -4,6 +4,7 @@ import com.r3corda.core.contracts.* import com.r3corda.core.contracts.clauses.* import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.SecureHash +import com.r3corda.core.node.services.ServiceType import com.r3corda.core.protocols.ProtocolLogicRefFactory import com.r3corda.core.transactions.TransactionBuilder import com.r3corda.core.utilities.suggestInterestRateAnnouncementTimeWindow @@ -187,6 +188,8 @@ class FloatingRatePaymentEvent(date: LocalDate, class InterestRateSwap() : Contract { override val legalContractReference = SecureHash.sha256("is_this_the_text_of_the_contract ? TBD") + object OracleType : ServiceType("corda.interest_rates") + /** * This Common area contains all the information that is not leg specific. */ @@ -653,6 +656,9 @@ class InterestRateSwap() : Contract { override val contract = IRS_PROGRAM_ID + override val oracleType: ServiceType + get() = OracleType + override val ref = common.tradeID override val participants: List diff --git a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt index 0d0c1c2294..3c9bdc77d5 100644 --- a/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/com/r3corda/core/contracts/Structures.kt @@ -4,6 +4,7 @@ import com.r3corda.core.contracts.clauses.Clause import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.toStringShort +import com.r3corda.core.node.services.ServiceType import com.r3corda.core.protocols.ProtocolLogicRef import com.r3corda.core.protocols.ProtocolLogicRefFactory import com.r3corda.core.serialization.OpaqueBytes @@ -302,6 +303,11 @@ interface FixableDealState : DealState { */ fun nextFixingOf(): FixOf? + /** + * What oracle service to use for the fixing + */ + val oracleType: ServiceType + /** * Generate a fixing command for this deal and fix. * diff --git a/core/src/main/kotlin/com/r3corda/core/node/services/NetworkMapCache.kt b/core/src/main/kotlin/com/r3corda/core/node/services/NetworkMapCache.kt index 5b9fb4e346..3235eca87e 100644 --- a/core/src/main/kotlin/com/r3corda/core/node/services/NetworkMapCache.kt +++ b/core/src/main/kotlin/com/r3corda/core/node/services/NetworkMapCache.kt @@ -28,8 +28,6 @@ interface NetworkMapCache { val networkMapNodes: List /** A list of nodes that advertise a notary service */ val notaryNodes: List - /** A list of nodes that advertise a rates oracle service */ - val ratesOracleNodes: List /** A list of all nodes the cache is aware of */ val partyNodes: List /** Tracks changes to the network map cache */ diff --git a/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt b/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt index bd9eb8d95a..7479bd4c3e 100644 --- a/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt +++ b/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt @@ -8,6 +8,7 @@ import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.signWithECDSA import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.services.DEFAULT_SESSION_ID +import com.r3corda.core.node.services.ServiceType import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.random63BitValue import com.r3corda.core.seconds @@ -374,7 +375,10 @@ object TwoPartyDealProtocol { val newDeal = deal val ptx = TransactionType.General.Builder(txState.notary) - val addFixing = object : RatesFixProtocol(ptx, serviceHub.networkMapCache.ratesOracleNodes[0].identity, fixOf, BigDecimal.ZERO, BigDecimal.ONE) { + + val oracle = serviceHub.networkMapCache.get(initiation.oracleType).first() + + val addFixing = object : RatesFixProtocol(ptx, oracle.identity, fixOf, BigDecimal.ZERO, BigDecimal.ONE) { @Suspendable override fun beforeSigning(fix: Fix) { newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload), fix) @@ -423,7 +427,7 @@ object TwoPartyDealProtocol { /** Used to set up the session between [Floater] and [Fixer] */ - data class FixingSessionInitiation(val sessionID: Long, val party: Party, val sender: Party, val timeout: Duration) + data class FixingSessionInitiation(val sessionID: Long, val party: Party, val sender: Party, val timeout: Duration, val oracleType: ServiceType) /** * This protocol looks at the deal and decides whether to be the Fixer or Floater role in agreeing a fixing. @@ -451,11 +455,13 @@ object TwoPartyDealProtocol { progressTracker.nextStep() val dealToFix = serviceHub.loadState(ref) // TODO: this is not the eventual mechanism for identifying the parties - val sortedParties = (dealToFix.data as FixableDealState).parties.sortedBy { it.name } + val fixableDeal = (dealToFix.data as FixableDealState) + val sortedParties = fixableDeal.parties.sortedBy { it.name } + val oracleType = fixableDeal.oracleType if (sortedParties[0].name == serviceHub.storageService.myLegalIdentity.name) { // Generate sessionID val sessionID = random63BitValue() - val initation = FixingSessionInitiation(sessionID, sortedParties[0], serviceHub.storageService.myLegalIdentity, timeout) + val initation = FixingSessionInitiation(sessionID, sortedParties[0], serviceHub.storageService.myLegalIdentity, timeout, oracleType) // Send initiation to other side to launch one side of the fixing protocol (the Fixer). send(sortedParties[1], DEFAULT_SESSION_ID, initation) diff --git a/node/src/main/kotlin/com/r3corda/node/services/network/InMemoryNetworkMapCache.kt b/node/src/main/kotlin/com/r3corda/node/services/network/InMemoryNetworkMapCache.kt index ae3c671119..3d54f1854d 100644 --- a/node/src/main/kotlin/com/r3corda/node/services/network/InMemoryNetworkMapCache.kt +++ b/node/src/main/kotlin/com/r3corda/node/services/network/InMemoryNetworkMapCache.kt @@ -21,7 +21,6 @@ import com.r3corda.core.serialization.SingletonSerializeAsToken import com.r3corda.core.serialization.deserialize import com.r3corda.core.serialization.serialize import com.r3corda.node.services.api.RegulatorService -import com.r3corda.node.services.clientapi.NodeInterestRates import com.r3corda.node.services.transactions.NotaryService import com.r3corda.node.utilities.AddOrRemove import rx.Observable @@ -42,8 +41,6 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach get() = get(RegulatorService.Type) override val notaryNodes: List get() = get(NotaryService.Type) - override val ratesOracleNodes: List - get() = get(NodeInterestRates.Type) override val partyNodes: List get() = registeredNodes.map { it.value } private val _changed = PublishSubject.create() diff --git a/node/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry b/node/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry index 6ddd29d16d..fc0921e785 100644 --- a/node/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry +++ b/node/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry @@ -1,5 +1,4 @@ # Register a ServiceLoader service extending from com.r3corda.node.CordaPluginRegistry com.r3corda.node.services.clientapi.FixingSessionInitiation$Plugin -com.r3corda.node.services.clientapi.NodeInterestRates$Plugin com.r3corda.node.services.NotaryChange$Plugin com.r3corda.node.services.persistence.DataVending$Plugin \ No newline at end of file diff --git a/src/main/kotlin/com/r3corda/demos/IRSDemo.kt b/src/main/kotlin/com/r3corda/demos/IRSDemo.kt index 8ef46411a1..a09bafb3d6 100644 --- a/src/main/kotlin/com/r3corda/demos/IRSDemo.kt +++ b/src/main/kotlin/com/r3corda/demos/IRSDemo.kt @@ -21,7 +21,7 @@ import com.r3corda.demos.utilities.putJson import com.r3corda.demos.utilities.uploadFile import com.r3corda.node.internal.AbstractNode import com.r3corda.node.internal.Node -import com.r3corda.node.services.clientapi.NodeInterestRates +import com.r3corda.demos.api.NodeInterestRates import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.config.NodeConfigurationFromConfig import com.r3corda.node.services.messaging.ArtemisMessagingClient diff --git a/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt b/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt index 4a267a5546..ae0c40f0b9 100644 --- a/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt +++ b/src/main/kotlin/com/r3corda/demos/RateFixDemo.kt @@ -1,28 +1,23 @@ package com.r3corda.demos import com.google.common.net.HostAndPort +import com.r3corda.contracts.InterestRateSwap import com.r3corda.contracts.asset.Cash import com.r3corda.core.contracts.* -import com.r3corda.core.crypto.Party import com.r3corda.core.logElapsedTime -import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.services.ServiceType -import com.r3corda.testing.node.makeTestDataSourceProperties -import com.r3corda.core.serialization.deserialize import com.r3corda.core.utilities.Emoji import com.r3corda.core.utilities.LogHelper +import com.r3corda.demos.api.NodeInterestRates import com.r3corda.node.internal.Node -import com.r3corda.node.services.clientapi.NodeInterestRates import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.messaging.ArtemisMessagingClient -import com.r3corda.node.services.network.NetworkMapService -import com.r3corda.node.services.transactions.NotaryService import com.r3corda.protocols.RatesFixProtocol +import com.r3corda.testing.node.makeTestDataSourceProperties import joptsimple.OptionParser import org.slf4j.Logger import org.slf4j.LoggerFactory import java.math.BigDecimal -import java.nio.file.Files import java.nio.file.Paths import java.util.* import kotlin.system.exitProcess @@ -78,7 +73,7 @@ fun main(args: Array) { advertisedServices, DemoClock()).setup().start() } node.networkMapRegistrationFuture.get() val notaryNode = node.services.networkMapCache.notaryNodes[0] - val rateOracle = node.services.networkMapCache.ratesOracleNodes[0] + val rateOracle = node.services.networkMapCache.get(InterestRateSwap.OracleType).first() // Make a garbage transaction that includes a rate fix. val tx = TransactionType.General.Builder(notaryNode.identity) diff --git a/node/src/main/kotlin/com/r3corda/node/services/clientapi/NodeInterestRates.kt b/src/main/kotlin/com/r3corda/demos/api/NodeInterestRates.kt similarity index 98% rename from node/src/main/kotlin/com/r3corda/node/services/clientapi/NodeInterestRates.kt rename to src/main/kotlin/com/r3corda/demos/api/NodeInterestRates.kt index a55aea4bd8..c4e11a7a35 100644 --- a/node/src/main/kotlin/com/r3corda/node/services/clientapi/NodeInterestRates.kt +++ b/src/main/kotlin/com/r3corda/demos/api/NodeInterestRates.kt @@ -1,4 +1,4 @@ -package com.r3corda.node.services.clientapi +package com.r3corda.demos.api import co.paralleluniverse.fibers.Suspendable import com.r3corda.core.RetryableException @@ -49,7 +49,7 @@ object NodeInterestRates { */ class Plugin : CordaPluginRegistry() { override val requiredProtocols: Map> = mapOf(Pair(TwoPartyDealProtocol.FixingRoleDecider::class.java.name, setOf(Duration::class.java.name, StateRef::class.java.name))) - override val servicePlugins: List> = listOf(NodeInterestRates.Service::class.java) + override val servicePlugins: List> = listOf(Service::class.java) } /** diff --git a/src/main/kotlin/com/r3corda/simulation/Simulation.kt b/src/main/kotlin/com/r3corda/simulation/Simulation.kt index 85377dbfd1..c88ba935f6 100644 --- a/src/main/kotlin/com/r3corda/simulation/Simulation.kt +++ b/src/main/kotlin/com/r3corda/simulation/Simulation.kt @@ -10,7 +10,7 @@ import com.r3corda.core.node.services.ServiceType import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.then import com.r3corda.core.utilities.ProgressTracker -import com.r3corda.node.services.clientapi.NodeInterestRates +import com.r3corda.demos.api.NodeInterestRates import com.r3corda.node.services.config.NodeConfiguration import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.transactions.SimpleNotaryService @@ -109,7 +109,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, object RatesOracleFactory : MockNetwork.Factory { override fun create(dir: Path, config: com.r3corda.node.services.config.NodeConfiguration, network: MockNetwork, networkMapAddr: SingleMessageRecipient?, advertisedServices: Set, id: Int, keyPair: KeyPair?): MockNetwork.MockNode { - require(advertisedServices.contains(com.r3corda.node.services.clientapi.NodeInterestRates.Type)) + require(advertisedServices.contains(NodeInterestRates.Type)) val cfg = object : com.r3corda.node.services.config.NodeConfiguration { override val myLegalName: String = "Rates Service Provider" override val exportJMXto: String = "" @@ -121,7 +121,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, return object : SimulatedNode(dir, cfg, network, networkMapAddr, advertisedServices, id, keyPair) { override fun start(): MockNetwork.MockNode { super.start() - findService().upload(javaClass.getResourceAsStream("example.rates.txt")) + findService().upload(javaClass.getResourceAsStream("example.rates.txt")) return this } } @@ -156,7 +156,7 @@ abstract class Simulation(val networkSendManuallyPumped: Boolean, = network.createNode(networkMap.info.address, nodeFactory = NotaryNodeFactory, advertisedServices = com.r3corda.node.services.transactions.SimpleNotaryService.Type) as SimulatedNode val regulators: List = listOf(network.createNode(networkMap.info.address, start = false, nodeFactory = RegulatorFactory) as SimulatedNode) val ratesOracle: SimulatedNode - = network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = com.r3corda.node.services.clientapi.NodeInterestRates.Type) as SimulatedNode + = network.createNode(networkMap.info.address, start = false, nodeFactory = RatesOracleFactory, advertisedServices = NodeInterestRates.Type) as SimulatedNode // All nodes must be in one of these two lists for the purposes of the visualiser tool. val serviceProviders: List = listOf(notary, ratesOracle, networkMap) diff --git a/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry b/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry index 33d9c399d8..3a781ec23d 100644 --- a/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry +++ b/src/main/resources/META-INF/services/com.r3corda.core.node.CordaPluginRegistry @@ -1,5 +1,6 @@ # Register a ServiceLoader service extending from com.r3corda.node.CordaPluginRegistry com.r3corda.demos.IRSDemoPluginRegistry +com.r3corda.demos.api.NodeInterestRates$Plugin com.r3corda.demos.protocols.AutoOfferProtocol$Plugin com.r3corda.demos.protocols.ExitServerProtocol$Plugin com.r3corda.demos.protocols.UpdateBusinessDayProtocol$Plugin \ No newline at end of file diff --git a/node/src/test/kotlin/com/r3corda/node/services/NodeInterestRatesTest.kt b/src/test/kotlin/com/r3corda/core/testing/NodeInterestRatesTest.kt similarity index 98% rename from node/src/test/kotlin/com/r3corda/node/services/NodeInterestRatesTest.kt rename to src/test/kotlin/com/r3corda/core/testing/NodeInterestRatesTest.kt index cab98cf3c6..b5e195450a 100644 --- a/node/src/test/kotlin/com/r3corda/node/services/NodeInterestRatesTest.kt +++ b/src/test/kotlin/com/r3corda/core/testing/NodeInterestRatesTest.kt @@ -1,4 +1,4 @@ -package com.r3corda.node.services +package com.r3corda.core.testing import com.r3corda.contracts.asset.CASH import com.r3corda.contracts.asset.Cash @@ -14,7 +14,7 @@ import com.r3corda.core.crypto.generateKeyPair import com.r3corda.core.utilities.DUMMY_NOTARY import com.r3corda.core.utilities.LogHelper import com.r3corda.testing.node.MockNetwork -import com.r3corda.node.services.clientapi.NodeInterestRates +import com.r3corda.demos.api.NodeInterestRates import com.r3corda.protocols.RatesFixProtocol import com.r3corda.testing.ALICE_PUBKEY import com.r3corda.testing.MEGA_CORP