From 2f5efb34d6c0d1d300c4f86837ef332c2a3d6035 Mon Sep 17 00:00:00 2001 From: Clinton Alexander Date: Fri, 21 Oct 2016 09:30:32 +0100 Subject: [PATCH] Removed the RatesFixProtocol and dependent code and moved to the IRS repo. --- .../core/protocols/ProtocolLogicRef.kt | 2 +- .../com/r3corda/protocols/RatesFixProtocol.kt | 109 ---------------- .../r3corda/protocols/TwoPartyDealProtocol.kt | 122 ------------------ .../clientapi/FixingSessionInitiation.kt | 25 ---- 4 files changed, 1 insertion(+), 257 deletions(-) delete mode 100644 core/src/main/kotlin/com/r3corda/protocols/RatesFixProtocol.kt delete mode 100644 node/src/main/kotlin/com/r3corda/node/services/clientapi/FixingSessionInitiation.kt diff --git a/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogicRef.kt b/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogicRef.kt index 06ac12b156..c7b3862219 100644 --- a/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogicRef.kt +++ b/core/src/main/kotlin/com/r3corda/core/protocols/ProtocolLogicRef.kt @@ -27,7 +27,7 @@ import kotlin.reflect.primaryConstructor */ class ProtocolLogicRefFactory(private val protocolWhitelist: Map>) : SingletonSerializeAsToken() { - constructor() : this(mapOf(Pair(TwoPartyDealProtocol.FixingRoleDecider::class.java.name, setOf(StateRef::class.java.name, Duration::class.java.name)))) + constructor() : this(mapOf()) // Pending real dependence on AppContext for class loading etc @Suppress("UNUSED_PARAMETER") diff --git a/core/src/main/kotlin/com/r3corda/protocols/RatesFixProtocol.kt b/core/src/main/kotlin/com/r3corda/protocols/RatesFixProtocol.kt deleted file mode 100644 index e955ddbb61..0000000000 --- a/core/src/main/kotlin/com/r3corda/protocols/RatesFixProtocol.kt +++ /dev/null @@ -1,109 +0,0 @@ -package com.r3corda.protocols - -import co.paralleluniverse.fibers.Suspendable -import com.r3corda.core.contracts.Fix -import com.r3corda.core.contracts.FixOf -import com.r3corda.core.crypto.DigitalSignature -import com.r3corda.core.crypto.Party -import com.r3corda.core.protocols.ProtocolLogic -import com.r3corda.core.transactions.TransactionBuilder -import com.r3corda.core.transactions.WireTransaction -import com.r3corda.core.utilities.ProgressTracker -import com.r3corda.core.utilities.suggestInterestRateAnnouncementTimeWindow -import com.r3corda.protocols.RatesFixProtocol.FixOutOfRange -import java.math.BigDecimal -import java.time.Instant -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 - * 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, - 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() { - - companion object { - class QUERYING(val name: String) : ProgressTracker.Step("Querying oracle for $name interest rate") - object WORKING : ProgressTracker.Step("Working with data returned by oracle") - object SIGNING : ProgressTracker.Step("Requesting confirmation signature from interest rate oracle") - - fun tracker(fixName: String) = ProgressTracker(QUERYING(fixName), WORKING, SIGNING) - } - - class FixOutOfRange(@Suppress("unused") val byAmount: BigDecimal) : Exception("Fix out of range by $byAmount") - - data class QueryRequest(val queries: List, val deadline: Instant) - data class SignRequest(val tx: WireTransaction) - - @Suspendable - override fun call() { - progressTracker.currentStep = progressTracker.steps[1] - val fix = subProtocol(FixQueryProtocol(fixOf, oracle)) - progressTracker.currentStep = WORKING - checkFixIsNearExpected(fix) - tx.addCommand(fix, oracle.owningKey) - beforeSigning(fix) - progressTracker.currentStep = SIGNING - val signature = subProtocol(FixSignProtocol(tx, oracle)) - tx.addSignatureUnchecked(signature) - } - - /** - * You can override this to perform any additional work needed after the fix is added to the transaction but - * before it's sent back to the oracle for signing (for example, adding output states that depend on the fix). - */ - @Suspendable - protected open fun beforeSigning(fix: Fix) { - } - - private fun checkFixIsNearExpected(fix: Fix) { - val delta = (fix.value - expectedRate).abs() - if (delta > rateTolerance) { - // TODO: Kick to a user confirmation / ui flow if it's out of bounds instead of raising an exception. - throw FixOutOfRange(delta) - } - } - - - class FixQueryProtocol(val fixOf: FixOf, val oracle: Party) : ProtocolLogic() { - @Suspendable - override fun call(): Fix { - val deadline = suggestInterestRateAnnouncementTimeWindow(fixOf.name, oracle.name, fixOf.forDay).end - // TODO: add deadline to receive - val resp = sendAndReceive>(oracle, QueryRequest(listOf(fixOf), deadline)) - - return resp.unwrap { - val fix = it.first() - // Check the returned fix is for what we asked for. - check(fix.of == fixOf) - fix - } - } - } - - - class FixSignProtocol(val tx: TransactionBuilder, val oracle: Party) : ProtocolLogic() { - @Suspendable - override fun call(): DigitalSignature.LegallyIdentifiable { - val wtx = tx.toWireTransaction() - val resp = sendAndReceive(oracle, SignRequest(wtx)) - - return resp.unwrap { sig -> - check(sig.signer == oracle) - tx.checkSignature(sig) - sig - } - } - } - -} diff --git a/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt b/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt index da0a649953..8f8d32c388 100644 --- a/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt +++ b/core/src/main/kotlin/com/r3corda/protocols/TwoPartyDealProtocol.kt @@ -306,126 +306,4 @@ object TwoPartyDealProtocol { } } - /** - * One side of the fixing protocol 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. - */ - class Fixer(override val otherParty: Party, - override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary() { - - private lateinit var txState: TransactionState<*> - private lateinit var deal: FixableDealState - - override fun validateHandshake(handshake: Handshake): Handshake { - logger.trace { "Got fixing request for: ${handshake.payload}" } - - txState = serviceHub.loadState(handshake.payload.ref) - deal = txState.data as FixableDealState - - // validate the party that initiated is the one on the deal and that the recipient corresponds with it. - // TODO: this is in no way secure and will be replaced by general session initiation logic in the future - val myName = serviceHub.myInfo.legalIdentity.name - // Also check we are one of the parties - deal.parties.filter { it.name == myName }.single() - - return handshake - } - - @Suspendable - override fun assembleSharedTX(handshake: Handshake): Pair> { - @Suppress("UNCHECKED_CAST") - val fixOf = deal.nextFixingOf()!! - - // TODO Do we need/want to substitute in new public keys for the Parties? - val myName = serviceHub.myInfo.legalIdentity.name - val myOldParty = deal.parties.single { it.name == myName } - - val newDeal = deal - - val ptx = TransactionType.General.Builder(txState.notary) - - val oracle = serviceHub.networkMapCache.get(handshake.payload.oracleType).first() - - val addFixing = object : RatesFixProtocol(ptx, oracle.serviceIdentities(handshake.payload.oracleType).first(), fixOf, BigDecimal.ZERO, BigDecimal.ONE) { - @Suspendable - override fun beforeSigning(fix: Fix) { - newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload.ref), fix) - - // And add a request for timestamping: it may be that none of the contracts need this! But it can't hurt - // to have one. - ptx.setTime(serviceHub.clock.instant(), 30.seconds) - } - } - subProtocol(addFixing) - return Pair(ptx, arrayListOf(myOldParty.owningKey)) - } - } - - /** - * One side of the fixing protocol 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. - */ - class Floater(override val otherParty: Party, - override val payload: FixingSession, - override val progressTracker: ProgressTracker = Primary.tracker()) : Primary() { - - @Suppress("UNCHECKED_CAST") - internal val dealToFix: StateAndRef by TransientProperty { - val state = serviceHub.loadState(payload.ref) as TransactionState - StateAndRef(state, payload.ref) - } - - override val myKeyPair: KeyPair get() { - val myName = serviceHub.myInfo.legalIdentity.name - val publicKey = dealToFix.state.data.parties.filter { it.name == myName }.single().owningKey - return serviceHub.keyManagementService.toKeyPair(publicKey) - } - - override val notaryNode: NodeInfo get() = - serviceHub.networkMapCache.notaryNodes.filter { it.notaryIdentity == dealToFix.state.notary }.single() - } - - - /** Used to set up the session between [Floater] and [Fixer] */ - 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. - * - * 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 - * handled by the [FixingSessionInitiationHandler]. - * - * TODO: Replace [FixingSession] and [FixingSessionInitiationHandler] with generic session initiation logic once it exists. - */ - class FixingRoleDecider(val ref: StateRef, - override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic() { - - companion object { - class LOADING() : ProgressTracker.Step("Loading state to decide fixing role") - - fun tracker() = ProgressTracker(LOADING()) - } - - @Suspendable - override fun call(): Unit { - progressTracker.nextStep() - val dealToFix = serviceHub.loadState(ref) - // TODO: this is not the eventual mechanism for identifying the parties - val fixableDeal = (dealToFix.data as FixableDealState) - val sortedParties = fixableDeal.parties.sortedBy { it.name } - 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)) - } - } - } - } diff --git a/node/src/main/kotlin/com/r3corda/node/services/clientapi/FixingSessionInitiation.kt b/node/src/main/kotlin/com/r3corda/node/services/clientapi/FixingSessionInitiation.kt deleted file mode 100644 index 8e3cf7f591..0000000000 --- a/node/src/main/kotlin/com/r3corda/node/services/clientapi/FixingSessionInitiation.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.r3corda.node.services.clientapi - -import com.r3corda.core.node.CordaPluginRegistry -import com.r3corda.core.serialization.SingletonSerializeAsToken -import com.r3corda.node.services.api.ServiceHubInternal -import com.r3corda.protocols.TwoPartyDealProtocol.Fixer -import com.r3corda.protocols.TwoPartyDealProtocol.Floater - -/** - * This is a temporary handler required for establishing random sessionIDs for the [Fixer] and [Floater] as part of - * running scheduled fixings for the [InterestRateSwap] contract. - * - * TODO: This will be replaced with the symmetric session work - */ -object FixingSessionInitiation { - class Plugin: CordaPluginRegistry() { - override val servicePlugins: List> = listOf(Service::class.java) - } - - class Service(services: ServiceHubInternal) : SingletonSerializeAsToken() { - init { - services.registerProtocolInitiator(Floater::class) { Fixer(it) } - } - } -}