send and sendAndReceive use Party for the destination

This commit is contained in:
Shams Asari 2016-06-30 11:18:28 +01:00
parent aef111114f
commit a02263937c
39 changed files with 237 additions and 220 deletions

View File

@ -7,7 +7,6 @@ import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.DigitalSignature import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.signWithECDSA import com.r3corda.core.crypto.signWithECDSA
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
@ -61,7 +60,7 @@ object TwoPartyTradeProtocol {
class SignaturesFromSeller(val sellerSig: DigitalSignature.WithKey, class SignaturesFromSeller(val sellerSig: DigitalSignature.WithKey,
val notarySig: DigitalSignature.LegallyIdentifiable) val notarySig: DigitalSignature.LegallyIdentifiable)
open class Seller(val otherSide: SingleMessageRecipient, open class Seller(val otherSide: Party,
val notaryNode: NodeInfo, val notaryNode: NodeInfo,
val assetToSell: StateAndRef<OwnableState>, val assetToSell: StateAndRef<OwnableState>,
val price: Amount<Issued<Currency>>, val price: Amount<Issued<Currency>>,
@ -172,7 +171,7 @@ object TwoPartyTradeProtocol {
} }
} }
open class Buyer(val otherSide: SingleMessageRecipient, open class Buyer(val otherSide: Party,
val notary: Party, val notary: Party,
val acceptablePrice: Amount<Issued<Currency>>, val acceptablePrice: Amount<Issued<Currency>>,
val typeToBuy: Class<out OwnableState>, val typeToBuy: Class<out OwnableState>,

View File

@ -169,6 +169,7 @@ interface StorageService {
* Returns the legal identity that this node is configured with. Assumed to be initialised when the node is * Returns the legal identity that this node is configured with. Assumed to be initialised when the node is
* first installed. * first installed.
*/ */
//TODO this should be in the IdentityService, or somewhere not here
val myLegalIdentity: Party val myLegalIdentity: Party
val myLegalIdentityKey: KeyPair val myLegalIdentityKey: KeyPair
} }

View File

@ -1,7 +1,7 @@
package com.r3corda.core.protocols package com.r3corda.core.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3corda.core.messaging.MessageRecipients import com.r3corda.core.crypto.Party
import com.r3corda.core.node.ServiceHub import com.r3corda.core.node.ServiceHub
import com.r3corda.core.utilities.ProgressTracker import com.r3corda.core.utilities.ProgressTracker
import com.r3corda.core.utilities.UntrustworthyData import com.r3corda.core.utilities.UntrustworthyData
@ -39,9 +39,12 @@ abstract class ProtocolLogic<T> {
val serviceHub: ServiceHub get() = psm.serviceHub val serviceHub: ServiceHub get() = psm.serviceHub
// Kotlin helpers that allow the use of generic types. // Kotlin helpers that allow the use of generic types.
inline fun <reified T : Any> sendAndReceive(topic: String, destination: MessageRecipients, sessionIDForSend: Long, inline fun <reified T : Any> sendAndReceive(topic: String,
sessionIDForReceive: Long, obj: Any): UntrustworthyData<T> { destination: Party,
return psm.sendAndReceive(topic, destination, sessionIDForSend, sessionIDForReceive, obj, T::class.java) sessionIDForSend: Long,
sessionIDForReceive: Long,
payload: Any): UntrustworthyData<T> {
return psm.sendAndReceive(topic, destination, sessionIDForSend, sessionIDForReceive, payload, T::class.java)
} }
inline fun <reified T : Any> receive(topic: String, sessionIDForReceive: Long): UntrustworthyData<T> { inline fun <reified T : Any> receive(topic: String, sessionIDForReceive: Long): UntrustworthyData<T> {
@ -52,8 +55,8 @@ abstract class ProtocolLogic<T> {
return psm.receive(topic, sessionIDForReceive, clazz) return psm.receive(topic, sessionIDForReceive, clazz)
} }
@Suspendable fun send(topic: String, destination: MessageRecipients, sessionID: Long, obj: Any) { @Suspendable fun send(topic: String, destination: Party, sessionID: Long, payload: Any) {
psm.send(topic, destination, sessionID, obj) psm.send(topic, destination, sessionID, payload)
} }
/** /**

View File

@ -1,7 +1,7 @@
package com.r3corda.core.protocols package com.r3corda.core.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3corda.core.messaging.MessageRecipients import com.r3corda.core.crypto.Party
import com.r3corda.core.node.ServiceHub import com.r3corda.core.node.ServiceHub
import com.r3corda.core.utilities.UntrustworthyData import com.r3corda.core.utilities.UntrustworthyData
import org.slf4j.Logger import org.slf4j.Logger
@ -12,14 +12,14 @@ import org.slf4j.Logger
*/ */
interface ProtocolStateMachine<R> { interface ProtocolStateMachine<R> {
@Suspendable @Suspendable
fun <T : Any> sendAndReceive(topic: String, destination: MessageRecipients, sessionIDForSend: Long, sessionIDForReceive: Long, fun <T : Any> sendAndReceive(topic: String, destination: Party, sessionIDForSend: Long, sessionIDForReceive: Long,
obj: Any, recvType: Class<T>): UntrustworthyData<T> payload: Any, recvType: Class<T>): UntrustworthyData<T>
@Suspendable @Suspendable
fun <T : Any> receive(topic: String, sessionIDForReceive: Long, recvType: Class<T>): UntrustworthyData<T> fun <T : Any> receive(topic: String, sessionIDForReceive: Long, recvType: Class<T>): UntrustworthyData<T>
@Suspendable @Suspendable
fun send(topic: String, destination: MessageRecipients, sessionID: Long, obj: Any) fun send(topic: String, destination: Party, sessionID: Long, payload: Any)
val serviceHub: ServiceHub val serviceHub: ServiceHub
val logger: Logger val logger: Logger

View File

@ -1,9 +0,0 @@
package com.r3corda.protocols
import com.r3corda.core.messaging.MessageRecipients
/**
* Abstract superclass for request messages sent to services, which includes common
* fields such as replyTo and replyToTopic.
*/
abstract class AbstractRequestMessage(val replyTo: MessageRecipients, val sessionID: Long?)

View File

@ -1,9 +1,9 @@
package com.r3corda.protocols package com.r3corda.protocols
import com.r3corda.core.contracts.Attachment import com.r3corda.core.contracts.Attachment
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.crypto.sha256 import com.r3corda.core.crypto.sha256
import com.r3corda.core.messaging.SingleMessageRecipient
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.InputStream import java.io.InputStream
@ -12,7 +12,7 @@ import java.io.InputStream
* attachments are saved to local storage automatically. * attachments are saved to local storage automatically.
*/ */
class FetchAttachmentsProtocol(requests: Set<SecureHash>, class FetchAttachmentsProtocol(requests: Set<SecureHash>,
otherSide: SingleMessageRecipient) : FetchDataProtocol<Attachment, ByteArray>(requests, otherSide) { otherSide: Party) : FetchDataProtocol<Attachment, ByteArray>(requests, otherSide) {
companion object { companion object {
const val TOPIC = "platform.fetch.attachment" const val TOPIC = "platform.fetch.attachment"
} }

View File

@ -2,8 +2,8 @@ package com.r3corda.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3corda.core.contracts.NamedByHash import com.r3corda.core.contracts.NamedByHash
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
import com.r3corda.core.utilities.UntrustworthyData import com.r3corda.core.utilities.UntrustworthyData
@ -27,13 +27,13 @@ import java.util.*
*/ */
abstract class FetchDataProtocol<T : NamedByHash, W : Any>( abstract class FetchDataProtocol<T : NamedByHash, W : Any>(
protected val requests: Set<SecureHash>, protected val requests: Set<SecureHash>,
protected val otherSide: SingleMessageRecipient) : ProtocolLogic<FetchDataProtocol.Result<T>>() { protected val otherSide: Party) : ProtocolLogic<FetchDataProtocol.Result<T>>() {
open class BadAnswer : Exception() open class BadAnswer : Exception()
class HashNotFound(val requested: SecureHash) : BadAnswer() class HashNotFound(val requested: SecureHash) : BadAnswer()
class DownloadedVsRequestedDataMismatch(val requested: SecureHash, val got: SecureHash) : BadAnswer() class DownloadedVsRequestedDataMismatch(val requested: SecureHash, val got: SecureHash) : BadAnswer()
class Request(val hashes: List<SecureHash>, replyTo: SingleMessageRecipient, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) class Request(val hashes: List<SecureHash>, replyTo: Party, override val sessionID: Long) : AbstractRequestMessage(replyTo)
data class Result<T : NamedByHash>(val fromDisk: List<T>, val downloaded: List<T>) data class Result<T : NamedByHash>(val fromDisk: List<T>, val downloaded: List<T>)
protected abstract val queryTopic: String protected abstract val queryTopic: String
@ -49,7 +49,7 @@ abstract class FetchDataProtocol<T : NamedByHash, W : Any>(
logger.trace("Requesting ${toFetch.size} dependency(s) for verification") logger.trace("Requesting ${toFetch.size} dependency(s) for verification")
val sid = random63BitValue() val sid = random63BitValue()
val fetchReq = Request(toFetch, serviceHub.networkService.myAddress, sid) val fetchReq = Request(toFetch, serviceHub.storageService.myLegalIdentity, sid)
// TODO: Support "large message" response streaming so response sizes are not limited by RAM. // TODO: Support "large message" response streaming so response sizes are not limited by RAM.
val maybeItems = sendAndReceive<ArrayList<W?>>(queryTopic, otherSide, 0, sid, fetchReq) val maybeItems = sendAndReceive<ArrayList<W?>>(queryTopic, otherSide, 0, sid, fetchReq)
// Check for a buggy/malicious peer answering with something that we didn't ask for. // Check for a buggy/malicious peer answering with something that we didn't ask for.

View File

@ -1,8 +1,8 @@
package com.r3corda.protocols package com.r3corda.protocols
import com.r3corda.core.contracts.SignedTransaction import com.r3corda.core.contracts.SignedTransaction
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.messaging.SingleMessageRecipient
/** /**
* Given a set of tx hashes (IDs), either loads them from local disk or asks the remote peer to provide them. * Given a set of tx hashes (IDs), either loads them from local disk or asks the remote peer to provide them.
@ -12,7 +12,7 @@ import com.r3corda.core.messaging.SingleMessageRecipient
* results in a [FetchDataProtocol.HashNotFound] exception. Note that returned transactions are not inserted into * results in a [FetchDataProtocol.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. * the database, because it's up to the caller to actually verify the transactions are valid.
*/ */
class FetchTransactionsProtocol(requests: Set<SecureHash>, otherSide: SingleMessageRecipient) : class FetchTransactionsProtocol(requests: Set<SecureHash>, otherSide: Party) :
FetchDataProtocol<SignedTransaction, SignedTransaction>(requests, otherSide) { FetchDataProtocol<SignedTransaction, SignedTransaction>(requests, otherSide) {
companion object { companion object {
const val TOPIC = "platform.fetch.tx" const val TOPIC = "platform.fetch.tx"

View File

@ -9,8 +9,6 @@ import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SignedData import com.r3corda.core.crypto.SignedData
import com.r3corda.core.crypto.signWithECDSA import com.r3corda.core.crypto.signWithECDSA
import com.r3corda.core.messaging.Ack import com.r3corda.core.messaging.Ack
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.TimestampChecker import com.r3corda.core.node.services.TimestampChecker
import com.r3corda.core.node.services.UniquenessException import com.r3corda.core.node.services.UniquenessException
import com.r3corda.core.node.services.UniquenessProvider import com.r3corda.core.node.services.UniquenessProvider
@ -45,21 +43,21 @@ object NotaryProtocol {
fun tracker() = ProgressTracker(REQUESTING, VALIDATING) fun tracker() = ProgressTracker(REQUESTING, VALIDATING)
} }
lateinit var notaryNode: NodeInfo lateinit var notaryParty: Party
@Suspendable @Suspendable
override fun call(): DigitalSignature.LegallyIdentifiable { override fun call(): DigitalSignature.LegallyIdentifiable {
progressTracker.currentStep = REQUESTING progressTracker.currentStep = REQUESTING
notaryNode = findNotaryNode() notaryParty = findNotaryParty()
val sendSessionID = random63BitValue() val sendSessionID = random63BitValue()
val receiveSessionID = random63BitValue() val receiveSessionID = random63BitValue()
val handshake = Handshake(serviceHub.networkService.myAddress, sendSessionID, receiveSessionID) val handshake = Handshake(serviceHub.storageService.myLegalIdentity, sendSessionID, receiveSessionID)
sendAndReceive<Ack>(TOPIC_INITIATE, notaryNode.address, 0, receiveSessionID, handshake) sendAndReceive<Ack>(TOPIC_INITIATE, notaryParty, 0, receiveSessionID, handshake)
val request = SignRequest(stx, serviceHub.storageService.myLegalIdentity) val request = SignRequest(stx, serviceHub.storageService.myLegalIdentity)
val response = sendAndReceive<Result>(TOPIC, notaryNode.address, sendSessionID, receiveSessionID, request) val response = sendAndReceive<Result>(TOPIC, notaryParty, sendSessionID, receiveSessionID, request)
val notaryResult = validateResponse(response) val notaryResult = validateResponse(response)
return notaryResult.sig ?: throw NotaryException(notaryResult.error!!) return notaryResult.sig ?: throw NotaryException(notaryResult.error!!)
@ -72,17 +70,17 @@ object NotaryProtocol {
if (it.sig != null) validateSignature(it.sig, stx.txBits) if (it.sig != null) validateSignature(it.sig, stx.txBits)
else if (it.error is NotaryError.Conflict) it.error.conflict.verified() else if (it.error is NotaryError.Conflict) it.error.conflict.verified()
else if (it.error == null || it.error !is NotaryError) else if (it.error == null || it.error !is NotaryError)
throw IllegalStateException("Received invalid result from Notary service '${notaryNode.identity}'") throw IllegalStateException("Received invalid result from Notary service '$notaryParty'")
return it return it
} }
} }
private fun validateSignature(sig: DigitalSignature.LegallyIdentifiable, data: SerializedBytes<WireTransaction>) { private fun validateSignature(sig: DigitalSignature.LegallyIdentifiable, data: SerializedBytes<WireTransaction>) {
check(sig.signer == notaryNode.identity) { "Notary result not signed by the correct service" } check(sig.signer == notaryParty) { "Notary result not signed by the correct service" }
sig.verifyWithECDSA(data) sig.verifyWithECDSA(data)
} }
private fun findNotaryNode(): NodeInfo { private fun findNotaryParty(): Party {
var maybeNotaryKey: PublicKey? = null var maybeNotaryKey: PublicKey? = null
val wtx = stx.tx val wtx = stx.tx
@ -97,8 +95,8 @@ object NotaryProtocol {
} }
val notaryKey = maybeNotaryKey ?: throw IllegalStateException("Transaction does not specify a Notary") val notaryKey = maybeNotaryKey ?: throw IllegalStateException("Transaction does not specify a Notary")
val notaryNode = serviceHub.networkMapCache.getNodeByPublicKey(notaryKey) val notaryParty = serviceHub.networkMapCache.getNodeByPublicKey(notaryKey)?.identity
return notaryNode ?: throw IllegalStateException("No Notary node can be found with the specified public key") return notaryParty ?: throw IllegalStateException("No Notary node can be found with the specified public key")
} }
} }
@ -110,7 +108,7 @@ object NotaryProtocol {
* *
* TODO: the notary service should only be able to see timestamp commands and inputs * TODO: the notary service should only be able to see timestamp commands and inputs
*/ */
open class Service(val otherSide: SingleMessageRecipient, open class Service(val otherSide: Party,
val sendSessionID: Long, val sendSessionID: Long,
val receiveSessionID: Long, val receiveSessionID: Long,
val timestampChecker: TimestampChecker, val timestampChecker: TimestampChecker,
@ -181,9 +179,9 @@ object NotaryProtocol {
} }
class Handshake( class Handshake(
replyTo: SingleMessageRecipient, replyTo: Party,
val sendSessionID: Long, val sendSessionID: Long,
sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) override val sessionID: Long) : AbstractRequestMessage(replyTo)
/** TODO: The caller must authenticate instead of just specifying its identity */ /** TODO: The caller must authenticate instead of just specifying its identity */
class SignRequest(val tx: SignedTransaction, class SignRequest(val tx: SignedTransaction,
@ -197,7 +195,7 @@ object NotaryProtocol {
} }
interface Factory { interface Factory {
fun create(otherSide: SingleMessageRecipient, fun create(otherSide: Party,
sendSessionID: Long, sendSessionID: Long,
receiveSessionID: Long, receiveSessionID: Long,
timestampChecker: TimestampChecker, timestampChecker: TimestampChecker,
@ -205,7 +203,7 @@ object NotaryProtocol {
} }
object DefaultFactory : Factory { object DefaultFactory : Factory {
override fun create(otherSide: SingleMessageRecipient, override fun create(otherSide: Party,
sendSessionID: Long, sendSessionID: Long,
receiveSessionID: Long, receiveSessionID: Long,
timestampChecker: TimestampChecker, timestampChecker: TimestampChecker,

View File

@ -6,8 +6,7 @@ import com.r3corda.core.contracts.FixOf
import com.r3corda.core.contracts.TransactionBuilder import com.r3corda.core.contracts.TransactionBuilder
import com.r3corda.core.contracts.WireTransaction import com.r3corda.core.contracts.WireTransaction
import com.r3corda.core.crypto.DigitalSignature import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.messaging.SingleMessageRecipient import com.r3corda.core.crypto.Party
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
import com.r3corda.core.utilities.ProgressTracker import com.r3corda.core.utilities.ProgressTracker
@ -28,7 +27,7 @@ import java.util.*
* @throws FixOutOfRange if the returned fix was further away from the expected rate by the given amount. * @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 RatesFixProtocol(protected val tx: TransactionBuilder,
private val oracle: NodeInfo, private val oracle: Party,
private val fixOf: FixOf, private val fixOf: FixOf,
private val expectedRate: BigDecimal, private val expectedRate: BigDecimal,
private val rateTolerance: BigDecimal, private val rateTolerance: BigDecimal,
@ -48,8 +47,8 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder,
class FixOutOfRange(val byAmount: BigDecimal) : Exception() class FixOutOfRange(val byAmount: BigDecimal) : Exception()
class QueryRequest(val queries: List<FixOf>, replyTo: SingleMessageRecipient, sessionID: Long, val deadline: Instant) : AbstractRequestMessage(replyTo, sessionID) class QueryRequest(val queries: List<FixOf>, replyTo: Party, override val sessionID: Long, val deadline: Instant) : AbstractRequestMessage(replyTo)
class SignRequest(val tx: WireTransaction, replyTo: SingleMessageRecipient, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) class SignRequest(val tx: WireTransaction, replyTo: Party, override val sessionID: Long) : AbstractRequestMessage(replyTo)
@Suspendable @Suspendable
override fun call() { override fun call() {
@ -57,7 +56,7 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder,
val fix = query() val fix = query()
progressTracker.currentStep = WORKING progressTracker.currentStep = WORKING
checkFixIsNearExpected(fix) checkFixIsNearExpected(fix)
tx.addCommand(fix, oracle.identity.owningKey) tx.addCommand(fix, oracle.owningKey)
beforeSigning(fix) beforeSigning(fix)
progressTracker.currentStep = SIGNING progressTracker.currentStep = SIGNING
tx.addSignatureUnchecked(sign()) tx.addSignatureUnchecked(sign())
@ -83,11 +82,11 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder,
fun sign(): DigitalSignature.LegallyIdentifiable { fun sign(): DigitalSignature.LegallyIdentifiable {
val sessionID = random63BitValue() val sessionID = random63BitValue()
val wtx = tx.toWireTransaction() val wtx = tx.toWireTransaction()
val req = SignRequest(wtx, serviceHub.networkService.myAddress, sessionID) val req = SignRequest(wtx, serviceHub.storageService.myLegalIdentity, sessionID)
val resp = sendAndReceive<DigitalSignature.LegallyIdentifiable>(TOPIC_SIGN, oracle.address, 0, sessionID, req) val resp = sendAndReceive<DigitalSignature.LegallyIdentifiable>(TOPIC_SIGN, oracle, 0, sessionID, req)
return resp.validate { sig -> return resp.validate { sig ->
check(sig.signer == oracle.identity) check(sig.signer == oracle)
tx.checkSignature(sig) tx.checkSignature(sig)
sig sig
} }
@ -96,10 +95,10 @@ open class RatesFixProtocol(protected val tx: TransactionBuilder,
@Suspendable @Suspendable
fun query(): Fix { fun query(): Fix {
val sessionID = random63BitValue() val sessionID = random63BitValue()
val deadline = suggestInterestRateAnnouncementTimeWindow(fixOf.name, oracle.identity.name, fixOf.forDay).end val deadline = suggestInterestRateAnnouncementTimeWindow(fixOf.name, oracle.name, fixOf.forDay).end
val req = QueryRequest(listOf(fixOf), serviceHub.networkService.myAddress, sessionID, deadline) val req = QueryRequest(listOf(fixOf), serviceHub.storageService.myLegalIdentity, sessionID, deadline)
// TODO: add deadline to receive // TODO: add deadline to receive
val resp = sendAndReceive<ArrayList<Fix>>(TOPIC_QUERY, oracle.address, 0, sessionID, req) val resp = sendAndReceive<ArrayList<Fix>>(TOPIC_QUERY, oracle, 0, sessionID, req)
return resp.validate { return resp.validate {
val fix = it.first() val fix = it.first()

View File

@ -2,8 +2,8 @@ package com.r3corda.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3corda.core.contracts.* import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import java.util.* import java.util.*
@ -21,7 +21,7 @@ import java.util.*
* protocol is helpful when resolving and verifying a finished but partially signed transaction. * protocol is helpful when resolving and verifying a finished but partially signed transaction.
*/ */
class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>, class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>,
private val otherSide: SingleMessageRecipient) : ProtocolLogic<Unit>() { private val otherSide: Party) : ProtocolLogic<Unit>() {
companion object { companion object {
private fun dependencyIDs(wtx: WireTransaction) = wtx.inputs.map { it.txhash }.toSet() private fun dependencyIDs(wtx: WireTransaction) = wtx.inputs.map { it.txhash }.toSet()
@ -33,11 +33,11 @@ class ResolveTransactionsProtocol(private val txHashes: Set<SecureHash>,
private var stx: SignedTransaction? = null private var stx: SignedTransaction? = null
private var wtx: WireTransaction? = null private var wtx: WireTransaction? = null
constructor(stx: SignedTransaction, otherSide: SingleMessageRecipient) : this(stx.tx, otherSide) { constructor(stx: SignedTransaction, otherSide: Party) : this(stx.tx, otherSide) {
this.stx = stx this.stx = stx
} }
constructor(wtx: WireTransaction, otherSide: SingleMessageRecipient) : this(dependencyIDs(wtx), otherSide) { constructor(wtx: WireTransaction, otherSide: Party) : this(dependencyIDs(wtx), otherSide) {
this.wtx = wtx this.wtx = wtx
} }

View File

@ -0,0 +1,20 @@
package com.r3corda.protocols
import com.r3corda.core.crypto.Party
import com.r3corda.core.messaging.MessageRecipients
import com.r3corda.core.node.services.NetworkMapCache
/**
* Abstract superclass for request messages sent to services, which includes common
* fields such as replyTo and replyToTopic.
*/
interface ServiceRequestMessage {
val sessionID: Long
fun getReplyTo(networkMapCache: NetworkMapCache): MessageRecipients
}
abstract class AbstractRequestMessage(val replyToParty: Party): ServiceRequestMessage {
override fun getReplyTo(networkMapCache: NetworkMapCache): MessageRecipients {
return networkMapCache.partyNodes.single { it.identity == replyToParty }.address
}
}

View File

@ -6,7 +6,6 @@ import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.DigitalSignature import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.signWithECDSA import com.r3corda.core.crypto.signWithECDSA
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
@ -72,7 +71,7 @@ object TwoPartyDealProtocol {
abstract val payload: U abstract val payload: U
abstract val notaryNode: NodeInfo abstract val notaryNode: NodeInfo
abstract val otherSide: SingleMessageRecipient abstract val otherSide: Party
abstract val otherSessionID: Long abstract val otherSessionID: Long
abstract val myKeyPair: KeyPair abstract val myKeyPair: KeyPair
@ -153,7 +152,7 @@ object TwoPartyDealProtocol {
// Copy the transaction to every regulator in the network. This is obviously completely bogus, it's // Copy the transaction to every regulator in the network. This is obviously completely bogus, it's
// just for demo purposes. // just for demo purposes.
for (regulator in regulators) { for (regulator in regulators) {
send("regulator.all.seeing.eye", regulator.address, 0, fullySigned) send("regulator.all.seeing.eye", regulator.identity, 0, fullySigned)
} }
} }
@ -203,7 +202,7 @@ object TwoPartyDealProtocol {
fun tracker() = ProgressTracker(RECEIVING, VERIFYING, SIGNING, SWAPPING_SIGNATURES, RECORDING) fun tracker() = ProgressTracker(RECEIVING, VERIFYING, SIGNING, SWAPPING_SIGNATURES, RECORDING)
} }
abstract val otherSide: SingleMessageRecipient abstract val otherSide: Party
abstract val sessionID: Long abstract val sessionID: Long
@Suspendable @Suspendable
@ -276,7 +275,7 @@ object TwoPartyDealProtocol {
/** /**
* One side of the protocol for inserting a pre-agreed deal. * One side of the protocol for inserting a pre-agreed deal.
*/ */
open class Instigator<T : DealState>(override val otherSide: SingleMessageRecipient, open class Instigator<T : DealState>(override val otherSide: Party,
val notary: Party, val notary: Party,
override val payload: T, override val payload: T,
override val myKeyPair: KeyPair, override val myKeyPair: KeyPair,
@ -290,7 +289,7 @@ object TwoPartyDealProtocol {
/** /**
* One side of the protocol for inserting a pre-agreed deal. * One side of the protocol for inserting a pre-agreed deal.
*/ */
open class Acceptor<T : DealState>(override val otherSide: SingleMessageRecipient, open class Acceptor<T : DealState>(override val otherSide: Party,
val notary: Party, val notary: Party,
val dealToBuy: T, val dealToBuy: T,
override val sessionID: Long, override val sessionID: Long,
@ -342,7 +341,7 @@ object TwoPartyDealProtocol {
override val sessionID: Long get() = initiation.sessionID override val sessionID: Long get() = initiation.sessionID
override val otherSide: SingleMessageRecipient get() = initiation.sender override val otherSide: Party get() = initiation.sender
private lateinit var txState: TransactionState<*> private lateinit var txState: TransactionState<*>
private lateinit var deal: FixableDealState private lateinit var deal: FixableDealState
@ -360,8 +359,6 @@ object TwoPartyDealProtocol {
val myName = serviceHub.storageService.myLegalIdentity.name val myName = serviceHub.storageService.myLegalIdentity.name
val otherParty = deal.parties.filter { it.name != myName }.single() val otherParty = deal.parties.filter { it.name != myName }.single()
check(otherParty == initiation.party) check(otherParty == initiation.party)
val otherPartyAddress = serviceHub.networkMapCache.getNodeByLegalName(otherParty.name)!!.address
check(otherPartyAddress == otherSide)
// Also check we are one of the parties // Also check we are one of the parties
deal.parties.filter { it.name == myName }.single() deal.parties.filter { it.name == myName }.single()
@ -380,7 +377,7 @@ object TwoPartyDealProtocol {
val newDeal = deal val newDeal = deal
val ptx = TransactionType.General.Builder() val ptx = TransactionType.General.Builder()
val addFixing = object : RatesFixProtocol(ptx, serviceHub.networkMapCache.ratesOracleNodes[0], fixOf, BigDecimal.ZERO, BigDecimal.ONE, initiation.timeout) { val addFixing = object : RatesFixProtocol(ptx, serviceHub.networkMapCache.ratesOracleNodes[0].identity, fixOf, BigDecimal.ZERO, BigDecimal.ONE, initiation.timeout) {
@Suspendable @Suspendable
override fun beforeSigning(fix: Fix) { override fun beforeSigning(fix: Fix) {
newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload), fix) newDeal.generateFix(ptx, StateAndRef(txState, handshake.payload), fix)
@ -417,11 +414,10 @@ object TwoPartyDealProtocol {
return serviceHub.keyManagementService.toKeyPair(publicKey) return serviceHub.keyManagementService.toKeyPair(publicKey)
} }
override val otherSide: SingleMessageRecipient get() { override val otherSide: Party get() {
// TODO: what happens if there's no node? Move to messaging taking Party and then handled in messaging layer // TODO: what happens if there's no node? Move to messaging taking Party and then handled in messaging layer
val myName = serviceHub.storageService.myLegalIdentity.name val myName = serviceHub.storageService.myLegalIdentity.name
val otherParty = dealToFix.state.data.parties.filter { it.name != myName }.single() return dealToFix.state.data.parties.filter { it.name != myName }.single()
return serviceHub.networkMapCache.getNodeByLegalName(otherParty.name)!!.address
} }
override val notaryNode: NodeInfo get() = override val notaryNode: NodeInfo get() =
@ -432,7 +428,7 @@ object TwoPartyDealProtocol {
val FIX_INITIATE_TOPIC = "platform.fix.initiate" val FIX_INITIATE_TOPIC = "platform.fix.initiate"
/** Used to set up the session between [Floater] and [Fixer] */ /** Used to set up the session between [Floater] and [Fixer] */
data class FixingSessionInitiation(val sessionID: Long, val party: Party, val sender: SingleMessageRecipient, val timeout: Duration) data class FixingSessionInitiation(val sessionID: Long, val party: Party, val sender: Party, val timeout: Duration)
/** /**
* This protocol looks at the deal and decides whether to be the Fixer or Floater role in agreeing a fixing. * This protocol looks at the deal and decides whether to be the Fixer or Floater role in agreeing a fixing.
@ -459,10 +455,10 @@ object TwoPartyDealProtocol {
if (sortedParties[0].name == serviceHub.storageService.myLegalIdentity.name) { if (sortedParties[0].name == serviceHub.storageService.myLegalIdentity.name) {
// Generate sessionID // Generate sessionID
val sessionID = random63BitValue() val sessionID = random63BitValue()
val initation = FixingSessionInitiation(sessionID, sortedParties[0], serviceHub.networkService.myAddress, timeout) val initation = FixingSessionInitiation(sessionID, sortedParties[0], serviceHub.storageService.myLegalIdentity, timeout)
// Send initiation to other side to launch one side of the fixing protocol (the Fixer). // Send initiation to other side to launch one side of the fixing protocol (the Fixer).
send(FIX_INITIATE_TOPIC, serviceHub.networkMapCache.getNodeByLegalName(sortedParties[1].name)!!.address, 0, initation) send(FIX_INITIATE_TOPIC, sortedParties[1], 0, initation)
// Then start the other side of the fixing protocol. // Then start the other side of the fixing protocol.
val protocol = Floater(ref, sessionID) val protocol = Floater(ref, sessionID)

View File

@ -6,7 +6,6 @@ import com.r3corda.core.contracts.TransactionVerificationException
import com.r3corda.core.contracts.WireTransaction import com.r3corda.core.contracts.WireTransaction
import com.r3corda.core.contracts.toLedgerTransaction import com.r3corda.core.contracts.toLedgerTransaction
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.services.TimestampChecker import com.r3corda.core.node.services.TimestampChecker
import com.r3corda.core.node.services.UniquenessProvider import com.r3corda.core.node.services.UniquenessProvider
import java.security.SignatureException import java.security.SignatureException
@ -17,7 +16,7 @@ import java.security.SignatureException
* has its input states "blocked" by a transaction from another party, and needs to establish whether that transaction was * has its input states "blocked" by a transaction from another party, and needs to establish whether that transaction was
* indeed valid * indeed valid
*/ */
class ValidatingNotaryProtocol(otherSide: SingleMessageRecipient, class ValidatingNotaryProtocol(otherSide: Party,
sessionIdForSend: Long, sessionIdForSend: Long,
sessionIdForReceive: Long, sessionIdForReceive: Long,
timestampChecker: TimestampChecker, timestampChecker: TimestampChecker,
@ -52,7 +51,6 @@ class ValidatingNotaryProtocol(otherSide: SingleMessageRecipient,
@Suspendable @Suspendable
private fun validateDependencies(reqIdentity: Party, wtx: WireTransaction) { private fun validateDependencies(reqIdentity: Party, wtx: WireTransaction) {
val otherSide = serviceHub.networkMapCache.getNodeByPublicKey(reqIdentity.owningKey)!!.address subProtocol(ResolveTransactionsProtocol(wtx, reqIdentity))
subProtocol(ResolveTransactionsProtocol(wtx, otherSide))
} }
} }

View File

@ -6,7 +6,6 @@ import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.signWithECDSA import com.r3corda.core.crypto.signWithECDSA
import com.r3corda.core.messaging.Ack import com.r3corda.core.messaging.Ack
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
@ -34,8 +33,8 @@ abstract class AbstractStateReplacementProtocol<T> {
} }
class Handshake(val sessionIdForSend: Long, class Handshake(val sessionIdForSend: Long,
replyTo: SingleMessageRecipient, replyTo: Party,
replySessionId: Long) : AbstractRequestMessage(replyTo, replySessionId) override val sessionID: Long) : AbstractRequestMessage(replyTo)
abstract class Instigator<S : ContractState, T>(val originalState: StateAndRef<S>, abstract class Instigator<S : ContractState, T>(val originalState: StateAndRef<S>,
val modification: T, val modification: T,
@ -89,7 +88,7 @@ abstract class AbstractStateReplacementProtocol<T> {
} }
val allSignatures = participantSignatures + getNotarySignature(stx) val allSignatures = participantSignatures + getNotarySignature(stx)
sessions.forEach { send(TOPIC_CHANGE, it.key.address, it.value, allSignatures) } sessions.forEach { send(TOPIC_CHANGE, it.key.identity, it.value, allSignatures) }
return allSignatures return allSignatures
} }
@ -99,10 +98,10 @@ abstract class AbstractStateReplacementProtocol<T> {
val sessionIdForReceive = random63BitValue() val sessionIdForReceive = random63BitValue()
val proposal = assembleProposal(originalState.ref, modification, stx) val proposal = assembleProposal(originalState.ref, modification, stx)
val handshake = Handshake(sessionIdForSend, serviceHub.networkService.myAddress, sessionIdForReceive) val handshake = Handshake(sessionIdForSend, serviceHub.storageService.myLegalIdentity, sessionIdForReceive)
sendAndReceive<Ack>(TOPIC_INITIATE, node.address, 0, sessionIdForReceive, handshake) sendAndReceive<Ack>(TOPIC_INITIATE, node.identity, 0, sessionIdForReceive, handshake)
val response = sendAndReceive<Result>(TOPIC_CHANGE, node.address, sessionIdForSend, sessionIdForReceive, proposal) val response = sendAndReceive<Result>(TOPIC_CHANGE, node.identity, sessionIdForSend, sessionIdForReceive, proposal)
val participantSignature = response.validate { val participantSignature = response.validate {
if (it.sig == null) throw StateReplacementException(it.error!!) if (it.sig == null) throw StateReplacementException(it.error!!)
else { else {
@ -122,7 +121,7 @@ abstract class AbstractStateReplacementProtocol<T> {
} }
} }
abstract class Acceptor<T>(val otherSide: SingleMessageRecipient, abstract class Acceptor<T>(val otherSide: Party,
val sessionIdForSend: Long, val sessionIdForSend: Long,
val sessionIdForReceive: Long, val sessionIdForReceive: Long,
override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic<Unit>() { override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic<Unit>() {
@ -241,4 +240,4 @@ class StateReplacementRefused(val identity: Party, val state: StateRef, val deta
} }
class StateReplacementException(val error: StateReplacementRefused) class StateReplacementException(val error: StateReplacementRefused)
: Exception("State change failed - ${error}") : Exception("State change failed - $error")

View File

@ -2,18 +2,8 @@ package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.r3corda.core.contracts.* import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.DigitalSignature
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.signWithECDSA
import com.r3corda.core.messaging.Ack
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo
import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue
import com.r3corda.core.utilities.ProgressTracker import com.r3corda.core.utilities.ProgressTracker
import com.r3corda.protocols.AbstractRequestMessage
import com.r3corda.protocols.NotaryProtocol
import com.r3corda.protocols.ResolveTransactionsProtocol
import java.security.PublicKey import java.security.PublicKey
/** /**
@ -58,7 +48,7 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol<Party>() {
} }
} }
class Acceptor(otherSide: SingleMessageRecipient, class Acceptor(otherSide: Party,
sessionIdForSend: Long, sessionIdForSend: Long,
sessionIdForReceive: Long, sessionIdForReceive: Long,
override val progressTracker: ProgressTracker = tracker()) override val progressTracker: ProgressTracker = tracker())

View File

@ -33,6 +33,7 @@ import com.r3corda.node.services.keys.E2ETestKeyManagementService
import com.r3corda.node.services.network.InMemoryNetworkMapCache import com.r3corda.node.services.network.InMemoryNetworkMapCache
import com.r3corda.node.services.network.InMemoryNetworkMapService import com.r3corda.node.services.network.InMemoryNetworkMapService
import com.r3corda.node.services.network.NetworkMapService import com.r3corda.node.services.network.NetworkMapService
import com.r3corda.node.services.network.NetworkMapService.Companion.REGISTER_PROTOCOL_TOPIC
import com.r3corda.node.services.network.NodeRegistration import com.r3corda.node.services.network.NodeRegistration
import com.r3corda.node.services.persistence.* import com.r3corda.node.services.persistence.*
import com.r3corda.node.services.statemachine.StateMachineManager import com.r3corda.node.services.statemachine.StateMachineManager
@ -50,7 +51,6 @@ import java.nio.file.FileAlreadyExistsException
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.security.KeyPair import java.security.KeyPair
import java.security.Security
import java.time.Clock import java.time.Clock
import java.util.* import java.util.*
@ -160,8 +160,8 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
// This object doesn't need to be referenced from this class because it registers handlers on the network // This object doesn't need to be referenced from this class because it registers handlers on the network
// service and so that keeps it from being collected. // service and so that keeps it from being collected.
DataVendingService(net, storage) DataVendingService(net, storage, services.networkMapCache)
NotaryChangeService(net, smm) NotaryChangeService(net, smm, services.networkMapCache)
buildAdvertisedServices() buildAdvertisedServices()
@ -231,9 +231,9 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
val reg = NodeRegistration(info, networkMapSeq++, type, expires) val reg = NodeRegistration(info, networkMapSeq++, type, expires)
val sessionID = random63BitValue() val sessionID = random63BitValue()
val request = NetworkMapService.RegistrationRequest(reg.toWire(storage.myLegalIdentityKey.private), net.myAddress, sessionID) val request = NetworkMapService.RegistrationRequest(reg.toWire(storage.myLegalIdentityKey.private), net.myAddress, sessionID)
val message = net.createMessage(NetworkMapService.REGISTER_PROTOCOL_TOPIC + ".0", request.serialize().bits) val message = net.createMessage("$REGISTER_PROTOCOL_TOPIC.0", request.serialize().bits)
val future = SettableFuture.create<NetworkMapService.RegistrationResponse>() val future = SettableFuture.create<NetworkMapService.RegistrationResponse>()
val topic = NetworkMapService.REGISTER_PROTOCOL_TOPIC + "." + sessionID val topic = "$REGISTER_PROTOCOL_TOPIC.$sessionID"
net.runOnNextMessage(topic, RunOnCallerThread) { message -> net.runOnNextMessage(topic, RunOnCallerThread) { message ->
future.set(message.data.deserialize()) future.set(message.data.deserialize())
@ -254,8 +254,8 @@ abstract class AbstractNode(val dir: Path, val configuration: NodeConfiguration,
val timestampChecker = TimestampChecker(platformClock, 30.seconds) val timestampChecker = TimestampChecker(platformClock, 30.seconds)
inNodeNotaryService = when (type) { inNodeNotaryService = when (type) {
is SimpleNotaryService.Type -> SimpleNotaryService(smm, net, timestampChecker, uniquenessProvider) is SimpleNotaryService.Type -> SimpleNotaryService(smm, net, timestampChecker, uniquenessProvider, services.networkMapCache)
is ValidatingNotaryService.Type -> ValidatingNotaryService(smm, net, timestampChecker, uniquenessProvider) is ValidatingNotaryService.Type -> ValidatingNotaryService(smm, net, timestampChecker, uniquenessProvider, services.networkMapCache)
else -> null else -> null
} }
} }

View File

@ -130,8 +130,8 @@ class IRSSimulation(networkSendManuallyPumped: Boolean, runAsync: Boolean, laten
val sessionID = random63BitValue() val sessionID = random63BitValue()
val instigator = TwoPartyDealProtocol.Instigator(node2.net.myAddress, notary.info.identity, irs, nodeAKey!!, sessionID) val instigator = TwoPartyDealProtocol.Instigator(node2.info.identity, notary.info.identity, irs, nodeAKey!!, sessionID)
val acceptor = TwoPartyDealProtocol.Acceptor(node1.net.myAddress, notary.info.identity, irs, sessionID) val acceptor = TwoPartyDealProtocol.Acceptor(node1.info.identity, notary.info.identity, irs, sessionID)
showProgressFor(listOf(node1, node2)) showProgressFor(listOf(node1, node2))
showConsensusFor(listOf(node1, node2, regulators[0])) showConsensusFor(listOf(node1, node2, regulators[0]))

View File

@ -44,10 +44,19 @@ class TradeSimulation(runAsync: Boolean, latencyInjector: InMemoryMessagingNetwo
val cashIssuerKey = generateKeyPair() val cashIssuerKey = generateKeyPair()
val amount = 1000.DOLLARS `issued by` Party("Big friendly bank", cashIssuerKey.public).ref(1) val amount = 1000.DOLLARS `issued by` Party("Big friendly bank", cashIssuerKey.public).ref(1)
val sessionID = random63BitValue() val sessionID = random63BitValue()
val buyerProtocol = TwoPartyTradeProtocol.Buyer(seller.net.myAddress, notary.info.identity, val buyerProtocol = TwoPartyTradeProtocol.Buyer(
amount, CommercialPaper.State::class.java, sessionID) seller.info.identity,
val sellerProtocol = TwoPartyTradeProtocol.Seller(buyer.net.myAddress, notary.info, notary.info.identity,
issuance.tx.outRef(0), amount, seller.storage.myLegalIdentityKey, sessionID) amount,
CommercialPaper.State::class.java,
sessionID)
val sellerProtocol = TwoPartyTradeProtocol.Seller(
buyer.info.identity,
notary.info,
issuance.tx.outRef(0),
amount,
seller.storage.myLegalIdentityKey,
sessionID)
showConsensusFor(listOf(buyer, seller, notary)) showConsensusFor(listOf(buyer, seller, notary))
showProgressFor(listOf(buyer, seller)) showProgressFor(listOf(buyer, seller))

View File

@ -2,7 +2,7 @@ package com.r3corda.node.services
import com.r3corda.core.messaging.Ack import com.r3corda.core.messaging.Ack
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.messaging.SingleMessageRecipient import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.node.services.api.AbstractNodeService import com.r3corda.node.services.api.AbstractNodeService
import com.r3corda.node.services.statemachine.StateMachineManager import com.r3corda.node.services.statemachine.StateMachineManager
import protocols.AbstractStateReplacementProtocol import protocols.AbstractStateReplacementProtocol
@ -12,7 +12,7 @@ import protocols.NotaryChangeProtocol
* A service that monitors the network for requests for changing the notary of a state, * 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 [NotaryChangeProtocol] if the auto-accept criteria are met.
*/ */
class NotaryChangeService(net: MessagingService, val smm: StateMachineManager) : AbstractNodeService(net) { class NotaryChangeService(net: MessagingService, val smm: StateMachineManager, networkMapCache: NetworkMapCache) : AbstractNodeService(net, networkMapCache) {
init { init {
addMessageHandler(NotaryChangeProtocol.TOPIC_INITIATE, addMessageHandler(NotaryChangeProtocol.TOPIC_INITIATE,
{ req: AbstractStateReplacementProtocol.Handshake -> handleChangeNotaryRequest(req) } { req: AbstractStateReplacementProtocol.Handshake -> handleChangeNotaryRequest(req) }
@ -21,8 +21,8 @@ class NotaryChangeService(net: MessagingService, val smm: StateMachineManager) :
private fun handleChangeNotaryRequest(req: AbstractStateReplacementProtocol.Handshake): Ack { private fun handleChangeNotaryRequest(req: AbstractStateReplacementProtocol.Handshake): Ack {
val protocol = NotaryChangeProtocol.Acceptor( val protocol = NotaryChangeProtocol.Acceptor(
req.replyTo as SingleMessageRecipient, req.replyToParty,
req.sessionID!!, req.sessionID,
req.sessionIdForSend) req.sessionIdForSend)
smm.add(NotaryChangeProtocol.TOPIC_CHANGE, protocol) smm.add(NotaryChangeProtocol.TOPIC_CHANGE, protocol)
return Ack return Ack

View File

@ -2,18 +2,19 @@ package com.r3corda.node.services.api
import com.r3corda.core.messaging.Message import com.r3corda.core.messaging.Message
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.TOPIC_DEFAULT_POSTFIX import com.r3corda.core.node.services.TOPIC_DEFAULT_POSTFIX
import com.r3corda.core.serialization.SingletonSerializeAsToken import com.r3corda.core.serialization.SingletonSerializeAsToken
import com.r3corda.core.serialization.deserialize import com.r3corda.core.serialization.deserialize
import com.r3corda.core.serialization.serialize import com.r3corda.core.serialization.serialize
import com.r3corda.protocols.AbstractRequestMessage import com.r3corda.protocols.ServiceRequestMessage
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
/** /**
* Abstract superclass for services that a node can host, which provides helper functions. * Abstract superclass for services that a node can host, which provides helper functions.
*/ */
@ThreadSafe @ThreadSafe
abstract class AbstractNodeService(val net: MessagingService) : SingletonSerializeAsToken() { abstract class AbstractNodeService(val net: MessagingService, val networkMapCache: NetworkMapCache) : SingletonSerializeAsToken() {
/** /**
* Register a handler for a message topic. In comparison to using net.addMessageHandler() this manages a lot of * Register a handler for a message topic. In comparison to using net.addMessageHandler() this manages a lot of
@ -24,18 +25,18 @@ abstract class AbstractNodeService(val net: MessagingService) : SingletonSeriali
* @param handler a function to handle the deserialised request and return an optional response (if return type not Unit) * @param handler a function to handle the deserialised request and return an optional response (if return type not Unit)
* @param exceptionConsumer a function to which any thrown exception is passed. * @param exceptionConsumer a function to which any thrown exception is passed.
*/ */
protected inline fun <reified Q : AbstractRequestMessage, reified R : Any> protected inline fun <reified Q : ServiceRequestMessage, reified R : Any>
addMessageHandler(topic: String, addMessageHandler(topic: String,
crossinline handler: (Q) -> R, crossinline handler: (Q) -> R,
crossinline exceptionConsumer: (Message, Exception) -> Unit) { crossinline exceptionConsumer: (Message, Exception) -> Unit) {
net.addMessageHandler(topic + TOPIC_DEFAULT_POSTFIX, null) { message, r -> net.addMessageHandler(topic + TOPIC_DEFAULT_POSTFIX, null) { message, r ->
try { try {
val req = message.data.deserialize<Q>() val request = message.data.deserialize<Q>()
val data = handler(req) val response = handler(request)
// If the return type R is Unit, then do not send a response // If the return type R is Unit, then do not send a response
if (data.javaClass != Unit.javaClass) { if (response.javaClass != Unit.javaClass) {
val msg = net.createMessage("$topic.${req.sessionID}", data.serialize().bits) val msg = net.createMessage("$topic.${request.sessionID}", response.serialize().bits)
net.send(msg, req.replyTo) net.send(msg, request.getReplyTo(networkMapCache))
} }
} catch(e: Exception) { } catch(e: Exception) {
exceptionConsumer(message, e) exceptionConsumer(message, e)
@ -51,7 +52,7 @@ abstract class AbstractNodeService(val net: MessagingService) : SingletonSeriali
* @param topic the topic, without the default session ID postfix (".0) * @param topic the topic, without the default session ID postfix (".0)
* @param handler a function to handle the deserialised request and return an optional response (if return type not Unit) * @param handler a function to handle the deserialised request and return an optional response (if return type not Unit)
*/ */
protected inline fun <reified Q : AbstractRequestMessage, reified R : Any> protected inline fun <reified Q : ServiceRequestMessage, reified R : Any>
addMessageHandler(topic: String, addMessageHandler(topic: String,
crossinline handler: (Q) -> R) { crossinline handler: (Q) -> R) {
addMessageHandler(topic, handler, { message: Message, exception: Exception -> throw exception }) addMessageHandler(topic, handler, { message: Message, exception: Exception -> throw exception })

View File

@ -41,7 +41,7 @@ object NodeInterestRates {
/** /**
* The Service that wraps [Oracle] and handles messages/network interaction/request scrubbing. * The Service that wraps [Oracle] and handles messages/network interaction/request scrubbing.
*/ */
class Service(node: AbstractNode) : AcceptsFileUpload, AbstractNodeService(node.services.networkService) { class Service(node: AbstractNode) : AcceptsFileUpload, AbstractNodeService(node.services.networkService, node.services.networkMapCache) {
val ss = node.services.storageService val ss = node.services.storageService
val oracle = Oracle(ss.myLegalIdentity, ss.myLegalIdentityKey, node.services.clock) val oracle = Oracle(ss.myLegalIdentity, ss.myLegalIdentityKey, node.services.clock)
@ -84,7 +84,7 @@ object NodeInterestRates {
override fun call(): Unit { override fun call(): Unit {
val answers = service.oracle.query(request.queries, request.deadline) val answers = service.oracle.query(request.queries, request.deadline)
progressTracker.currentStep = SENDING progressTracker.currentStep = SENDING
send("${RatesFixProtocol.TOPIC}.query", request.replyTo, request.sessionID!!, answers) send("${RatesFixProtocol.TOPIC}.query", request.replyToParty, request.sessionID, answers)
} }
} }

View File

@ -7,16 +7,16 @@ import com.r3corda.core.messaging.MessageRecipients
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.messaging.SingleMessageRecipient import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.NetworkMapCache import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.TOPIC_DEFAULT_POSTFIX import com.r3corda.core.node.services.TOPIC_DEFAULT_POSTFIX
import com.r3corda.core.serialization.SerializedBytes import com.r3corda.core.serialization.SerializedBytes
import com.r3corda.core.serialization.deserialize import com.r3corda.core.serialization.deserialize
import com.r3corda.core.serialization.serialize import com.r3corda.core.serialization.serialize
import com.r3corda.node.services.api.AbstractNodeService import com.r3corda.node.services.api.AbstractNodeService
import com.r3corda.node.utilities.AddOrRemove import com.r3corda.node.utilities.AddOrRemove
import com.r3corda.protocols.ServiceRequestMessage
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import com.r3corda.protocols.AbstractRequestMessage
import java.security.PrivateKey import java.security.PrivateKey
import java.security.SignatureException import java.security.SignatureException
import java.time.Instant import java.time.Instant
@ -61,20 +61,25 @@ interface NetworkMapService {
val nodes: List<NodeInfo> val nodes: List<NodeInfo>
class FetchMapRequest(val subscribe: Boolean, val ifChangedSinceVersion: Int?, replyTo: MessageRecipients, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) abstract class NetworkMapRequestMessage(val replyTo: MessageRecipients) : ServiceRequestMessage {
override fun getReplyTo(networkMapCache: NetworkMapCache): MessageRecipients = replyTo
}
class FetchMapRequest(val subscribe: Boolean, val ifChangedSinceVersion: Int?, replyTo: MessageRecipients, override val sessionID: Long) : NetworkMapRequestMessage(replyTo)
data class FetchMapResponse(val nodes: Collection<NodeRegistration>?, val version: Int) data class FetchMapResponse(val nodes: Collection<NodeRegistration>?, val version: Int)
class QueryIdentityRequest(val identity: Party, replyTo: MessageRecipients, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) class QueryIdentityRequest(val identity: Party, replyTo: MessageRecipients, override val sessionID: Long) : NetworkMapRequestMessage(replyTo)
data class QueryIdentityResponse(val node: NodeInfo?) data class QueryIdentityResponse(val node: NodeInfo?)
class RegistrationRequest(val wireReg: WireNodeRegistration, replyTo: MessageRecipients, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) class RegistrationRequest(val wireReg: WireNodeRegistration, replyTo: MessageRecipients, override val sessionID: Long) : NetworkMapRequestMessage(replyTo)
data class RegistrationResponse(val success: Boolean) data class RegistrationResponse(val success: Boolean)
class SubscribeRequest(val subscribe: Boolean, replyTo: MessageRecipients, sessionID: Long) : AbstractRequestMessage(replyTo, sessionID) class SubscribeRequest(val subscribe: Boolean, replyTo: MessageRecipients, override val sessionID: Long) : NetworkMapRequestMessage(replyTo)
data class SubscribeResponse(val confirmed: Boolean) data class SubscribeResponse(val confirmed: Boolean)
data class Update(val wireReg: WireNodeRegistration, val replyTo: MessageRecipients) data class Update(val wireReg: WireNodeRegistration, val replyTo: MessageRecipients)
data class UpdateAcknowledge(val wireRegHash: SecureHash, val replyTo: MessageRecipients) data class UpdateAcknowledge(val wireRegHash: SecureHash, val replyTo: MessageRecipients)
} }
@ThreadSafe @ThreadSafe
class InMemoryNetworkMapService(net: MessagingService, home: NodeRegistration, val cache: NetworkMapCache) : NetworkMapService, AbstractNodeService(net) { class InMemoryNetworkMapService(net: MessagingService, home: NodeRegistration, val cache: NetworkMapCache) : NetworkMapService, AbstractNodeService(net, cache) {
private val registeredNodes = ConcurrentHashMap<Party, NodeRegistration>() private val registeredNodes = ConcurrentHashMap<Party, NodeRegistration>()
// Map from subscriber address, to a list of unacknowledged updates // Map from subscriber address, to a list of unacknowledged updates
private val subscribers = ThreadBox(mutableMapOf<SingleMessageRecipient, MutableList<SecureHash>>()) private val subscribers = ThreadBox(mutableMapOf<SingleMessageRecipient, MutableList<SecureHash>>())

View File

@ -2,6 +2,7 @@ package com.r3corda.node.services.persistence
import com.r3corda.core.contracts.SignedTransaction import com.r3corda.core.contracts.SignedTransaction
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.StorageService import com.r3corda.core.node.services.StorageService
import com.r3corda.core.utilities.loggerFor import com.r3corda.core.utilities.loggerFor
import com.r3corda.node.services.api.AbstractNodeService import com.r3corda.node.services.api.AbstractNodeService
@ -24,7 +25,7 @@ import javax.annotation.concurrent.ThreadSafe
* Additionally, because nodes do not store invalid transactions, requesting such a transaction will always yield null. * Additionally, because nodes do not store invalid transactions, requesting such a transaction will always yield null.
*/ */
@ThreadSafe @ThreadSafe
class DataVendingService(net: MessagingService, private val storage: StorageService) : AbstractNodeService(net) { class DataVendingService(net: MessagingService, private val storage: StorageService, networkMapCache: NetworkMapCache) : AbstractNodeService(net, networkMapCache) {
companion object { companion object {
val logger = loggerFor<DataVendingService>() val logger = loggerFor<DataVendingService>()
} }

View File

@ -5,7 +5,7 @@ import co.paralleluniverse.fibers.FiberScheduler
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import com.r3corda.core.messaging.MessageRecipients import com.r3corda.core.crypto.Party
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.protocols.ProtocolStateMachine import com.r3corda.core.protocols.ProtocolStateMachine
import com.r3corda.core.utilities.UntrustworthyData import com.r3corda.core.utilities.UntrustworthyData
@ -81,9 +81,13 @@ class ProtocolStateMachineImpl<R>(val logic: ProtocolLogic<R>,
} }
@Suspendable @Suppress("UNCHECKED_CAST") @Suspendable @Suppress("UNCHECKED_CAST")
override fun <T : Any> sendAndReceive(topic: String, destination: MessageRecipients, sessionIDForSend: Long, sessionIDForReceive: Long, override fun <T : Any> sendAndReceive(topic: String,
obj: Any, recvType: Class<T>): UntrustworthyData<T> { destination: Party,
val result = StateMachineManager.FiberRequest.ExpectingResponse(topic, destination, sessionIDForSend, sessionIDForReceive, obj, recvType) sessionIDForSend: Long,
sessionIDForReceive: Long,
payload: Any,
recvType: Class<T>): UntrustworthyData<T> {
val result = StateMachineManager.FiberRequest.ExpectingResponse(topic, destination, sessionIDForSend, sessionIDForReceive, payload, recvType)
return suspendAndExpectReceive(result) return suspendAndExpectReceive(result)
} }
@ -94,8 +98,8 @@ class ProtocolStateMachineImpl<R>(val logic: ProtocolLogic<R>,
} }
@Suspendable @Suspendable
override fun send(topic: String, destination: MessageRecipients, sessionID: Long, obj: Any) { override fun send(topic: String, destination: Party, sessionID: Long, payload: Any) {
val result = StateMachineManager.FiberRequest.NotExpectingResponse(topic, destination, sessionID, obj) val result = StateMachineManager.FiberRequest.NotExpectingResponse(topic, destination, sessionID, payload)
suspend(result) suspend(result)
} }

View File

@ -8,7 +8,7 @@ import com.esotericsoftware.kryo.Kryo
import com.google.common.base.Throwables import com.google.common.base.Throwables
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.r3corda.core.abbreviate import com.r3corda.core.abbreviate
import com.r3corda.core.messaging.MessageRecipients import com.r3corda.core.crypto.Party
import com.r3corda.core.messaging.runOnNextMessage import com.r3corda.core.messaging.runOnNextMessage
import com.r3corda.core.messaging.send import com.r3corda.core.messaging.send
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
@ -253,7 +253,8 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, tokenizableService
request.payload?.let { request.payload?.let {
val topic = "${request.topic}.${request.sessionIDForSend}" val topic = "${request.topic}.${request.sessionIDForSend}"
psm.logger.trace { "Sending message of type ${it.javaClass.name} using topic $topic to ${request.destination} (${it.toString().abbreviate(50)})" } psm.logger.trace { "Sending message of type ${it.javaClass.name} using topic $topic to ${request.destination} (${it.toString().abbreviate(50)})" }
serviceHub.networkService.send(topic, it, request.destination!!) val address = serviceHub.networkMapCache.getNodeByLegalName(request.destination!!.name)!!.address
serviceHub.networkService.send(topic, it, address)
} }
if (request is FiberRequest.NotExpectingResponse) { if (request is FiberRequest.NotExpectingResponse) {
// We sent a message, but don't expect a response, so re-enter the continuation to let it keep going. // We sent a message, but don't expect a response, so re-enter the continuation to let it keep going.
@ -307,7 +308,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, tokenizableService
// TODO: Clean this up // TODO: Clean this up
open class FiberRequest(val topic: String, open class FiberRequest(val topic: String,
val destination: MessageRecipients?, val destination: Party?,
val sessionIDForSend: Long, val sessionIDForSend: Long,
val sessionIDForReceive: Long, val sessionIDForReceive: Long,
val payload: Any?) { val payload: Any?) {
@ -317,7 +318,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, tokenizableService
class ExpectingResponse<R : Any>( class ExpectingResponse<R : Any>(
topic: String, topic: String,
destination: MessageRecipients?, destination: Party?,
sessionIDForSend: Long, sessionIDForSend: Long,
sessionIDForReceive: Long, sessionIDForReceive: Long,
obj: Any?, obj: Any?,
@ -326,7 +327,7 @@ class StateMachineManager(val serviceHub: ServiceHubInternal, tokenizableService
class NotExpectingResponse( class NotExpectingResponse(
topic: String, topic: String,
destination: MessageRecipients, destination: Party,
sessionIDForSend: Long, sessionIDForSend: Long,
obj: Any? obj: Any?
) : FiberRequest(topic, destination, sessionIDForSend, -1, obj) ) : FiberRequest(topic, destination, sessionIDForSend, -1, obj)

View File

@ -2,7 +2,7 @@ package com.r3corda.node.services.transactions
import com.r3corda.core.messaging.Ack import com.r3corda.core.messaging.Ack
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.messaging.SingleMessageRecipient import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.TimestampChecker import com.r3corda.core.node.services.TimestampChecker
import com.r3corda.core.node.services.UniquenessProvider import com.r3corda.core.node.services.UniquenessProvider
@ -22,7 +22,8 @@ import com.r3corda.protocols.NotaryProtocol
abstract class NotaryService(val smm: StateMachineManager, abstract class NotaryService(val smm: StateMachineManager,
net: MessagingService, net: MessagingService,
val timestampChecker: TimestampChecker, val timestampChecker: TimestampChecker,
val uniquenessProvider: UniquenessProvider) : AbstractNodeService(net) { val uniquenessProvider: UniquenessProvider,
networkMapCache: NetworkMapCache) : AbstractNodeService(net, networkMapCache) {
object Type : ServiceType("corda.notary") object Type : ServiceType("corda.notary")
abstract val logger: org.slf4j.Logger abstract val logger: org.slf4j.Logger
@ -37,8 +38,9 @@ abstract class NotaryService(val smm: StateMachineManager,
} }
private fun processRequest(req: NotaryProtocol.Handshake): Ack { private fun processRequest(req: NotaryProtocol.Handshake): Ack {
val protocol = protocolFactory.create(req.replyTo as SingleMessageRecipient, val protocol = protocolFactory.create(
req.sessionID!!, req.replyToParty,
req.sessionID,
req.sendSessionID, req.sendSessionID,
timestampChecker, timestampChecker,
uniquenessProvider) uniquenessProvider)

View File

@ -1,6 +1,7 @@
package com.r3corda.node.services.transactions package com.r3corda.node.services.transactions
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.TimestampChecker import com.r3corda.core.node.services.TimestampChecker
import com.r3corda.core.node.services.UniquenessProvider import com.r3corda.core.node.services.UniquenessProvider
@ -13,7 +14,8 @@ class SimpleNotaryService(
smm: StateMachineManager, smm: StateMachineManager,
net: MessagingService, net: MessagingService,
timestampChecker: TimestampChecker, timestampChecker: TimestampChecker,
uniquenessProvider: UniquenessProvider) : NotaryService(smm, net, timestampChecker, uniquenessProvider) { uniquenessProvider: UniquenessProvider,
networkMapCache: NetworkMapCache) : NotaryService(smm, net, timestampChecker, uniquenessProvider, networkMapCache) {
object Type : ServiceType("corda.notary.simple") object Type : ServiceType("corda.notary.simple")
override val logger = loggerFor<SimpleNotaryService>() override val logger = loggerFor<SimpleNotaryService>()

View File

@ -1,7 +1,8 @@
package com.r3corda.node.services.transactions package com.r3corda.node.services.transactions
import com.r3corda.core.crypto.Party
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.messaging.SingleMessageRecipient import com.r3corda.core.node.services.NetworkMapCache
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.node.services.TimestampChecker import com.r3corda.core.node.services.TimestampChecker
import com.r3corda.core.node.services.UniquenessProvider import com.r3corda.core.node.services.UniquenessProvider
@ -15,14 +16,15 @@ class ValidatingNotaryService(
smm: StateMachineManager, smm: StateMachineManager,
net: MessagingService, net: MessagingService,
timestampChecker: TimestampChecker, timestampChecker: TimestampChecker,
uniquenessProvider: UniquenessProvider uniquenessProvider: UniquenessProvider,
) : NotaryService(smm, net, timestampChecker, uniquenessProvider) { networkMapCache: NetworkMapCache
) : NotaryService(smm, net, timestampChecker, uniquenessProvider, networkMapCache) {
object Type : ServiceType("corda.notary.validating") object Type : ServiceType("corda.notary.validating")
override val logger = loggerFor<ValidatingNotaryService>() override val logger = loggerFor<ValidatingNotaryService>()
override val protocolFactory = object : NotaryProtocol.Factory { override val protocolFactory = object : NotaryProtocol.Factory {
override fun create(otherSide: SingleMessageRecipient, override fun create(otherSide: Party,
sendSessionID: Long, sendSessionID: Long,
receiveSessionID: Long, receiveSessionID: Long,
timestampChecker: TimestampChecker, timestampChecker: TimestampChecker,

View File

@ -59,7 +59,8 @@ class AttachmentTests {
val id = n0.storage.attachments.importAttachment(ByteArrayInputStream(fakeAttachment())) 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 protocol to fetch it and insert it.
val f1 = n1.smm.add("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.net.myAddress)) network.runNetwork()
val f1 = n1.smm.add("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.identity))
network.runNetwork() network.runNetwork()
assertEquals(0, f1.get().fromDisk.size) assertEquals(0, f1.get().fromDisk.size)
@ -70,7 +71,7 @@ class AttachmentTests {
// Shut down node zero and ensure node one can still resolve the attachment. // Shut down node zero and ensure node one can still resolve the attachment.
n0.stop() n0.stop()
val response: FetchDataProtocol.Result<Attachment> = n1.smm.add("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.net.myAddress)).get() val response: FetchDataProtocol.Result<Attachment> = n1.smm.add("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.identity)).get()
assertEquals(attachment, response.fromDisk[0]) assertEquals(attachment, response.fromDisk[0])
} }
@ -80,14 +81,15 @@ class AttachmentTests {
// Get node one to fetch a non-existent attachment. // Get node one to fetch a non-existent attachment.
val hash = SecureHash.randomSHA256() val hash = SecureHash.randomSHA256()
val f1 = n1.smm.add("tests.fetch2", FetchAttachmentsProtocol(setOf(hash), n0.net.myAddress)) network.runNetwork()
val f1 = n1.smm.add("tests.fetch2", FetchAttachmentsProtocol(setOf(hash), n0.info.identity))
network.runNetwork() network.runNetwork()
val e = assertFailsWith<FetchDataProtocol.HashNotFound> { rootCauseExceptions { f1.get() } } val e = assertFailsWith<FetchDataProtocol.HashNotFound> { rootCauseExceptions { f1.get() } }
assertEquals(hash, e.requested) assertEquals(hash, e.requested)
} }
@Test @Test
fun maliciousResponse() { fun `malicious response`() {
// Make a node that doesn't do sanity checking at load time. // Make a node that doesn't do sanity checking at load time.
val n0 = network.createNode(null, -1, object : MockNetwork.Factory { val n0 = network.createNode(null, -1, object : MockNetwork.Factory {
override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?, override fun create(dir: Path, config: NodeConfiguration, network: MockNetwork, networkMapAddr: NodeInfo?,
@ -112,7 +114,8 @@ class AttachmentTests {
writer.close() writer.close()
// Get n1 to fetch the attachment. Should receive corrupted bytes. // Get n1 to fetch the attachment. Should receive corrupted bytes.
val f1 = n1.smm.add("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.net.myAddress)) network.runNetwork()
val f1 = n1.smm.add("tests.fetch1", FetchAttachmentsProtocol(setOf(id), n0.info.identity))
network.runNetwork() network.runNetwork()
assertFailsWith<FetchDataProtocol.DownloadedVsRequestedDataMismatch> { assertFailsWith<FetchDataProtocol.DownloadedVsRequestedDataMismatch> {
rootCauseExceptions { f1.get() } rootCauseExceptions { f1.get() }

View File

@ -11,7 +11,6 @@ import com.r3corda.core.contracts.*
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.SecureHash import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.days import com.r3corda.core.days
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.ServiceHub import com.r3corda.core.node.ServiceHub
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
@ -56,14 +55,14 @@ class TwoPartyTradeProtocolTests {
lateinit var net: MockNetwork lateinit var net: MockNetwork
private fun runSeller(smm: StateMachineManager, notary: NodeInfo, private fun runSeller(smm: StateMachineManager, notary: NodeInfo,
otherSide: SingleMessageRecipient, assetToSell: StateAndRef<OwnableState>, price: Amount<Issued<Currency>>, otherSide: Party, assetToSell: StateAndRef<OwnableState>, price: Amount<Issued<Currency>>,
myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<SignedTransaction> { myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<SignedTransaction> {
val seller = TwoPartyTradeProtocol.Seller(otherSide, notary, assetToSell, price, myKeyPair, buyerSessionID) val seller = TwoPartyTradeProtocol.Seller(otherSide, notary, assetToSell, price, myKeyPair, buyerSessionID)
return smm.add("${TwoPartyTradeProtocol.TRADE_TOPIC}.seller", seller) return smm.add("${TwoPartyTradeProtocol.TRADE_TOPIC}.seller", seller)
} }
private fun runBuyer(smm: StateMachineManager, notaryNode: NodeInfo, private fun runBuyer(smm: StateMachineManager, notaryNode: NodeInfo,
otherSide: SingleMessageRecipient, acceptablePrice: Amount<Issued<Currency>>, typeToBuy: Class<out OwnableState>, otherSide: Party, acceptablePrice: Amount<Issued<Currency>>, typeToBuy: Class<out OwnableState>,
sessionID: Long): ListenableFuture<SignedTransaction> { sessionID: Long): ListenableFuture<SignedTransaction> {
val buyer = TwoPartyTradeProtocol.Buyer(otherSide, notaryNode.identity, acceptablePrice, typeToBuy, sessionID) val buyer = TwoPartyTradeProtocol.Buyer(otherSide, notaryNode.identity, acceptablePrice, typeToBuy, sessionID)
return smm.add("${TwoPartyTradeProtocol.TRADE_TOPIC}.buyer", buyer) return smm.add("${TwoPartyTradeProtocol.TRADE_TOPIC}.buyer", buyer)
@ -105,7 +104,7 @@ class TwoPartyTradeProtocolTests {
val bobResult = runBuyer( val bobResult = runBuyer(
bobNode.smm, bobNode.smm,
notaryNode.info, notaryNode.info,
aliceNode.net.myAddress, aliceNode.info.identity,
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
CommercialPaper.State::class.java, CommercialPaper.State::class.java,
buyerSessionID buyerSessionID
@ -113,7 +112,7 @@ class TwoPartyTradeProtocolTests {
val aliceResult = runSeller( val aliceResult = runSeller(
aliceNode.smm, aliceNode.smm,
notaryNode.info, notaryNode.info,
bobNode.net.myAddress, bobNode.info.identity,
lookup("alice's paper"), lookup("alice's paper"),
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
ALICE_KEY, ALICE_KEY,
@ -139,7 +138,6 @@ class TwoPartyTradeProtocolTests {
val aliceNode = net.createPartyNode(notaryNode.info, ALICE.name, ALICE_KEY) val aliceNode = net.createPartyNode(notaryNode.info, ALICE.name, ALICE_KEY)
var bobNode = net.createPartyNode(notaryNode.info, BOB.name, BOB_KEY) var bobNode = net.createPartyNode(notaryNode.info, BOB.name, BOB_KEY)
val aliceAddr = aliceNode.net.myAddress
val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle
val networkMapAddr = notaryNode.info val networkMapAddr = notaryNode.info
val issuer = bobNode.services.storageService.myLegalIdentity.ref(0) val issuer = bobNode.services.storageService.myLegalIdentity.ref(0)
@ -156,7 +154,7 @@ class TwoPartyTradeProtocolTests {
val aliceFuture = runSeller( val aliceFuture = runSeller(
aliceNode.smm, aliceNode.smm,
notaryNode.info, notaryNode.info,
bobAddr, bobNode.info.identity,
lookup("alice's paper"), lookup("alice's paper"),
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
ALICE_KEY, ALICE_KEY,
@ -165,7 +163,7 @@ class TwoPartyTradeProtocolTests {
runBuyer( runBuyer(
bobNode.smm, bobNode.smm,
notaryNode.info, notaryNode.info,
aliceAddr, aliceNode.info.identity,
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
CommercialPaper.State::class.java, CommercialPaper.State::class.java,
buyerSessionID buyerSessionID
@ -276,7 +274,7 @@ class TwoPartyTradeProtocolTests {
runSeller( runSeller(
aliceNode.smm, aliceNode.smm,
notaryNode.info, notaryNode.info,
bobNode.net.myAddress, bobNode.info.identity,
lookup("alice's paper"), lookup("alice's paper"),
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
ALICE_KEY, ALICE_KEY,
@ -285,7 +283,7 @@ class TwoPartyTradeProtocolTests {
runBuyer( runBuyer(
bobNode.smm, bobNode.smm,
notaryNode.info, notaryNode.info,
aliceNode.net.myAddress, aliceNode.info.identity,
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
CommercialPaper.State::class.java, CommercialPaper.State::class.java,
buyerSessionID buyerSessionID
@ -371,9 +369,6 @@ class TwoPartyTradeProtocolTests {
val bobNode = net.createPartyNode(notaryNode.info, BOB.name, BOB_KEY) val bobNode = net.createPartyNode(notaryNode.info, BOB.name, BOB_KEY)
val issuer = MEGA_CORP.ref(1, 2, 3) val issuer = MEGA_CORP.ref(1, 2, 3)
val aliceAddr = aliceNode.net.myAddress
val bobAddr = bobNode.net.myAddress as InMemoryMessagingNetwork.Handle
val bobKey = bobNode.keyManagement.freshKey() val bobKey = bobNode.keyManagement.freshKey()
val bobsBadCash = fillUpForBuyer(bobError, bobKey.public).second val bobsBadCash = fillUpForBuyer(bobError, bobKey.public).second
val alicesFakePaper = fillUpForSeller(aliceError, aliceNode.storage.myLegalIdentity.owningKey, val alicesFakePaper = fillUpForSeller(aliceError, aliceNode.storage.myLegalIdentity.owningKey,
@ -389,7 +384,7 @@ class TwoPartyTradeProtocolTests {
val aliceResult = runSeller( val aliceResult = runSeller(
aliceNode.smm, aliceNode.smm,
notaryNode.info, notaryNode.info,
bobAddr, bobNode.info.identity,
lookup("alice's paper"), lookup("alice's paper"),
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
ALICE_KEY, ALICE_KEY,
@ -398,7 +393,7 @@ class TwoPartyTradeProtocolTests {
val bobResult = runBuyer( val bobResult = runBuyer(
bobNode.smm, bobNode.smm,
notaryNode.info, notaryNode.info,
aliceAddr, aliceNode.info.identity,
1000.DOLLARS `issued by` issuer, 1000.DOLLARS `issued by` issuer,
CommercialPaper.State::class.java, CommercialPaper.State::class.java,
buyerSessionID buyerSessionID

View File

@ -59,7 +59,7 @@ class InMemoryNetworkMapServiceTest {
assertEquals(2, service.nodes.count()) assertEquals(2, service.nodes.count())
// Confirm that de-registering the node succeeds and drops it from the node lists // Confirm that de-registering the node succeeds and drops it from the node lists
var removeChange = NodeRegistration(registerNode.info, seq, AddOrRemove.REMOVE, expires) val removeChange = NodeRegistration(registerNode.info, seq, AddOrRemove.REMOVE, expires)
val removeWireChange = removeChange.toWire(nodeKey.private) val removeWireChange = removeChange.toWire(nodeKey.private)
assert(service.processRegistrationChangeRequest(NetworkMapService.RegistrationRequest(removeWireChange, mapServiceNode.info.address, Long.MIN_VALUE)).success) assert(service.processRegistrationChangeRequest(NetworkMapService.RegistrationRequest(removeWireChange, mapServiceNode.info.address, Long.MIN_VALUE)).success)
assertNull(service.processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.identity, mapServiceNode.info.address, Long.MIN_VALUE)).node) assertNull(service.processQueryRequest(NetworkMapService.QueryIdentityRequest(registerNode.info.identity, mapServiceNode.info.address, Long.MIN_VALUE)).node)
@ -73,7 +73,7 @@ class InMemoryNetworkMapServiceTest {
@Suspendable @Suspendable
override fun call() { override fun call() {
val req = NetworkMapService.UpdateAcknowledge(hash, serviceHub.networkService.myAddress) val req = NetworkMapService.UpdateAcknowledge(hash, serviceHub.networkService.myAddress)
send(NetworkMapService.PUSH_ACK_PROTOCOL_TOPIC, server.address, 0, req) send(NetworkMapService.PUSH_ACK_PROTOCOL_TOPIC, server.identity, 0, req)
} }
} }
@ -84,7 +84,7 @@ class InMemoryNetworkMapServiceTest {
val sessionID = random63BitValue() val sessionID = random63BitValue()
val req = NetworkMapService.FetchMapRequest(subscribe, ifChangedSinceVersion, serviceHub.networkService.myAddress, sessionID) val req = NetworkMapService.FetchMapRequest(subscribe, ifChangedSinceVersion, serviceHub.networkService.myAddress, sessionID)
return sendAndReceive<NetworkMapService.FetchMapResponse>( return sendAndReceive<NetworkMapService.FetchMapResponse>(
NetworkMapService.FETCH_PROTOCOL_TOPIC, server.address, 0, sessionID, req) NetworkMapService.FETCH_PROTOCOL_TOPIC, server.identity, 0, sessionID, req)
.validate { it.nodes } .validate { it.nodes }
} }
} }
@ -97,7 +97,7 @@ class InMemoryNetworkMapServiceTest {
val req = NetworkMapService.RegistrationRequest(reg.toWire(privateKey), serviceHub.networkService.myAddress, sessionID) val req = NetworkMapService.RegistrationRequest(reg.toWire(privateKey), serviceHub.networkService.myAddress, sessionID)
return sendAndReceive<NetworkMapService.RegistrationResponse>( return sendAndReceive<NetworkMapService.RegistrationResponse>(
NetworkMapService.REGISTER_PROTOCOL_TOPIC, server.address, 0, sessionID, req) NetworkMapService.REGISTER_PROTOCOL_TOPIC, server.identity, 0, sessionID, req)
.validate { it } .validate { it }
} }
} }
@ -110,19 +110,20 @@ class InMemoryNetworkMapServiceTest {
val req = NetworkMapService.SubscribeRequest(subscribe, serviceHub.networkService.myAddress, sessionID) val req = NetworkMapService.SubscribeRequest(subscribe, serviceHub.networkService.myAddress, sessionID)
return sendAndReceive<NetworkMapService.SubscribeResponse>( return sendAndReceive<NetworkMapService.SubscribeResponse>(
NetworkMapService.SUBSCRIPTION_PROTOCOL_TOPIC, server.address, 0, sessionID, req) NetworkMapService.SUBSCRIPTION_PROTOCOL_TOPIC, server.identity, 0, sessionID, req)
.validate { it } .validate { it }
} }
} }
@Test @Test
fun successWithNetwork() { fun `success with network`() {
val (mapServiceNode, registerNode) = network.createTwoNodes() val (mapServiceNode, registerNode) = network.createTwoNodes()
// Confirm there's a network map service on node 0 // Confirm there's a network map service on node 0
assertNotNull(mapServiceNode.inNodeNetworkMapService) assertNotNull(mapServiceNode.inNodeNetworkMapService)
// Confirm all nodes have registered themselves // Confirm all nodes have registered themselves
network.runNetwork()
var fetchPsm = registerNode.smm.add(NetworkMapService.FETCH_PROTOCOL_TOPIC, TestFetchPSM(mapServiceNode.info, false)) var fetchPsm = registerNode.smm.add(NetworkMapService.FETCH_PROTOCOL_TOPIC, TestFetchPSM(mapServiceNode.info, false))
network.runNetwork() network.runNetwork()
assertEquals(2, fetchPsm.get()?.count()) assertEquals(2, fetchPsm.get()?.count())
@ -143,11 +144,12 @@ class InMemoryNetworkMapServiceTest {
} }
@Test @Test
fun subscribeWithNetwork() { fun `subscribe with network`() {
val (mapServiceNode, registerNode) = network.createTwoNodes() val (mapServiceNode, registerNode) = network.createTwoNodes()
val service = (mapServiceNode.inNodeNetworkMapService as InMemoryNetworkMapService) val service = (mapServiceNode.inNodeNetworkMapService as InMemoryNetworkMapService)
// Test subscribing to updates // Test subscribing to updates
network.runNetwork()
val subscribePsm = registerNode.smm.add(NetworkMapService.SUBSCRIPTION_PROTOCOL_TOPIC, val subscribePsm = registerNode.smm.add(NetworkMapService.SUBSCRIPTION_PROTOCOL_TOPIC,
TestSubscribePSM(mapServiceNode.info, true)) TestSubscribePSM(mapServiceNode.info, true))
network.runNetwork() network.runNetwork()

View File

@ -1,8 +1,8 @@
package com.r3corda.node.services package com.r3corda.node.services
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry
import com.r3corda.core.contracts.SignedTransaction
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.r3corda.core.contracts.SignedTransaction
import com.r3corda.core.messaging.MessagingService import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.node.services.* import com.r3corda.core.node.services.*
import com.r3corda.core.node.services.testing.MockStorageService import com.r3corda.core.node.services.testing.MockStorageService
@ -68,7 +68,7 @@ open class MockServices(
if (net != null && storage != null) { if (net != null && storage != null) {
// Creating this class is sufficient, we don't have to store it anywhere, because it registers a listener // Creating this class is sufficient, we don't have to store it anywhere, because it registers a listener
// on the networking service, so that will keep it from being collected. // on the networking service, so that will keep it from being collected.
DataVendingService(net, storage) DataVendingService(net, storage, networkMapCache)
} }
} }
} }

View File

@ -8,9 +8,9 @@ import com.r3corda.contracts.testing.`with notary`
import com.r3corda.core.bd import com.r3corda.core.bd
import com.r3corda.core.contracts.DOLLARS import com.r3corda.core.contracts.DOLLARS
import com.r3corda.core.contracts.Fix import com.r3corda.core.contracts.Fix
import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.crypto.generateKeyPair import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.contracts.TransactionType
import com.r3corda.core.testing.ALICE_PUBKEY import com.r3corda.core.testing.ALICE_PUBKEY
import com.r3corda.core.testing.DUMMY_NOTARY import com.r3corda.core.testing.DUMMY_NOTARY
import com.r3corda.core.testing.MEGA_CORP import com.r3corda.core.testing.MEGA_CORP
@ -109,8 +109,9 @@ class NodeInterestRatesTest {
val tx = TransactionType.General.Builder() val tx = TransactionType.General.Builder()
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val protocol = RatesFixProtocol(tx, n2.info, fixOf, "0.675".bd, "0.1".bd, Duration.ofNanos(1)) val protocol = RatesFixProtocol(tx, n2.info.identity, fixOf, "0.675".bd, "0.1".bd, Duration.ofNanos(1))
BriefLogFormatter.initVerbose("rates") BriefLogFormatter.initVerbose("rates")
net.runNetwork()
val future = n1.smm.add("rates", protocol) val future = n1.smm.add("rates", protocol)
net.runNetwork() net.runNetwork()

View File

@ -65,7 +65,7 @@ fun main(args: Array<String>) {
val rateTolerance = BigDecimal(options.valueOf(rateToleranceArg)) val rateTolerance = BigDecimal(options.valueOf(rateToleranceArg))
// Bring up node. // Bring up node.
var advertisedServices: Set<ServiceType> = emptySet() val advertisedServices: Set<ServiceType> = emptySet()
val myNetAddr = ArtemisMessagingService.toHostAndPort(options.valueOf(networkAddressArg)) val myNetAddr = ArtemisMessagingService.toHostAndPort(options.valueOf(networkAddressArg))
val config = object : NodeConfiguration { val config = object : NodeConfiguration {
override val myLegalName: String = "Rate fix demo node" override val myLegalName: String = "Rate fix demo node"
@ -84,7 +84,7 @@ fun main(args: Array<String>) {
// Make a garbage transaction that includes a rate fix. // Make a garbage transaction that includes a rate fix.
val tx = TransactionType.General.Builder() val tx = TransactionType.General.Builder()
tx.addOutputState(TransactionState(Cash.State(1500.DOLLARS `issued by` node.storage.myLegalIdentity.ref(1), node.keyManagement.freshKey().public), notary.identity)) tx.addOutputState(TransactionState(Cash.State(1500.DOLLARS `issued by` node.storage.myLegalIdentity.ref(1), node.keyManagement.freshKey().public), notary.identity))
val protocol = RatesFixProtocol(tx, oracleNode, fixOf, expectedRate, rateTolerance, 24.hours) val protocol = RatesFixProtocol(tx, oracleNode.identity, fixOf, expectedRate, rateTolerance, 24.hours)
node.smm.add("demo.ratefix", protocol).get() node.smm.add("demo.ratefix", protocol).get()
node.stop() node.stop()

View File

@ -11,7 +11,6 @@ import com.r3corda.core.crypto.SecureHash
import com.r3corda.core.crypto.generateKeyPair import com.r3corda.core.crypto.generateKeyPair
import com.r3corda.core.days import com.r3corda.core.days
import com.r3corda.core.logElapsedTime import com.r3corda.core.logElapsedTime
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.node.NodeInfo import com.r3corda.core.node.NodeInfo
import com.r3corda.core.node.services.ServiceType import com.r3corda.core.node.services.ServiceType
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
@ -163,17 +162,13 @@ fun runTraderDemo(args: Array<String>): Int {
if (role == Role.BUYER) { if (role == Role.BUYER) {
runBuyer(node, amount) runBuyer(node, amount)
} else { } else {
val recipient = ArtemisMessagingService.makeRecipient(theirNetAddr) runSeller(node, amount, cashIssuer)
runSeller(myNetAddr, node, recipient, amount)
} }
return 0 return 0
} }
private fun runSeller(myNetAddr: HostAndPort, private fun runSeller(node: Node, amount: Amount<Issued<Currency>>, otherSide: Party) {
node: Node,
recipient: SingleMessageRecipient,
amount: Amount<Issued<Currency>>) {
// The seller will sell some commercial paper to the buyer, who will pay with (self issued) cash. // The seller will sell some commercial paper to the buyer, who will pay with (self issued) cash.
// //
// The CP sale transaction comes with a prospectus PDF, which will tag along for the ride in an // The CP sale transaction comes with a prospectus PDF, which will tag along for the ride in an
@ -192,7 +187,7 @@ private fun runSeller(myNetAddr: HostAndPort,
it.second.get() it.second.get()
} }
} else { } else {
val seller = TraderDemoProtocolSeller(myNetAddr, recipient, amount) val seller = TraderDemoProtocolSeller(otherSide, amount)
node.smm.add("demo.seller", seller).get() node.smm.add("demo.seller", seller).get()
} }
@ -208,8 +203,7 @@ private fun runBuyer(node: Node, amount: Amount<Issued<Currency>>) {
} }
val future = if (node.isPreviousCheckpointsPresent) { val future = if (node.isPreviousCheckpointsPresent) {
val (@Suppress("UNUSED_VARIABLE") buyer, future) = node.smm.findStateMachines(TraderDemoProtocolBuyer::class.java).single() node.smm.findStateMachines(TraderDemoProtocolBuyer::class.java).single().second
future
} else { } else {
// We use a simple scenario-specific wrapper protocol to make things happen. // We use a simple scenario-specific wrapper protocol to make things happen.
val buyer = TraderDemoProtocolBuyer(attachmentsPath, node.info.identity, amount) val buyer = TraderDemoProtocolBuyer(attachmentsPath, node.info.identity, amount)
@ -249,16 +243,19 @@ private class TraderDemoProtocolBuyer(private val attachmentsPath: Path,
// As the seller initiates the two-party trade protocol, here, we will be the buyer. // As the seller initiates the two-party trade protocol, here, we will be the buyer.
try { try {
progressTracker.currentStep = WAITING_FOR_SELLER_TO_CONNECT progressTracker.currentStep = WAITING_FOR_SELLER_TO_CONNECT
val origin = receive<HostAndPort>(DEMO_TOPIC, 0).validate { it.withDefaultPort(Node.DEFAULT_PORT) } val newPartnerParty = receive<Party>(DEMO_TOPIC, 0).validate {
val recipient = ArtemisMessagingService.makeRecipient(origin as HostAndPort) val ourVersionOfParty = serviceHub.networkMapCache.getNodeByLegalName(it.name)!!.identity
require(ourVersionOfParty == it)
it
}
// The session ID disambiguates the test trade. // The session ID disambiguates the test trade.
val sessionID = random63BitValue() val sessionID = random63BitValue()
progressTracker.currentStep = STARTING_BUY progressTracker.currentStep = STARTING_BUY
send(DEMO_TOPIC, recipient, 0, sessionID) send(DEMO_TOPIC, newPartnerParty, 0, sessionID)
val notary = serviceHub.networkMapCache.notaryNodes[0] val notary = serviceHub.networkMapCache.notaryNodes[0]
val buyer = TwoPartyTradeProtocol.Buyer(recipient, notary.identity, amount, val buyer = TwoPartyTradeProtocol.Buyer(newPartnerParty, notary.identity, amount,
CommercialPaper.State::class.java, sessionID) CommercialPaper.State::class.java, sessionID)
// This invokes the trading protocol and out pops our finished transaction. // This invokes the trading protocol and out pops our finished transaction.
@ -301,10 +298,9 @@ ${Emoji.renderIfSupported(cpIssuance)}""")
} }
} }
private class TraderDemoProtocolSeller(val myAddress: HostAndPort, private class TraderDemoProtocolSeller(val otherSide: Party,
val otherSide: SingleMessageRecipient, val amount: Amount<Issued<Currency>>,
val amount: Amount<Issued<Currency>>, override val progressTracker: ProgressTracker = TraderDemoProtocolSeller.tracker()) : ProtocolLogic<Unit>() {
override val progressTracker: ProgressTracker = TraderDemoProtocolSeller.tracker()) : ProtocolLogic<Unit>() {
companion object { companion object {
val PROSPECTUS_HASH = SecureHash.parse("decd098666b9657314870e192ced0c3519c2c9d395507a238338f8d003929de9") val PROSPECTUS_HASH = SecureHash.parse("decd098666b9657314870e192ced0c3519c2c9d395507a238338f8d003929de9")
@ -326,7 +322,7 @@ private class TraderDemoProtocolSeller(val myAddress: HostAndPort,
override fun call() { override fun call() {
progressTracker.currentStep = ANNOUNCING progressTracker.currentStep = ANNOUNCING
val sessionID = sendAndReceive<Long>(DEMO_TOPIC, otherSide, 0, 0, myAddress).validate { it } val sessionID = sendAndReceive<Long>(DEMO_TOPIC, otherSide, 0, 0, serviceHub.storageService.myLegalIdentity).validate { it }
progressTracker.currentStep = SELF_ISSUING progressTracker.currentStep = SELF_ISSUING

View File

@ -6,7 +6,6 @@ import com.google.common.util.concurrent.Futures
import com.r3corda.core.contracts.DealState import com.r3corda.core.contracts.DealState
import com.r3corda.core.contracts.SignedTransaction import com.r3corda.core.contracts.SignedTransaction
import com.r3corda.core.crypto.Party import com.r3corda.core.crypto.Party
import com.r3corda.core.messaging.SingleMessageRecipient
import com.r3corda.core.protocols.ProtocolLogic import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.random63BitValue import com.r3corda.core.random63BitValue
import com.r3corda.core.serialization.deserialize import com.r3corda.core.serialization.deserialize
@ -24,7 +23,7 @@ import com.r3corda.protocols.TwoPartyDealProtocol
object AutoOfferProtocol { object AutoOfferProtocol {
val TOPIC = "autooffer.topic" val TOPIC = "autooffer.topic"
data class AutoOfferMessage(val otherSide: SingleMessageRecipient, data class AutoOfferMessage(val otherSide: Party,
val notary: Party, val notary: Party,
val otherSessionID: Long, val dealBeingOffered: DealState) val otherSessionID: Long, val dealBeingOffered: DealState)
@ -67,7 +66,7 @@ object AutoOfferProtocol {
} }
class Requester<T>(val dealToBeOffered: DealState) : ProtocolLogic<SignedTransaction>() { class Requester(val dealToBeOffered: DealState) : ProtocolLogic<SignedTransaction>() {
companion object { companion object {
object RECEIVED : ProgressTracker.Step("Received API call") object RECEIVED : ProgressTracker.Step("Received API call")
@ -98,9 +97,9 @@ object AutoOfferProtocol {
val otherParty = notUs(*dealToBeOffered.parties).single() val otherParty = notUs(*dealToBeOffered.parties).single()
val otherNode = (serviceHub.networkMapCache.getNodeByLegalName(otherParty.name)) val otherNode = (serviceHub.networkMapCache.getNodeByLegalName(otherParty.name))
requireNotNull(otherNode) { "Cannot identify other party " + otherParty.name + ", know about: " + serviceHub.networkMapCache.partyNodes.map { it.identity } } requireNotNull(otherNode) { "Cannot identify other party " + otherParty.name + ", know about: " + serviceHub.networkMapCache.partyNodes.map { it.identity } }
val otherSide = otherNode!!.address val otherSide = otherNode!!.identity
progressTracker.currentStep = ANNOUNCING progressTracker.currentStep = ANNOUNCING
send(TOPIC, otherSide, 0, AutoOfferMessage(serviceHub.networkService.myAddress, notary, ourSessionID, dealToBeOffered)) send(TOPIC, otherSide, 0, AutoOfferMessage(serviceHub.storageService.myLegalIdentity, notary, ourSessionID, dealToBeOffered))
progressTracker.currentStep = DEALING progressTracker.currentStep = DEALING
val stx = subProtocol(TwoPartyDealProtocol.Acceptor(otherSide, notary, dealToBeOffered, ourSessionID, progressTracker.getChildProgressTracker(DEALING)!!)) val stx = subProtocol(TwoPartyDealProtocol.Acceptor(otherSide, notary, dealToBeOffered, ourSessionID, progressTracker.getChildProgressTracker(DEALING)!!))
return stx return stx

View File

@ -22,7 +22,7 @@ object ExitServerProtocol {
object Handler { object Handler {
fun register(node: Node) { fun register(node: Node) {
node.net.addMessageHandler("${TOPIC}.0") { msg, registration -> node.net.addMessageHandler("$TOPIC.0") { msg, registration ->
// Just to validate we got the message // Just to validate we got the message
if (enabled) { if (enabled) {
val message = msg.data.deserialize<ExitMessage>() val message = msg.data.deserialize<ExitMessage>()
@ -62,7 +62,7 @@ object ExitServerProtocol {
} else { } else {
// TODO: messaging ourselves seems to trigger a bug for the time being and we continuously receive messages // TODO: messaging ourselves seems to trigger a bug for the time being and we continuously receive messages
if (recipient.identity != serviceHub.storageService.myLegalIdentity) { if (recipient.identity != serviceHub.storageService.myLegalIdentity) {
send(TOPIC, recipient.address, 0, message) send(TOPIC, recipient.identity, 0, message)
} }
} }
} }

View File

@ -52,7 +52,7 @@ object UpdateBusinessDayProtocol {
if (recipient.address is MockNetworkMapCache.MockAddress) { if (recipient.address is MockNetworkMapCache.MockAddress) {
// Ignore // Ignore
} else { } else {
send(TOPIC, recipient.address, 0, message) send(TOPIC, recipient.identity, 0, message)
} }
} }
} }