From f3863ac5efb3419d31f6564226e76bdb39e5931b Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Thu, 7 Apr 2016 19:02:14 +0200 Subject: [PATCH] Minor: eliminate compiler warnings --- contracts/src/main/kotlin/contracts/IRS.kt | 4 ++-- .../src/main/kotlin/contracts/IRSUtils.kt | 6 ++--- core/src/main/kotlin/core/Structures.kt | 6 ++++- src/main/kotlin/api/APIServerImpl.kt | 10 ++++++--- .../core/node/services/NodeWalletService.kt | 2 +- .../kotlin/core/node/services/Services.kt | 20 ++++++----------- .../core/node/services/StorageServiceImpl.kt | 5 +++-- .../core/testing/InMemoryMessagingNetwork.kt | 6 ++--- src/main/kotlin/demos/IRSDemo.kt | 10 +++++---- .../demos/protocols/ExitServerProtocol.kt | 4 ++-- .../protocols/UpdateBusinessDayProtocol.kt | 10 +++++---- .../kotlin/protocols/TwoPartyDealProtocol.kt | 22 +++++++++++-------- src/test/kotlin/contracts/IRSTests.kt | 10 --------- 13 files changed, 58 insertions(+), 57 deletions(-) diff --git a/contracts/src/main/kotlin/contracts/IRS.kt b/contracts/src/main/kotlin/contracts/IRS.kt index d7c559c543..f084568149 100644 --- a/contracts/src/main/kotlin/contracts/IRS.kt +++ b/contracts/src/main/kotlin/contracts/IRS.kt @@ -453,7 +453,6 @@ class InterestRateSwap() : Contract { val calculation: Calculation, val common: Common ) : FixableDealState { - override val programRef = IRS_PROGRAM_ID override val thread = SecureHash.sha256(common.tradeID) override val ref = common.tradeID @@ -465,7 +464,8 @@ class InterestRateSwap() : Contract { override val parties: Array get() = arrayOf(fixedLeg.fixedRatePayer, floatingLeg.floatingRatePayer) - override fun withPublicKey(before: Party, after: PublicKey): State { + // TODO: This changing of the public key violates the assumption that Party is a fixed identity key. + override fun withPublicKey(before: Party, after: PublicKey): DealState { val newParty = Party(before.name, after) if (before == fixedLeg.fixedRatePayer) { val deal = copy() diff --git a/contracts/src/main/kotlin/contracts/IRSUtils.kt b/contracts/src/main/kotlin/contracts/IRSUtils.kt index 0bc634ba95..caf270abce 100644 --- a/contracts/src/main/kotlin/contracts/IRSUtils.kt +++ b/contracts/src/main/kotlin/contracts/IRSUtils.kt @@ -45,8 +45,8 @@ open class PercentageRatioUnit(percentageAsString: String) : RatioUnit(BigDecima val String.percent: PercentageRatioUnit get() = PercentageRatioUnit(this) /** - * Interface representing an agreement that exposes various attributes that are common and allow - * implementation of general protocols that manipulate many agreement types + * Interface representing an agreement that exposes various attributes that are common. Implementing it simplifies + * implementation of general protocols that manipulate many agreement types. */ interface DealState : LinearState { @@ -56,7 +56,7 @@ interface DealState : LinearState { /** Exposes the Parties involved in a generic way */ val parties: Array - /** Allow swapping in of potentially transaction specific public keys prior to signing */ + // TODO: This works by editing the keys used by a Party which is invalid. fun withPublicKey(before: Party, after: PublicKey): DealState /** diff --git a/core/src/main/kotlin/core/Structures.kt b/core/src/main/kotlin/core/Structures.kt index a29cd728ca..2d2e25b07f 100644 --- a/core/src/main/kotlin/core/Structures.kt +++ b/core/src/main/kotlin/core/Structures.kt @@ -18,7 +18,6 @@ import java.io.OutputStream import java.security.PublicKey import java.time.Duration import java.time.Instant -import java.time.LocalDate import java.util.jar.JarInputStream /** Implemented by anything that can be named by a secure hash value (e.g. transactions, attachments). */ @@ -75,6 +74,11 @@ data class StateRef(val txhash: SecureHash, val index: Int) { /** A StateAndRef is simply a (state, ref) pair. For instance, a wallet (which holds available assets) contains these. */ data class StateAndRef(val state: T, val ref: StateRef) +/** Filters a list of [StateAndRef] objects according to the type of the states */ +inline fun List>.filterStatesOfType(): List> { + return mapNotNull { if (it.state is T) StateAndRef(it.state, it.ref) else null } +} + /** A [Party] is well known (name, pubkey) pair. In a real system this would probably be an X.509 certificate. */ data class Party(val name: String, val owningKey: PublicKey) { override fun toString() = name diff --git a/src/main/kotlin/api/APIServerImpl.kt b/src/main/kotlin/api/APIServerImpl.kt index ee9013b315..501972c6e1 100644 --- a/src/main/kotlin/api/APIServerImpl.kt +++ b/src/main/kotlin/api/APIServerImpl.kt @@ -2,10 +2,14 @@ package api import com.google.common.util.concurrent.ListenableFuture import contracts.DealState -import core.* +import core.ContractState +import core.SignedTransaction +import core.StateRef +import core.WireTransaction import core.crypto.DigitalSignature import core.crypto.SecureHash import core.node.AbstractNode +import core.node.services.linearHeadsOfType import core.protocols.ProtocolLogic import core.serialization.SerializedBytes import core.utilities.ANSIProgressRenderer @@ -28,8 +32,8 @@ class APIServerImpl(val node: AbstractNode): APIServer { return states.values.map { it.ref } } else if (query.criteria is StatesQuery.Criteria.Deal) { - val states = node.services.walletService.linearHeadsInstanceOf(DealState::class.java) { - it.ref == query.criteria.ref + val states = node.services.walletService.linearHeadsOfType().filterValues { + it.state.ref == query.criteria.ref } return states.values.map { it.ref } } diff --git a/src/main/kotlin/core/node/services/NodeWalletService.kt b/src/main/kotlin/core/node/services/NodeWalletService.kt index 1841be036b..630b25e635 100644 --- a/src/main/kotlin/core/node/services/NodeWalletService.kt +++ b/src/main/kotlin/core/node/services/NodeWalletService.kt @@ -48,7 +48,7 @@ class NodeWalletService(private val services: ServiceHub) : WalletService { */ override val linearHeads: Map> get() = mutex.locked { wallet }.let { wallet -> - wallet.states.filter { it.state is LinearState }.associateBy { (it.state as LinearState).thread }.mapValues { it.value as StateAndRef } + wallet.states.filterStatesOfType().associateBy { it.state.thread }.mapValues { it.value } } override fun notifyAll(txns: Iterable): Wallet { diff --git a/src/main/kotlin/core/node/services/Services.kt b/src/main/kotlin/core/node/services/Services.kt index 6f3194727e..41e0cdc2df 100644 --- a/src/main/kotlin/core/node/services/Services.kt +++ b/src/main/kotlin/core/node/services/Services.kt @@ -72,8 +72,12 @@ interface WalletService { */ val linearHeads: Map> - fun linearHeadsInstanceOf(clazz: Class, predicate: (T) -> Boolean = { true } ): Map> { - return linearHeads.filterValues { clazz.isInstance(it.state) }.filterValues { predicate(it.state as T) }.mapValues { StateAndRef(it.value.state as T, it.value.ref) } + // TODO: When KT-10399 is fixed, rename this and remove the inline version below. + + /** Returns the [linearHeads] only when the type of the state would be considered an 'instanceof' the given type. */ + @Suppress("UNCHECKED_CAST") + fun linearHeadsOfType_(stateType: Class): Map> { + return linearHeads.filterValues { stateType.isInstance(it.state) }.mapValues { StateAndRef(it.value.state as T, it.value.ref) } } fun statesForRefs(refs: List): Map { @@ -95,17 +99,7 @@ interface WalletService { fun notify(tx: WireTransaction): Wallet = notifyAll(listOf(tx)) } -// TODO: Document this -@Suppress("UNCHECKED_CAST") -inline fun WalletService.linearHeadsOfType(): Map> { - return linearHeads.mapNotNull { - val s = it.value.state - if (s is T) - Pair(it.key, it.value as StateAndRef) - else - null - }.toMap() -} +inline fun WalletService.linearHeadsOfType() = linearHeadsOfType_(T::class.java) /** * The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example, diff --git a/src/main/kotlin/core/node/services/StorageServiceImpl.kt b/src/main/kotlin/core/node/services/StorageServiceImpl.kt index b0a0490282..53173438b5 100644 --- a/src/main/kotlin/core/node/services/StorageServiceImpl.kt +++ b/src/main/kotlin/core/node/services/StorageServiceImpl.kt @@ -16,12 +16,13 @@ open class StorageServiceImpl(attachments: AttachmentStorage, // This parameter is for unit tests that want to observe operation details. val recordingAs: (String) -> String = { tableName -> "" }) : StorageService { - protected val tables = HashMap>() + protected val tables = HashMap>() private fun getMapOriginal(tableName: String): MutableMap { synchronized(tables) { + @Suppress("UNCHECKED_CAST") return tables.getOrPut(tableName) { - recorderWrap(Collections.synchronizedMap(HashMap()), tableName); + recorderWrap(Collections.synchronizedMap(HashMap()), tableName) } as MutableMap } } diff --git a/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt b/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt index 70601f41f3..1f5ac4700f 100644 --- a/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt +++ b/src/main/kotlin/core/testing/InMemoryMessagingNetwork.kt @@ -89,15 +89,15 @@ class InMemoryMessagingNetwork { if (calc != null && recipients is SingleMessageRecipient) { // Inject some artificial latency. timer.schedule(calc.between(from.myAddress, recipients).toMillis()) { - msgSendInternal(from, message, recipients) + msgSendInternal(message, recipients) } } else { - msgSendInternal(from, message, recipients) + msgSendInternal(message, recipients) } _allMessages.onNext(Triple(from.myAddress, message, recipients)) } - private fun msgSendInternal(from: InMemoryMessaging, message: Message, recipients: MessageRecipients) { + private fun msgSendInternal(message: Message, recipients: MessageRecipients) { when (recipients) { is Handle -> getQueueForHandle(recipients).add(message) diff --git a/src/main/kotlin/demos/IRSDemo.kt b/src/main/kotlin/demos/IRSDemo.kt index dbbed14153..b35ec1df82 100644 --- a/src/main/kotlin/demos/IRSDemo.kt +++ b/src/main/kotlin/demos/IRSDemo.kt @@ -16,14 +16,14 @@ import core.node.Node import core.node.NodeConfiguration import core.node.NodeConfigurationFromConfig import core.node.services.ArtemisMessagingService -import core.node.services.NodeInfo import core.node.services.MockNetworkMapCache +import core.node.services.NodeInfo import core.serialization.deserialize import core.utilities.BriefLogFormatter -import joptsimple.OptionParser import demos.protocols.AutoOfferProtocol import demos.protocols.ExitServerProtocol import demos.protocols.UpdateBusinessDayProtocol +import joptsimple.OptionParser import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths @@ -122,8 +122,10 @@ fun main(args: Array) { UpdateBusinessDayProtocol.Handler.register(node) ExitServerProtocol.Handler.register(node) - while(true) { - Thread.sleep(1000L) + try { + while (true) Thread.sleep(Long.MAX_VALUE) + } catch(e: InterruptedException) { + node.stop() } exitProcess(0) } diff --git a/src/main/kotlin/demos/protocols/ExitServerProtocol.kt b/src/main/kotlin/demos/protocols/ExitServerProtocol.kt index 260f2356d1..1cb6f3c7a0 100644 --- a/src/main/kotlin/demos/protocols/ExitServerProtocol.kt +++ b/src/main/kotlin/demos/protocols/ExitServerProtocol.kt @@ -3,8 +3,8 @@ package demos.protocols import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.strands.Strand import core.node.Node -import core.node.services.NodeInfo import core.node.services.MockNetworkMapCache +import core.node.services.NodeInfo import core.protocols.ProtocolLogic import core.serialization.deserialize import java.util.concurrent.TimeUnit @@ -37,7 +37,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: Integer) : ProtocolLogic() { + class Broadcast(@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") val exitCode: Integer) : ProtocolLogic() { @Suspendable override fun call(): Boolean { diff --git a/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt b/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt index 409d175795..dc28a9182b 100644 --- a/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt +++ b/src/main/kotlin/demos/protocols/UpdateBusinessDayProtocol.kt @@ -6,8 +6,9 @@ import contracts.DealState import contracts.InterestRateSwap import core.StateAndRef import core.node.Node -import core.node.services.NodeInfo import core.node.services.MockNetworkMapCache +import core.node.services.NodeInfo +import core.node.services.linearHeadsOfType import core.protocols.ProtocolLogic import core.random63BitValue import core.serialization.deserialize @@ -41,7 +42,7 @@ object UpdateBusinessDayProtocol { override fun call(): Boolean { // Get deals progressTracker.currentStep = FETCHING - val dealStateRefs = serviceHub.walletService.linearHeadsInstanceOf(DealState::class.java) + val dealStateRefs = serviceHub.walletService.linearHeadsOfType() val otherPartyToDeals = dealStateRefs.values.groupBy { otherParty(it.state) } // TODO we need to process these in parallel to stop there being an ordering problem across more than two nodes @@ -65,8 +66,9 @@ object UpdateBusinessDayProtocol { // TODO we should make this more object oriented when we can ask a state for it's contract @Suspendable fun processDeal(party: NodeInfo, deal: StateAndRef, date: LocalDate, sessionID: Long) { - when(deal.state) { - is InterestRateSwap.State -> processInterestRateSwap(party, StateAndRef(deal.state as InterestRateSwap.State, deal.ref), date, sessionID) + val s = deal.state + when (s) { + is InterestRateSwap.State -> processInterestRateSwap(party, StateAndRef(s, deal.ref), date, sessionID) } } diff --git a/src/main/kotlin/protocols/TwoPartyDealProtocol.kt b/src/main/kotlin/protocols/TwoPartyDealProtocol.kt index 29de9746bf..3061d2a32c 100644 --- a/src/main/kotlin/protocols/TwoPartyDealProtocol.kt +++ b/src/main/kotlin/protocols/TwoPartyDealProtocol.kt @@ -239,7 +239,7 @@ object TwoPartyDealProtocol { private fun receiveAndValidateHandshake(): Handshake { progressTracker.currentStep = RECEIVING // Wait for a trade request to come in on our pre-provided session ID. - val handshake = receive(DEAL_TOPIC, sessionID, Handshake::class.java) + val handshake = receive>(DEAL_TOPIC, sessionID) progressTracker.currentStep = VERIFYING handshake.validate { @@ -267,7 +267,7 @@ object TwoPartyDealProtocol { return ptx.toSignedTransaction(checkSufficientSignatures = false) } - @Suspendable protected abstract fun validateHandshake(handshake: Handshake<*>): Handshake + @Suspendable protected abstract fun validateHandshake(handshake: Handshake): Handshake @Suspendable protected abstract fun assembleSharedTX(handshake: Handshake): Pair> } @@ -291,10 +291,10 @@ object TwoPartyDealProtocol { override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary(otherSide, timestampingAuthority, sessionID) { @Suspendable - override fun validateHandshake(handshake: Handshake<*>): Handshake { - with(handshake as Handshake) { + override fun validateHandshake(handshake: Handshake): Handshake { + with(handshake) { // What is the seller trying to sell us? - val deal = handshake.payload + val deal: T = handshake.payload val otherKey = handshake.publicKey logger.trace { "Got deal request for: ${handshake.payload}" } @@ -308,7 +308,10 @@ object TwoPartyDealProtocol { val myOldParty = deal.parties.single { it.name == myName } val theirOldParty = deal.parties.single { it.name != myName } - val newDeal = deal.withPublicKey(myOldParty, serviceHub.keyManagementService.freshKey().public).withPublicKey(theirOldParty, otherKey) as T + @Suppress("UNCHECKED_CAST") + val newDeal = deal. + withPublicKey(myOldParty, serviceHub.keyManagementService.freshKey().public). + withPublicKey(theirOldParty, otherKey) as T return handshake.copy(payload = newDeal) } @@ -341,8 +344,8 @@ object TwoPartyDealProtocol { override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary(otherSide, timestampingAuthority, sessionID) { @Suspendable - override fun validateHandshake(handshake: Handshake<*>): Handshake { - with(handshake as Handshake) { + override fun validateHandshake(handshake: Handshake): Handshake { + with(handshake) { logger.trace { "Got fixing request for: ${dealToFix.state}" } // Check the start message for acceptability. @@ -363,11 +366,12 @@ object TwoPartyDealProtocol { // TODO Do we need/want to substitute in new public keys for the Parties? val myName = serviceHub.storageService.myLegalIdentity.name - val deal = dealToFix.state + val deal: T = dealToFix.state val myOldParty = deal.parties.single { it.name == myName } val theirOldParty = deal.parties.single { it.name != myName } val myNewKey = serviceHub.keyManagementService.freshKey().public + @Suppress("UNCHECKED_CAST") val newDeal = deal.withPublicKey(myOldParty, myNewKey).withPublicKey(theirOldParty, handshake.publicKey) as T val oldRef = dealToFix.ref diff --git a/src/test/kotlin/contracts/IRSTests.kt b/src/test/kotlin/contracts/IRSTests.kt index 0ed2295f49..6126737896 100644 --- a/src/test/kotlin/contracts/IRSTests.kt +++ b/src/test/kotlin/contracts/IRSTests.kt @@ -326,19 +326,9 @@ class IRSTests { assert(100 * r1 == 5) } - @Test - fun `more rate tests`() { - val r1 = FixedRate(PercentageRatioUnit("10")) - val r2 = FixedRate(PercentageRatioUnit("10")) - - // TODO: r1+r2 ? Do we want to allow these. - // TODO: r1*r2 ? - } - @Test fun `expression calculation testing`() { val dummyIRS = singleIRS() - val v = FixedRate(PercentageRatioUnit("4.5")) val stuffToPrint: ArrayList = arrayListOf( "fixedLeg.notional.pennies", "fixedLeg.fixedRate.ratioUnit",